コード例 #1
0
ファイル: reader.c プロジェクト: YauzZ/upb
static bool field_endmsg(void *closure, const void *hd, upb_status *status) {
  UPB_UNUSED(hd);
  upb_descreader *r = closure;
  upb_fielddef *f = r->f;
  // TODO: verify that all required fields were present.
  assert(upb_fielddef_number(f) != 0);
  assert(upb_fielddef_name(f) != NULL);
  assert((upb_fielddef_subdefname(f) != NULL) == upb_fielddef_hassubdef(f));

  if (r->default_string) {
    if (upb_fielddef_issubmsg(f)) {
      upb_status_seterrmsg(status, "Submessages cannot have defaults.");
      return false;
    }
    if (upb_fielddef_isstring(f) || upb_fielddef_type(f) == UPB_TYPE_ENUM) {
      upb_fielddef_setdefaultcstr(f, r->default_string, NULL);
    } else {
      if (r->default_string && !parse_default(r->default_string, f)) {
        // We don't worry too much about giving a great error message since the
        // compiler should have ensured this was correct.
        upb_status_seterrmsg(status, "Error converting default value.");
        return false;
      }
    }
  }
  return true;
}
コード例 #2
0
/**
 * lupb_msg_index
 *
 * Handles:
 *   msg.foo
 *   msg["foo"]
 *   msg[field_descriptor]  # (for extensions) (TODO)
 */
