1 /* 2 * Copyright (c) 2009-2021, Google LLC 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * * Neither the name of Google LLC nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #ifndef UPB_MINI_TABLE_ENCODE_INTERNAL_HPP_ 29 #define UPB_MINI_TABLE_ENCODE_INTERNAL_HPP_ 30 31 #include <string> 32 33 #include "upb/base/log2.h" 34 #include "upb/mini_table/encode_internal.h" 35 36 namespace upb { 37 38 class MtDataEncoder { 39 public: MtDataEncoder()40 MtDataEncoder() : appender_(&encoder_) {} 41 StartMessage(uint64_t msg_mod)42 bool StartMessage(uint64_t msg_mod) { 43 return appender_([=](char* buf) { 44 return upb_MtDataEncoder_StartMessage(&encoder_, buf, msg_mod); 45 }); 46 } 47 PutField(upb_FieldType type,uint32_t field_num,uint64_t field_mod)48 bool PutField(upb_FieldType type, uint32_t field_num, uint64_t field_mod) { 49 return appender_([=](char* buf) { 50 return upb_MtDataEncoder_PutField(&encoder_, buf, type, field_num, 51 field_mod); 52 }); 53 } 54 StartOneof()55 bool StartOneof() { 56 return appender_([=](char* buf) { 57 return upb_MtDataEncoder_StartOneof(&encoder_, buf); 58 }); 59 } 60 PutOneofField(uint32_t field_num)61 bool PutOneofField(uint32_t field_num) { 62 return appender_([=](char* buf) { 63 return upb_MtDataEncoder_PutOneofField(&encoder_, buf, field_num); 64 }); 65 } 66 StartEnum()67 bool StartEnum() { 68 return appender_( 69 [=](char* buf) { return upb_MtDataEncoder_StartEnum(&encoder_, buf); }); 70 } 71 PutEnumValue(uint32_t enum_value)72 bool PutEnumValue(uint32_t enum_value) { 73 return appender_([=](char* buf) { 74 return upb_MtDataEncoder_PutEnumValue(&encoder_, buf, enum_value); 75 }); 76 } 77 EndEnum()78 bool EndEnum() { 79 return appender_( 80 [=](char* buf) { return upb_MtDataEncoder_EndEnum(&encoder_, buf); }); 81 } 82 EncodeExtension(upb_FieldType type,uint32_t field_num,uint64_t field_mod)83 bool EncodeExtension(upb_FieldType type, uint32_t field_num, 84 uint64_t field_mod) { 85 return appender_([=](char* buf) { 86 return upb_MtDataEncoder_EncodeExtension(&encoder_, buf, type, field_num, 87 field_mod); 88 }); 89 } 90 EncodeMap(upb_FieldType key_type,upb_FieldType val_type,uint64_t key_mod,uint64_t val_mod)91 bool EncodeMap(upb_FieldType key_type, upb_FieldType val_type, 92 uint64_t key_mod, uint64_t val_mod) { 93 return appender_([=](char* buf) { 94 return upb_MtDataEncoder_EncodeMap(&encoder_, buf, key_type, val_type, 95 key_mod, val_mod); 96 }); 97 } 98 EncodeMessageSet()99 bool EncodeMessageSet() { 100 return appender_([=](char* buf) { 101 return upb_MtDataEncoder_EncodeMessageSet(&encoder_, buf); 102 }); 103 } 104 data() const105 const std::string& data() const { return appender_.data(); } 106 107 private: 108 class StringAppender { 109 public: StringAppender(upb_MtDataEncoder * e)110 StringAppender(upb_MtDataEncoder* e) { e->end = buf_ + sizeof(buf_); } 111 112 template <class T> operator ()(T && func)113 bool operator()(T&& func) { 114 char* end = func(buf_); 115 if (!end) return false; 116 // C++ does not guarantee that string has doubling growth behavior, but 117 // we need it to avoid O(n^2). 118 str_.reserve(upb_Log2CeilingSize(str_.size() + (end - buf_))); 119 str_.append(buf_, end - buf_); 120 return true; 121 } 122 data() const123 const std::string& data() const { return str_; } 124 125 private: 126 char buf_[kUpb_MtDataEncoder_MinSize]; 127 std::string str_; 128 }; 129 130 upb_MtDataEncoder encoder_; 131 StringAppender appender_; 132 }; 133 134 } // namespace upb 135 136 #endif /* UPB_MINI_TABLE_ENCODE_INTERNAL_HPP_ */ 137