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