int encode_fields(lua_sandbox* lsb, output_data* d, char id, const char* name, int index) { int result = 0; lua_getfield(lsb->lua, index, name); if (!lua_istable(lsb->lua, -1)) { return result; } size_t len_pos, len; lua_checkstack(lsb->lua, 2); lua_pushnil(lsb->lua); while (result == 0 && lua_next(lsb->lua, -2) != 0) { if (pb_write_tag(d, id, 2)) return 1; len_pos = d->pos; if (pb_write_varint(d, 0)) return 1; // length tbd later if (lua_isstring(lsb->lua, -2)) { const char* s = lua_tolstring(lsb->lua, -2, &len); if (pb_write_string(d, 1, s, len)) return 1; } else { snprintf(lsb->error_message, LSB_ERROR_SIZE, "field name must be a string"); return 1; } if (encode_field_value(lsb, d, 1, NULL)) return 1; if (update_field_length(d, len_pos)) return 1; lua_pop(lsb->lua, 1); // Remove the value leaving the key on top for // the next interation. } lua_pop(lsb->lua, 1); // remove the fields table return result; }
int encode_string(lua_sandbox* lsb, output_data* d, char id, const char* name) { int result = 0; lua_getfield(lsb->m_lua, 1, name); if (lua_isstring(lsb->m_lua, -1)) { size_t len; const char* s = lua_tolstring(lsb->m_lua, -1, &len); result = pb_write_string(d, id, s, len); } lua_pop(lsb->m_lua, 1); return result; }
int encode_field_value(lua_sandbox* lsb, output_data* d, int first, const char* representation) { int result = 1; size_t len; const char* s; int t = lua_type(lsb->lua, -1); switch (t) { case LUA_TSTRING: if (first && representation) { // this uglyness keeps the protobuf // fields in order without additional // lookups if (pb_write_string(d, 3, representation, strlen(representation))) { return 1; } } s = lua_tolstring(lsb->lua, -1, &len); result = pb_write_string(d, 4, s, len); break; case LUA_TNUMBER: if (first) { if (pb_write_tag(d, 2, 0)) return 1; if (pb_write_varint(d, 3)) return 1; if (representation) { if (pb_write_string(d, 3, representation, strlen(representation))) { return 1; } } } result = encode_double(lsb, d, 7); break; case LUA_TBOOLEAN: if (first) { if (pb_write_tag(d, 2, 0)) return 1; if (pb_write_varint(d, 4)) return 1; if (representation) { if (pb_write_string(d, 3, representation, strlen(representation))) { return 1; } } } if (pb_write_tag(d, 8, 0)) return 1; result = pb_write_bool(d, lua_toboolean(lsb->lua, -1)); break; case LUA_TTABLE: { lua_rawgeti(lsb->lua, -1, 1); int t = lua_type(lsb->lua, -1); lua_pop(lsb->lua, 1); // remove the array test value if (LUA_TNIL == t) { result = encode_field_object(lsb, d); } else { result = encode_field_array(lsb, d, t, representation); } } break; default: snprintf(lsb->error_message, LSB_ERROR_SIZE, "unsupported type %d", t); result = 1; } return result; }