parent
6c4dc6f9e8
commit
c033eff26f
21 changed files with 813 additions and 648 deletions
@ -0,0 +1,79 @@ |
||||
/*
|
||||
* Copyright (c) 2009-2021, 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. |
||||
*/ |
||||
|
||||
#include "upb/mini_table/common.h" |
||||
|
||||
#include <inttypes.h> |
||||
|
||||
#include "upb/arena.h" |
||||
#include "upb/mini_table/common_internal.h" |
||||
#include "upb/upb.h" |
||||
|
||||
// Must be last.
|
||||
#include "upb/port_def.inc" |
||||
|
||||
const char _kUpb_ToBase92[] = { |
||||
' ', '!', '#', '$', '%', '&', '(', ')', '*', '+', ',', '-', '.', '/', |
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', |
||||
'>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', |
||||
'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', |
||||
'Z', '[', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', |
||||
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', |
||||
'w', 'x', 'y', 'z', '{', '|', '}', '~', |
||||
}; |
||||
|
||||
const int8_t _kUpb_FromBase92[] = { |
||||
0, 1, -1, 2, 3, 4, 5, -1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, |
||||
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, |
||||
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, |
||||
55, 56, 57, -1, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, |
||||
73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, |
||||
}; |
||||
|
||||
const upb_MiniTable_Field* upb_MiniTable_FindFieldByNumber( |
||||
const upb_MiniTable* table, uint32_t number) { |
||||
int n = table->field_count; |
||||
for (int i = 0; i < n; i++) { |
||||
if (table->fields[i].number == number) { |
||||
return &table->fields[i]; |
||||
} |
||||
} |
||||
return NULL; |
||||
} |
||||
|
||||
upb_FieldType upb_MiniTableField_Type(const upb_MiniTable_Field* field) { |
||||
if (field->mode & kUpb_LabelFlags_IsAlternate) { |
||||
if (field->descriptortype == kUpb_FieldType_Int32) { |
||||
return kUpb_FieldType_Enum; |
||||
} else if (field->descriptortype == kUpb_FieldType_Bytes) { |
||||
return kUpb_FieldType_String; |
||||
} else { |
||||
UPB_ASSERT(false); |
||||
} |
||||
} |
||||
return field->descriptortype; |
||||
} |
@ -0,0 +1,123 @@ |
||||
/*
|
||||
* 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_COMMON_INTERNAL_H_ |
||||
#define UPB_MINI_TABLE_COMMON_INTERNAL_H_ |
||||
|
||||
#include "upb/upb.h" |
||||
|
||||
// Must be last.
|
||||
#include "upb/port_def.inc" |
||||
|
||||
typedef enum { |
||||
kUpb_EncodedType_Double = 0, |
||||
kUpb_EncodedType_Float = 1, |
||||
kUpb_EncodedType_Fixed32 = 2, |
||||
kUpb_EncodedType_Fixed64 = 3, |
||||
kUpb_EncodedType_SFixed32 = 4, |
||||
kUpb_EncodedType_SFixed64 = 5, |
||||
kUpb_EncodedType_Int32 = 6, |
||||
kUpb_EncodedType_UInt32 = 7, |
||||
kUpb_EncodedType_SInt32 = 8, |
||||
kUpb_EncodedType_Int64 = 9, |
||||
kUpb_EncodedType_UInt64 = 10, |
||||
kUpb_EncodedType_SInt64 = 11, |
||||
kUpb_EncodedType_OpenEnum = 12, |
||||
kUpb_EncodedType_Bool = 13, |
||||
kUpb_EncodedType_Bytes = 14, |
||||
kUpb_EncodedType_String = 15, |
||||
kUpb_EncodedType_Group = 16, |
||||
kUpb_EncodedType_Message = 17, |
||||
kUpb_EncodedType_ClosedEnum = 18, |
||||
|
||||
kUpb_EncodedType_RepeatedBase = 20, |
||||
} upb_EncodedType; |
||||
|
||||
typedef enum { |
||||
kUpb_EncodedFieldModifier_FlipPacked = 1 << 0, |
||||
// upb only.
|
||||
kUpb_EncodedFieldModifier_IsProto3Singular = 1 << 2, |
||||
kUpb_EncodedFieldModifier_IsRequired = 1 << 3, |
||||
} upb_EncodedFieldModifier; |
||||
|
||||
enum { |
||||
kUpb_EncodedValue_MinField = ' ', |
||||
kUpb_EncodedValue_MaxField = 'I', |
||||
kUpb_EncodedValue_MinModifier = 'L', |
||||
kUpb_EncodedValue_MaxModifier = '[', |
||||
kUpb_EncodedValue_End = '^', |
||||
kUpb_EncodedValue_MinSkip = '_', |
||||
kUpb_EncodedValue_MaxSkip = '~', |
||||
kUpb_EncodedValue_OneofSeparator = '~', |
||||
kUpb_EncodedValue_FieldSeparator = '|', |
||||
kUpb_EncodedValue_MinOneofField = ' ', |
||||
kUpb_EncodedValue_MaxOneofField = 'b', |
||||
kUpb_EncodedValue_MaxEnumMask = 'A', |
||||
}; |
||||
|
||||
enum { |
||||
kUpb_EncodedVersion_EnumV1 = '!', |
||||
kUpb_EncodedVersion_ExtensionV1 = '#', |
||||
kUpb_EncodedVersion_MapV1 = '%', |
||||
kUpb_EncodedVersion_MessageV1 = '$', |
||||
kUpb_EncodedVersion_MessageSetV1 = '&', |
||||
}; |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
UPB_INLINE char _upb_ToBase92(int8_t ch) { |
||||
extern const char _kUpb_ToBase92[]; |
||||
UPB_ASSERT(0 <= ch && ch < 92); |
||||
return _kUpb_ToBase92[ch]; |
||||
} |
||||
|
||||
UPB_INLINE char _upb_FromBase92(uint8_t ch) { |
||||
extern const int8_t _kUpb_FromBase92[]; |
||||
if (' ' > ch || ch > '~') return -1; |
||||
return _kUpb_FromBase92[ch - ' ']; |
||||
} |
||||
|
||||
UPB_INLINE bool _upb_FieldType_IsPackable(upb_FieldType type) { |
||||
// clang-format off
|
||||
const unsigned kUnpackableTypes = |
||||
(1 << kUpb_FieldType_String) | |
||||
(1 << kUpb_FieldType_Bytes) | |
||||
(1 << kUpb_FieldType_Message) | |
||||
(1 << kUpb_FieldType_Group); |
||||
// clang-format on
|
||||
return (1 << type) & ~kUnpackableTypes; |
||||
} |
||||
|
||||
#ifdef __cplusplus |
||||
} /* extern "C" */ |
||||
#endif |
||||
|
||||
#include "upb/port_undef.inc" |
||||
|
||||
#endif /* UPB_MINI_TABLE_COMMON_INTERNAL_H_ */ |
@ -0,0 +1,97 @@ |
||||
/*
|
||||
* 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_DECODE_H_ |
||||
#define UPB_MINI_TABLE_DECODE_H_ |
||||
|
||||
#include "upb/mini_table/common.h" |
||||
|
||||
// Must be last.
|
||||
#include "upb/port_def.inc" |
||||
|
||||
typedef enum { |
||||
kUpb_MiniTablePlatform_32Bit, |
||||
kUpb_MiniTablePlatform_64Bit, |
||||
kUpb_MiniTablePlatform_Native = |
||||
UPB_SIZE(kUpb_MiniTablePlatform_32Bit, kUpb_MiniTablePlatform_64Bit), |
||||
} upb_MiniTablePlatform; |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
// 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); |
||||
|
||||
// Links a sub-message field to a MiniTable for that sub-message. If a
|
||||
// sub-message field is not linked, it will be treated as an unknown field
|
||||
// during parsing, and setting the field will not be allowed. It is possible
|
||||
// to link the message field later, at which point it will no longer be treated
|
||||
// as unknown. However there is no synchronization for this operation, which
|
||||
// means parallel mutation requires external synchronization.
|
||||
void upb_MiniTable_SetSubMessage(upb_MiniTable* table, |
||||
upb_MiniTable_Field* field, |
||||
const upb_MiniTable* sub); |
||||
|
||||
// Links an enum field to a MiniTable for that enum. All enum fields must
|
||||
// be linked prior to parsing.
|
||||
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, |
||||
const upb_MiniTable* extendee, |
||||
upb_MiniTable_Sub sub, |
||||
upb_Status* status); |
||||
|
||||
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); |
||||
|
||||
#ifdef __cplusplus |
||||
} /* extern "C" */ |
||||
#endif |
||||
|
||||
#include "upb/port_undef.inc" |
||||
|
||||
#endif /* UPB_MINI_TABLE_DECODE_H_ */ |
@ -0,0 +1,301 @@ |
||||
/*
|
||||
* Copyright (c) 2009-2021, 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. |
||||
*/ |
||||
|
||||
#include "upb/mini_table/encode.h" |
||||
|
||||
#include <inttypes.h> |
||||
|
||||
#include "upb/arena.h" |
||||
#include "upb/mini_table/common.h" |
||||
#include "upb/mini_table/common_internal.h" |
||||
#include "upb/upb.h" |
||||
|
||||
// Must be last.
|
||||
#include "upb/port_def.inc" |
||||
|
||||
typedef struct { |
||||
uint64_t present_values_mask; |
||||
uint32_t last_written_value; |
||||
} upb_MtDataEncoderInternal_EnumState; |
||||
|
||||
typedef struct { |
||||
uint64_t msg_modifiers; |
||||
uint32_t last_field_num; |
||||
enum { |
||||
kUpb_OneofState_NotStarted, |
||||
kUpb_OneofState_StartedOneof, |
||||
kUpb_OneofState_EmittedOneofField, |
||||
} oneof_state; |
||||
} upb_MtDataEncoderInternal_MsgState; |
||||
|
||||
typedef struct { |
||||
char* buf_start; // Only for checking kUpb_MtDataEncoder_MinSize.
|
||||
union { |
||||
upb_MtDataEncoderInternal_EnumState enum_state; |
||||
upb_MtDataEncoderInternal_MsgState msg_state; |
||||
} state; |
||||
} upb_MtDataEncoderInternal; |
||||
|
||||
static upb_MtDataEncoderInternal* upb_MtDataEncoder_GetInternal( |
||||
upb_MtDataEncoder* e, char* buf_start) { |
||||
UPB_ASSERT(sizeof(upb_MtDataEncoderInternal) <= sizeof(e->internal)); |
||||
upb_MtDataEncoderInternal* ret = (upb_MtDataEncoderInternal*)e->internal; |
||||
ret->buf_start = buf_start; |
||||
return ret; |
||||
} |
||||
|
||||
static char* upb_MtDataEncoder_PutRaw(upb_MtDataEncoder* e, char* ptr, |
||||
char ch) { |
||||
upb_MtDataEncoderInternal* in = (upb_MtDataEncoderInternal*)e->internal; |
||||
UPB_ASSERT(ptr - in->buf_start < kUpb_MtDataEncoder_MinSize); |
||||
if (ptr == e->end) return NULL; |
||||
*ptr++ = ch; |
||||
return ptr; |
||||
} |
||||
|
||||
static char* upb_MtDataEncoder_Put(upb_MtDataEncoder* e, char* ptr, char ch) { |
||||
return upb_MtDataEncoder_PutRaw(e, ptr, _upb_ToBase92(ch)); |
||||
} |
||||
|
||||
static char* upb_MtDataEncoder_PutBase92Varint(upb_MtDataEncoder* e, char* ptr, |
||||
uint32_t val, int min, int max) { |
||||
int shift = _upb_Log2Ceiling(_upb_FromBase92(max) - _upb_FromBase92(min) + 1); |
||||
UPB_ASSERT(shift <= 6); |
||||
uint32_t mask = (1 << shift) - 1; |
||||
do { |
||||
uint32_t bits = val & mask; |
||||
ptr = upb_MtDataEncoder_Put(e, ptr, bits + _upb_FromBase92(min)); |
||||
if (!ptr) return NULL; |
||||
val >>= shift; |
||||
} while (val); |
||||
return ptr; |
||||
} |
||||
|
||||
char* upb_MtDataEncoder_PutModifier(upb_MtDataEncoder* e, char* ptr, |
||||
uint64_t mod) { |
||||
if (mod) { |
||||
ptr = upb_MtDataEncoder_PutBase92Varint(e, ptr, mod, |
||||
kUpb_EncodedValue_MinModifier, |
||||
kUpb_EncodedValue_MaxModifier); |
||||
} |
||||
return ptr; |
||||
} |
||||
|
||||
char* upb_MtDataEncoder_EncodeExtension(upb_MtDataEncoder* e, char* ptr, |
||||
upb_FieldType type, uint32_t field_num, |
||||
uint64_t field_mod) { |
||||
upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr); |
||||
in->state.msg_state.msg_modifiers = 0; |
||||
in->state.msg_state.last_field_num = 0; |
||||
in->state.msg_state.oneof_state = kUpb_OneofState_NotStarted; |
||||
|
||||
ptr = upb_MtDataEncoder_PutRaw(e, ptr, kUpb_EncodedVersion_ExtensionV1); |
||||
if (!ptr) return NULL; |
||||
|
||||
return upb_MtDataEncoder_PutField(e, ptr, type, field_num, field_mod); |
||||
} |
||||
|
||||
char* upb_MtDataEncoder_EncodeMap(upb_MtDataEncoder* e, char* ptr, |
||||
upb_FieldType key_type, |
||||
upb_FieldType value_type, |
||||
uint64_t value_mod) { |
||||
upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr); |
||||
in->state.msg_state.msg_modifiers = 0; |
||||
in->state.msg_state.last_field_num = 0; |
||||
in->state.msg_state.oneof_state = kUpb_OneofState_NotStarted; |
||||
|
||||
ptr = upb_MtDataEncoder_PutRaw(e, ptr, kUpb_EncodedVersion_MapV1); |
||||
if (!ptr) return NULL; |
||||
|
||||
ptr = upb_MtDataEncoder_PutField(e, ptr, key_type, 1, 0); |
||||
if (!ptr) return NULL; |
||||
|
||||
return upb_MtDataEncoder_PutField(e, ptr, value_type, 2, value_mod); |
||||
} |
||||
|
||||
char* upb_MtDataEncoder_EncodeMessageSet(upb_MtDataEncoder* e, char* ptr) { |
||||
(void)upb_MtDataEncoder_GetInternal(e, ptr); |
||||
return upb_MtDataEncoder_PutRaw(e, ptr, kUpb_EncodedVersion_MessageSetV1); |
||||
} |
||||
|
||||
char* upb_MtDataEncoder_StartMessage(upb_MtDataEncoder* e, char* ptr, |
||||
uint64_t msg_mod) { |
||||
upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr); |
||||
in->state.msg_state.msg_modifiers = msg_mod; |
||||
in->state.msg_state.last_field_num = 0; |
||||
in->state.msg_state.oneof_state = kUpb_OneofState_NotStarted; |
||||
|
||||
ptr = upb_MtDataEncoder_PutRaw(e, ptr, kUpb_EncodedVersion_MessageV1); |
||||
if (!ptr) return NULL; |
||||
|
||||
return upb_MtDataEncoder_PutModifier(e, ptr, msg_mod); |
||||
} |
||||
|
||||
char* upb_MtDataEncoder_PutField(upb_MtDataEncoder* e, char* ptr, |
||||
upb_FieldType type, uint32_t field_num, |
||||
uint64_t field_mod) { |
||||
static const char kUpb_TypeToEncoded[] = { |
||||
[kUpb_FieldType_Double] = kUpb_EncodedType_Double, |
||||
[kUpb_FieldType_Float] = kUpb_EncodedType_Float, |
||||
[kUpb_FieldType_Int64] = kUpb_EncodedType_Int64, |
||||
[kUpb_FieldType_UInt64] = kUpb_EncodedType_UInt64, |
||||
[kUpb_FieldType_Int32] = kUpb_EncodedType_Int32, |
||||
[kUpb_FieldType_Fixed64] = kUpb_EncodedType_Fixed64, |
||||
[kUpb_FieldType_Fixed32] = kUpb_EncodedType_Fixed32, |
||||
[kUpb_FieldType_Bool] = kUpb_EncodedType_Bool, |
||||
[kUpb_FieldType_String] = kUpb_EncodedType_String, |
||||
[kUpb_FieldType_Group] = kUpb_EncodedType_Group, |
||||
[kUpb_FieldType_Message] = kUpb_EncodedType_Message, |
||||
[kUpb_FieldType_Bytes] = kUpb_EncodedType_Bytes, |
||||
[kUpb_FieldType_UInt32] = kUpb_EncodedType_UInt32, |
||||
[kUpb_FieldType_Enum] = kUpb_EncodedType_OpenEnum, |
||||
[kUpb_FieldType_SFixed32] = kUpb_EncodedType_SFixed32, |
||||
[kUpb_FieldType_SFixed64] = kUpb_EncodedType_SFixed64, |
||||
[kUpb_FieldType_SInt32] = kUpb_EncodedType_SInt32, |
||||
[kUpb_FieldType_SInt64] = kUpb_EncodedType_SInt64, |
||||
}; |
||||
|
||||
upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr); |
||||
if (field_num <= in->state.msg_state.last_field_num) return NULL; |
||||
if (in->state.msg_state.last_field_num + 1 != field_num) { |
||||
// Put skip.
|
||||
UPB_ASSERT(field_num > in->state.msg_state.last_field_num); |
||||
uint32_t skip = field_num - in->state.msg_state.last_field_num; |
||||
ptr = upb_MtDataEncoder_PutBase92Varint( |
||||
e, ptr, skip, kUpb_EncodedValue_MinSkip, kUpb_EncodedValue_MaxSkip); |
||||
if (!ptr) return NULL; |
||||
} |
||||
in->state.msg_state.last_field_num = field_num; |
||||
|
||||
uint32_t encoded_modifiers = 0; |
||||
|
||||
// Put field type.
|
||||
int encoded_type = kUpb_TypeToEncoded[type]; |
||||
if (field_mod & kUpb_FieldModifier_IsClosedEnum) { |
||||
UPB_ASSERT(type == kUpb_FieldType_Enum); |
||||
encoded_type = kUpb_EncodedType_ClosedEnum; |
||||
} |
||||
if (field_mod & kUpb_FieldModifier_IsRepeated) { |
||||
// Repeated fields shift the type number up (unlike other modifiers which
|
||||
// are bit flags).
|
||||
encoded_type += kUpb_EncodedType_RepeatedBase; |
||||
|
||||
if (_upb_FieldType_IsPackable(type)) { |
||||
bool field_is_packed = field_mod & kUpb_FieldModifier_IsPacked; |
||||
bool default_is_packed = in->state.msg_state.msg_modifiers & |
||||
kUpb_MessageModifier_DefaultIsPacked; |
||||
if (field_is_packed != default_is_packed) { |
||||
encoded_modifiers |= kUpb_EncodedFieldModifier_FlipPacked; |
||||
} |
||||
} |
||||
} |
||||
ptr = upb_MtDataEncoder_Put(e, ptr, encoded_type); |
||||
if (!ptr) return NULL; |
||||
|
||||
if (field_mod & kUpb_FieldModifier_IsProto3Singular) { |
||||
encoded_modifiers |= kUpb_EncodedFieldModifier_IsProto3Singular; |
||||
} |
||||
if (field_mod & kUpb_FieldModifier_IsRequired) { |
||||
encoded_modifiers |= kUpb_EncodedFieldModifier_IsRequired; |
||||
} |
||||
return upb_MtDataEncoder_PutModifier(e, ptr, encoded_modifiers); |
||||
} |
||||
|
||||
char* upb_MtDataEncoder_StartOneof(upb_MtDataEncoder* e, char* ptr) { |
||||
upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr); |
||||
if (in->state.msg_state.oneof_state == kUpb_OneofState_NotStarted) { |
||||
ptr = upb_MtDataEncoder_Put(e, ptr, _upb_FromBase92(kUpb_EncodedValue_End)); |
||||
} else { |
||||
ptr = upb_MtDataEncoder_Put( |
||||
e, ptr, _upb_FromBase92(kUpb_EncodedValue_OneofSeparator)); |
||||
} |
||||
in->state.msg_state.oneof_state = kUpb_OneofState_StartedOneof; |
||||
return ptr; |
||||
} |
||||
|
||||
char* upb_MtDataEncoder_PutOneofField(upb_MtDataEncoder* e, char* ptr, |
||||
uint32_t field_num) { |
||||
upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr); |
||||
if (in->state.msg_state.oneof_state == kUpb_OneofState_EmittedOneofField) { |
||||
ptr = upb_MtDataEncoder_Put( |
||||
e, ptr, _upb_FromBase92(kUpb_EncodedValue_FieldSeparator)); |
||||
if (!ptr) return NULL; |
||||
} |
||||
ptr = upb_MtDataEncoder_PutBase92Varint(e, ptr, field_num, _upb_ToBase92(0), |
||||
_upb_ToBase92(63)); |
||||
in->state.msg_state.oneof_state = kUpb_OneofState_EmittedOneofField; |
||||
return ptr; |
||||
} |
||||
|
||||
char* upb_MtDataEncoder_StartEnum(upb_MtDataEncoder* e, char* ptr) { |
||||
upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr); |
||||
in->state.enum_state.present_values_mask = 0; |
||||
in->state.enum_state.last_written_value = 0; |
||||
|
||||
return upb_MtDataEncoder_PutRaw(e, ptr, kUpb_EncodedVersion_EnumV1); |
||||
} |
||||
|
||||
static char* upb_MtDataEncoder_FlushDenseEnumMask(upb_MtDataEncoder* e, |
||||
char* ptr) { |
||||
upb_MtDataEncoderInternal* in = (upb_MtDataEncoderInternal*)e->internal; |
||||
ptr = upb_MtDataEncoder_Put(e, ptr, in->state.enum_state.present_values_mask); |
||||
in->state.enum_state.present_values_mask = 0; |
||||
in->state.enum_state.last_written_value += 5; |
||||
return ptr; |
||||
} |
||||
|
||||
char* upb_MtDataEncoder_PutEnumValue(upb_MtDataEncoder* e, char* ptr, |
||||
uint32_t val) { |
||||
// TODO(b/229641772): optimize this encoding.
|
||||
upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr); |
||||
UPB_ASSERT(val >= in->state.enum_state.last_written_value); |
||||
uint32_t delta = val - in->state.enum_state.last_written_value; |
||||
if (delta >= 5 && in->state.enum_state.present_values_mask) { |
||||
ptr = upb_MtDataEncoder_FlushDenseEnumMask(e, ptr); |
||||
if (!ptr) { |
||||
return NULL; |
||||
} |
||||
delta -= 5; |
||||
} |
||||
|
||||
if (delta >= 5) { |
||||
ptr = upb_MtDataEncoder_PutBase92Varint( |
||||
e, ptr, delta, kUpb_EncodedValue_MinSkip, kUpb_EncodedValue_MaxSkip); |
||||
in->state.enum_state.last_written_value += delta; |
||||
delta = 0; |
||||
} |
||||
|
||||
UPB_ASSERT((in->state.enum_state.present_values_mask >> delta) == 0); |
||||
in->state.enum_state.present_values_mask |= 1ULL << delta; |
||||
return ptr; |
||||
} |
||||
|
||||
char* upb_MtDataEncoder_EndEnum(upb_MtDataEncoder* e, char* ptr) { |
||||
upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr); |
||||
if (!in->state.enum_state.present_values_mask) return ptr; |
||||
return upb_MtDataEncoder_FlushDenseEnumMask(e, ptr); |
||||
} |
@ -0,0 +1,109 @@ |
||||
/*
|
||||
* 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_ENCODE_H_ |
||||
#define UPB_MINI_TABLE_ENCODE_H_ |
||||
|
||||
#include "upb/mini_table/common.h" |
||||
|
||||
// Must be last.
|
||||
#include "upb/port_def.inc" |
||||
|
||||
// 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 |
||||
|
||||
typedef struct { |
||||
char* end; // Limit of the buffer passed as a parameter.
|
||||
// Aliased to internal-only members in .cc.
|
||||
char internal[32]; |
||||
} upb_MtDataEncoder; |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
// 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.
|
||||
char* upb_MtDataEncoder_StartEnum(upb_MtDataEncoder* e, char* ptr); |
||||
char* upb_MtDataEncoder_PutEnumValue(upb_MtDataEncoder* e, char* ptr, |
||||
uint32_t val); |
||||
char* upb_MtDataEncoder_EndEnum(upb_MtDataEncoder* e, char* ptr); |
||||
|
||||
// Encodes an entire mini descriptor for an extension.
|
||||
char* upb_MtDataEncoder_EncodeExtension(upb_MtDataEncoder* e, char* ptr, |
||||
upb_FieldType type, uint32_t field_num, |
||||
uint64_t field_mod); |
||||
|
||||
// Encodes an entire mini descriptor for a map.
|
||||
char* upb_MtDataEncoder_EncodeMap(upb_MtDataEncoder* e, char* ptr, |
||||
upb_FieldType key_type, |
||||
upb_FieldType value_type, uint64_t value_mod); |
||||
|
||||
// Encodes an entire mini descriptor for a message set.
|
||||
char* upb_MtDataEncoder_EncodeMessageSet(upb_MtDataEncoder* e, char* ptr); |
||||
|
||||
#ifdef __cplusplus |
||||
} /* extern "C" */ |
||||
#endif |
||||
|
||||
#include "upb/port_undef.inc" |
||||
|
||||
#endif /* UPB_MINI_TABLE_ENCODE_H_ */ |
@ -1,36 +0,0 @@ |
||||
/*
|
||||
* 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_ACCESSORS_INTERNAL_H_ |
||||
#define UPB_MINI_TABLE_ACCESSORS_INTERNAL_H_ |
||||
|
||||
// TODO(b/232091617): Delete this entire header which currently exists only for
|
||||
// temporary backwards compatibility.
|
||||
|
||||
#include "upb/internal/mini_table_accessors.h" |
||||
|
||||
#endif // UPB_MINI_TABLE_ACCESSORS_INTERNAL_H_
|
Loading…
Reference in new issue