/* * Copyright (c) 2009-2022, Google LLC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Google LLC nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef UPB_MINI_TABLE_H_ #define UPB_MINI_TABLE_H_ #include "upb/msg_internal.h" // Must be last. #include "upb/port_def.inc" #ifdef __cplusplus extern "C" { #endif const upb_MiniTable_Field* upb_MiniTable_FindFieldByNumber( const upb_MiniTable* table, uint32_t number); UPB_INLINE const upb_MiniTable* upb_MiniTable_GetSubMessageTable( const upb_MiniTable* mini_table, const upb_MiniTable_Field* field) { return mini_table->subs[field->submsg_index].submsg; } UPB_INLINE const upb_MiniTable_Enum* upb_MiniTable_GetSubEnumTable( const upb_MiniTable* mini_table, const upb_MiniTable_Field* field) { return mini_table->subs[field->submsg_index].subenum; } // Validates enum value against range defined by enum mini table. UPB_INLINE bool upb_MiniTable_Enum_CheckValue(const upb_MiniTable_Enum* e, int32_t val) { uint32_t uval = (uint32_t)val; if (uval < 64) return e->mask & (1ULL << uval); // OPT: binary search long lists? int n = e->value_count; for (int i = 0; i < n; i++) { if (e->values[i] == val) return true; } return false; } /** upb_MtDataEncoder *********************************************************/ // Functions to encode a string in a format that can be loaded by // upb_MiniTable_Build(). typedef enum { kUpb_MessageModifier_ValidateUtf8 = 1 << 0, kUpb_MessageModifier_DefaultIsPacked = 1 << 1, kUpb_MessageModifier_IsExtendable = 1 << 2, } kUpb_MessageModifier; typedef enum { kUpb_FieldModifier_IsRepeated = 1 << 0, kUpb_FieldModifier_IsPacked = 1 << 1, kUpb_FieldModifier_IsClosedEnum = 1 << 2, kUpb_FieldModifier_IsProto3Singular = 1 << 3, kUpb_FieldModifier_IsRequired = 1 << 4, } kUpb_FieldModifier; typedef struct { char* end; // Limit of the buffer passed as a parameter. // Aliased to internal-only members in .cc. char internal[32]; } upb_MtDataEncoder; // If the input buffer has at least this many bytes available, the encoder call // is guaranteed to succeed (as long as field number order is maintained). #define kUpb_MtDataEncoder_MinSize 16 // Encodes field/oneof information for a given message. The sequence of calls // should look like: // // upb_MtDataEncoder e; // char buf[256]; // char* ptr = buf; // e.end = ptr + sizeof(buf); // unit64_t msg_mod = ...; // bitwise & of kUpb_MessageModifiers or zero // ptr = upb_MtDataEncoder_StartMessage(&e, ptr, msg_mod); // // Fields *must* be in field number order. // ptr = upb_MtDataEncoder_PutField(&e, ptr, ...); // ptr = upb_MtDataEncoder_PutField(&e, ptr, ...); // ptr = upb_MtDataEncoder_PutField(&e, ptr, ...); // // // If oneofs are present. Oneofs must be encoded after regular fields. // ptr = upb_MiniTable_StartOneof(&e, ptr) // ptr = upb_MiniTable_PutOneofField(&e, ptr, ...); // ptr = upb_MiniTable_PutOneofField(&e, ptr, ...); // // ptr = upb_MiniTable_StartOneof(&e, ptr); // ptr = upb_MiniTable_PutOneofField(&e, ptr, ...); // ptr = upb_MiniTable_PutOneofField(&e, ptr, ...); // // Oneofs must be encoded after all regular fields. char* upb_MtDataEncoder_StartMessage(upb_MtDataEncoder* e, char* ptr, uint64_t msg_mod); char* upb_MtDataEncoder_PutField(upb_MtDataEncoder* e, char* ptr, upb_FieldType type, uint32_t field_num, uint64_t field_mod); char* upb_MtDataEncoder_StartOneof(upb_MtDataEncoder* e, char* ptr); char* upb_MtDataEncoder_PutOneofField(upb_MtDataEncoder* e, char* ptr, uint32_t field_num); // Encodes the set of values for a given enum. The values must be given in // order (after casting to uint32_t), and repeats are not allowed. void upb_MtDataEncoder_StartEnum(upb_MtDataEncoder* e); char* upb_MtDataEncoder_PutEnumValue(upb_MtDataEncoder* e, char* ptr, uint32_t val); char* upb_MtDataEncoder_EndEnum(upb_MtDataEncoder* e, char* ptr); /** upb_MiniTable *************************************************************/ typedef enum { kUpb_MiniTablePlatform_32Bit, kUpb_MiniTablePlatform_64Bit, kUpb_MiniTablePlatform_Native = UPB_SIZE(kUpb_MiniTablePlatform_32Bit, kUpb_MiniTablePlatform_64Bit), } upb_MiniTablePlatform; // Builds a mini table from the data encoded in the buffer [data, len]. If any // errors occur, returns NULL and sets a status message. In the success case, // the caller must call upb_MiniTable_SetSub*() for all message or proto2 enum // fields to link the table to the appropriate sub-tables. upb_MiniTable* upb_MiniTable_Build(const char* data, size_t len, upb_MiniTablePlatform platform, upb_Arena* arena, upb_Status* status); void upb_MiniTable_SetSubMessage(upb_MiniTable* table, upb_MiniTable_Field* field, const upb_MiniTable* sub); void upb_MiniTable_SetSubEnum(upb_MiniTable* table, upb_MiniTable_Field* field, const upb_MiniTable_Enum* sub); const char* upb_MiniTable_BuildExtension(const char* data, size_t len, upb_MiniTable_Extension* ext, upb_MiniTable_Sub sub, upb_Status* status); // Special-case functions for MessageSet layout and map entries. upb_MiniTable* upb_MiniTable_BuildMessageSet(upb_MiniTablePlatform platform, upb_Arena* arena); upb_MiniTable* upb_MiniTable_BuildMapEntry(upb_FieldType key_type, upb_FieldType value_type, bool value_is_proto3_enum, upb_MiniTablePlatform platform, upb_Arena* arena); upb_MiniTable_Enum* upb_MiniTable_BuildEnum(const char* data, size_t len, upb_Arena* arena, upb_Status* status); // Like upb_MiniTable_Build(), but the user provides a buffer of layout data so // it can be reused from call to call, avoiding repeated realloc()/free(). // // The caller owns `*buf` both before and after the call, and must free() it // when it is no longer in use. The function will realloc() `*buf` as // necessary, updating `*size` accordingly. upb_MiniTable* upb_MiniTable_BuildWithBuf(const char* data, size_t len, upb_MiniTablePlatform platform, upb_Arena* arena, void** buf, size_t* buf_size, upb_Status* status); // For testing only. char upb_ToBase92(int8_t ch); char upb_FromBase92(uint8_t ch); bool upb_IsTypePackable(upb_FieldType type); #ifdef __cplusplus } /* extern "C" */ #endif #include "upb/port_undef.inc" #endif /* UPB_MINI_TABLE_H_ */