static dynamic sliceMacro()

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;
    }
  }