Line data Source code
1 : /* pb_common.c: Common support functions for pb_encode.c and pb_decode.c. 2 : * 3 : * 2014 Petteri Aimonen <jpa@kapsi.fi> 4 : */ 5 : 6 : #include "pb_common.h" 7 : 8 : static bool load_descriptor_values(pb_field_iter_t *iter) 9 45590277 : { 10 45590277 : uint32_t word0; 11 45590277 : uint32_t data_offset; 12 45590277 : int_least8_t size_offset; 13 : 14 45590277 : if (iter->index >= iter->descriptor->field_count) 15 0 : return false; 16 : 17 45590277 : word0 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]); 18 45590277 : iter->type = (pb_type_t)((word0 >> 8) & 0xFF); 19 : 20 45590277 : switch(word0 & 3) 21 45590277 : { 22 18992265 : case 0: { 23 : /* 1-word format */ 24 18992265 : iter->array_size = 1; 25 18992265 : iter->tag = (pb_size_t)((word0 >> 2) & 0x3F); 26 18992265 : size_offset = (int_least8_t)((word0 >> 24) & 0x0F); 27 18992265 : data_offset = (word0 >> 16) & 0xFF; 28 18992265 : iter->data_size = (pb_size_t)((word0 >> 28) & 0x0F); 29 18992265 : break; 30 0 : } 31 : 32 26598012 : case 1: { 33 : /* 2-word format */ 34 26598012 : uint32_t word1 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 1]); 35 : 36 26598012 : iter->array_size = (pb_size_t)((word0 >> 16) & 0x0FFF); 37 26598012 : iter->tag = (pb_size_t)(((word0 >> 2) & 0x3F) | ((word1 >> 28) << 6)); 38 26598012 : size_offset = (int_least8_t)((word0 >> 28) & 0x0F); 39 26598012 : data_offset = word1 & 0xFFFF; 40 26598012 : iter->data_size = (pb_size_t)((word1 >> 16) & 0x0FFF); 41 26598012 : break; 42 0 : } 43 : 44 0 : case 2: { 45 : /* 4-word format */ 46 0 : uint32_t word1 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 1]); 47 0 : uint32_t word2 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 2]); 48 0 : uint32_t word3 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 3]); 49 : 50 0 : iter->array_size = (pb_size_t)(word0 >> 16); 51 0 : iter->tag = (pb_size_t)(((word0 >> 2) & 0x3F) | ((word1 >> 8) << 6)); 52 0 : size_offset = (int_least8_t)(word1 & 0xFF); 53 0 : data_offset = word2; 54 0 : iter->data_size = (pb_size_t)word3; 55 0 : break; 56 0 : } 57 : 58 0 : default: { 59 : /* 8-word format */ 60 0 : uint32_t word1 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 1]); 61 0 : uint32_t word2 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 2]); 62 0 : uint32_t word3 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 3]); 63 0 : uint32_t word4 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 4]); 64 : 65 0 : iter->array_size = (pb_size_t)word4; 66 0 : iter->tag = (pb_size_t)(((word0 >> 2) & 0x3F) | ((word1 >> 8) << 6)); 67 0 : size_offset = (int_least8_t)(word1 & 0xFF); 68 0 : data_offset = word2; 69 0 : iter->data_size = (pb_size_t)word3; 70 0 : break; 71 0 : } 72 45590277 : } 73 : 74 45590277 : if (!iter->message) 75 0 : { 76 : /* Avoid doing arithmetic on null pointers, it is undefined */ 77 0 : iter->pField = NULL; 78 0 : iter->pSize = NULL; 79 0 : } 80 45590277 : else 81 45590277 : { 82 45590277 : iter->pField = (char*)iter->message + data_offset; 83 : 84 45590277 : if (size_offset) 85 5173899 : { 86 5173899 : iter->pSize = (char*)iter->pField - size_offset; 87 5173899 : } 88 40416378 : else if (PB_HTYPE(iter->type) == PB_HTYPE_REPEATED && 89 40416378 : (PB_ATYPE(iter->type) == PB_ATYPE_STATIC || 90 0 : PB_ATYPE(iter->type) == PB_ATYPE_POINTER)) 91 0 : { 92 : /* Fixed count array */ 93 0 : iter->pSize = &iter->array_size; 94 0 : } 95 40416378 : else 96 40416378 : { 97 40416378 : iter->pSize = NULL; 98 40416378 : } 99 : 100 45590277 : if (PB_ATYPE(iter->type) == PB_ATYPE_POINTER && iter->pField != NULL) 101 4653201 : { 102 4653201 : iter->pData = *(void**)iter->pField; 103 4653201 : } 104 40937076 : else 105 40937076 : { 106 40937076 : iter->pData = iter->pField; 107 40937076 : } 108 45590277 : } 109 : 110 45590277 : if (PB_LTYPE_IS_SUBMSG(iter->type)) 111 4692555 : { 112 4692555 : iter->submsg_desc = iter->descriptor->submsg_info[iter->submessage_index]; 113 4692555 : } 114 40897722 : else 115 40897722 : { 116 40897722 : iter->submsg_desc = NULL; 117 40897722 : } 118 : 119 45590277 : return true; 120 45590277 : } 121 : 122 : static void advance_iterator(pb_field_iter_t *iter) 123 39541161 : { 124 39541161 : iter->index++; 125 : 126 39541161 : if (iter->index >= iter->descriptor->field_count) 127 7189734 : { 128 : /* Restart */ 129 7189734 : iter->index = 0; 130 7189734 : iter->field_info_index = 0; 131 7189734 : iter->submessage_index = 0; 132 7189734 : iter->required_field_index = 0; 133 7189734 : } 134 32351427 : else 135 32351427 : { 136 : /* Increment indexes based on previous field type. 137 : * All field info formats have the following fields: 138 : * - lowest 2 bits tell the amount of words in the descriptor (2^n words) 139 : * - bits 2..7 give the lowest bits of tag number. 140 : * - bits 8..15 give the field type. 141 : */ 142 32351427 : uint32_t prev_descriptor = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]); 143 32351427 : pb_type_t prev_type = (prev_descriptor >> 8) & 0xFF; 144 32351427 : pb_size_t descriptor_len = (pb_size_t)(1 << (prev_descriptor & 3)); 145 : 146 : /* Add to fields. 147 : * The cast to pb_size_t is needed to avoid -Wconversion warning. 148 : * Because the data is is constants from generator, there is no danger of overflow. 149 : */ 150 32351427 : iter->field_info_index = (pb_size_t)(iter->field_info_index + descriptor_len); 151 32351427 : iter->required_field_index = (pb_size_t)(iter->required_field_index + (PB_HTYPE(prev_type) == PB_HTYPE_REQUIRED)); 152 32351427 : iter->submessage_index = (pb_size_t)(iter->submessage_index + PB_LTYPE_IS_SUBMSG(prev_type)); 153 32351427 : } 154 39541161 : } 155 : 156 : bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_msgdesc_t *desc, void *message) 157 8095596 : { 158 8095596 : memset(iter, 0, sizeof(*iter)); 159 : 160 8095596 : iter->descriptor = desc; 161 8095596 : iter->message = message; 162 : 163 8095596 : return load_descriptor_values(iter); 164 8095596 : } 165 : 166 : bool pb_field_iter_begin_extension(pb_field_iter_t *iter, pb_extension_t *extension) 167 0 : { 168 0 : const pb_msgdesc_t *msg = (const pb_msgdesc_t*)extension->type->arg; 169 0 : bool status; 170 : 171 0 : uint32_t word0 = PB_PROGMEM_READU32(msg->field_info[0]); 172 0 : if (PB_ATYPE(word0 >> 8) == PB_ATYPE_POINTER) 173 0 : { 174 : /* For pointer extensions, the pointer is stored directly 175 : * in the extension structure. This avoids having an extra 176 : * indirection. */ 177 0 : status = pb_field_iter_begin(iter, msg, &extension->dest); 178 0 : } 179 0 : else 180 0 : { 181 0 : status = pb_field_iter_begin(iter, msg, extension->dest); 182 0 : } 183 : 184 0 : iter->pSize = &extension->found; 185 0 : return status; 186 0 : } 187 : 188 : bool pb_field_iter_next(pb_field_iter_t *iter) 189 30984972 : { 190 30984972 : advance_iterator(iter); 191 30984972 : (void)load_descriptor_values(iter); 192 30984972 : return iter->index != 0; 193 30984972 : } 194 : 195 : bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag) 196 11958273 : { 197 11958273 : if (iter->tag == tag) 198 5427570 : { 199 5427570 : return true; /* Nothing to do, correct field already. */ 200 5427570 : } 201 6530703 : else if (tag > iter->descriptor->largest_tag) 202 21027 : { 203 21027 : return false; 204 21027 : } 205 6509676 : else 206 6509676 : { 207 6509676 : pb_size_t start = iter->index; 208 6509676 : uint32_t fieldinfo; 209 : 210 6509676 : if (tag < iter->tag) 211 0 : { 212 : /* Fields are in tag number order, so we know that tag is between 213 : * 0 and our start position. Setting index to end forces 214 : * advance_iterator() call below to restart from beginning. */ 215 0 : iter->index = iter->descriptor->field_count; 216 0 : } 217 : 218 6509676 : do 219 8556075 : { 220 : /* Advance iterator but don't load values yet */ 221 8556075 : advance_iterator(iter); 222 : 223 : /* Do fast check for tag number match */ 224 8556075 : fieldinfo = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]); 225 : 226 8556075 : if (((fieldinfo >> 2) & 0x3F) == (tag & 0x3F)) 227 6509676 : { 228 : /* Good candidate, check further */ 229 6509676 : (void)load_descriptor_values(iter); 230 : 231 6509676 : if (iter->tag == tag && 232 6509676 : PB_LTYPE(iter->type) != PB_LTYPE_EXTENSION) 233 6509676 : { 234 : /* Found it */ 235 6509676 : return true; 236 6509676 : } 237 6509676 : } 238 8556075 : } while (iter->index != start); 239 : 240 : /* Searched all the way back to start, and found nothing. */ 241 0 : (void)load_descriptor_values(iter); 242 0 : return false; 243 6509676 : } 244 11958273 : } 245 : 246 : bool pb_field_iter_find_extension(pb_field_iter_t *iter) 247 33 : { 248 33 : if (PB_LTYPE(iter->type) == PB_LTYPE_EXTENSION) 249 0 : { 250 0 : return true; 251 0 : } 252 33 : else 253 33 : { 254 33 : pb_size_t start = iter->index; 255 33 : uint32_t fieldinfo; 256 : 257 33 : do 258 114 : { 259 : /* Advance iterator but don't load values yet */ 260 114 : advance_iterator(iter); 261 : 262 : /* Do fast check for field type */ 263 114 : fieldinfo = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]); 264 : 265 114 : if (PB_LTYPE((fieldinfo >> 8) & 0xFF) == PB_LTYPE_EXTENSION) 266 0 : { 267 0 : return load_descriptor_values(iter); 268 0 : } 269 114 : } while (iter->index != start); 270 : 271 : /* Searched all the way back to start, and found nothing. */ 272 33 : (void)load_descriptor_values(iter); 273 33 : return false; 274 33 : } 275 33 : } 276 : 277 : static void *pb_const_cast(const void *p) 278 34116 : { 279 : /* Note: this casts away const, in order to use the common field iterator 280 : * logic for both encoding and decoding. The cast is done using union 281 : * to avoid spurious compiler warnings. */ 282 34116 : union { 283 34116 : void *p1; 284 34116 : const void *p2; 285 34116 : } t; 286 34116 : t.p2 = p; 287 34116 : return t.p1; 288 34116 : } 289 : 290 : bool pb_field_iter_begin_const(pb_field_iter_t *iter, const pb_msgdesc_t *desc, const void *message) 291 34116 : { 292 34116 : return pb_field_iter_begin(iter, desc, pb_const_cast(message)); 293 34116 : } 294 : 295 : bool pb_field_iter_begin_extension_const(pb_field_iter_t *iter, const pb_extension_t *extension) 296 0 : { 297 0 : return pb_field_iter_begin_extension(iter, (pb_extension_t*)pb_const_cast(extension)); 298 0 : } 299 : 300 : bool pb_default_field_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_t *field) 301 280929 : { 302 280929 : if (field->data_size == sizeof(pb_callback_t)) 303 280929 : { 304 280929 : pb_callback_t *pCallback = (pb_callback_t*)field->pData; 305 : 306 280929 : if (pCallback != NULL) 307 280929 : { 308 280929 : if (istream != NULL && pCallback->funcs.decode != NULL) 309 0 : { 310 0 : return pCallback->funcs.decode(istream, field, &pCallback->arg); 311 0 : } 312 : 313 280929 : if (ostream != NULL && pCallback->funcs.encode != NULL) 314 0 : { 315 0 : return pCallback->funcs.encode(ostream, field, &pCallback->arg); 316 0 : } 317 280929 : } 318 280929 : } 319 : 320 280929 : return true; /* Success, but didn't do anything */ 321 : 322 280929 : } 323 : 324 : #ifdef PB_VALIDATE_UTF8 325 : 326 : /* This function checks whether a string is valid UTF-8 text. 327 : * 328 : * Algorithm is adapted from https://www.cl.cam.ac.uk/~mgk25/ucs/utf8_check.c 329 : * Original copyright: Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/> 2005-03-30 330 : * Licensed under "Short code license", which allows use under MIT license or 331 : * any compatible with it. 332 : */ 333 : 334 : bool pb_validate_utf8(const char *str) 335 : { 336 : const pb_byte_t *s = (const pb_byte_t*)str; 337 : while (*s) 338 : { 339 : if (*s < 0x80) 340 : { 341 : /* 0xxxxxxx */ 342 : s++; 343 : } 344 : else if ((s[0] & 0xe0) == 0xc0) 345 : { 346 : /* 110XXXXx 10xxxxxx */ 347 : if ((s[1] & 0xc0) != 0x80 || 348 : (s[0] & 0xfe) == 0xc0) /* overlong? */ 349 : return false; 350 : else 351 : s += 2; 352 : } 353 : else if ((s[0] & 0xf0) == 0xe0) 354 : { 355 : /* 1110XXXX 10Xxxxxx 10xxxxxx */ 356 : if ((s[1] & 0xc0) != 0x80 || 357 : (s[2] & 0xc0) != 0x80 || 358 : (s[0] == 0xe0 && (s[1] & 0xe0) == 0x80) || /* overlong? */ 359 : (s[0] == 0xed && (s[1] & 0xe0) == 0xa0) || /* surrogate? */ 360 : (s[0] == 0xef && s[1] == 0xbf && 361 : (s[2] & 0xfe) == 0xbe)) /* U+FFFE or U+FFFF? */ 362 : return false; 363 : else 364 : s += 3; 365 : } 366 : else if ((s[0] & 0xf8) == 0xf0) 367 : { 368 : /* 11110XXX 10XXxxxx 10xxxxxx 10xxxxxx */ 369 : if ((s[1] & 0xc0) != 0x80 || 370 : (s[2] & 0xc0) != 0x80 || 371 : (s[3] & 0xc0) != 0x80 || 372 : (s[0] == 0xf0 && (s[1] & 0xf0) == 0x80) || /* overlong? */ 373 : (s[0] == 0xf4 && s[1] > 0x8f) || s[0] > 0xf4) /* > U+10FFFF? */ 374 : return false; 375 : else 376 : s += 4; 377 : } 378 : else 379 : { 380 : return false; 381 : } 382 : } 383 : 384 : return true; 385 : } 386 : 387 : #endif 388 :