예제 #1
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;
}
예제 #2
0
/**
 * lupb_map_typecheck()
 *
 * Checks that the lupb_map at index |narg| can be safely assigned to the
 * field |f| of the message at index |msg|.  If so, returns a upb_msgval for
 * this map.  Otherwise, raises a Lua error.
 */
static upb_msgval lupb_map_typecheck(lua_State *L, int narg, int msg,
                                     const upb_fielddef *f) {
  lupb_map *lmap = lupb_map_check(L, narg);
  upb_map *map = lmap->map;
  const upb_msgdef *entry = upb_fielddef_msgsubdef(f);
  const upb_fielddef *key_field = upb_msgdef_itof(entry, UPB_MAPENTRY_KEY);
  const upb_fielddef *value_field = upb_msgdef_itof(entry, UPB_MAPENTRY_VALUE);

  UPB_ASSERT(entry && key_field && value_field);

  if (upb_map_keytype(map) != upb_fielddef_type(key_field)) {
    luaL_error(L, "Map key type invalid");
  }

  if (upb_map_valuetype(map) != upb_fielddef_type(value_field)) {
    luaL_error(L, "Map had incorrect value type (expected: %s, got: %s)",
               upb_fielddef_type(value_field), upb_map_valuetype(map));
  }

  if (upb_map_valuetype(map) == UPB_TYPE_MESSAGE) {
    lupb_msgclass_typecheck(
        L, lupb_msg_msgclassfor(L, msg, upb_fielddef_msgsubdef(value_field)),
        lmap->value_lmsgclass);
  }

  return upb_msgval_map(map);
}
예제 #3
0
bool upb_array_set(upb_array *arr, size_t i, upb_msgval val) {
  size_t element_size = upb_msgval_sizeof(arr->type);
  UPB_ASSERT(i <= arr->len);

  if (i == arr->len) {
    /* Extending the array. */

    if (i == arr->size) {
      /* Need to reallocate. */
      size_t new_size = UPB_MAX(arr->size * 2, 8);
      size_t new_bytes = new_size * element_size;
      size_t old_bytes = arr->size * element_size;
      upb_alloc *alloc = upb_arena_alloc(arr->arena);
      upb_msgval *new_data =
          upb_realloc(alloc, arr->data, old_bytes, new_bytes);

      if (!new_data) {
        return false;
      }

      arr->data = new_data;
      arr->size = new_size;
    }

    arr->len = i + 1;
  }

  upb_msgval_write(arr->data, i * element_size, val, element_size);
  return true;
}
예제 #4
0
static upb_msgval lupb_tomsgval(lua_State *L, upb_fieldtype_t type, int narg,
                                const lupb_msgclass *lmsgclass) {
  switch (type) {
    case UPB_TYPE_INT32:
    case UPB_TYPE_ENUM:
      return upb_msgval_int32(lupb_checkint32(L, narg));
    case UPB_TYPE_INT64:
      return upb_msgval_int64(lupb_checkint64(L, narg));
    case UPB_TYPE_UINT32:
      return upb_msgval_uint32(lupb_checkuint32(L, narg));
    case UPB_TYPE_UINT64:
      return upb_msgval_uint64(lupb_checkuint64(L, narg));
    case UPB_TYPE_DOUBLE:
      return upb_msgval_double(lupb_checkdouble(L, narg));
    case UPB_TYPE_FLOAT:
      return upb_msgval_float(lupb_checkfloat(L, narg));
    case UPB_TYPE_BOOL:
      return upb_msgval_bool(lupb_checkbool(L, narg));
    case UPB_TYPE_STRING:
    case UPB_TYPE_BYTES: {
      size_t len;
      const char *ptr = lupb_checkstring(L, narg, &len);
      return upb_msgval_str(ptr, len);
    }
    case UPB_TYPE_MESSAGE:
      UPB_ASSERT(lmsgclass);
      return upb_msgval_msg(lupb_msg_checkmsg(L, narg, lmsgclass));
  }
  UPB_UNREACHABLE();
}
예제 #5
0
파일: textprinter.c 프로젝트: google/upb
bool putf(upb_textprinter *p, const char *fmt, ...) {
  va_list args;
  va_list args_copy;
  char *str;
  int written;
  int len;
  bool ok;

  va_start(args, fmt);

  /* Run once to get the length of the string. */
  _upb_va_copy(args_copy, args);
  len = _upb_vsnprintf(NULL, 0, fmt, args_copy);
  va_end(args_copy);

  /* + 1 for NULL terminator (vsprintf() requires it even if we don't). */
  str = upb_gmalloc(len + 1);
  if (!str) return false;
  written = vsprintf(str, fmt, args);
  va_end(args);
  UPB_ASSERT(written == len);

  ok = upb_bytessink_putbuf(p->output_, p->subc, str, len, NULL);
  upb_gfree(str);
  return ok;
}
예제 #6
0
static int lupb_msgclass_pushnew(lua_State *L, int factory, const upb_msglayout *l) {
  const lupb_msgfactory *lfactory = lupb_msgfactory_check(L, factory);
  lupb_msgclass *lmc = lupb_newuserdata(L, sizeof(*lmc), LUPB_MSGCLASS);

  UPB_ASSERT(l);
  lupb_uservalseti(L, -1, LUPB_MSGCLASS_FACTORY, factory);
  lmc->layout = l;
  lmc->lfactory = lfactory;

  return 1;
}
예제 #7
0
/* Returns the global lupb_alloc func that was created in our luaopen().
 * Callers can be guaranteed that it will be alive as long as |L| is. */