static int lupb_msg_index(lua_State *L) {
  lupb_msg *lmsg = lupb_msg_check(L, 1);
  const upb_fielddef *f = lupb_msg_checkfield(L, lmsg, 2);
  const upb_msglayout *l = lmsg->lmsgclass->layout;

  if (in_userval(f)) {
    lupb_uservalgeti(L, 1, lupb_fieldindex(f));

    if (lua_isnil(L, -1)) {
      /* Check if we need to lazily create wrapper. */
      if (upb_fielddef_isseq(f)) {
        /* TODO(haberman) */
      } else if (upb_fielddef_issubmsg(f)) {
        /* TODO(haberman) */
      } else {
        UPB_ASSERT(upb_fielddef_isstring(f));
        if (upb_msg_has(lmsg->msg, f, l)) {
          upb_msgval val = upb_msg_get(lmsg->msg, f, l);
          lua_pop(L, 1);
          lua_pushlstring(L, val.str.ptr, val.str.len);
          lupb_uservalseti(L, 1, lupb_fieldindex(f), -1);
        }
      }
    }
  } else {
    lupb_pushmsgval(L, upb_fielddef_type(f), upb_msg_get(lmsg->msg, f, l));
  }

  return 1;
}
コード例 #3
0
ファイル: reader.c プロジェクト: imageoptimiser/upb
static void field_endmsg(void *_r, upb_status *status) {
  upb_descreader *r = _r;
  upb_fielddef *f = r->f;
  // TODO: verify that all required fields were present.
  assert(upb_fielddef_number(f) != 0 && upb_fielddef_name(f) != NULL);
  assert((upb_fielddef_subdefname(f) != NULL) == upb_fielddef_hassubdef(f));

  if (r->default_string) {
    if (upb_fielddef_issubmsg(f)) {
      upb_status_seterrliteral(status, "Submessages cannot have defaults.");
      return;
    }
    if (upb_fielddef_isstring(f) || upb_fielddef_type(f) == UPB_TYPE(ENUM)) {
      upb_fielddef_setdefaultcstr(f, r->default_string);
    } else {
      upb_value val;
      upb_value_setptr(&val, NULL);  // Silence inaccurate compiler warnings.
      if (!parse_default(r->default_string, &val, upb_fielddef_type(f))) {
        // We don't worry too much about giving a great error message since the
        // compiler should have ensured this was correct.
        upb_status_seterrliteral(status, "Error converting default value.");
        return;
      }
      upb_fielddef_setdefault(f, val);
    }
  }
}
コード例 #4
0
ファイル: def.c プロジェクト: imageoptimiser/upb
void upb_fielddef_setdefault(upb_fielddef *f, upb_value value) {
  assert(!upb_fielddef_isfrozen(f));
  assert(!upb_fielddef_isstring(f) && !upb_fielddef_issubmsg(f));
  if (f->default_is_string) {
    upb_byteregion *bytes = upb_value_getbyteregion(f->defaultval);
    assert(bytes);
    upb_byteregion_free(bytes);
  }
  f->defaultval = value;
  f->default_is_string = false;
}
コード例 #5
0
ファイル: def.c プロジェクト: Phuehvk/upb
void upb_fielddef_setdefault(upb_fielddef *f, upb_value value) {
  assert(f->type_is_set_);
  assert(!upb_fielddef_isfrozen(f));
  assert(!upb_fielddef_isstring(f) && !upb_fielddef_issubmsg(f));
  if (f->default_is_string) {
    str_t *s = upb_value_getptr(f->defaultval);
    assert(s);
    freestr(s);
  }
  f->defaultval = value;
  f->default_is_string = false;
}
コード例 #6
0
ファイル: handlers.c プロジェクト: YauzZ/upb
uint32_t upb_handlers_selectorcount(const upb_fielddef *f) {
  uint32_t ret = 1;
  if (upb_fielddef_isseq(f)) ret += 2;    // STARTSEQ/ENDSEQ
  if (upb_fielddef_isstring(f)) ret += 2; // [STRING]/STARTSTR/ENDSTR
  if (upb_fielddef_issubmsg(f)) {
    // ENDSUBMSG (STARTSUBMSG is at table beginning)
    ret += 0;
    if (upb_fielddef_lazy(f)) {
      // STARTSTR/ENDSTR/STRING (for lazy)
      ret += 3;
    }
  }
  return ret;
}
コード例 #7
0
ファイル: def.c プロジェクト: Phuehvk/upb
bool upb_fielddef_setdefaultstr(upb_fielddef *f, const void *str, size_t len,
                                upb_status *s) {
  assert(upb_fielddef_isstring(f) || f->type_ == UPB_TYPE_ENUM);
  if (f->type_ == UPB_TYPE_ENUM && !upb_isident(str, len, false, s))
    return false;

  if (f->default_is_string) {
    str_t *s = upb_value_getptr(f->defaultval);
    assert(s);
    freestr(s);
  } else {
    assert(f->type_ == UPB_TYPE_ENUM);
  }

  str_t *str2 = newstr(str, len);
  upb_value_setptr(&f->defaultval, str2);
  f->default_is_string = true;
  return true;
}
コード例 #8
0
ファイル: def.c プロジェクト: imageoptimiser/upb
bool upb_fielddef_setdefaultstr(upb_fielddef *f, const void *str, size_t len) {
  assert(upb_fielddef_isstring(f) || f->type_ == UPB_TYPE(ENUM));
  if (f->type_ == UPB_TYPE(ENUM) && !upb_isident(str, len, false)) return false;

  if (f->default_is_string) {
    upb_byteregion *bytes = upb_value_getbyteregion(f->defaultval);
    assert(bytes);
    upb_byteregion_free(bytes);
  } else {
    assert(f->type_ == UPB_TYPE(ENUM));
  }

  upb_byteregion *r = upb_byteregion_newl(str, len);
  upb_value_setbyteregion(&f->defaultval, r);
  upb_bytesuccess_t ret = upb_byteregion_fetch(r);
  UPB_ASSERT_VAR(ret, ret == (len == 0 ? UPB_BYTE_EOF : UPB_BYTE_OK));
  assert(upb_byteregion_available(r, 0) == upb_byteregion_len(r));
  f->default_is_string = true;
  return true;
}
コード例 #9
0
ファイル: encode_decode.c プロジェクト: Holygitzdq/ElVis
static void putmsg(VALUE msg_rb, const Descriptor* desc,
                   upb_sink *sink, int depth) {
    MessageHeader* msg;
    upb_msg_field_iter i;
    upb_status status;

    upb_sink_startmsg(sink);

    // Protect against cycles (possible because users may freely reassign message
    // and repeated fields) by imposing a maximum recursion depth.
    if (depth > ENCODE_MAX_NESTING) {
        rb_raise(rb_eRuntimeError,
                 "Maximum recursion depth exceeded during encoding.");
    }

    TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);

    for (upb_msg_field_begin(&i, desc->msgdef);
            !upb_msg_field_done(&i);
            upb_msg_field_next(&i)) {
        upb_fielddef *f = upb_msg_iter_field(&i);
        uint32_t offset =
            desc->layout->fields[upb_fielddef_index(f)].offset +
            sizeof(MessageHeader);

        if (upb_fielddef_containingoneof(f)) {
            uint32_t oneof_case_offset =
                desc->layout->fields[upb_fielddef_index(f)].case_offset +
                sizeof(MessageHeader);
            // For a oneof, check that this field is actually present -- skip all the
            // below if not.
            if (DEREF(msg, oneof_case_offset, uint32_t) !=
                    upb_fielddef_number(f)) {
                continue;
            }
            // Otherwise, fall through to the appropriate singular-field handler
            // below.
        }

        if (is_map_field(f)) {
            VALUE map = DEREF(msg, offset, VALUE);
            if (map != Qnil) {
                putmap(map, f, sink, depth);
            }
        } else if (upb_fielddef_isseq(f)) {
            VALUE ary = DEREF(msg, offset, VALUE);
            if (ary != Qnil) {
                putary(ary, f, sink, depth);
            }
        } else if (upb_fielddef_isstring(f)) {
            VALUE str = DEREF(msg, offset, VALUE);
            if (RSTRING_LEN(str) > 0) {
                putstr(str, f, sink);
            }
        } else if (upb_fielddef_issubmsg(f)) {
            putsubmsg(DEREF(msg, offset, VALUE), f, sink, depth);
        } else {
            upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f));

