File indexing completed on 2026-09-20 09:29:10
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef UPB_TEXT_ENCODE_INTERNAL_H_
0009 #define UPB_TEXT_ENCODE_INTERNAL_H_
0010
0011 #include <stdarg.h>
0012 #include <string.h>
0013
0014 #include "upb/base/descriptor_constants.h"
0015 #include "upb/base/string_view.h"
0016 #include "upb/message/array.h"
0017 #include "upb/message/internal/map_sorter.h"
0018 #include "upb/message/message.h"
0019 #include "upb/port/vsnprintf_compat.h"
0020 #include "upb/text/options.h"
0021 #include "upb/wire/eps_copy_input_stream.h"
0022 #include "utf8_range.h"
0023
0024
0025 #include "upb/port/def.inc"
0026
0027 typedef struct {
0028 char *buf, *ptr, *end;
0029 size_t overflow;
0030 int indent_depth;
0031 int options;
0032 const struct upb_DefPool* ext_pool;
0033 _upb_mapsorter sorter;
0034 } txtenc;
0035
0036 UPB_INLINE void UPB_PRIVATE(_upb_TextEncode_PutBytes)(txtenc* e,
0037 const void* data,
0038 size_t len) {
0039 size_t have = e->end - e->ptr;
0040 if (UPB_LIKELY(have >= len)) {
0041 memcpy(e->ptr, data, len);
0042 e->ptr += len;
0043 } else {
0044 if (have) {
0045 memcpy(e->ptr, data, have);
0046 e->ptr += have;
0047 }
0048 e->overflow += (len - have);
0049 }
0050 }
0051
0052 UPB_INLINE void UPB_PRIVATE(_upb_TextEncode_PutStr)(txtenc* e,
0053 const char* str) {
0054 UPB_PRIVATE(_upb_TextEncode_PutBytes)(e, str, strlen(str));
0055 }
0056
0057 UPB_INLINE void UPB_PRIVATE(_upb_TextEncode_Printf)(txtenc* e, const char* fmt,
0058 ...) {
0059 size_t n;
0060 size_t have = e->end - e->ptr;
0061 va_list args;
0062
0063 va_start(args, fmt);
0064 n = _upb_vsnprintf(e->ptr, have, fmt, args);
0065 va_end(args);
0066
0067 if (UPB_LIKELY(have > n)) {
0068 e->ptr += n;
0069 } else {
0070 e->ptr = UPB_PTRADD(e->ptr, have);
0071 e->overflow += (n - have);
0072 }
0073 }
0074
0075 UPB_INLINE void UPB_PRIVATE(_upb_TextEncode_Indent)(txtenc* e) {
0076 if ((e->options & UPB_TXTENC_SINGLELINE) == 0) {
0077 int i = e->indent_depth;
0078 while (i-- > 0) {
0079 UPB_PRIVATE(_upb_TextEncode_PutStr)(e, " ");
0080 }
0081 }
0082 }
0083
0084 UPB_INLINE void UPB_PRIVATE(_upb_TextEncode_EndField)(txtenc* e) {
0085 if (e->options & UPB_TXTENC_SINGLELINE) {
0086 UPB_PRIVATE(_upb_TextEncode_PutStr)(e, " ");
0087 } else {
0088 UPB_PRIVATE(_upb_TextEncode_PutStr)(e, "\n");
0089 }
0090 }
0091
0092 UPB_INLINE void UPB_PRIVATE(_upb_TextEncode_Escaped)(txtenc* e,
0093 unsigned char ch) {
0094 switch (ch) {
0095 case '\n':
0096 UPB_PRIVATE(_upb_TextEncode_PutStr)(e, "\\n");
0097 break;
0098 case '\r':
0099 UPB_PRIVATE(_upb_TextEncode_PutStr)(e, "\\r");
0100 break;
0101 case '\t':
0102 UPB_PRIVATE(_upb_TextEncode_PutStr)(e, "\\t");
0103 break;
0104 case '\"':
0105 UPB_PRIVATE(_upb_TextEncode_PutStr)(e, "\\\"");
0106 break;
0107 case '\'':
0108 UPB_PRIVATE(_upb_TextEncode_PutStr)(e, "\\'");
0109 break;
0110 case '\\':
0111 UPB_PRIVATE(_upb_TextEncode_PutStr)(e, "\\\\");
0112 break;
0113 default:
0114 UPB_PRIVATE(_upb_TextEncode_Printf)(e, "\\%03o", ch);
0115 break;
0116 }
0117 }
0118
0119
0120
0121 UPB_INLINE bool UPB_PRIVATE(_upb_DefinitelyNeedsEscape)(unsigned char ch) {
0122 if (ch < 32) return true;
0123 switch (ch) {
0124 case '\"':
0125 case '\'':
0126 case '\\':
0127 case 127:
0128 return true;
0129 }
0130 return false;
0131 }
0132
0133 UPB_INLINE bool UPB_PRIVATE(_upb_AsciiIsPrint)(unsigned char ch) {
0134 return ch >= 32 && ch < 127;
0135 }
0136
0137
0138
0139 UPB_INLINE bool UPB_PRIVATE(_upb_NeedsUtf8Validation)(unsigned char ch) {
0140 return ch > 127;
0141 }
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151 UPB_INLINE size_t UPB_PRIVATE(_SkipPassthroughBytes)(const char* ptr,
0152 size_t size) {
0153 for (size_t i = 0; i < size; i++) {
0154 unsigned char uc = ptr[i];
0155 if (UPB_PRIVATE(_upb_DefinitelyNeedsEscape)(uc)) return i;
0156 if (UPB_PRIVATE(_upb_NeedsUtf8Validation)(uc)) {
0157
0158
0159
0160
0161
0162
0163
0164 size_t end = i + 1;
0165 for (; end < size; end++) {
0166 if (!UPB_PRIVATE(_upb_NeedsUtf8Validation)(ptr[end])) break;
0167 }
0168 size_t n = end - i;
0169 size_t ok = utf8_range_ValidPrefix(ptr + i, n);
0170 if (ok != n) return i + ok;
0171 i += ok - 1;
0172 }
0173 }
0174 return size;
0175 }
0176
0177 UPB_INLINE void UPB_PRIVATE(_upb_HardenedPrintString)(txtenc* e,
0178 const char* ptr,
0179 size_t len) {
0180
0181
0182
0183
0184
0185 UPB_PRIVATE(_upb_TextEncode_PutStr)(e, "\"");
0186 const char* end = ptr + len;
0187 while (ptr < end) {
0188 size_t n = UPB_PRIVATE(_SkipPassthroughBytes)(ptr, end - ptr);
0189 if (n != 0) {
0190 UPB_PRIVATE(_upb_TextEncode_PutBytes)(e, ptr, n);
0191 ptr += n;
0192 if (ptr == end) break;
0193 }
0194
0195
0196
0197 UPB_PRIVATE(_upb_TextEncode_Escaped)(e, *ptr);
0198 ptr++;
0199 }
0200 UPB_PRIVATE(_upb_TextEncode_PutStr)(e, "\"");
0201 }
0202
0203 UPB_INLINE void UPB_PRIVATE(_upb_TextEncode_Bytes)(txtenc* e,
0204 upb_StringView data) {
0205 const char* ptr = data.data;
0206 const char* end = ptr + data.size;
0207 UPB_PRIVATE(_upb_TextEncode_PutStr)(e, "\"");
0208 for (; ptr < end; ptr++) {
0209 unsigned char uc = *ptr;
0210 if (UPB_PRIVATE(_upb_AsciiIsPrint)(uc) &&
0211 !UPB_PRIVATE(_upb_DefinitelyNeedsEscape)(uc)) {
0212 UPB_PRIVATE(_upb_TextEncode_PutBytes)(e, ptr, 1);
0213 } else {
0214 UPB_PRIVATE(_upb_TextEncode_Escaped)(e, uc);
0215 }
0216 }
0217 UPB_PRIVATE(_upb_TextEncode_PutStr)(e, "\"");
0218 }
0219
0220 UPB_INLINE size_t UPB_PRIVATE(_upb_TextEncode_Nullz)(txtenc* e, size_t size) {
0221 size_t ret = e->ptr - e->buf + e->overflow;
0222
0223 if (size > 0) {
0224 if (e->ptr == e->end) e->ptr--;
0225 *e->ptr = '\0';
0226 }
0227
0228 return ret;
0229 }
0230
0231 const char* UPB_PRIVATE(_upb_TextEncode_Unknown)(txtenc* e, const char* ptr,
0232 upb_EpsCopyInputStream* stream,
0233 int groupnum);
0234
0235 void UPB_PRIVATE(_upb_TextEncode_ParseUnknown)(txtenc* e,
0236 const upb_Message* msg);
0237
0238
0239
0240 void UPB_PRIVATE(_upb_TextEncode_Scalar)(txtenc* e, upb_MessageValue val,
0241 upb_CType ctype);
0242
0243 #include "upb/port/undef.inc"
0244
0245 #endif