00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef ADBUS_ITERATOR_H
00027 #define ADBUS_ITERATOR_H
00028
00029 #include <adbus.h>
00030 #include <stdint.h>
00031 #include <stdlib.h>
00032 #include <assert.h>
00033 #include <string.h>
00034
00257 struct adbus_Iterator
00258 {
00259 const char* data;
00260 size_t size;
00261 const char* sig;
00262 };
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275 #define ADBUS_ALIGN(PTR, BOUNDARY) \
00276 ((((uintptr_t) (PTR)) + (((uintptr_t) (BOUNDARY)) - 1)) & (~(((uintptr_t)(BOUNDARY))-1)))
00277
00278
00279 ADBUS_INLINE int adbus_iter_align(adbus_Iterator* i, int alignment)
00280 {
00281 size_t diff = (char*) ADBUS_ALIGN(i->data, alignment) - i->data;
00282 if (i->size < diff)
00283 return -1;
00284
00285 i->data += diff;
00286 i->size -= diff;
00287 return 0;
00288 }
00289
00290 ADBUS_INLINE int adbus_iter_alignfield(adbus_Iterator* i, char field)
00291 {
00292 switch (field)
00293 {
00294 case 'y':
00295 case 'g':
00296 case 'v':
00297 return 0;
00298
00299 case 'n':
00300 case 'q':
00301 return adbus_iter_align(i,2);
00302
00303 case 'b':
00304 case 'i':
00305 case 'u':
00306 case 's':
00307 case 'o':
00308 case 'a':
00309 return adbus_iter_align(i,4);
00310
00311 case 'x':
00312 case 't':
00313 case 'd':
00314 case '(':
00315 case '{':
00316 return adbus_iter_align(i,8);
00317
00318 default:
00319 assert(0);
00320 return -1;
00321 }
00322 }
00323
00324 ADBUS_INLINE int adbusI_iter_sig(adbus_Iterator* i, char field)
00325 {
00326 if (*i->sig++ != field) {
00327 assert(0);
00328 return -1;
00329 }
00330 return 0;
00331 }
00332
00333 ADBUS_INLINE int adbusI_iter_get8(adbus_Iterator* i, const uint8_t** v)
00334 {
00335 if (i->size < 1)
00336 return -1;
00337
00338 if (v)
00339 *v = (const uint8_t*) i->data;
00340 i->data += 1;
00341 i->size -= 1;
00342 return 0;
00343 }
00344
00345 ADBUS_INLINE int adbusI_iter_get16(adbus_Iterator* i, const uint16_t** v)
00346 {
00347 if (adbus_iter_align(i, 2) || i->size < 2)
00348 return -1;
00349
00350 if (v)
00351 *v = (const uint16_t*) i->data;
00352 i->data += 2;
00353 i->size -= 2;
00354 return 0;
00355 }
00356
00357 ADBUS_INLINE int adbusI_iter_get32(adbus_Iterator* i, const uint32_t** v)
00358 {
00359 if (adbus_iter_align(i, 4) || i->size < 4)
00360 return -1;
00361
00362 if (v)
00363 *v = (const uint32_t*) i->data;
00364 i->data += 4;
00365 i->size -= 4;
00366 return 0;
00367 }
00368
00369 ADBUS_INLINE int adbusI_iter_get64(adbus_Iterator* i, const uint64_t** v)
00370 {
00371 if (adbus_iter_align(i, 8) || i->size < 8)
00372 return -1;
00373
00374 if (v)
00375 *v = (const uint64_t*) i->data;
00376 i->data += 8;
00377 i->size -= 8;
00378 return 0;
00379 }
00380
00384 ADBUS_INLINE int adbus_iter_bool(adbus_Iterator* i, const adbus_Bool** v)
00385 { return adbusI_iter_sig(i, 'b') || adbusI_iter_get32(i, (const uint32_t**) v); }
00386
00390 ADBUS_INLINE int adbus_iter_u8(adbus_Iterator* i, const uint8_t** v)
00391 { return adbusI_iter_sig(i, 'y') || adbusI_iter_get8(i, v); }
00392
00396 ADBUS_INLINE int adbus_iter_i16(adbus_Iterator* i, const int16_t** v)
00397 { return adbusI_iter_sig(i, 'n') || adbusI_iter_get16(i, (const uint16_t**) v); }
00398
00402 ADBUS_INLINE int adbus_iter_u16(adbus_Iterator* i, const uint16_t** v)
00403 { return adbusI_iter_sig(i, 'q') || adbusI_iter_get16(i, v); }
00404
00408 ADBUS_INLINE int adbus_iter_i32(adbus_Iterator* i, const int32_t** v)
00409 { return adbusI_iter_sig(i, 'i') || adbusI_iter_get32(i, (const uint32_t**) v); }
00410
00414 ADBUS_INLINE int adbus_iter_u32(adbus_Iterator* i, const uint32_t** v)
00415 { return adbusI_iter_sig(i, 'u') || adbusI_iter_get32(i, v); }
00416
00420 ADBUS_INLINE int adbus_iter_i64(adbus_Iterator* i, const int64_t** v)
00421 { return adbusI_iter_sig(i, 'x') || adbusI_iter_get64(i, (const uint64_t**) v); }
00422
00426 ADBUS_INLINE int adbus_iter_u64(adbus_Iterator* i, const uint64_t** v)
00427 { return adbusI_iter_sig(i, 't') || adbusI_iter_get64(i, v); }
00428
00432 ADBUS_INLINE int adbus_iter_double(adbus_Iterator* i, const double** v)
00433 { return adbusI_iter_sig(i, 'd') || adbusI_iter_get64(i, (const uint64_t**) v); }
00434
00435 ADBUS_INLINE int adbusI_iter_getstring(adbus_Iterator* i, size_t strsz, const char** pstr, size_t* pstrsz)
00436 {
00437 const char* str = i->data;
00438 if (i->size < (size_t) (strsz + 1))
00439 return -1;
00440 if (memchr(str, '\0', strsz + 1) != str + strsz)
00441 return -1;
00442 i->data += strsz + 1;
00443 i->size -= strsz + 1;
00444 if (pstr)
00445 *pstr = str;
00446 if (pstrsz)
00447 *pstrsz = strsz;
00448 return 0;
00449 }
00450
00454 ADBUS_INLINE int adbus_iter_string(adbus_Iterator* i, const char** str, size_t* strsz)
00455 {
00456 const uint32_t* len;
00457 return adbusI_iter_sig(i, 's')
00458 || adbusI_iter_get32(i, &len)
00459 || adbusI_iter_getstring(i, *len, str, strsz);
00460 }
00461
00465 ADBUS_INLINE int adbus_iter_objectpath(adbus_Iterator* i, const char** str, size_t* strsz)
00466 {
00467 const uint32_t* len;
00468 return adbusI_iter_sig(i, 'o')
00469 || adbusI_iter_get32(i, &len)
00470 || adbusI_iter_getstring(i, *len, str, strsz);
00471 }
00472
00476 ADBUS_INLINE int adbus_iter_signature(adbus_Iterator* i, const char** str, size_t* strsz)
00477 {
00478 const uint8_t* len;
00479 return adbusI_iter_sig(i, 'g')
00480 || adbusI_iter_get8(i, &len)
00481 || adbusI_iter_getstring(i, *len, str, strsz);
00482 }
00483
00489 struct adbus_IterArray
00490 {
00491 const char* sig;
00492 size_t sigsz;
00493 const char* data;
00494 size_t size;
00495 };
00496
00497 ADBUS_API const char* adbus_nextarg(const char* sig);
00498
00499 #define ADBUS_MAXIMUM_ARRAY_LENGTH 67108864
00500
00503 ADBUS_INLINE int adbus_iter_beginarray(adbus_Iterator* i, adbus_IterArray* a)
00504 {
00505 const uint32_t* len;
00506 if (adbusI_iter_sig(i, 'a') || adbusI_iter_get32(i, &len))
00507 return -1;
00508
00509 if (*len > ADBUS_MAXIMUM_ARRAY_LENGTH)
00510 return -1;
00511
00512 if (adbus_iter_alignfield(i, *i->sig))
00513 return -1;
00514
00515 const char* sigend = adbus_nextarg(i->sig);
00516 if (sigend == NULL)
00517 return -1;
00518
00519 a->data = i->data;
00520 a->size = *len;
00521 a->sig = i->sig;
00522 a->sigsz = sigend - a->sig;
00523 return 0;
00524 }
00525
00529 ADBUS_INLINE adbus_Bool adbus_iter_inarray(adbus_Iterator* i, adbus_IterArray* a)
00530 {
00531 if (i->data < a->data + a->size) {
00532 i->sig = a->sig;
00533 return 1;
00534 } else {
00535 return 0;
00536 }
00537 }
00538
00542 ADBUS_INLINE int adbus_iter_endarray(adbus_Iterator* i, adbus_IterArray* a)
00543 {
00544 i->data = a->data + a->size;
00545 i->sig = a->sig + a->sigsz;
00546 return 0;
00547 }
00548
00552 ADBUS_INLINE int adbus_iter_begindictentry(adbus_Iterator* i)
00553 { return adbusI_iter_sig(i, '{') || adbus_iter_align(i, 8); }
00554
00558 ADBUS_INLINE int adbus_iter_enddictentry(adbus_Iterator* i)
00559 { return adbusI_iter_sig(i, '}'); }
00560
00564 ADBUS_INLINE int adbus_iter_beginstruct(adbus_Iterator* i)
00565 { return adbusI_iter_sig(i, '(') || adbus_iter_align(i, 8); }
00566
00570 ADBUS_INLINE int adbus_iter_endstruct(adbus_Iterator* i)
00571 { return adbusI_iter_sig(i, ')'); }
00572
00576 struct adbus_IterVariant
00577 {
00578 const char* origsig;
00579 const char* sig;
00580 const char* data;
00581 size_t size;
00582 };
00583
00587 ADBUS_INLINE int adbus_iter_beginvariant(adbus_Iterator* i, adbus_IterVariant* v)
00588 {
00589 const char* vsig;
00590 const uint8_t* len;
00591 if ( adbusI_iter_sig(i, 'v')
00592 || adbusI_iter_get8(i, &len)
00593 || adbusI_iter_getstring(i, *len, &vsig, NULL)
00594 || adbus_iter_alignfield(i, *vsig))
00595 {
00596 return -1;
00597 }
00598
00599 v->origsig = i->sig;
00600 v->data = i->data;
00601 v->sig = vsig;
00602 i->sig = vsig;
00603 return 0;
00604 }
00605
00609 ADBUS_INLINE int adbus_iter_endvariant(adbus_Iterator* i, adbus_IterVariant* v)
00610 {
00611 if (*i->sig)
00612 return -1;
00613 i->sig = v->origsig;
00614 v->size = i->data - v->data;
00615 return 0;
00616 }
00617
00618
00619 #endif
00620