static upb_alloc *lupb_alloc_get(lua_State *L) {
  lupb_alloc *lalloc;

  lua_pushlightuserdata(L, &lupb_alloc_cache_key);
  lua_gettable(L, LUA_REGISTRYINDEX);
  lalloc = lua_touserdata(L, -1);
  UPB_ASSERT(lalloc);
  lua_pop(L, 1);

  return &lalloc->alloc;
}
예제 #8
0
/* Pushes a new userdata with the given metatable. */
static void *lupb_newuserdata(lua_State *L, size_t size, const char *type) {
  void *ret = lua_newuserdata(L, size);

  /* Set metatable. */
  luaL_getmetatable(L, type);
  UPB_ASSERT(!lua_isnil(L, -1));  /* Should have been created by luaopen_upb. */
  lua_setmetatable(L, -2);

  /* We don't set a uservalue here -- we lazily create it later if necessary. */

  return ret;
}
예제 #9
0
파일: msgfactory.c 프로젝트: google/upb
const upb_msglayout *upb_msgfactory_getlayout(upb_msgfactory *f,
                                              const upb_msgdef *m) {
  upb_value v;
  UPB_ASSERT(upb_symtab_lookupmsg(f->symtab, upb_msgdef_fullname(m)) == m);
  UPB_ASSERT(!upb_msgdef_mapentry(m));

  if (upb_inttable_lookupptr(&f->layouts, m, &v)) {
    UPB_ASSERT(upb_value_getptr(v));
    return upb_value_getptr(v);
  } else {
    /* In case of circular dependency, layout has to be inserted first. */
    upb_msglayout *l = upb_gmalloc(sizeof(*l));
    upb_msgfactory *mutable_f = (void*)f;
    upb_inttable_insertptr(&mutable_f->layouts, m, upb_value_ptr(l));
    UPB_ASSERT(l);
    if (!upb_msglayout_init(m, l, f)) {
      upb_msglayout_free(l);
    }
    return l;
  }
}
예제 #10
0
static upb_ctype_t upb_fieldtotabtype(upb_fieldtype_t type) {
  switch (type) {
    case UPB_TYPE_FLOAT: return UPB_CTYPE_FLOAT;
    case UPB_TYPE_DOUBLE: return UPB_CTYPE_DOUBLE;
    case UPB_TYPE_BOOL: return UPB_CTYPE_BOOL;
    case UPB_TYPE_BYTES:
    case UPB_TYPE_MESSAGE:
    case UPB_TYPE_STRING: return UPB_CTYPE_CONSTPTR;
    case UPB_TYPE_ENUM:
    case UPB_TYPE_INT32: return UPB_CTYPE_INT32;
    case UPB_TYPE_UINT32: return UPB_CTYPE_UINT32;
    case UPB_TYPE_INT64: return UPB_CTYPE_INT64;
    case UPB_TYPE_UINT64: return UPB_CTYPE_UINT64;
    default: UPB_ASSERT(false); return 0;
  }
}
예제 #11
0
bool upb_msg_has(const upb_msg *msg,
                 int field_index,
                 const upb_msglayout *l) {
  const upb_msglayout_field *field = upb_msg_checkfield(field_index, l);

  UPB_ASSERT(field->presence);

  if (upb_msg_inoneof(field)) {
    /* Oneofs are set when the oneof number is set to this field. */
    return *upb_msg_oneofcase(msg, field_index, l) == field->number;
  } else {
    /* Other fields are set when their hasbit is set. */
    uint32_t hasbit = field->presence;
    return DEREF(msg, hasbit / 8, char) | (1 << (hasbit % 8));
  }
}
예제 #12
0
upb_map *upb_map_new(upb_fieldtype_t ktype, upb_fieldtype_t vtype,
                     upb_arena *a) {
  upb_ctype_t vtabtype = upb_fieldtotabtype(vtype);
  upb_alloc *alloc = upb_arena_alloc(a);
  upb_map *map = upb_malloc(alloc, sizeof(upb_map));

  if (!map) {
    return NULL;
  }

  UPB_ASSERT(upb_fieldtype_mapkeyok(ktype));
  map->key_type = ktype;
  map->val_type = vtype;
  map->arena = a;

  if (!upb_strtable_init2(&map->strtab, vtabtype, alloc)) {
    return NULL;
  }

  return map;
}
예제 #13
0
upb_msgval upb_array_get(const upb_array *arr, size_t i) {
  size_t element_size = upb_msgval_sizeof(arr->type);
  UPB_ASSERT(i < arr->len);
  return upb_msgval_read(arr->data, i * element_size, element_size);
}
예제 #14
0
static uint32_t *upb_msg_oneofcase(const upb_msg *msg, int field_index,
                                   const upb_msglayout *l) {
  const upb_msglayout_field *field = upb_msg_checkfield(field_index, l);
  UPB_ASSERT(upb_msg_inoneof(field));
  return PTR_AT(msg, ~field->presence, uint32_t);
}
예제 #15
0
static const upb_msglayout_field *upb_msg_checkfield(int field_index,
                                                     const upb_msglayout *l) {
  UPB_ASSERT(field_index >= 0 && field_index < l->field_count);
  return &l->fields[field_index];
}
예제 #16
0
파일: msgfactory.c 프로젝트: google/upb
/* Align up to the given power of 2. */
static size_t align_up(size_t val, size_t align) {
  UPB_ASSERT(is_power_of_two(align));
  return (val + align - 1) & ~(align - 1);
}