void BaseFormatter::operator()

in folly/Format-inl.h [171:280]


void BaseFormatter<Derived, containerMode, Args...>::operator()(
    Output& out) const {
  // Copy raw string (without format specifiers) to output;
  // not as simple as we'd like, as we still need to translate "}}" to "}"
  // and throw if we see any lone "}"
  auto outputString = [&out](StringPiece s) {
    auto p = s.begin();
    auto end = s.end();
    while (p != end) {
      auto q = static_cast<const char*>(memchr(p, '}', size_t(end - p)));
      if (!q) {
        out(StringPiece(p, end));
        break;
      }
      ++q;
      out(StringPiece(p, q));
      p = q;

      if (p == end || *p != '}') {
        throw_exception<BadFormatArg>(
            "folly::format: single '}' in format string");
      }
      ++p;
    }
  };

  auto p = str_.begin();
  auto end = str_.end();

  int nextArg = 0;
  bool hasDefaultArgIndex = false;
  bool hasExplicitArgIndex = false;
  while (p != end) {
    auto q = static_cast<const char*>(memchr(p, '{', size_t(end - p)));
    if (!q) {
      outputString(StringPiece(p, end));
      break;
    }
    outputString(StringPiece(p, q));
    p = q + 1;

    if (p == end) {
      throw_exception<BadFormatArg>(
          "folly::format: '}' at end of format string");
    }

    // "{{" -> "{"
    if (*p == '{') {
      out(StringPiece(p, 1));
      ++p;
      continue;
    }

    // Format string
    q = static_cast<const char*>(memchr(p, '}', size_t(end - p)));
    if (q == nullptr) {
      throw_exception<BadFormatArg>("folly::format: missing ending '}'");
    }
    FormatArg arg(StringPiece(p, q));
    p = q + 1;

    int argIndex = 0;
    auto piece = arg.splitKey<true>(); // empty key component is okay
    if (containerMode) { // static
      arg.enforce(
          arg.width != FormatArg::kDynamicWidth,
          "dynamic field width not supported in vformat()");
      if (piece.empty()) {
        arg.setNextIntKey(nextArg++);
        hasDefaultArgIndex = true;
      } else {
        arg.setNextKey(piece);
        hasExplicitArgIndex = true;
      }
    } else {
      if (piece.empty()) {
        if (arg.width == FormatArg::kDynamicWidth) {
          arg.enforce(
              arg.widthIndex == FormatArg::kNoIndex,
              "cannot provide width arg index without value arg index");
          int sizeArg = nextArg++;
          arg.width = asDerived().getSizeArg(size_t(sizeArg), arg);
        }

        argIndex = nextArg++;
        hasDefaultArgIndex = true;
      } else {
        if (arg.width == FormatArg::kDynamicWidth) {
          arg.enforce(
              arg.widthIndex != FormatArg::kNoIndex,
              "cannot provide value arg index without width arg index");
          arg.width = asDerived().getSizeArg(size_t(arg.widthIndex), arg);
        }

        auto result = tryTo<int>(piece);
        arg.enforce(result, "argument index must be integer");
        argIndex = *result;
        arg.enforce(argIndex >= 0, "argument index must be non-negative");
        hasExplicitArgIndex = true;
      }
    }

    if (hasDefaultArgIndex && hasExplicitArgIndex) {
      throw_exception<BadFormatArg>(
          "folly::format: may not have both default and explicit arg indexes");
    }

    asDerived().doFormat(size_t(argIndex), arg, out);
  }
}