sproto.c 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438
  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include <stdio.h>
  4. #include <assert.h>
  5. #include "msvcint.h"
  6. #include "sproto.h"
  7. #define CHUNK_SIZE 1000
  8. #define SIZEOF_LENGTH 4
  9. #define SIZEOF_HEADER 2
  10. #define SIZEOF_FIELD 2
  11. #define SIZEOF_INT64 ((int)sizeof(uint64_t))
  12. #define SIZEOF_INT32 ((int)sizeof(uint32_t))
  13. struct field {
  14. int tag;
  15. int type;
  16. const char * name;
  17. struct sproto_type * st;
  18. int key;
  19. int map; // interpreted two fields struct as map
  20. int extra;
  21. };
  22. struct sproto_type {
  23. const char * name;
  24. int n;
  25. int base;
  26. int maxn;
  27. struct field *f;
  28. };
  29. struct protocol {
  30. const char *name;
  31. int tag;
  32. int confirm; // confirm == 1 where response nil
  33. struct sproto_type * p[2];
  34. };
  35. struct chunk {
  36. struct chunk * next;
  37. };
  38. struct pool {
  39. struct chunk * header;
  40. struct chunk * current;
  41. int current_used;
  42. };
  43. struct sproto {
  44. struct pool memory;
  45. int type_n;
  46. int protocol_n;
  47. struct sproto_type * type;
  48. struct protocol * proto;
  49. };
  50. static void
  51. pool_init(struct pool *p) {
  52. p->header = NULL;
  53. p->current = NULL;
  54. p->current_used = 0;
  55. }
  56. static void
  57. pool_release(struct pool *p) {
  58. struct chunk * tmp = p->header;
  59. while (tmp) {
  60. struct chunk * n = tmp->next;
  61. free(tmp);
  62. tmp = n;
  63. }
  64. }
  65. static void *
  66. pool_newchunk(struct pool *p, size_t sz) {
  67. struct chunk * t = malloc(sz + sizeof(struct chunk));
  68. if (t == NULL)
  69. return NULL;
  70. t->next = p->header;
  71. p->header = t;
  72. return t+1;
  73. }
  74. static void *
  75. pool_alloc(struct pool *p, size_t sz) {
  76. // align by 8
  77. sz = (sz + 7) & ~7;
  78. if (sz >= CHUNK_SIZE) {
  79. return pool_newchunk(p, sz);
  80. }
  81. if (p->current == NULL) {
  82. if (pool_newchunk(p, CHUNK_SIZE) == NULL)
  83. return NULL;
  84. p->current = p->header;
  85. }
  86. if (sz + p->current_used <= CHUNK_SIZE) {
  87. void * ret = (char *)(p->current+1) + p->current_used;
  88. p->current_used += sz;
  89. return ret;
  90. }
  91. if (sz >= p->current_used) {
  92. return pool_newchunk(p, sz);
  93. } else {
  94. void * ret = pool_newchunk(p, CHUNK_SIZE);
  95. p->current = p->header;
  96. p->current_used = sz;
  97. return ret;
  98. }
  99. }
  100. static inline int
  101. toword(const uint8_t * p) {
  102. return p[0] | p[1]<<8;
  103. }
  104. static inline uint32_t
  105. todword(const uint8_t *p) {
  106. return p[0] | p[1]<<8 | p[2]<<16 | p[3]<<24;
  107. }
  108. static int
  109. count_array(const uint8_t * stream) {
  110. uint32_t length = todword(stream);
  111. int n = 0;
  112. stream += SIZEOF_LENGTH;
  113. while (length > 0) {
  114. uint32_t nsz;
  115. if (length < SIZEOF_LENGTH)
  116. return -1;
  117. nsz = todword(stream);
  118. nsz += SIZEOF_LENGTH;
  119. if (nsz > length)
  120. return -1;
  121. ++n;
  122. stream += nsz;
  123. length -= nsz;
  124. }
  125. return n;
  126. }
  127. static int
  128. struct_field(const uint8_t * stream, size_t sz) {
  129. const uint8_t * field;
  130. int fn, header, i;
  131. if (sz < SIZEOF_LENGTH)
  132. return -1;
  133. fn = toword(stream);
  134. header = SIZEOF_HEADER + SIZEOF_FIELD * fn;
  135. if (sz < header)
  136. return -1;
  137. field = stream + SIZEOF_HEADER;
  138. sz -= header;
  139. stream += header;
  140. for (i=0;i<fn;i++) {
  141. int value= toword(field + i * SIZEOF_FIELD);
  142. uint32_t dsz;
  143. if (value != 0)
  144. continue;
  145. if (sz < SIZEOF_LENGTH)
  146. return -1;
  147. dsz = todword(stream);
  148. if (sz < SIZEOF_LENGTH + dsz)
  149. return -1;
  150. stream += SIZEOF_LENGTH + dsz;
  151. sz -= SIZEOF_LENGTH + dsz;
  152. }
  153. return fn;
  154. }
  155. static const char *
  156. import_string(struct sproto *s, const uint8_t * stream) {
  157. uint32_t sz = todword(stream);
  158. char * buffer = pool_alloc(&s->memory, sz+1);
  159. memcpy(buffer, stream+SIZEOF_LENGTH, sz);
  160. buffer[sz] = '\0';
  161. return buffer;
  162. }
  163. static int
  164. calc_pow(int base, int n) {
  165. int r;
  166. if (n == 0)
  167. return 1;
  168. r = calc_pow(base * base , n / 2);
  169. if (n&1) {
  170. r *= base;
  171. }
  172. return r;
  173. }
  174. static const uint8_t *
  175. import_field(struct sproto *s, struct field *f, const uint8_t * stream) {
  176. uint32_t sz;
  177. const uint8_t * result;
  178. int fn;
  179. int i;
  180. int array = 0;
  181. int tag = -1;
  182. f->tag = -1;
  183. f->type = -1;
  184. f->name = NULL;
  185. f->st = NULL;
  186. f->key = -1;
  187. f->map = -1;
  188. f->extra = 0;
  189. sz = todword(stream);
  190. stream += SIZEOF_LENGTH;
  191. result = stream + sz;
  192. fn = struct_field(stream, sz);
  193. if (fn < 0)
  194. return NULL;
  195. stream += SIZEOF_HEADER;
  196. for (i=0;i<fn;i++) {
  197. int value;
  198. ++tag;
  199. value = toword(stream + SIZEOF_FIELD * i);
  200. if (value & 1) {
  201. tag+= value/2;
  202. continue;
  203. }
  204. if (tag == 0) { // name
  205. if (value != 0)
  206. return NULL;
  207. f->name = import_string(s, stream + fn * SIZEOF_FIELD);
  208. continue;
  209. }
  210. if (value == 0)
  211. return NULL;
  212. value = value/2 - 1;
  213. switch(tag) {
  214. case 1: // buildin
  215. if (value >= SPROTO_TSTRUCT)
  216. return NULL; // invalid buildin type
  217. f->type = value;
  218. break;
  219. case 2: // type index
  220. if (f->type == SPROTO_TINTEGER) {
  221. f->extra = calc_pow(10, value);
  222. } else if (f->type == SPROTO_TSTRING) {
  223. f->extra = value; // string if 0 ; binary is 1
  224. } else {
  225. if (value >= s->type_n)
  226. return NULL; // invalid type index
  227. if (f->type >= 0)
  228. return NULL;
  229. f->type = SPROTO_TSTRUCT;
  230. f->st = &s->type[value];
  231. }
  232. break;
  233. case 3: // tag
  234. f->tag = value;
  235. break;
  236. case 4: // array
  237. if (value)
  238. array = SPROTO_TARRAY;
  239. break;
  240. case 5: // key
  241. f->key = value;
  242. break;
  243. case 6: // map
  244. if (value)
  245. f->map = 1;
  246. break;
  247. default:
  248. return NULL;
  249. }
  250. }
  251. if (f->tag < 0 || f->type < 0 || f->name == NULL)
  252. return NULL;
  253. f->type |= array;
  254. return result;
  255. }
  256. /*
  257. .type {
  258. .field {
  259. name 0 : string
  260. buildin 1 : integer
  261. type 2 : integer
  262. tag 3 : integer
  263. array 4 : boolean
  264. key 5 : integer
  265. map 6 : boolean // Interpreted two fields struct as map when decoding
  266. }
  267. name 0 : string
  268. fields 1 : *field
  269. }
  270. */
  271. static const uint8_t *
  272. import_type(struct sproto *s, struct sproto_type *t, const uint8_t * stream) {
  273. const uint8_t * result;
  274. uint32_t sz = todword(stream);
  275. int i;
  276. int fn;
  277. int n;
  278. int maxn;
  279. int last;
  280. stream += SIZEOF_LENGTH;
  281. result = stream + sz;
  282. fn = struct_field(stream, sz);
  283. if (fn <= 0 || fn > 2)
  284. return NULL;
  285. for (i=0;i<fn*SIZEOF_FIELD;i+=SIZEOF_FIELD) {
  286. // name and fields must encode to 0
  287. int v = toword(stream + SIZEOF_HEADER + i);
  288. if (v != 0)
  289. return NULL;
  290. }
  291. memset(t, 0, sizeof(*t));
  292. stream += SIZEOF_HEADER + fn * SIZEOF_FIELD;
  293. t->name = import_string(s, stream);
  294. if (fn == 1) {
  295. return result;
  296. }
  297. stream += todword(stream)+SIZEOF_LENGTH; // second data
  298. n = count_array(stream);
  299. if (n<0)
  300. return NULL;
  301. stream += SIZEOF_LENGTH;
  302. maxn = n;
  303. last = -1;
  304. t->n = n;
  305. t->f = pool_alloc(&s->memory, sizeof(struct field) * n);
  306. for (i=0;i<n;i++) {
  307. int tag;
  308. struct field *f = &t->f[i];
  309. stream = import_field(s, f, stream);
  310. if (stream == NULL)
  311. return NULL;
  312. tag = f->tag;
  313. if (tag <= last)
  314. return NULL; // tag must in ascending order
  315. if (tag > last+1) {
  316. ++maxn;
  317. }
  318. last = tag;
  319. }
  320. t->maxn = maxn;
  321. t->base = t->f[0].tag;
  322. n = t->f[n-1].tag - t->base + 1;
  323. if (n != t->n) {
  324. t->base = -1;
  325. }
  326. return result;
  327. }
  328. /*
  329. .protocol {
  330. name 0 : string
  331. tag 1 : integer
  332. request 2 : integer
  333. response 3 : integer
  334. }
  335. */
  336. static const uint8_t *
  337. import_protocol(struct sproto *s, struct protocol *p, const uint8_t * stream) {
  338. const uint8_t * result;
  339. uint32_t sz = todword(stream);
  340. int fn;
  341. int i;
  342. int tag;
  343. stream += SIZEOF_LENGTH;
  344. result = stream + sz;
  345. fn = struct_field(stream, sz);
  346. stream += SIZEOF_HEADER;
  347. p->name = NULL;
  348. p->tag = -1;
  349. p->p[SPROTO_REQUEST] = NULL;
  350. p->p[SPROTO_RESPONSE] = NULL;
  351. p->confirm = 0;
  352. tag = 0;
  353. for (i=0;i<fn;i++,tag++) {
  354. int value = toword(stream + SIZEOF_FIELD * i);
  355. if (value & 1) {
  356. tag += (value-1)/2;
  357. continue;
  358. }
  359. value = value/2 - 1;
  360. switch (i) {
  361. case 0: // name
  362. if (value != -1) {
  363. return NULL;
  364. }
  365. p->name = import_string(s, stream + SIZEOF_FIELD *fn);
  366. break;
  367. case 1: // tag
  368. if (value < 0) {
  369. return NULL;
  370. }
  371. p->tag = value;
  372. break;
  373. case 2: // request
  374. if (value < 0 || value>=s->type_n)
  375. return NULL;
  376. p->p[SPROTO_REQUEST] = &s->type[value];
  377. break;
  378. case 3: // response
  379. if (value < 0 || value>=s->type_n)
  380. return NULL;
  381. p->p[SPROTO_RESPONSE] = &s->type[value];
  382. break;
  383. case 4: // confirm
  384. p->confirm = value;
  385. break;
  386. default:
  387. return NULL;
  388. }
  389. }
  390. if (p->name == NULL || p->tag<0) {
  391. return NULL;
  392. }
  393. return result;
  394. }
  395. static struct sproto *
  396. create_from_bundle(struct sproto *s, const uint8_t * stream, size_t sz) {
  397. const uint8_t * content;
  398. const uint8_t * typedata = NULL;
  399. const uint8_t * protocoldata = NULL;
  400. int fn = struct_field(stream, sz);
  401. int i;
  402. if (fn < 0 || fn > 2)
  403. return NULL;
  404. stream += SIZEOF_HEADER;
  405. content = stream + fn*SIZEOF_FIELD;
  406. for (i=0;i<fn;i++) {
  407. int value = toword(stream + i*SIZEOF_FIELD);
  408. int n;
  409. if (value != 0)
  410. return NULL;
  411. n = count_array(content);
  412. if (n<0)
  413. return NULL;
  414. if (i == 0) {
  415. typedata = content+SIZEOF_LENGTH;
  416. s->type_n = n;
  417. s->type = pool_alloc(&s->memory, n * sizeof(*s->type));
  418. } else {
  419. protocoldata = content+SIZEOF_LENGTH;
  420. s->protocol_n = n;
  421. s->proto = pool_alloc(&s->memory, n * sizeof(*s->proto));
  422. }
  423. content += todword(content) + SIZEOF_LENGTH;
  424. }
  425. for (i=0;i<s->type_n;i++) {
  426. typedata = import_type(s, &s->type[i], typedata);
  427. if (typedata == NULL) {
  428. return NULL;
  429. }
  430. }
  431. for (i=0;i<s->protocol_n;i++) {
  432. protocoldata = import_protocol(s, &s->proto[i], protocoldata);
  433. if (protocoldata == NULL) {
  434. return NULL;
  435. }
  436. }
  437. return s;
  438. }
  439. struct sproto *
  440. sproto_create(const void * proto, size_t sz) {
  441. struct pool mem;
  442. struct sproto * s;
  443. pool_init(&mem);
  444. s = pool_alloc(&mem, sizeof(*s));
  445. if (s == NULL)
  446. return NULL;
  447. memset(s, 0, sizeof(*s));
  448. s->memory = mem;
  449. if (create_from_bundle(s, proto, sz) == NULL) {
  450. pool_release(&s->memory);
  451. return NULL;
  452. }
  453. return s;
  454. }
  455. void
  456. sproto_release(struct sproto * s) {
  457. if (s == NULL)
  458. return;
  459. pool_release(&s->memory);
  460. }
  461. static const char *
  462. get_typename(int type, struct field *f) {
  463. if (type == SPROTO_TSTRUCT) {
  464. return f->st->name;
  465. } else {
  466. switch (type) {
  467. case SPROTO_TINTEGER:
  468. if (f->extra)
  469. return "decimal";
  470. else
  471. return "integer";
  472. case SPROTO_TBOOLEAN:
  473. return "boolean";
  474. case SPROTO_TSTRING:
  475. if (f->extra == SPROTO_TSTRING_BINARY)
  476. return "binary";
  477. else
  478. return "string";
  479. case SPROTO_TDOUBLE:
  480. return "double";
  481. default:
  482. return "invalid";
  483. }
  484. }
  485. }
  486. void
  487. sproto_dump(struct sproto *s) {
  488. int i,j;
  489. printf("=== %d types ===\n", s->type_n);
  490. for (i=0;i<s->type_n;i++) {
  491. struct sproto_type *t = &s->type[i];
  492. printf("%s\n", t->name);
  493. for (j=0;j<t->n;j++) {
  494. char container[2] = { 0, 0 };
  495. const char * typename = NULL;
  496. struct field *f = &t->f[j];
  497. int type = f->type & ~SPROTO_TARRAY;
  498. if (f->type & SPROTO_TARRAY) {
  499. container[0] = '*';
  500. } else {
  501. container[0] = 0;
  502. }
  503. typename = get_typename(type, f);
  504. printf("\t%s (%d) %s%s", f->name, f->tag, container, typename);
  505. if (type == SPROTO_TINTEGER && f->extra > 0) {
  506. printf("(%d)", f->extra);
  507. }
  508. if (f->key >= 0) {
  509. printf(" key[%d]", f->key);
  510. if (f->map >= 0) {
  511. printf(" value[%d]", f->st->f[1].tag);
  512. }
  513. }
  514. printf("\n");
  515. }
  516. }
  517. printf("=== %d protocol ===\n", s->protocol_n);
  518. for (i=0;i<s->protocol_n;i++) {
  519. struct protocol *p = &s->proto[i];
  520. if (p->p[SPROTO_REQUEST]) {
  521. printf("\t%s (%d) request:%s", p->name, p->tag, p->p[SPROTO_REQUEST]->name);
  522. } else {
  523. printf("\t%s (%d) request:(null)", p->name, p->tag);
  524. }
  525. if (p->p[SPROTO_RESPONSE]) {
  526. printf(" response:%s", p->p[SPROTO_RESPONSE]->name);
  527. } else if (p->confirm) {
  528. printf(" response nil");
  529. }
  530. printf("\n");
  531. }
  532. }
  533. // query
  534. int
  535. sproto_prototag(const struct sproto *sp, const char * name) {
  536. int i;
  537. for (i=0;i<sp->protocol_n;i++) {
  538. if (strcmp(name, sp->proto[i].name) == 0) {
  539. return sp->proto[i].tag;
  540. }
  541. }
  542. return -1;
  543. }
  544. static struct protocol *
  545. query_proto(const struct sproto *sp, int tag) {
  546. int begin = 0, end = sp->protocol_n;
  547. while(begin<end) {
  548. int mid = (begin+end)/2;
  549. int t = sp->proto[mid].tag;
  550. if (t==tag) {
  551. return &sp->proto[mid];
  552. }
  553. if (tag > t) {
  554. begin = mid+1;
  555. } else {
  556. end = mid;
  557. }
  558. }
  559. return NULL;
  560. }
  561. struct sproto_type *
  562. sproto_protoquery(const struct sproto *sp, int proto, int what) {
  563. struct protocol * p;
  564. if (what <0 || what >1) {
  565. return NULL;
  566. }
  567. p = query_proto(sp, proto);
  568. if (p) {
  569. return p->p[what];
  570. }
  571. return NULL;
  572. }
  573. int
  574. sproto_protoresponse(const struct sproto * sp, int proto) {
  575. struct protocol * p = query_proto(sp, proto);
  576. return (p!=NULL && (p->p[SPROTO_RESPONSE] || p->confirm));
  577. }
  578. const char *
  579. sproto_protoname(const struct sproto *sp, int proto) {
  580. struct protocol * p = query_proto(sp, proto);
  581. if (p) {
  582. return p->name;
  583. }
  584. return NULL;
  585. }
  586. struct sproto_type *
  587. sproto_type(const struct sproto *sp, const char * type_name) {
  588. int i;
  589. for (i=0;i<sp->type_n;i++) {
  590. if (strcmp(type_name, sp->type[i].name) == 0) {
  591. return &sp->type[i];
  592. }
  593. }
  594. return NULL;
  595. }
  596. const char *
  597. sproto_name(struct sproto_type * st) {
  598. return st->name;
  599. }
  600. static struct field *
  601. findtag(const struct sproto_type *st, int tag) {
  602. int begin, end;
  603. if (st->base >=0 ) {
  604. tag -= st->base;
  605. if (tag < 0 || tag >= st->n)
  606. return NULL;
  607. return &st->f[tag];
  608. }
  609. begin = 0;
  610. end = st->n;
  611. while (begin < end) {
  612. int mid = (begin+end)/2;
  613. struct field *f = &st->f[mid];
  614. int t = f->tag;
  615. if (t == tag) {
  616. return f;
  617. }
  618. if (tag > t) {
  619. begin = mid + 1;
  620. } else {
  621. end = mid;
  622. }
  623. }
  624. return NULL;
  625. }
  626. // encode & decode
  627. // sproto_callback(void *ud, int tag, int type, struct sproto_type *, void *value, int length)
  628. // return size, -1 means error
  629. static inline int
  630. fill_size(uint8_t * data, int sz) {
  631. data[0] = sz & 0xff;
  632. data[1] = (sz >> 8) & 0xff;
  633. data[2] = (sz >> 16) & 0xff;
  634. data[3] = (sz >> 24) & 0xff;
  635. return sz + SIZEOF_LENGTH;
  636. }
  637. static int
  638. encode_integer(uint32_t v, uint8_t * data, int size) {
  639. if (size < SIZEOF_LENGTH + sizeof(v))
  640. return -1;
  641. data[4] = v & 0xff;
  642. data[5] = (v >> 8) & 0xff;
  643. data[6] = (v >> 16) & 0xff;
  644. data[7] = (v >> 24) & 0xff;
  645. return fill_size(data, sizeof(v));
  646. }
  647. static int
  648. encode_uint64(uint64_t v, uint8_t * data, int size) {
  649. if (size < SIZEOF_LENGTH + sizeof(v))
  650. return -1;
  651. data[4] = v & 0xff;
  652. data[5] = (v >> 8) & 0xff;
  653. data[6] = (v >> 16) & 0xff;
  654. data[7] = (v >> 24) & 0xff;
  655. data[8] = (v >> 32) & 0xff;
  656. data[9] = (v >> 40) & 0xff;
  657. data[10] = (v >> 48) & 0xff;
  658. data[11] = (v >> 56) & 0xff;
  659. return fill_size(data, sizeof(v));
  660. }
  661. /*
  662. //#define CB(tagname,type,index,subtype,value,length) cb(ud, tagname,type,index,subtype,value,length)
  663. static int
  664. do_cb(sproto_callback cb, void *ud, const char *tagname, int type, int index, struct sproto_type *subtype, void *value, int length) {
  665. if (subtype) {
  666. if (type >= 0) {
  667. printf("callback: tag=%s[%d], subtype[%s]:%d\n",tagname,index, subtype->name, type);
  668. } else {
  669. printf("callback: tag=%s[%d], subtype[%s]\n",tagname,index, subtype->name);
  670. }
  671. } else if (index > 0) {
  672. printf("callback: tag=%s[%d]\n",tagname,index);
  673. } else if (index == 0) {
  674. printf("callback: tag=%s\n",tagname);
  675. } else {
  676. printf("callback: tag=%s [mainkey]\n",tagname);
  677. }
  678. return cb(ud, tagname,type,index,subtype,value,length);
  679. }
  680. #define CB(tagname,type,index,subtype,value,length) do_cb(cb,ud, tagname,type,index,subtype,value,length)
  681. */
  682. static int
  683. encode_object(sproto_callback cb, struct sproto_arg *args, uint8_t *data, int size) {
  684. int sz;
  685. if (size < SIZEOF_LENGTH)
  686. return -1;
  687. args->value = data+SIZEOF_LENGTH;
  688. args->length = size-SIZEOF_LENGTH;
  689. sz = cb(args);
  690. if (sz < 0) {
  691. if (sz == SPROTO_CB_NIL)
  692. return 0;
  693. return -1; // sz == SPROTO_CB_ERROR
  694. }
  695. assert(sz <= size-SIZEOF_LENGTH); // verify buffer overflow
  696. return fill_size(data, sz);
  697. }
  698. static inline void
  699. uint32_to_uint64(int negative, uint8_t *buffer) {
  700. if (negative) {
  701. buffer[4] = 0xff;
  702. buffer[5] = 0xff;
  703. buffer[6] = 0xff;
  704. buffer[7] = 0xff;
  705. } else {
  706. buffer[4] = 0;
  707. buffer[5] = 0;
  708. buffer[6] = 0;
  709. buffer[7] = 0;
  710. }
  711. }
  712. static uint8_t *
  713. encode_integer_array(sproto_callback cb, struct sproto_arg *args, uint8_t *buffer, int size, int *noarray) {
  714. uint8_t * header = buffer;
  715. int intlen;
  716. int index;
  717. if (size < 1)
  718. return NULL;
  719. buffer++;
  720. size--;
  721. intlen = SIZEOF_INT32;
  722. index = 1;
  723. *noarray = 0;
  724. for (;;) {
  725. int sz;
  726. union {
  727. uint64_t u64;
  728. uint32_t u32;
  729. } u;
  730. args->value = &u;
  731. args->length = sizeof(u);
  732. args->index = index;
  733. sz = cb(args);
  734. if (sz <= 0) {
  735. if (sz == SPROTO_CB_NIL) // nil object, end of array
  736. break;
  737. if (sz == SPROTO_CB_NOARRAY) { // no array, don't encode it
  738. *noarray = 1;
  739. break;
  740. }
  741. return NULL; // sz == SPROTO_CB_ERROR
  742. }
  743. // notice: sizeof(uint64_t) is size_t (unsigned) , size may be negative. See issue #75
  744. // so use MACRO SIZOF_INT64 instead
  745. if (size < SIZEOF_INT64)
  746. return NULL;
  747. if (sz == SIZEOF_INT32) {
  748. uint32_t v = u.u32;
  749. buffer[0] = v & 0xff;
  750. buffer[1] = (v >> 8) & 0xff;
  751. buffer[2] = (v >> 16) & 0xff;
  752. buffer[3] = (v >> 24) & 0xff;
  753. if (intlen == SIZEOF_INT64) {
  754. uint32_to_uint64(v & 0x80000000, buffer);
  755. }
  756. } else {
  757. uint64_t v;
  758. if (sz != SIZEOF_INT64)
  759. return NULL;
  760. if (intlen == SIZEOF_INT32) {
  761. int i;
  762. // rearrange
  763. size -= (index-1) * SIZEOF_INT32;
  764. if (size < SIZEOF_INT64)
  765. return NULL;
  766. buffer += (index-1) * SIZEOF_INT32;
  767. for (i=index-2;i>=0;i--) {
  768. int negative;
  769. memcpy(header+1+i*SIZEOF_INT64, header+1+i*SIZEOF_INT32, SIZEOF_INT32);
  770. negative = header[1+i*SIZEOF_INT64+3] & 0x80;
  771. uint32_to_uint64(negative, header+1+i*SIZEOF_INT64);
  772. }
  773. intlen = SIZEOF_INT64;
  774. }
  775. v = u.u64;
  776. buffer[0] = v & 0xff;
  777. buffer[1] = (v >> 8) & 0xff;
  778. buffer[2] = (v >> 16) & 0xff;
  779. buffer[3] = (v >> 24) & 0xff;
  780. buffer[4] = (v >> 32) & 0xff;
  781. buffer[5] = (v >> 40) & 0xff;
  782. buffer[6] = (v >> 48) & 0xff;
  783. buffer[7] = (v >> 56) & 0xff;
  784. }
  785. size -= intlen;
  786. buffer += intlen;
  787. index++;
  788. }
  789. if (buffer == header + 1) {
  790. return header;
  791. }
  792. *header = (uint8_t)intlen;
  793. return buffer;
  794. }
  795. static uint8_t *
  796. encode_array_object(sproto_callback cb, struct sproto_arg *args, uint8_t *buffer, int size, int *noarray) {
  797. int sz;
  798. *noarray = 0;
  799. args->index = 1;
  800. for (;;) {
  801. if (size < SIZEOF_LENGTH)
  802. return NULL;
  803. size -= SIZEOF_LENGTH;
  804. args->value = buffer + SIZEOF_LENGTH;
  805. args->length = size;
  806. sz = cb(args);
  807. if (sz < 0) {
  808. if (sz == SPROTO_CB_NIL) {
  809. break;
  810. }
  811. if (sz == SPROTO_CB_NOARRAY) { // no array, don't encode it
  812. *noarray = 1;
  813. break;
  814. }
  815. return NULL; // sz == SPROTO_CB_ERROR
  816. }
  817. fill_size(buffer, sz);
  818. buffer += SIZEOF_LENGTH+sz;
  819. size -= sz;
  820. ++args->index;
  821. }
  822. return buffer;
  823. }
  824. static int
  825. encode_array(sproto_callback cb, struct sproto_arg *args, uint8_t *data, int size) {
  826. uint8_t * buffer;
  827. int sz;
  828. if (size < SIZEOF_LENGTH)
  829. return -1;
  830. size -= SIZEOF_LENGTH;
  831. buffer = data + SIZEOF_LENGTH;
  832. switch (args->type) {
  833. case SPROTO_TDOUBLE:
  834. case SPROTO_TINTEGER: {
  835. int noarray;
  836. buffer = encode_integer_array(cb,args,buffer,size, &noarray);
  837. if (buffer == NULL)
  838. return -1;
  839. if (noarray) {
  840. return 0;
  841. }
  842. break;
  843. }
  844. case SPROTO_TBOOLEAN:
  845. args->index = 1;
  846. for (;;) {
  847. int v = 0;
  848. args->value = &v;
  849. args->length = sizeof(v);
  850. sz = cb(args);
  851. if (sz < 0) {
  852. if (sz == SPROTO_CB_NIL) // nil object , end of array
  853. break;
  854. if (sz == SPROTO_CB_NOARRAY) // no array, don't encode it
  855. return 0;
  856. return -1; // sz == SPROTO_CB_ERROR
  857. }
  858. if (size < 1)
  859. return -1;
  860. buffer[0] = v ? 1: 0;
  861. size -= 1;
  862. buffer += 1;
  863. ++args->index;
  864. }
  865. break;
  866. default: {
  867. int noarray;
  868. buffer = encode_array_object(cb, args, buffer, size, &noarray);
  869. if (buffer == NULL)
  870. return -1;
  871. if (noarray)
  872. return 0;
  873. break;
  874. }
  875. }
  876. sz = buffer - (data + SIZEOF_LENGTH);
  877. return fill_size(data, sz);
  878. }
  879. int
  880. sproto_encode(const struct sproto_type *st, void * buffer, int size, sproto_callback cb, void *ud) {
  881. struct sproto_arg args;
  882. uint8_t * header = buffer;
  883. uint8_t * data;
  884. int header_sz = SIZEOF_HEADER + st->maxn * SIZEOF_FIELD;
  885. int i;
  886. int index;
  887. int lasttag;
  888. int datasz;
  889. if (size < header_sz)
  890. return -1;
  891. args.ud = ud;
  892. data = header + header_sz;
  893. size -= header_sz;
  894. index = 0;
  895. lasttag = -1;
  896. for (i=0;i<st->n;i++) {
  897. struct field *f = &st->f[i];
  898. int type = f->type;
  899. int value = 0;
  900. int sz = -1;
  901. args.tagname = f->name;
  902. args.tagid = f->tag;
  903. args.subtype = f->st;
  904. args.mainindex = f->key;
  905. args.extra = f->extra;
  906. args.ktagname = NULL;
  907. args.vtagname = NULL;
  908. if (type & SPROTO_TARRAY) {
  909. args.type = type & (~SPROTO_TARRAY);
  910. if (f->map > 0) {
  911. args.ktagname = f->st->f[0].name;
  912. args.vtagname = f->st->f[1].name;
  913. }
  914. sz = encode_array(cb, &args, data, size);
  915. } else {
  916. args.type = type;
  917. args.index = 0;
  918. switch(type) {
  919. case SPROTO_TDOUBLE:
  920. case SPROTO_TINTEGER:
  921. case SPROTO_TBOOLEAN: {
  922. union {
  923. uint64_t u64;
  924. uint32_t u32;
  925. } u;
  926. args.value = &u;
  927. args.length = sizeof(u);
  928. sz = cb(&args);
  929. if (sz < 0) {
  930. if (sz == SPROTO_CB_NIL)
  931. continue;
  932. if (sz == SPROTO_CB_NOARRAY) // no array, don't encode it
  933. return 0;
  934. return -1; // sz == SPROTO_CB_ERROR
  935. }
  936. if (sz == SIZEOF_INT32) {
  937. if (u.u32 < 0x7fff) {
  938. value = (u.u32+1) * 2;
  939. sz = 2; // sz can be any number > 0
  940. } else {
  941. sz = encode_integer(u.u32, data, size);
  942. }
  943. } else if (sz == SIZEOF_INT64) {
  944. sz= encode_uint64(u.u64, data, size);
  945. } else {
  946. return -1;
  947. }
  948. break;
  949. }
  950. case SPROTO_TSTRUCT:
  951. case SPROTO_TSTRING:
  952. sz = encode_object(cb, &args, data, size);
  953. break;
  954. }
  955. }
  956. if (sz < 0)
  957. return -1;
  958. if (sz > 0) {
  959. uint8_t * record;
  960. int tag;
  961. if (value == 0) {
  962. data += sz;
  963. size -= sz;
  964. }
  965. record = header+SIZEOF_HEADER+SIZEOF_FIELD*index;
  966. tag = f->tag - lasttag - 1;
  967. if (tag > 0) {
  968. // skip tag
  969. tag = (tag - 1) * 2 + 1;
  970. if (tag > 0xffff)
  971. return -1;
  972. record[0] = tag & 0xff;
  973. record[1] = (tag >> 8) & 0xff;
  974. ++index;
  975. record += SIZEOF_FIELD;
  976. }
  977. ++index;
  978. record[0] = value & 0xff;
  979. record[1] = (value >> 8) & 0xff;
  980. lasttag = f->tag;
  981. }
  982. }
  983. header[0] = index & 0xff;
  984. header[1] = (index >> 8) & 0xff;
  985. datasz = data - (header + header_sz);
  986. data = header + header_sz;
  987. if (index != st->maxn) {
  988. memmove(header + SIZEOF_HEADER + index * SIZEOF_FIELD, data, datasz);
  989. }
  990. return SIZEOF_HEADER + index * SIZEOF_FIELD + datasz;
  991. }
  992. static int
  993. decode_array_object(sproto_callback cb, struct sproto_arg *args, uint8_t * stream, int sz) {
  994. uint32_t hsz;
  995. int index = 1;
  996. while (sz > 0) {
  997. if (sz < SIZEOF_LENGTH)
  998. return -1;
  999. hsz = todword(stream);
  1000. stream += SIZEOF_LENGTH;
  1001. sz -= SIZEOF_LENGTH;
  1002. if (hsz > sz)
  1003. return -1;
  1004. args->index = index;
  1005. args->value = stream;
  1006. args->length = hsz;
  1007. if (cb(args))
  1008. return -1;
  1009. sz -= hsz;
  1010. stream += hsz;
  1011. ++index;
  1012. }
  1013. return 0;
  1014. }
  1015. static inline uint64_t
  1016. expand64(uint32_t v) {
  1017. uint64_t value = v;
  1018. if (value & 0x80000000) {
  1019. value |= (uint64_t)~0 << 32 ;
  1020. }
  1021. return value;
  1022. }
  1023. static int
  1024. decode_empty_array(sproto_callback cb, struct sproto_arg *args) {
  1025. // It's empty array, call cb with index == -1 to create the empty array.
  1026. args->index = -1;
  1027. args->value = NULL;
  1028. args->length = 0;
  1029. return cb(args);
  1030. }
  1031. static int
  1032. decode_array(sproto_callback cb, struct sproto_arg *args, uint8_t * stream) {
  1033. uint32_t sz = todword(stream);
  1034. int type = args->type;
  1035. int i;
  1036. if (sz == 0) {
  1037. return decode_empty_array(cb, args);
  1038. }
  1039. stream += SIZEOF_LENGTH;
  1040. switch (type) {
  1041. case SPROTO_TDOUBLE:
  1042. case SPROTO_TINTEGER: {
  1043. if (--sz == 0) {
  1044. // An empty array but with a len prefix
  1045. return decode_empty_array(cb, args);
  1046. }
  1047. int len = *stream;
  1048. ++stream;
  1049. if (len == SIZEOF_INT32) {
  1050. if (sz % SIZEOF_INT32 != 0)
  1051. return -1;
  1052. for (i=0;i<sz/SIZEOF_INT32;i++) {
  1053. uint64_t value = expand64(todword(stream + i*SIZEOF_INT32));
  1054. args->index = i+1;
  1055. args->value = &value;
  1056. args->length = sizeof(value);
  1057. cb(args);
  1058. }
  1059. } else if (len == SIZEOF_INT64) {
  1060. if (sz % SIZEOF_INT64 != 0)
  1061. return -1;
  1062. for (i=0;i<sz/SIZEOF_INT64;i++) {
  1063. uint64_t low = todword(stream + i*SIZEOF_INT64);
  1064. uint64_t hi = todword(stream + i*SIZEOF_INT64 + SIZEOF_INT32);
  1065. uint64_t value = low | hi << 32;
  1066. args->index = i+1;
  1067. args->value = &value;
  1068. args->length = sizeof(value);
  1069. cb(args);
  1070. }
  1071. } else {
  1072. return -1;
  1073. }
  1074. break;
  1075. }
  1076. case SPROTO_TBOOLEAN:
  1077. for (i=0;i<sz;i++) {
  1078. uint64_t value = stream[i];
  1079. args->index = i+1;
  1080. args->value = &value;
  1081. args->length = sizeof(value);
  1082. cb(args);
  1083. }
  1084. break;
  1085. case SPROTO_TSTRING:
  1086. case SPROTO_TSTRUCT:
  1087. return decode_array_object(cb, args, stream, sz);
  1088. default:
  1089. return -1;
  1090. }
  1091. return 0;
  1092. }
  1093. int
  1094. sproto_decode(const struct sproto_type *st, const void * data, int size, sproto_callback cb, void *ud) {
  1095. struct sproto_arg args;
  1096. int total = size;
  1097. uint8_t * stream;
  1098. uint8_t * datastream;
  1099. int fn;
  1100. int i;
  1101. int tag;
  1102. if (size < SIZEOF_HEADER)
  1103. return -1;
  1104. // debug print
  1105. // printf("sproto_decode[%p] (%s)\n", ud, st->name);
  1106. stream = (void *)data;
  1107. fn = toword(stream);
  1108. stream += SIZEOF_HEADER;
  1109. size -= SIZEOF_HEADER ;
  1110. if (size < fn * SIZEOF_FIELD)
  1111. return -1;
  1112. datastream = stream + fn * SIZEOF_FIELD;
  1113. size -= fn * SIZEOF_FIELD;
  1114. args.ud = ud;
  1115. tag = -1;
  1116. for (i=0;i<fn;i++) {
  1117. uint8_t * currentdata;
  1118. struct field * f;
  1119. int value = toword(stream + i * SIZEOF_FIELD);
  1120. ++ tag;
  1121. if (value & 1) {
  1122. tag += value/2;
  1123. continue;
  1124. }
  1125. value = value/2 - 1;
  1126. currentdata = datastream;
  1127. if (value < 0) {
  1128. uint32_t sz;
  1129. if (size < SIZEOF_LENGTH)
  1130. return -1;
  1131. sz = todword(datastream);
  1132. if (size < sz + SIZEOF_LENGTH)
  1133. return -1;
  1134. datastream += sz+SIZEOF_LENGTH;
  1135. size -= sz+SIZEOF_LENGTH;
  1136. }
  1137. f = findtag(st, tag);
  1138. if (f == NULL)
  1139. continue;
  1140. args.tagname = f->name;
  1141. args.tagid = f->tag;
  1142. args.type = f->type;
  1143. args.subtype = f->st;
  1144. args.index = 0;
  1145. args.mainindex = f->key;
  1146. args.extra = f->extra;
  1147. args.ktagname = NULL;
  1148. args.vtagname = NULL;
  1149. if (value < 0) {
  1150. if (f->type & SPROTO_TARRAY) {
  1151. args.type = f->type & (~SPROTO_TARRAY);
  1152. if (f->map > 0) {
  1153. args.ktagname = f->st->f[0].name;
  1154. args.vtagname = f->st->f[1].name;
  1155. }
  1156. if (decode_array(cb, &args, currentdata)) {
  1157. return -1;
  1158. }
  1159. } else {
  1160. switch (f->type) {
  1161. case SPROTO_TDOUBLE:
  1162. case SPROTO_TINTEGER: {
  1163. uint32_t sz = todword(currentdata);
  1164. if (sz == SIZEOF_INT32) {
  1165. uint64_t v = expand64(todword(currentdata + SIZEOF_LENGTH));
  1166. args.value = &v;
  1167. args.length = sizeof(v);
  1168. cb(&args);
  1169. } else if (sz != SIZEOF_INT64) {
  1170. return -1;
  1171. } else {
  1172. uint32_t low = todword(currentdata + SIZEOF_LENGTH);
  1173. uint32_t hi = todword(currentdata + SIZEOF_LENGTH + SIZEOF_INT32);
  1174. uint64_t v = (uint64_t)low | (uint64_t) hi << 32;
  1175. args.value = &v;
  1176. args.length = sizeof(v);
  1177. cb(&args);
  1178. }
  1179. break;
  1180. }
  1181. case SPROTO_TSTRING:
  1182. case SPROTO_TSTRUCT: {
  1183. uint32_t sz = todword(currentdata);
  1184. args.value = currentdata+SIZEOF_LENGTH;
  1185. args.length = sz;
  1186. if (cb(&args))
  1187. return -1;
  1188. break;
  1189. }
  1190. default:
  1191. return -1;
  1192. }
  1193. }
  1194. } else if (f->type != SPROTO_TINTEGER && f->type != SPROTO_TBOOLEAN) {
  1195. return -1;
  1196. } else {
  1197. uint64_t v = value;
  1198. args.value = &v;
  1199. args.length = sizeof(v);
  1200. cb(&args);
  1201. }
  1202. }
  1203. return total - size;
  1204. }
  1205. // 0 pack
  1206. static int
  1207. pack_seg(const uint8_t *src, uint8_t * buffer, int sz, int n) {
  1208. uint8_t header = 0;
  1209. int notzero = 0;
  1210. int i;
  1211. uint8_t * obuffer = buffer;
  1212. ++buffer;
  1213. --sz;
  1214. if (sz < 0)
  1215. obuffer = NULL;
  1216. for (i=0;i<8;i++) {
  1217. if (src[i] != 0) {
  1218. notzero++;
  1219. header |= 1<<i;
  1220. if (sz > 0) {
  1221. *buffer = src[i];
  1222. ++buffer;
  1223. --sz;
  1224. }
  1225. }
  1226. }
  1227. if ((notzero == 7 || notzero == 6) && n > 0) {
  1228. notzero = 8;
  1229. }
  1230. if (notzero == 8) {
  1231. if (n > 0) {
  1232. return 8;
  1233. } else {
  1234. return 10;
  1235. }
  1236. }
  1237. if (obuffer) {
  1238. *obuffer = header;
  1239. }
  1240. return notzero + 1;
  1241. }
  1242. static inline void
  1243. write_ff(const uint8_t * src, const uint8_t * src_end, uint8_t * des, int n) {
  1244. des[0] = 0xff;
  1245. des[1] = n - 1;
  1246. if (src + n * 8 <= src_end) {
  1247. memcpy(des+2, src, n*8);
  1248. } else {
  1249. int sz = (int)(src_end - src);
  1250. memcpy(des+2, src, sz);
  1251. memset(des+2+sz, 0, n*8-sz);
  1252. }
  1253. }
  1254. int
  1255. sproto_pack(const void * srcv, int srcsz, void * bufferv, int bufsz) {
  1256. uint8_t tmp[8];
  1257. int i;
  1258. const uint8_t * ff_srcstart = NULL;
  1259. uint8_t * ff_desstart = NULL;
  1260. int ff_n = 0;
  1261. int size = 0;
  1262. const uint8_t * src = srcv;
  1263. const uint8_t * src_end = (uint8_t *)srcv + srcsz;
  1264. uint8_t * buffer = bufferv;
  1265. for (i=0;i<srcsz;i+=8) {
  1266. int n;
  1267. int padding = i+8 - srcsz;
  1268. if (padding > 0) {
  1269. int j;
  1270. memcpy(tmp, src, 8-padding);
  1271. for (j=0;j<padding;j++) {
  1272. tmp[7-j] = 0;
  1273. }
  1274. src = tmp;
  1275. }
  1276. n = pack_seg(src, buffer, bufsz, ff_n);
  1277. bufsz -= n;
  1278. if (n == 10) {
  1279. // first FF
  1280. ff_srcstart = src;
  1281. ff_desstart = buffer;
  1282. ff_n = 1;
  1283. } else if (n==8 && ff_n>0) {
  1284. ++ff_n;
  1285. if (ff_n == 256) {
  1286. if (bufsz >= 0) {
  1287. write_ff(ff_srcstart, src_end, ff_desstart, 256);
  1288. }
  1289. ff_n = 0;
  1290. }
  1291. } else {
  1292. if (ff_n > 0) {
  1293. if (bufsz >= 0) {
  1294. write_ff(ff_srcstart, src_end, ff_desstart, ff_n);
  1295. }
  1296. ff_n = 0;
  1297. }
  1298. }
  1299. src += 8;
  1300. buffer += n;
  1301. size += n;
  1302. }
  1303. if(bufsz >= 0 && ff_n > 0) {
  1304. write_ff(ff_srcstart, src_end, ff_desstart, ff_n);
  1305. }
  1306. return size;
  1307. }
  1308. int
  1309. sproto_unpack(const void * srcv, int srcsz, void * bufferv, int bufsz) {
  1310. const uint8_t * src = srcv;
  1311. uint8_t * buffer = bufferv;
  1312. int size = 0;
  1313. while (srcsz > 0) {
  1314. uint8_t header = src[0];
  1315. --srcsz;
  1316. ++src;
  1317. if (header == 0xff) {
  1318. int n;
  1319. if (srcsz <= 0) {
  1320. return -1;
  1321. }
  1322. n = (src[0] + 1) * 8;
  1323. if (srcsz < n + 1)
  1324. return -1;
  1325. srcsz -= n + 1;
  1326. ++src;
  1327. if (bufsz >= n) {
  1328. memcpy(buffer, src, n);
  1329. }
  1330. bufsz -= n;
  1331. buffer += n;
  1332. src += n;
  1333. size += n;
  1334. } else {
  1335. int i;
  1336. for (i=0;i<8;i++) {
  1337. int nz = (header >> i) & 1;
  1338. if (nz) {
  1339. if (srcsz <= 0)
  1340. return -1;
  1341. if (bufsz > 0) {
  1342. *buffer = *src;
  1343. --bufsz;
  1344. ++buffer;
  1345. }
  1346. ++src;
  1347. --srcsz;
  1348. } else {
  1349. if (bufsz > 0) {
  1350. *buffer = 0;
  1351. --bufsz;
  1352. ++buffer;
  1353. }
  1354. }
  1355. ++size;
  1356. }
  1357. }
  1358. }
  1359. return size;
  1360. }