static json_ref bunser_template()

in watchman/bser.cpp [523:603]


static json_ref bunser_template(
    const char* buf,
    const char* end,
    json_int_t* used,
    json_error_t* jerr) {
  json_int_t needed = 0;
  json_int_t total = 0;
  json_int_t i, nelems;
  json_int_t ip, np;

  buf++;
  total++;

  if (*buf != BSER_ARRAY) {
    snprintf(
        jerr->text,
        sizeof(jerr->text),
        "Expected array encoding, but found 0x%02x",
        *buf);
    *used = total;
    return nullptr;
  }

  // Load in the property names template
  auto templ = bunser_array(buf, end, &needed, jerr);
  if (!templ) {
    *used = needed + total;
    return nullptr;
  }
  total += needed;
  buf += needed;

  // And the number of objects
  needed = 0;
  if (!bunser_int(buf, end - buf, &needed, &nelems)) {
    *used = needed + total;
    snprintf(
        jerr->text,
        sizeof(jerr->text),
        "invalid object number encoding (needed %d but have %d)",
        (int)needed,
        (int)(end - buf));
    return nullptr;
  }
  total += needed;
  buf += needed;

  np = json_array_size(templ);

  // Now load up the array with object values
  auto arrval = json_array_of_size((size_t)nelems);
  for (i = 0; i < nelems; i++) {
    auto item = json_object_of_size((size_t)np);
    for (ip = 0; ip < np; ip++) {
      if (*buf == BSER_SKIP) {
        buf++;
        total++;
        continue;
      }

      needed = 0;
      auto val = bunser(buf, end, &needed, jerr);
      if (!val) {
        *used = needed + total;
        return nullptr;
      }
      buf += needed;
      total += needed;

      json_object_set_new_nocheck(
          item,
          json_string_value(json_array_get(templ, (size_t)ip)),
          std::move(val));
    }

    json_array_append_new(arrval, std::move(item));
  }

  *used = total;
  return arrval;
}