#define T(upbtypeconst, upbtype, ctype, default_value)                \
  case upbtypeconst: {                                                \
      ctype value = DEREF(msg, offset, ctype);                        \
      if (value != default_value) {                                   \
        upb_sink_put##upbtype(sink, sel, value);                      \
      }                                                               \
    }                                                                 \
    break;

            switch (upb_fielddef_type(f)) {
                T(UPB_TYPE_FLOAT,  float,  float, 0.0)
                T(UPB_TYPE_DOUBLE, double, double, 0.0)
                T(UPB_TYPE_BOOL,   bool,   uint8_t, 0)
            case UPB_TYPE_ENUM:
                T(UPB_TYPE_INT32,  int32,  int32_t, 0)
                T(UPB_TYPE_UINT32, uint32, uint32_t, 0)
                T(UPB_TYPE_INT64,  int64,  int64_t, 0)
                T(UPB_TYPE_UINT64, uint64, uint64_t, 0)

            case UPB_TYPE_STRING:
            case UPB_TYPE_BYTES:
            case UPB_TYPE_MESSAGE:
                rb_raise(rb_eRuntimeError, "Internal error.");
            }

#undef T

        }
    }

    upb_sink_endmsg(sink, &status);
}
コード例 #10
0
ファイル: handlers.c プロジェクト: YauzZ/upb
bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type,
                              upb_selector_t *s) {
  switch (type) {
    case UPB_HANDLER_INT32:
    case UPB_HANDLER_INT64:
    case UPB_HANDLER_UINT32:
    case UPB_HANDLER_UINT64:
    case UPB_HANDLER_FLOAT:
    case UPB_HANDLER_DOUBLE:
    case UPB_HANDLER_BOOL:
      if (!upb_fielddef_isprimitive(f) ||
          upb_handlers_getprimitivehandlertype(f) != type)
        return false;
      *s = f->selector_base;
      break;
    case UPB_HANDLER_STRING:
      if (upb_fielddef_isstring(f)) {
        *s = f->selector_base;
      } else if (upb_fielddef_issubmsg(f)) {
        *s = f->selector_base + 3;
      } else {
        return false;
      }
      break;
    case UPB_HANDLER_STARTSTR:
      if (upb_fielddef_isstring(f) || upb_fielddef_issubmsg(f)) {
        *s = f->selector_base + 1;
      } else {
        return false;
      }
      break;
    case UPB_HANDLER_ENDSTR:
      if (upb_fielddef_isstring(f) || upb_fielddef_issubmsg(f)) {
        *s = f->selector_base + 2;
      } else {
        return false;
      }
      break;
    case UPB_HANDLER_STARTSEQ:
      if (!upb_fielddef_isseq(f)) return false;
      *s = f->selector_base - 2;
      break;
    case UPB_HANDLER_ENDSEQ:
      if (!upb_fielddef_isseq(f)) return false;
      *s = f->selector_base - 1;
      break;
    case UPB_HANDLER_STARTSUBMSG:
      if (!upb_fielddef_issubmsg(f)) return false;
      // Selectors for STARTSUBMSG are at the beginning of the table so that the
      // selector can also be used as an index into the "sub" array of
      // subhandlers.  The indexes for the two into these two tables are the
      // same, except that in the handler table the static selectors come first.
      *s = f->index_ + UPB_STATIC_SELECTOR_COUNT;
      break;
    case UPB_HANDLER_ENDSUBMSG:
      if (!upb_fielddef_issubmsg(f)) return false;
      *s = f->selector_base;
      break;
  }
  assert(*s < upb_fielddef_containingtype(f)->selector_count);
  return true;
}
コード例 #11
0
ファイル: handlers.c プロジェクト: YauzZ/upb
bool upb_handlers_freeze(upb_handlers *const*handlers, int n, upb_status *s) {
  // TODO: verify we have a transitive closure.
  for (int i = 0; i < n; i++) {
    upb_handlers *h = handlers[i];

    if (!upb_ok(&h->status_)) {
      upb_status_seterrf(s, "handlers for message %s had error status: %s",
                         upb_msgdef_fullname(upb_handlers_msgdef(h)),
                         upb_status_errmsg(&h->status_));
      return false;
    }

    // Check that there are no closure mismatches due to missing Start* handlers
    // or subhandlers with different type-level types.
    upb_msg_iter j;
    for(upb_msg_begin(&j, h->msg); !upb_msg_done(&j); upb_msg_next(&j)) {

      const upb_fielddef *f = upb_msg_iter_field(&j);
      if (upb_fielddef_isseq(f)) {
        if (!checkstart(h, f, UPB_HANDLER_STARTSEQ, s))
          return false;
      }

      if (upb_fielddef_isstring(f)) {
        if (!checkstart(h, f, UPB_HANDLER_STARTSTR, s))
          return false;
      }

      if (upb_fielddef_issubmsg(f)) {
        bool hashandler = false;
        if (upb_handlers_gethandler(h, getsel(h, f, UPB_HANDLER_STARTSUBMSG)) ||
            upb_handlers_gethandler(h, getsel(h, f, UPB_HANDLER_ENDSUBMSG))) {
          hashandler = true;
        }

        if (upb_fielddef_isseq(f) &&
            (upb_handlers_gethandler(h, getsel(h, f, UPB_HANDLER_STARTSEQ)) ||
             upb_handlers_gethandler(h, getsel(h, f, UPB_HANDLER_ENDSEQ)))) {
          hashandler = true;
        }

        if (hashandler && !upb_handlers_getsubhandlers(h, f)) {
          // For now we add an empty subhandlers in this case.  It makes the
          // decoder code generator simpler, because it only has to handle two
          // cases (submessage has handlers or not) as opposed to three
          // (submessage has handlers in enclosing message but no subhandlers).
          //
          // This makes parsing less efficient in the case that we want to
          // notice a submessage but skip its contents (like if we're testing
          // for submessage presence or counting the number of repeated
          // submessages).  In this case we will end up parsing the submessage
          // field by field and throwing away the results for each, instead of
          // skipping the whole delimited thing at once.  If this is an issue we
          // can revisit it, but do remember that this only arises when you have
          // handlers (startseq/startsubmsg/endsubmsg/endseq) set for the
          // submessage but no subhandlers.  The uses cases for this are
          // limited.
          upb_handlers *sub = upb_handlers_new(upb_fielddef_msgsubdef(f), &sub);
          upb_handlers_setsubhandlers(h, f, sub);
          upb_handlers_unref(sub, &sub);
        }

        // TODO(haberman): check type of submessage.
        // This is slightly tricky; also consider whether we should check that
        // they match at setsubhandlers time.
      }
    }
  }

  if (!upb_refcounted_freeze((upb_refcounted*const*)handlers, n, s,
                             UPB_MAX_HANDLER_DEPTH)) {
    return false;
  }

  return true;
}
コード例 #12
0
ファイル: def.c プロジェクト: Phuehvk/upb
bool upb_fielddef_isprimitive(const upb_fielddef *f) {
  return !upb_fielddef_isstring(f) && !upb_fielddef_issubmsg(f);
}