initial commit
[arib_std_b25.git] / src / ts_section_parser.c
blob8791f733175686237de11c97b1d3450566155ff6
1 #include <stdlib.h>
2 #include <string.h>
4 #include "ts_section_parser.h"
5 #include "ts_section_parser_error_code.h"
7 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8 inner structures
9 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
10 typedef struct {
11 void *prev;
12 void *next;
13 TS_SECTION sect;
14 int32_t ref;
15 } TS_SECTION_ELEM;
17 typedef struct {
18 TS_SECTION_ELEM *head;
19 TS_SECTION_ELEM *tail;
20 int32_t count;
21 } TS_SECTION_LIST;
23 typedef struct {
25 int32_t pid;
27 TS_SECTION_ELEM *work;
28 TS_SECTION_ELEM *last;
30 TS_SECTION_LIST pool;
31 TS_SECTION_LIST buff;
33 TS_SECTION_PARSER_STAT stat;
35 } TS_SECTION_PARSER_PRIVATE_DATA;
37 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
38 constant values
39 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
40 #define MAX_RAW_SECTION_SIZE 4100
42 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
43 function prottypes (interface method)
44 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
45 static void release_ts_section_parser(void *parser);
46 static int reset_ts_section_parser(void *parser);
47 static int put_ts_section_parser(void *parser, TS_HEADER *hdr, uint8_t *data, int size);
48 static int get_ts_section_parser(void *parser, TS_SECTION *sect);
49 static int ret_ts_section_parser(void *parser, TS_SECTION *sect);
50 static int get_count_ts_section_parser(void *parser);
51 static int get_stat_ts_section_parser(void *parser, TS_SECTION_PARSER_STAT *stat);
53 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
54 global function implementation (factory method)
55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
56 TS_SECTION_PARSER *create_ts_section_parser()
58 TS_SECTION_PARSER *r;
59 TS_SECTION_PARSER_PRIVATE_DATA *prv;
61 int n;
63 n = sizeof(TS_SECTION_PARSER_PRIVATE_DATA);
64 n += sizeof(TS_SECTION_PARSER);
66 prv = (TS_SECTION_PARSER_PRIVATE_DATA *)calloc(1, n);
67 if(prv == NULL){
68 /* failed on malloc() - no enough memory */
69 return NULL;
72 prv->pid = -1;
74 r = (TS_SECTION_PARSER *)(prv+1);
75 r->private_data = prv;
77 r->release = release_ts_section_parser;
78 r->reset = reset_ts_section_parser;
80 r->put = put_ts_section_parser;
81 r->get = get_ts_section_parser;
82 r->ret = ret_ts_section_parser;
84 r->get_count = get_count_ts_section_parser;
86 r->get_stat = get_stat_ts_section_parser;
88 return r;
91 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
92 function prottypes (private method)
93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
94 static TS_SECTION_PARSER_PRIVATE_DATA *private_data(void *parser);
95 static void teardown(TS_SECTION_PARSER_PRIVATE_DATA *prv);
97 static int put_exclude_section_start(TS_SECTION_PARSER_PRIVATE_DATA *prv, uint8_t *data, int size);
98 static int put_include_section_start(TS_SECTION_PARSER_PRIVATE_DATA *prv, uint8_t *data, int size);
100 static void reset_section(TS_SECTION *sect);
101 static void append_section_data(TS_SECTION *sect, uint8_t *data, int size);
102 static int check_section_complete(TS_SECTION *sect);
104 static int compare_elem_section(TS_SECTION_ELEM *a, TS_SECTION_ELEM *b);
106 static void cancel_elem_empty(TS_SECTION_PARSER_PRIVATE_DATA *prv, TS_SECTION_ELEM *elem);
107 static void cancel_elem_error(TS_SECTION_PARSER_PRIVATE_DATA *prv, TS_SECTION_ELEM *elem);
108 static void cancel_elem_same(TS_SECTION_PARSER_PRIVATE_DATA *prv, TS_SECTION_ELEM *elem);
109 static void commit_elem_updated(TS_SECTION_PARSER_PRIVATE_DATA *prv, TS_SECTION_ELEM *elem);
111 static TS_SECTION_ELEM *query_work_elem(TS_SECTION_PARSER_PRIVATE_DATA *prv);
113 static void extract_ts_section_header(TS_SECTION *sect);
115 static TS_SECTION_ELEM *create_ts_section_elem();
116 static TS_SECTION_ELEM *get_ts_section_list_head(TS_SECTION_LIST *list);
117 static void put_ts_section_list_tail(TS_SECTION_LIST *list, TS_SECTION_ELEM *elem);
118 static void unlink_ts_section_list(TS_SECTION_LIST *list, TS_SECTION_ELEM *elem);
119 static void clear_ts_section_list(TS_SECTION_LIST *list);
121 static uint32_t crc32(uint8_t *head, uint8_t *tail);
123 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
124 function implementation (interface method)
125 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
126 static void release_ts_section_parser(void *parser)
128 TS_SECTION_PARSER_PRIVATE_DATA *prv;
130 prv = private_data(parser);
131 if(prv == NULL){
132 return;
135 teardown(prv);
137 memset(parser, 0, sizeof(TS_SECTION_PARSER));
138 free(prv);
141 static int reset_ts_section_parser(void *parser)
143 TS_SECTION_PARSER_PRIVATE_DATA *prv;
145 prv = private_data(parser);
146 if(prv == NULL){
147 return TS_SECTION_PARSER_ERROR_INVALID_PARAM;
150 teardown(prv);
152 return 0;
155 static int put_ts_section_parser(void *parser, TS_HEADER *hdr, uint8_t *data, int size)
157 TS_SECTION_PARSER_PRIVATE_DATA *prv;
159 prv = private_data(parser);
160 if( (prv == NULL) || (hdr == NULL) || (data == NULL) || (size < 1) ){
161 return TS_SECTION_PARSER_ERROR_INVALID_PARAM;
164 if( (prv->pid >= 0) && (prv->pid != hdr->pid) ){
165 return TS_SECTION_PARSER_ERROR_INVALID_TS_PID;
168 prv->pid = hdr->pid;
170 if(hdr->payload_unit_start_indicator == 0){
171 /* exclude section start */
172 return put_exclude_section_start(prv, data, size);
173 }else{
174 /* include section start */
175 return put_include_section_start(prv, data, size);
179 static int get_ts_section_parser(void *parser, TS_SECTION *sect)
181 TS_SECTION_PARSER_PRIVATE_DATA *prv;
182 TS_SECTION_ELEM *w;
184 prv = private_data(parser);
185 if( (prv == NULL) || (sect == NULL) ){
186 return TS_SECTION_PARSER_ERROR_INVALID_PARAM;
189 w = get_ts_section_list_head(&(prv->buff));
190 if(w == NULL){
191 memset(sect, 0, sizeof(TS_SECTION));
192 return TS_SECTION_PARSER_ERROR_NO_SECTION_DATA;
195 memcpy(sect, &(w->sect), sizeof(TS_SECTION));
196 put_ts_section_list_tail(&(prv->pool), w);
198 return 0;
201 static int ret_ts_section_parser(void *parser, TS_SECTION *sect)
203 TS_SECTION_PARSER_PRIVATE_DATA *prv;
204 TS_SECTION_ELEM *w;
206 prv = private_data(parser);
207 if( (prv == NULL) || (sect == NULL) ){
208 return TS_SECTION_PARSER_ERROR_INVALID_PARAM;
211 w = prv->pool.tail;
212 while(w != NULL){
213 if(w->sect.data == sect->data){
214 break;
216 w = (TS_SECTION_ELEM *)(w->prev);
219 if( (w != NULL) && (w->ref > 0) ){
220 w->ref -= 1;
223 return 0;
226 static int get_count_ts_section_parser(void *parser)
228 TS_SECTION_PARSER_PRIVATE_DATA *prv;
230 prv = private_data(parser);
231 if(prv == NULL){
232 return TS_SECTION_PARSER_ERROR_INVALID_PARAM;
235 return prv->buff.count;
238 static int get_stat_ts_section_parser(void *parser, TS_SECTION_PARSER_STAT *stat)
240 TS_SECTION_PARSER_PRIVATE_DATA *prv;
242 prv = private_data(parser);
243 if( (prv == NULL) || (stat == NULL) ){
244 return TS_SECTION_PARSER_ERROR_INVALID_PARAM;
247 memcpy(stat, &(prv->stat), sizeof(TS_SECTION_PARSER_STAT));
249 return 0;
252 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
253 function implementation (private method)
254 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
255 static TS_SECTION_PARSER_PRIVATE_DATA *private_data(void *parser)
257 TS_SECTION_PARSER_PRIVATE_DATA *r;
258 TS_SECTION_PARSER *p;
260 p = (TS_SECTION_PARSER *)parser;
261 if(p == NULL){
262 return NULL;
265 r = (TS_SECTION_PARSER_PRIVATE_DATA *)(p->private_data);
266 if( ((void *)(r+1)) != parser ){
267 return NULL;
270 return r;
273 static void teardown(TS_SECTION_PARSER_PRIVATE_DATA *prv)
275 prv->pid = -1;
277 if(prv->work != NULL){
278 free(prv->work);
279 prv->work = NULL;
282 prv->last = NULL;
284 clear_ts_section_list(&(prv->pool));
285 clear_ts_section_list(&(prv->buff));
287 memset(&(prv->stat), 0, sizeof(TS_SECTION_PARSER_STAT));
290 static int put_exclude_section_start(TS_SECTION_PARSER_PRIVATE_DATA *prv, uint8_t *data, int size)
292 TS_SECTION_ELEM *w;
294 w = prv->work;
295 if( (w == NULL) || (w->sect.raw == w->sect.tail) ){
296 /* no previous data */
297 return 0;
300 append_section_data(&(w->sect), data, size);
301 if(check_section_complete(&(w->sect)) == 0){
302 /* need more data */
303 return 0;
306 prv->work = NULL;
308 if( (w->sect.hdr.section_syntax_indicator != 0) &&
309 (crc32(w->sect.raw, w->sect.tail) != 0) ){
310 cancel_elem_error(prv, w);
311 return TS_SECTION_PARSER_WARN_CRC_MISSMATCH;
314 if(compare_elem_section(w, prv->last) == 0){
315 /* same section data */
316 cancel_elem_same(prv, w);
317 return 0;
320 commit_elem_updated(prv, w);
321 return 0;
324 static int put_include_section_start(TS_SECTION_PARSER_PRIVATE_DATA *prv, uint8_t *data, int size)
326 TS_SECTION_ELEM *w;
328 int pointer_field;
330 uint8_t *p;
331 uint8_t *tail;
333 int r;
334 int length;
336 p = data;
337 tail = p + size;
339 r = 0;
341 pointer_field = p[0];
342 p += 1;
344 if( (p+pointer_field) >= tail ){
345 /* input data is probably broken */
346 w = prv->work;
347 prv->work = NULL;
348 if(w != NULL) {
349 if(w->sect.raw != w->sect.tail){
350 cancel_elem_error(prv, w);
351 return TS_SECTION_PARSER_WARN_LENGTH_MISSMATCH;
353 cancel_elem_empty(prv, w);
355 return 0;
358 if(pointer_field > 0){
359 r = put_exclude_section_start(prv, p, pointer_field);
360 if(r < 0){
361 return r;
363 p += pointer_field;
366 w = prv->work;
367 prv->work = NULL;
369 if(w != NULL){
370 if(w->sect.raw != w->sect.tail){
371 cancel_elem_error(prv, w);
372 r = TS_SECTION_PARSER_WARN_LENGTH_MISSMATCH;
373 }else{
374 cancel_elem_empty(prv, w);
376 w = NULL;
379 do {
381 w = query_work_elem(prv);
382 if(w == NULL){
383 return TS_SECTION_PARSER_ERROR_NO_ENOUGH_MEMORY;
386 append_section_data(&(w->sect), p, tail-p);
387 if(check_section_complete(&(w->sect)) == 0){
388 /* need more data */
389 prv->work = w;
390 return 0;
392 length = (w->sect.tail - w->sect.raw);
394 if( (w->sect.hdr.section_syntax_indicator != 0) &&
395 (crc32(w->sect.raw, w->sect.tail) != 0) ){
396 cancel_elem_error(prv, w);
397 r = TS_SECTION_PARSER_WARN_CRC_MISSMATCH;
398 }else if(compare_elem_section(w, prv->last) == 0){
399 cancel_elem_same(prv, w);
400 }else{
401 commit_elem_updated(prv, w);
404 p += length;
406 } while ( (p < tail) && (p[0] != 0xff) );
408 return r;
411 static void reset_section(TS_SECTION *sect)
413 memset(&(sect->hdr), 0, sizeof(TS_SECTION_HEADER));
414 sect->tail = sect->raw;
415 sect->data = NULL;
418 static void append_section_data(TS_SECTION *sect, uint8_t *data, int size)
420 int m,n;
422 m = sect->tail - sect->raw;
423 n = MAX_RAW_SECTION_SIZE - m;
425 if(size < n){
426 n = size;
428 memcpy(sect->tail, data, n);
429 sect->tail += n;
430 m += n;
432 if(sect->data == NULL){
433 extract_ts_section_header(sect);
436 if(sect->data == NULL){
437 /* need more data */
438 return;
441 n = sect->hdr.section_length + 3;
442 if(m > n){
443 sect->tail = sect->raw + n;
446 return;
449 static int check_section_complete(TS_SECTION *sect)
451 int m,n;
453 if(sect->data == NULL){
454 return 0;
457 m = sect->tail - sect->raw;
458 n = sect->hdr.section_length + 3;
460 if(n > m){
461 return 0;
464 return 1;
467 static int compare_elem_section(TS_SECTION_ELEM *a, TS_SECTION_ELEM *b)
469 int m,n;
471 if( (a == NULL) || (b == NULL) ){
472 return 1;
475 m = a->sect.tail - a->sect.raw;
476 n = b->sect.tail - b->sect.raw;
477 if( m != n ){
478 return 1;
481 if(memcmp(a->sect.raw, b->sect.raw, m) != 0){
482 return 1;
485 return 0;
488 static void cancel_elem_empty(TS_SECTION_PARSER_PRIVATE_DATA *prv, TS_SECTION_ELEM *elem)
490 reset_section(&(elem->sect));
491 elem->ref = 0;
492 put_ts_section_list_tail(&(prv->pool), elem);
495 static void cancel_elem_error(TS_SECTION_PARSER_PRIVATE_DATA *prv, TS_SECTION_ELEM *elem)
497 reset_section(&(elem->sect));
498 elem->ref = 0;
499 put_ts_section_list_tail(&(prv->pool), elem);
500 prv->stat.total += 1;
501 prv->stat.error += 1;
504 static void cancel_elem_same(TS_SECTION_PARSER_PRIVATE_DATA *prv, TS_SECTION_ELEM *elem)
506 reset_section(&(elem->sect));
507 elem->ref = 0;
508 put_ts_section_list_tail(&(prv->pool), elem);
509 prv->stat.total +=1;
512 static void commit_elem_updated(TS_SECTION_PARSER_PRIVATE_DATA *prv, TS_SECTION_ELEM *elem)
514 if( (prv->last != NULL) && (prv->last->ref > 0) ){
515 prv->last->ref -= 1;
518 elem->ref = 2;
519 prv->last = elem;
520 put_ts_section_list_tail(&(prv->buff), elem);
521 prv->stat.total += 1;
522 prv->stat.unique += 1;
525 static TS_SECTION_ELEM *query_work_elem(TS_SECTION_PARSER_PRIVATE_DATA *prv)
527 TS_SECTION_ELEM *r;
529 r = prv->pool.head;
530 while(r != NULL){
531 if(r->ref < 1){
532 break;
534 r = (TS_SECTION_ELEM *)(r->next);
537 if(r != NULL){
538 unlink_ts_section_list(&(prv->pool), r);
539 reset_section(&(r->sect));
540 r->ref = 0;
541 return r;
544 return create_ts_section_elem();
547 static void extract_ts_section_header(TS_SECTION *sect)
549 int size;
550 uint8_t *p;
552 sect->data = NULL;
554 size = sect->tail - sect->raw;
555 if(size < 3){
556 /* need more data */
557 return;
560 p = sect->raw;
562 sect->hdr.table_id = p[0];
563 sect->hdr.section_syntax_indicator = (p[1] >> 7) & 0x01;
564 sect->hdr.private_indicator = (p[1] >> 6) & 0x01;
565 sect->hdr.section_length =((p[1] << 8) | p[2]) & 0x0fff;
567 if(sect->hdr.section_syntax_indicator == 0){
568 /* short format section header */
569 sect->data = p+3;
570 return;
573 /* long format section header */
575 if(size < 8){
576 /* need more data */
577 return;
580 sect->hdr.table_id_extension =((p[3] << 8) | p[4]);
581 sect->hdr.version_number = (p[5] >> 1) & 0x1f;
582 sect->hdr.current_next_indicator = p[5] & 0x01;
583 sect->hdr.section_number = p[6];
584 sect->hdr.last_section_number = p[7];
586 sect->data = p+8;
588 return;
591 static TS_SECTION_ELEM *create_ts_section_elem()
593 TS_SECTION_ELEM *r;
594 int n;
596 n = sizeof(TS_SECTION_ELEM) + MAX_RAW_SECTION_SIZE;
597 r = (TS_SECTION_ELEM *)calloc(1, n);
598 if(r == NULL){
599 /* failed on malloc() */
600 return NULL;
603 r->sect.raw = (uint8_t *)(r+1);
604 r->sect.tail = r->sect.raw;
606 return r;
609 static TS_SECTION_ELEM *get_ts_section_list_head(TS_SECTION_LIST *list)
611 TS_SECTION_ELEM *r;
613 if(list == NULL){/* invalid param */
614 return NULL;
617 r = list->head;
618 if(r == NULL){
619 return NULL;
622 list->head = (TS_SECTION_ELEM *)(r->next);
623 if(list->head != NULL){
624 list->head->prev = NULL;
625 list->count -= 1;
626 }else{
627 list->tail = NULL;
628 list->count = 0;
631 r->next = NULL;
633 return r;
636 static void put_ts_section_list_tail(TS_SECTION_LIST *list, TS_SECTION_ELEM *elem)
638 if( (list == NULL) || (elem == NULL) ){
639 /* invalid param */
640 return;
643 if(list->tail != NULL){
644 elem->prev = list->tail;
645 elem->next = NULL;
646 list->tail->next = elem;
647 list->tail = elem;
648 list->count += 1;
649 }else{
650 elem->prev = NULL;
651 elem->next = NULL;
652 list->head = elem;
653 list->tail = elem;
654 list->count = 1;
658 static void unlink_ts_section_list(TS_SECTION_LIST *list, TS_SECTION_ELEM *elem)
660 TS_SECTION_ELEM *prev;
661 TS_SECTION_ELEM *next;
663 if( (list == NULL) || (elem == NULL) ){
664 /* invalid param */
665 return;
668 prev = (TS_SECTION_ELEM *)(elem->prev);
669 next = (TS_SECTION_ELEM *)(elem->next);
671 if(prev != NULL){
672 prev->next = next;
673 }else{
674 list->head = next;
676 if(next != NULL){
677 next->prev = prev;
678 }else{
679 list->tail = prev;
681 list->count -= 1;
684 static void clear_ts_section_list(TS_SECTION_LIST *list)
686 TS_SECTION_ELEM *e;
687 TS_SECTION_ELEM *n;
689 if(list == NULL){ /* invalid param */
690 return;
693 e = list->head;
694 while(e != NULL){
695 n = (TS_SECTION_ELEM *)(e->next);
696 free(e);
697 e = n;
700 list->head = NULL;
701 list->tail = NULL;
702 list->count = 0;
705 static uint32_t crc32(uint8_t *head, uint8_t *tail)
707 uint32_t crc;
708 uint8_t *p;
710 static const uint32_t table[256] = {
711 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9,
712 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
713 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61,
714 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD,
716 0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9,
717 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75,
718 0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011,
719 0x791D4014, 0x7DDC5DA3, 0x709F7B7A, 0x745E66CD,
721 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039,
722 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5,
723 0xBE2B5B58, 0xBAEA46EF, 0xB7A96036, 0xB3687D81,
724 0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D,
726 0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49,
727 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95,
728 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1,
729 0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D,
731 0x34867077, 0x30476DC0, 0x3D044B19, 0x39C556AE,
732 0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072,
733 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16,
734 0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA,
736 0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE,
737 0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02,
738 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1, 0x53DC6066,
739 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA,
741 0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E,
742 0xBFA1B04B, 0xBB60ADFC, 0xB6238B25, 0xB2E29692,
743 0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6,
744 0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A,
746 0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E,
747 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2,
748 0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686,
749 0xD5B88683, 0xD1799B34, 0xDC3ABDED, 0xD8FBA05A,
751 0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637,
752 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB,
753 0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F,
754 0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53,
756 0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47,
757 0x36194D42, 0x32D850F5, 0x3F9B762C, 0x3B5A6B9B,
758 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF,
759 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623,
761 0xF12F560E, 0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7,
762 0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B,
763 0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F,
764 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3,
766 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7,
767 0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B,
768 0x9B3660C6, 0x9FF77D71, 0x92B45BA8, 0x9675461F,
769 0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3,
771 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640,
772 0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C,
773 0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8,
774 0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24,
776 0x119B4BE9, 0x155A565E, 0x18197087, 0x1CD86D30,
777 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC,
778 0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088,
779 0x2497D08D, 0x2056CD3A, 0x2D15EBE3, 0x29D4F654,
781 0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0,
782 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C,
783 0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18,
784 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4,
786 0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0,
787 0x9ABC8BD5, 0x9E7D9662, 0x933EB0BB, 0x97FFAD0C,
788 0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668,
789 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4,
792 crc = 0xffffffff;
794 p = head;
795 while(p < tail){
796 crc = (crc << 8) ^ table[ ((crc >> 24) ^ p[0]) & 0xff ];
797 p += 1;
800 return crc;