in mcrouter/lib/config/ConfigPreprocessor.cpp [797:841]
static dynamic sliceMacro(Context&& ctx) {
const auto& from = ctx.at("from");
const auto& to = ctx.at("to");
auto dict = ctx.move("dictionary");
checkLogic(
dict.isObject() || dict.isArray() || dict.isString(),
"Slice: dictionary is not array/object/string");
if (dict.isObject()) {
dynamic res = dynamic::object();
checkLogic(from.isString(), "Slice: from is not a string");
checkLogic(to.isString(), "Slice: to is not a string");
auto fromKey = from.stringPiece();
auto toKey = to.stringPiece();
// since dictionary is unordered, we should iterate over it
for (auto& it : dict.items()) {
auto& key = const_cast<dynamic&>(it.first);
auto& value = const_cast<dynamic&>(it.second);
if (fromKey <= key.stringPiece() && key.stringPiece() <= toKey) {
res.insert(std::move(key), std::move(value));
}
}
return res;
} else if (dict.isArray()) {
dynamic res = dynamic::array;
checkLogic(from.isInt() && to.isInt(), "Slice: from/to is not an int");
auto fromId = std::max((int64_t)0, from.asInt());
auto toId = std::min(to.asInt() + 1, (int64_t)dict.size());
for (auto i = fromId; i < toId; ++i) {
res.push_back(std::move(dict[i]));
}
return res;
} else { // string
string res;
auto dictStr = dict.stringPiece();
checkLogic(from.isInt() && to.isInt(), "Slice: from/to is not an int");
auto fromId = std::max((int64_t)0, from.asInt());
auto toId = std::min(to.asInt() + 1, (int64_t)dict.size());
for (auto i = fromId; i < toId; ++i) {
res += dictStr[i];
}
return res;
}
}