MSWSP: add two more Property Sets
[wireshark-wip.git] / epan / tvbparse.c
blob64e8a3883745a29f73ec58bf94714737964ee749
1 /* tvbparse.c
3 * Copyright 2005, Luis E. Garcia Ontanon <luis@ontanon.org>
5 * $Id$
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include "config.h"
28 #include <stdlib.h>
29 #include <string.h>
30 #include <glib.h>
32 #include <epan/emem.h>
33 #include <epan/proto.h>
34 #include <epan/packet_info.h>
35 #include <epan/tvbparse.h>
38 #define TVBPARSE_DEBUG_ALL 0xffffffff
40 #if 0
41 #define TVBPARSE_DEBUG_ 0x80000000
42 #define TVBPARSE_DEBUG_ 0x40000000
43 #define TVBPARSE_DEBUG_ 0x20000000
44 #define TVBPARSE_DEBUG_ 0x10000000
45 #endif
47 #define TVBPARSE_DEBUG_CHAR 0x08000000
48 #define TVBPARSE_DEBUG_CHARS 0x04000000
49 #define TVBPARSE_DEBUG_NOT_CHAR 0x02000000
50 #define TVBPARSE_DEBUG_NOT_CHARS 0x01000000
51 #define TVBPARSE_DEBUG_STRING 0x00800000
52 #define TVBPARSE_DEBUG_CASESTRING 0x00400000
53 #define TVBPARSE_DEBUG_ONEOF 0x00200000
54 #define TVBPARSE_DEBUG_HASH 0x00100000
55 #define TVBPARSE_DEBUG_SEQ 0x00080000
56 #define TVBPARSE_DEBUG_SOME 0x00040000
57 #define TVBPARSE_DEBUG_UNTIL 0x00020000
58 #if 0
59 #define TVBPARSE_DEBUG_ 0x00010000
60 #define TVBPARSE_DEBUG_ 0x00008000
61 #define TVBPARSE_DEBUG_ 0x00004000
62 #define TVBPARSE_DEBUG_ 0x00002000
63 #define TVBPARSE_DEBUG_ 0x00001000
64 #endif
65 #define TVBPARSE_DEBUG_TT 0x00000800
66 #define TVBPARSE_DEBUG_CB 0x00000400
67 #define TVBPARSE_DEBUG_GET 0x00000200
68 #define TVBPARSE_DEBUG_FIND 0x00000100
69 #define TVBPARSE_DEBUG_NEWTOK 0x00000080
70 #define TVBPARSE_DEBUG_IGNORE 0x00000040
71 #define TVBPARSE_DEBUG_PEEK 0x00000020
72 #if 0
73 #define TVBPARSE_DEBUG_ 0x00000010
74 #define TVBPARSE_DEBUG_ 0x00000008
75 #define TVBPARSE_DEBUG_ 0x00000004
76 #define TVBPARSE_DEBUG_ 0x00000002
77 #define TVBPARSE_DEBUG_ 0x00000001
78 #endif
81 #define TVBPARSE_DEBUG (TVBPARSE_DEBUG_SOME)
84 static tvbparse_elem_t* new_tok(tvbparse_t* tt,
85 int id,
86 int offset,
87 int len,
88 const tvbparse_wanted_t* wanted) {
89 tvbparse_elem_t* tok;
91 #ifdef TVBPARSE_DEBUG
92 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NEWTOK) g_warning("new_tok: id=%i offset=%u len=%u",id,offset,len);
93 #endif
95 tok = (tvbparse_elem_t *)ep_alloc(sizeof(tvbparse_elem_t));
97 tok->tvb = tt->tvb;
98 tok->id = id;
99 tok->offset = offset;
100 tok->len = len;
101 tok->data = NULL;
102 tok->sub = NULL;
103 tok->next = NULL;
104 tok->wanted = wanted;
105 tok->last = tok;
107 return tok;
110 static int ignore_fcn(tvbparse_t* tt, int offset) {
111 int len = 0;
112 int consumed;
113 tvbparse_elem_t* ignored = NULL;
115 if (!tt->ignore) return 0;
117 #ifdef TVBPARSE_DEBUG
118 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_IGNORE) g_warning("ignore: enter");
119 #endif
121 while ((consumed = tt->ignore->condition(tt,offset,tt->ignore,&ignored)) > 0) {
122 len += consumed;
123 offset += consumed;
124 #ifdef TVBPARSE_DEBUG
125 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_IGNORE) g_warning("ignore: consumed=%i",consumed);
126 #endif
130 #ifdef TVBPARSE_DEBUG
131 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_IGNORE) g_warning("ignore: len=%i",len);
132 #endif
134 return len;
138 static int cond_char (tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
139 gchar c,t;
140 guint i;
142 #ifdef TVBPARSE_DEBUG
143 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHAR) g_warning("cond_char: control='%s'",wanted->control.str);
144 #endif
146 if ( offset + 1 > tt->end_offset )
147 return -1;
149 t = (gchar) tvb_get_guint8(tt->tvb,offset);
151 for(i = 0; (c = wanted->control.str[i]) && offset <= tt->end_offset; i++) {
152 if ( c == t ) {
153 *tok = new_tok(tt,wanted->id,offset,1,wanted);
154 #ifdef TVBPARSE_DEBUG
155 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHAR) g_warning("cond_char: GOT: '%c'",c);
156 #endif
157 return 1;
161 return -1;
164 tvbparse_wanted_t* tvbparse_char(const int id,
165 const gchar* chr,
166 const void* data,
167 tvbparse_action_t before_cb,
168 tvbparse_action_t after_cb) {
169 tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_malloc0(sizeof(tvbparse_wanted_t));
171 w->condition = cond_char;
172 w->id = id;
173 w->control.str = chr;
174 w->len = 1;
175 w->data = data;
176 w->before = before_cb;
177 w->after = after_cb;
179 return w;
182 static int cond_chars (tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
183 guint length = 0;
184 int start = offset;
185 int left = tt->end_offset - offset;
187 #ifdef TVBPARSE_DEBUG
188 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHARS) g_warning("cond_chars: control='%s'",wanted->control.str);
189 #endif
191 if ( offset + (int)wanted->min > tt->end_offset )
192 return -1;
194 left = left < (int) wanted->max ? left : (int) wanted->max;
196 while( left > 0 ) {
197 gchar t = (gchar) tvb_get_guint8(tt->tvb,offset++);
198 gchar c;
199 guint i = 0;
201 while ( (c = wanted->control.str[i++]) ) {
202 if (c == t) goto next_char;
205 break;
207 next_char:
208 length++;
209 left--;
212 if (length < wanted->min) {
213 return -1;
214 } else {
215 *tok = new_tok(tt,wanted->id,start,length,wanted);
216 #ifdef TVBPARSE_DEBUG
217 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHARS) g_warning("cond_chars: GOT len=%i",length);
218 #endif
219 return length;
223 tvbparse_wanted_t* tvbparse_chars(const int id,
224 const guint min_len,
225 const guint max_len,
226 const gchar* chr,
227 const void* data,
228 tvbparse_action_t before_cb,
229 tvbparse_action_t after_cb) {
230 tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_malloc0(sizeof(tvbparse_wanted_t));
232 w->condition = cond_chars;
233 w->id = id;
234 w->control.str = chr;
235 w->min = min_len ? min_len : 1;
236 w->max = max_len ? max_len : G_MAXINT/2;
237 w->data = data;
238 w->before = before_cb;
239 w->after = after_cb;
241 return w;
245 static int cond_not_char(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
246 gchar c, t;
247 guint i;
248 gboolean not_matched = FALSE;
250 #ifdef TVBPARSE_DEBUG
251 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NOT_CHAR) g_warning("cond_not_char: control='%s'",wanted->control.str);
252 #endif
254 if (! offset < tt->end_offset ) {
255 return -1;
258 t = (gchar) tvb_get_guint8(tt->tvb,offset);
260 for(i = 0; (c = wanted->control.str[i]); i++) {
261 if ( c == t ) {
262 not_matched = TRUE;
266 if (not_matched) {
267 return -1;
268 } else {
269 *tok = new_tok(tt,wanted->id,offset,1,wanted);
270 #ifdef TVBPARSE_DEBUG
271 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NOT_CHAR) g_warning("cond_not_char: GOT='%c'",t);
272 #endif
273 return 1;
277 tvbparse_wanted_t* tvbparse_not_char(const int id,
278 const gchar* chr,
279 const void* data,
280 tvbparse_action_t before_cb,
281 tvbparse_action_t after_cb) {
282 tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_malloc0(sizeof(tvbparse_wanted_t));
284 w->condition = cond_not_char;
285 w->id = id;
286 w->control.str = chr;
287 w->data = data;
288 w->before = before_cb;
289 w->after = after_cb;
291 return w;
294 static int cond_not_chars(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
295 guint length = 0;
296 int left = tt->end_offset - offset;
297 int start = offset;
299 #ifdef TVBPARSE_DEBUG
300 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NOT_CHARS) g_warning("cond_not_chars: control='%s'",wanted->control.str);
301 #endif
303 if ( offset + (int)wanted->min > tt->end_offset )
304 return -1;
306 if (left < (int)wanted->min)
307 return -1;
309 left = left <= (int)wanted->max ? left : (int)wanted->max;
311 while( left > 0 ) {
312 gchar c;
313 gchar t = (gchar) tvb_get_guint8(tt->tvb,offset);
314 guint i = 0;
316 while ( (c = wanted->control.str[i++]) ) {
317 if (c == t) goto end_not_chars;
320 offset++;
321 length++;
322 left--;
324 end_not_chars:
326 if ( length < wanted->min ) {
327 return -1;
328 } else {
329 *tok = new_tok(tt,wanted->id,start,length,wanted);
330 #ifdef TVBPARSE_DEBUG
331 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NOT_CHARS) g_warning("cond_not_chars: GOT len=%i",length);
332 #endif
333 return length;
337 tvbparse_wanted_t* tvbparse_not_chars(const int id,
338 const guint min_len,
339 const guint max_len,
340 const gchar* chr,
341 const void* data,
342 tvbparse_action_t before_cb,
343 tvbparse_action_t after_cb){
344 tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_malloc0(sizeof(tvbparse_wanted_t));
346 w->condition = cond_not_chars;
347 w->id = id;
348 w->control.str = chr;
349 w->len = 0;
350 w->min = min_len ? min_len : 1;
351 w->max = max_len ? max_len : G_MAXINT/2;
352 w->data = data;
353 w->before = before_cb;
354 w->after = after_cb;
356 return w;
360 static int cond_string(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
361 int len = wanted->len;
362 #ifdef TVBPARSE_DEBUG
363 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_STRING) g_warning("cond_string: control='%s'",wanted->control.str);
364 #endif
366 if ( offset + wanted->len > tt->end_offset )
367 return -1;
369 if ( tvb_strneql(tt->tvb, offset, wanted->control.str, len) == 0 ) {
370 *tok = new_tok(tt,wanted->id,offset,len,wanted);
371 #ifdef TVBPARSE_DEBUG
372 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_STRING) g_warning("cond_string: GOT len=%i",len);
373 #endif
374 return len;
375 } else {
376 return -1;
380 tvbparse_wanted_t* tvbparse_string(const int id,
381 const gchar* str,
382 const void* data,
383 tvbparse_action_t before_cb,
384 tvbparse_action_t after_cb) {
385 tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_malloc0(sizeof(tvbparse_wanted_t));
387 w->condition = cond_string;
388 w->id = id;
389 w->control.str = str;
390 w->len = (int) strlen(str);
391 w->data = data;
392 w->before = before_cb;
393 w->after = after_cb;
395 return w;
398 static int cond_casestring(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
399 int len = wanted->len;
400 #ifdef TVBPARSE_DEBUG
401 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CASESTRING) g_warning("cond_casestring: control='%s'",wanted->control.str);
402 #endif
404 if ( offset + len > tt->end_offset )
405 return -1;
407 if ( tvb_strncaseeql(tt->tvb, offset, wanted->control.str, len) == 0 ) {
408 *tok = new_tok(tt,wanted->id,offset,len,wanted);
409 #ifdef TVBPARSE_DEBUG
410 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CASESTRING) g_warning("cond_casestring: GOT len=%i",len);
411 #endif
412 return len;
413 } else {
414 *tok = NULL;
415 return -1;
419 tvbparse_wanted_t* tvbparse_casestring(const int id,
420 const gchar* str,
421 const void* data,
422 tvbparse_action_t before_cb,
423 tvbparse_action_t after_cb) {
424 tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_malloc0(sizeof(tvbparse_wanted_t));
426 w->condition = cond_casestring;
427 w->id = id;
428 w->control.str = str;
429 w->len = (int) strlen(str);
430 w->data = data;
431 w->before = before_cb;
432 w->after = after_cb;
434 return w;
437 static int cond_one_of(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
438 guint i;
439 #ifdef TVBPARSE_DEBUG
440 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_ONEOF) g_warning("cond_one_of: START");
441 #endif
443 if ( offset > tt->end_offset )
444 return -1;
446 for(i=0; i < wanted->control.elems->len; i++) {
447 tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_ptr_array_index(wanted->control.elems,i);
448 tvbparse_elem_t* new_elem = NULL;
449 int curr_len;
451 if ( offset + w->len > tt->end_offset )
452 continue;
454 curr_len = w->condition(tt, offset, w, &new_elem);
456 if (curr_len >= 0) {
457 *tok = new_tok(tt, wanted->id, new_elem->offset, new_elem->len, wanted);
458 (*tok)->sub = new_elem;
459 #ifdef TVBPARSE_DEBUG
460 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_ONEOF) g_warning("cond_one_of: GOT len=%i",curr_len);
461 #endif
462 return curr_len;
466 return -1;
469 tvbparse_wanted_t* tvbparse_set_oneof(const int id,
470 const void* data,
471 tvbparse_action_t before_cb,
472 tvbparse_action_t after_cb,
473 ...) {
474 tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_malloc0(sizeof(tvbparse_wanted_t));
475 tvbparse_t* el;
476 va_list ap;
478 w->condition = cond_one_of;
479 w->id = id;
480 w->data = data;
481 w->before = before_cb;
482 w->after = after_cb;
483 w->control.elems = g_ptr_array_new();
485 va_start(ap,after_cb);
487 while(( el = va_arg(ap,tvbparse_t*) )) {
488 g_ptr_array_add(w->control.elems,el);
491 va_end(ap);
493 return w;
496 static int cond_hash(tvbparse_t* tt, const int offset, const tvbparse_wanted_t* wanted, tvbparse_elem_t** tok) {
497 int key_len;
498 gchar* key = NULL;
499 tvbparse_elem_t* key_elem = NULL;
500 tvbparse_wanted_t* value_wanted = NULL;
501 int value_len;
502 tvbparse_elem_t* value_elem = NULL;
503 int tot_len;
504 tvbparse_elem_t* ret_tok;
506 #ifdef TVBPARSE_DEBUG
507 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_HASH) g_warning("cond_hash: START");
508 #endif
510 if ( offset > tt->end_offset )
511 return -1;
513 key_len = wanted->control.hash.key->condition(tt, offset, wanted->control.hash.key, &key_elem);
515 if (key_len < 0)
516 return -1;
518 key = tvb_get_string(wmem_packet_scope(),key_elem->tvb,key_elem->offset,key_elem->len);
519 #ifdef TVBPARSE_DEBUG
520 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_HASH) g_warning("cond_hash: got key='%s'",key);
521 #endif
523 if ((value_wanted = (tvbparse_wanted_t *)g_hash_table_lookup(wanted->control.hash.table,key))) {
524 value_len = value_wanted->condition(tt, offset + key_len, value_wanted, &value_elem);
525 } else if (wanted->control.hash.other) {
526 value_len = wanted->control.hash.other->condition(tt, offset+key_len, wanted->control.hash.other, &value_elem);
527 if (value_len < 0)
528 return -1;
529 } else {
530 return -1;
533 tot_len = key_len + value_len;
535 ret_tok = new_tok(tt, value_elem->id, offset, tot_len, wanted);
536 ret_tok->sub = key_elem;
537 ret_tok->sub->last->next = value_elem;
539 *tok = ret_tok;
540 #ifdef TVBPARSE_DEBUG
541 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_HASH) g_warning("cond_hash: GOT len=%i",tot_len);
542 #endif
544 return tot_len;
547 tvbparse_wanted_t* tvbparse_hashed(const int id,
548 const void* data,
549 tvbparse_action_t before_cb,
550 tvbparse_action_t after_cb,
551 tvbparse_wanted_t* key,
552 tvbparse_wanted_t* other,
553 ...) {
554 tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_malloc0(sizeof(tvbparse_wanted_t));
555 gchar* name;
556 tvbparse_wanted_t* el;
557 va_list ap;
559 w->condition = cond_hash;
560 w->id = id;
561 w->data = data;
562 w->before = before_cb;
563 w->after = after_cb;
564 w->control.hash.table = g_hash_table_new(g_str_hash,g_str_equal);
565 w->control.hash.key = key;
566 w->control.hash.other = other;
568 va_start(ap,other);
570 while(( name = va_arg(ap,gchar*) )) {
571 el = va_arg(ap,tvbparse_wanted_t*);
572 g_hash_table_insert(w->control.hash.table,name,el);
575 va_end(ap);
577 return w;
580 void tvbparse_hashed_add(tvbparse_wanted_t* w, ...) {
581 tvbparse_wanted_t* el;
582 va_list ap;
583 gchar* name;
585 va_start(ap,w);
587 while (( name = va_arg(ap,gchar*) )) {
588 el = va_arg(ap,tvbparse_wanted_t*);
589 g_hash_table_insert(w->control.hash.table,name,el);
592 va_end(ap);
595 static int cond_seq(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
596 guint i;
597 int len = 0;
598 int start = offset;
599 tvbparse_elem_t* ret_tok = NULL;
601 if ( offset > tt->end_offset )
602 return -1;
603 #ifdef TVBPARSE_DEBUG
604 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SEQ) g_warning("cond_seq: START");
605 #endif
607 for(i=0; i < wanted->control.elems->len; i++) {
608 tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_ptr_array_index(wanted->control.elems,i);
609 tvbparse_elem_t* new_elem = NULL;
611 if ( offset + w->len > tt->end_offset )
612 return -1;
615 len = w->condition(tt, offset, w, &new_elem);
617 if (len >= 0) {
618 if (ret_tok) {
619 ret_tok->len = (new_elem->offset - ret_tok->offset) + new_elem->len;
620 ret_tok->sub->last->next = new_elem;
621 ret_tok->sub->last = new_elem;
622 } else {
623 ret_tok = new_tok(tt, wanted->id, new_elem->offset, new_elem->len, wanted);
624 ret_tok->sub = new_elem;
625 new_elem->last = new_elem;
627 } else {
628 return -1;
631 offset += len;
632 offset += ignore_fcn(tt,offset);
635 *tok = ret_tok;
637 #ifdef TVBPARSE_DEBUG
638 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SEQ) g_warning("cond_seq: GOT len=%i",offset - start);
639 #endif
641 return offset - start;
645 tvbparse_wanted_t* tvbparse_set_seq(const int id,
646 const void* data,
647 tvbparse_action_t before_cb,
648 tvbparse_action_t after_cb,
649 ...) {
650 tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_malloc0(sizeof(tvbparse_wanted_t));
651 tvbparse_wanted_t* el = NULL;
652 va_list ap;
654 w->condition = cond_seq;
655 w->id = id;
656 w->data = data;
657 w->before = before_cb;
658 w->after = after_cb;
659 w->control.elems = g_ptr_array_new();
661 va_start(ap,after_cb);
663 while(( el = va_arg(ap,tvbparse_wanted_t*) )) {
664 g_ptr_array_add(w->control.elems,el);
667 va_end(ap);
668 return w;
671 static int cond_some(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
672 guint got_so_far = 0;
673 int start = offset;
674 tvbparse_elem_t* ret_tok = NULL;
675 #ifdef TVBPARSE_DEBUG
676 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SOME) g_warning("cond_some: START");
677 #endif
679 if ( offset > tt->end_offset )
680 return -1;
682 if ( wanted->min == 0 ) {
683 ret_tok = new_tok(tt,wanted->id,offset,0,wanted);
686 while (got_so_far < wanted->max) {
687 tvbparse_elem_t* new_elem = NULL;
688 int consumed;
690 if ( offset > tt->end_offset )
691 return -1;
693 consumed = wanted->control.subelem->condition(tt, offset, wanted->control.subelem, &new_elem);
695 if(consumed >= 0) {
696 if (ret_tok) {
697 ret_tok->len = (new_elem->offset - ret_tok->offset) + new_elem->len;
699 if (ret_tok->sub) {
700 ret_tok->sub->last->next = new_elem;
701 ret_tok->sub->last = new_elem;
702 } else {
703 ret_tok->sub = new_elem;
705 } else {
706 ret_tok = new_tok(tt, wanted->id, new_elem->offset, new_elem->len, wanted);
707 ret_tok->sub = new_elem;
709 } else {
710 break;
713 offset += consumed;
714 got_so_far++;
717 #ifdef TVBPARSE_DEBUG
718 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SOME) g_warning("cond_some: got num=%u",got_so_far);
719 #endif
721 if(got_so_far < wanted->min) {
722 return -1;
725 *tok = ret_tok;
726 #ifdef TVBPARSE_DEBUG
727 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SOME) g_warning("cond_some: GOT len=%i",offset - start);
728 #endif
729 return offset - start;
732 tvbparse_wanted_t* tvbparse_some(const int id,
733 const guint from,
734 const guint to,
735 const void* data,
736 tvbparse_action_t before_cb,
737 tvbparse_action_t after_cb,
738 const tvbparse_wanted_t* el) {
740 tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_malloc0(sizeof(tvbparse_wanted_t));
742 g_assert(from <= to);
744 w->condition = cond_some;
745 w->id = id;
746 w->min = from;
747 w->max = to;
748 w->data = data;
749 w->before = before_cb;
750 w->after = after_cb;
751 w->control.subelem = el;
753 return w;
757 static int cond_until(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
758 tvbparse_elem_t* new_elem = NULL;
759 int len = 0;
760 int target_offset = offset;
761 #ifdef TVBPARSE_DEBUG
762 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) g_warning("cond_until: START");
763 #endif
765 if ( offset + wanted->control.until.subelem->len > tt->end_offset )
766 return -1;
768 do {
769 len = wanted->control.until.subelem->condition(tt, target_offset++, wanted->control.until.subelem, &new_elem);
770 } while(len < 0 && target_offset+1 < tt->end_offset);
772 if (len >= 0) {
774 new_elem->id = wanted->id;
775 new_elem->next = NULL;
776 new_elem->last = NULL;
777 new_elem->wanted = wanted;
778 new_elem->offset = offset;
780 (*tok) = new_elem;
782 switch (wanted->control.until.mode) {
783 case TP_UNTIL_INCLUDE:
784 new_elem->len = target_offset - offset - 1 + len;
785 #ifdef TVBPARSE_DEBUG
786 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) g_warning("cond_until: GOT len=%i",target_offset - offset -1 + len);
787 #endif
788 return target_offset - offset -1 + len;
789 case TP_UNTIL_SPEND:
790 new_elem->len = target_offset - offset - 1;
791 #ifdef TVBPARSE_DEBUG
792 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) g_warning("cond_until: GOT len=%i",target_offset - offset -1 + len);
793 #endif
794 return target_offset - offset - 1 + len;
795 case TP_UNTIL_LEAVE:
796 new_elem->len = target_offset - offset - 1;
797 #ifdef TVBPARSE_DEBUG
798 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) g_warning("cond_until: GOT len=%i",target_offset - offset -1);
799 #endif
800 return target_offset - offset -1;
801 default:
802 DISSECTOR_ASSERT_NOT_REACHED();
803 return -1;
806 } else {
807 return -1;
811 tvbparse_wanted_t* tvbparse_until(const int id,
812 const void* data,
813 tvbparse_action_t before_cb,
814 tvbparse_action_t after_cb,
815 const tvbparse_wanted_t* el,
816 until_mode_t until_mode) {
817 tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_malloc0(sizeof(tvbparse_wanted_t));
819 w->condition = cond_until;
820 w->control.until.mode = until_mode;
821 w->control.until.subelem = el;
822 w->id = id;
823 w->data = data;
824 w->before = before_cb;
825 w->after = after_cb;
827 return w;
830 static int cond_handle(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
831 tvbparse_wanted_t* w = *(wanted->control.handle);
832 int len = w->condition(tt, offset, w, tok);
834 if (len >= 0) {
835 return len;
836 } else {
837 return -1;
841 tvbparse_wanted_t* tvbparse_handle(tvbparse_wanted_t** handle) {
842 tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_malloc0(sizeof(tvbparse_wanted_t));
844 w->condition = cond_handle;
845 w->control.handle = handle;
847 return w;
850 static int cond_end(tvbparse_t* tt, const int offset, const tvbparse_wanted_t * wanted _U_, tvbparse_elem_t** tok) {
851 if (offset == tt->end_offset) {
852 *tok = new_tok(tt,wanted->id,offset,0,wanted);
853 return 0;
854 } else {
855 return -1;
859 tvbparse_wanted_t* tvbparse_end_of_buffer(const int id,
860 const void* data,
861 tvbparse_action_t before_cb,
862 tvbparse_action_t after_cb) {
863 tvbparse_wanted_t* w = (tvbparse_wanted_t *)g_malloc0(sizeof(tvbparse_wanted_t));
865 w->id = id;
866 w->condition = cond_end;
867 w->after = after_cb;
868 w->before = before_cb;
869 w->data = data;
870 return w;
875 #if 0
876 /* these extract binary values */
878 static int cond_ft(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
879 guint len = 0;
881 if ( offset + wanted->len > tt->end_offset )
882 return -1;
884 if (wanted->len) {
885 return wanted->len;
886 } else if (wanted->control.ftenum == FT_STRINGZ) {
887 if (( len = tvb_find_guint8(tt->tvb,offset,tt->end_offset - offset,'\0') >= 0 )) {
888 *tok = new_tok(tt,wanted->id,offset,len,wanted);
889 return len;
890 } else {
891 return -1;
893 } else {
894 return -2;
898 gint ft_lens[] = {-1,-1,-1, 1, 2, 3, 4, 8, 1, 2, 3, 4, 8, 4, 8,-1,-1,-1, 0, -1, 6, -1, -1, 4, sizeof(struct e_in6_addr), -1, -1, -1, -1 };
900 tvbparse_wanted_t* tvbparse_ft(int id,
901 const void* data,
902 tvbparse_action_t before_cb,
903 tvbparse_action_t after_cb,
904 enum ftenum ftenum) {
905 gint len = ft_lens[ftenum];
907 if (len >= 0) {
908 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
910 w->id = id;
911 w->condition = cond_ft;
912 w->len = len;
913 w->control.ftenum = ftenum;
914 w->after = after_cb;
915 w->before = before_cb;
916 w->data = data;
918 return w;
919 } else {
920 g_assert(! "unsupported ftenum" );
921 return NULL;
925 static int cond_ft_comp(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted _U_, tvbparse_elem_t** tok) {
926 void* l = wanted->control.number.extract(tt->tvb,offset);
927 const void* r = &(wanted->control.number.value);
929 if ( offset + wanted->len > tt->end_offset )
930 return -1;
932 if ( wanted->control.number.comp(&l,&r) ) {
933 *tok = new_tok(tt,wanted->id,offset,wanted->len,wanted);
934 return wanted->len;
935 } else {
936 return -1;
940 static gboolean comp_gt_i(void* lp, const void* rp) { return ( *((gint64*)lp) > *((gint64*)rp) ); }
941 static gboolean comp_ge_i(void* lp, const void* rp) { return ( *((gint64*)lp) >= *((gint64*)rp) ); }
942 static gboolean comp_eq_i(void* lp, const void* rp) { return ( *((gint64*)lp) == *((gint64*)rp) ); }
943 static gboolean comp_ne_i(void* lp, const void* rp) { return ( *((gint64*)lp) != *((gint64*)rp) ); }
944 static gboolean comp_le_i(void* lp, const void* rp) { return ( *((gint64*)lp) <= *((gint64*)rp) ); }
945 static gboolean comp_lt_i(void* lp, const void* rp) { return ( *((gint64*)lp) < *((gint64*)rp) ); }
947 static gboolean comp_gt_u(void* lp, const void* rp) { return ( *((guint64*)lp) > *((guint64*)rp) ); }
948 static gboolean comp_ge_u(void* lp, const void* rp) { return ( *((guint64*)lp) >= *((guint64*)rp) ); }
949 static gboolean comp_eq_u(void* lp, const void* rp) { return ( *((guint64*)lp) == *((guint64*)rp) ); }
950 static gboolean comp_ne_u(void* lp, const void* rp) { return ( *((guint64*)lp) != *((guint64*)rp) ); }
951 static gboolean comp_le_u(void* lp, const void* rp) { return ( *((guint64*)lp) <= *((guint64*)rp) ); }
952 static gboolean comp_lt_u(void* lp, const void* rp) { return ( *((guint64*)lp) < *((guint64*)rp) ); }
954 static gboolean comp_gt_f(void* lp, const void* rp) { return ( *((gdouble*)lp) > *((gdouble*)rp) ); }
955 static gboolean comp_ge_f(void* lp, const void* rp) { return ( *((gdouble*)lp) >= *((gdouble*)rp) ); }
956 static gboolean comp_eq_f(void* lp, const void* rp) { return ( *((gdouble*)lp) == *((gdouble*)rp) ); }
957 static gboolean comp_ne_f(void* lp, const void* rp) { return ( *((gdouble*)lp) != *((gdouble*)rp) ); }
958 static gboolean comp_le_f(void* lp, const void* rp) { return ( *((gdouble*)lp) <= *((gdouble*)rp) ); }
959 static gboolean comp_lt_f(void* lp, const void* rp) { return ( *((gdouble*)lp) < *((gdouble*)rp) ); }
961 static void* extract_u8(tvbuff_t* tvb, guint offset) {
962 guint64* p = ep_new(guint64);
963 *p = tvb_get_guint8(tvb,offset);
964 return p;
967 static void* extract_uns(tvbuff_t* tvb, guint offset) {
968 guint64* p = ep_new(guint64);
969 *p = tvb_get_ntohs(tvb,offset);
970 return p;
973 static void* extract_un24(tvbuff_t* tvb, guint offset) {
974 guint64* p = ep_new(guint64);
975 *p = tvb_get_ntoh24(tvb,offset);
976 return p;
979 static void* extract_unl(tvbuff_t* tvb, guint offset) {
980 guint64* p = ep_new(guint64);
981 *p = tvb_get_ntohl(tvb,offset);
982 return p;
985 static void* extract_un64(tvbuff_t* tvb, guint offset) {
986 guint64* p = ep_new(guint64);
987 *p = tvb_get_ntoh64(tvb,offset);
988 return p;
991 static void* extract_ules(tvbuff_t* tvb, guint offset) {
992 guint64* p = ep_new(guint64);
993 *p = tvb_get_letohs(tvb,offset);
994 return p;
997 static void* extract_ule24(tvbuff_t* tvb, guint offset) {
998 guint64* p = ep_new(guint64);
999 *p = tvb_get_letoh24(tvb,offset);
1000 return p;
1003 static void* extract_ulel(tvbuff_t* tvb, guint offset) {
1004 guint64* p = ep_new(guint64);
1005 *p = tvb_get_letohl(tvb,offset);
1006 return p;
1009 static void* extract_ule64(tvbuff_t* tvb, guint offset) {
1010 guint64* p = ep_new(guint64);
1011 *p = tvb_get_letoh64(tvb,offset);
1012 return p;
1015 static void* extract_ins(tvbuff_t* tvb, guint offset) {
1016 guint64* p = ep_new(guint64);
1017 *p = tvb_get_ntohs(tvb,offset);
1018 return p;
1021 static void* extract_in24(tvbuff_t* tvb, guint offset) {
1022 guint64* p = ep_new(guint64);
1023 *p = tvb_get_ntoh24(tvb,offset);
1024 return p;
1027 static void* extract_inl(tvbuff_t* tvb, guint offset) {
1028 guint64* p = ep_new(guint64);
1029 *p = tvb_get_ntohl(tvb,offset);
1030 return p;
1033 static void* extract_in64(tvbuff_t* tvb, guint offset) {
1034 guint64* p = ep_new(guint64);
1035 *p = tvb_get_ntoh64(tvb,offset);
1036 return p;
1039 static void* extract_iles(tvbuff_t* tvb, guint offset) {
1040 guint64* p = ep_new(guint64);
1041 *p = tvb_get_letohs(tvb,offset);
1042 return p;
1045 static void* extract_ile24(tvbuff_t* tvb, guint offset) {
1046 guint64* p = ep_new(guint64);
1047 *p = tvb_get_letoh24(tvb,offset);
1048 return p;
1051 static void* extract_ilel(tvbuff_t* tvb, guint offset) {
1052 guint64* p = ep_new(guint64);
1053 *p = tvb_get_letohl(tvb,offset);
1054 return p;
1057 static void* extract_ile64(tvbuff_t* tvb, guint offset) {
1058 guint64* p = ep_new(guint64);
1059 *p = tvb_get_letoh64(tvb,offset);
1060 return p;
1063 static void* extract_inf(tvbuff_t* tvb, guint offset) {
1064 gdouble* p = ep_new(gdouble);
1065 *p = tvb_get_ntohieee_float(tvb,offset);
1066 return p;
1069 static void* extract_ind(tvbuff_t* tvb, guint offset) {
1070 gdouble* p = ep_new(gdouble);
1071 *p = tvb_get_ntohieee_double(tvb,offset);
1072 return p;
1075 static void* extract_ilef(tvbuff_t* tvb, guint offset) {
1076 gdouble* p = ep_new(gdouble);
1077 *p = tvb_get_letohieee_float(tvb,offset);
1078 return p;
1081 static void* extract_iled(tvbuff_t* tvb, guint offset) {
1082 gdouble* p = ep_new(gdouble);
1083 *p = tvb_get_letohieee_double(tvb,offset);
1084 return p;
1089 static gboolean (*comps_u[])(void*, const void*) = {comp_gt_u,comp_ge_u,comp_eq_u,comp_ne_u,comp_le_u,comp_lt_u};
1090 static gboolean (*comps_i[])(void*, const void*) = {comp_gt_i,comp_ge_i,comp_eq_i,comp_ne_i,comp_le_i,comp_lt_i};
1091 static gboolean (*comps_f[])(void*, const void*) = {comp_gt_f,comp_ge_f,comp_eq_f,comp_ne_f,comp_le_f,comp_lt_f};
1093 static gboolean (**comps[])(void*, const void*) = {comps_u,comps_i,comps_f};
1095 static void* (*extract_n[])(tvbuff_t* tvb, guint offset) = {
1096 NULL, NULL, NULL, extract_u8, extract_uns, extract_un24, extract_unl,
1097 extract_un64, extract_u8, extract_ins, extract_in24, extract_inl,
1098 extract_in64, extract_inf, extract_ind, NULL, NULL, NULL, NULL, NULL, NULL,
1099 NULL, NULL, NULL, NULL, NULL, NULL,NULL, NULL
1101 static void* (*extract_le[])(tvbuff_t* tvb, guint offset) = {
1102 NULL, NULL, NULL, extract_u8, extract_ules, extract_ule24, extract_ulel,
1103 extract_ule64, extract_u8, extract_iles, extract_ile24, extract_ilel,
1104 extract_ile64, extract_ilef, extract_iled, NULL, NULL, NULL, NULL, NULL,
1105 NULL, NULL, NULL, NULL, NULL, NULL, NULL,NULL, NULL
1108 static void* (**extracts[])(tvbuff_t* tvb, guint offset) = { extract_n, extract_le};
1111 tvbparse_wanted_t* tvbparse_ft_numcmp(int id,
1112 const void* data,
1113 tvbparse_action_t before_cb,
1114 tvbparse_action_t after_cb,
1115 enum ftenum ftenum,
1116 int little_endian,
1117 enum ft_cmp_op ft_cmp_op,
1118 ... ) {
1119 tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
1120 va_list ap;
1122 va_start(ap,ft_cmp_op);
1124 switch (ftenum) {
1125 case FT_UINT8:
1126 case FT_UINT16:
1127 case FT_UINT24:
1128 case FT_UINT32:
1129 w->control.number.comp = comps[0][ft_cmp_op];
1130 w->control.number.value.u = va_arg(ap,guint32);
1131 break;
1132 case FT_UINT64:
1133 w->control.number.comp = comps[0][ft_cmp_op];
1134 w->control.number.value.u = va_arg(ap,guint64);
1135 break;
1136 case FT_INT8:
1137 case FT_INT16:
1138 case FT_INT24:
1139 case FT_INT32:
1140 w->control.number.comp = comps[1][ft_cmp_op];
1141 w->control.number.value.i = va_arg(ap,gint32);
1142 break;
1143 case FT_INT64:
1144 w->control.number.comp = comps[1][ft_cmp_op];
1145 w->control.number.value.i = va_arg(ap,gint64);
1146 break;
1147 case FT_FLOAT:
1148 case FT_DOUBLE:
1149 w->control.number.comp = comps[1][ft_cmp_op];
1150 w->control.number.value.i = va_arg(ap,gdouble);
1151 break;
1152 default:
1153 g_assert(! "comparison unsupported");
1156 w->control.number.extract = extracts[little_endian][ftenum];
1158 g_assert(w->control.number.extract && "extraction unsupported");
1160 w->id = id;
1161 w->condition = cond_ft_comp;
1162 w->after = after_cb;
1163 w->before = before_cb;
1164 w->data = data;
1166 return w;
1169 #endif
1172 tvbparse_wanted_t* tvbparse_quoted(const int id,
1173 const void* data,
1174 tvbparse_action_t before_cb,
1175 tvbparse_action_t after_cb,
1176 const char quote,
1177 const char esc) {
1179 gchar* esc_quot = g_strdup_printf("%c%c",esc,quote);
1180 gchar* quot = g_strdup_printf("%c",quote);
1181 tvbparse_wanted_t* want_quot = tvbparse_char(-1,quot,NULL,NULL,NULL);
1183 return tvbparse_set_oneof(id, data, before_cb, after_cb,
1184 tvbparse_set_seq(-1, NULL, NULL, NULL,
1185 want_quot,
1186 tvbparse_set_seq(-1,NULL,NULL,NULL,
1187 tvbparse_set_oneof(-1, NULL, NULL, NULL,
1188 tvbparse_string(-1,esc_quot,NULL,NULL,NULL),
1189 tvbparse_not_chars(-1,0,0,quot,NULL,NULL,NULL),
1190 NULL),
1191 NULL),
1192 want_quot,
1193 NULL),
1194 tvbparse_set_seq(-1, NULL, NULL, NULL,
1195 want_quot,
1196 want_quot,
1197 NULL),
1198 NULL);
1201 void tvbparse_shrink_token_cb(void* tvbparse_data _U_,
1202 const void* wanted_data _U_,
1203 tvbparse_elem_t* tok) {
1204 tok->offset += 1;
1205 tok->len -= 2;
1208 tvbparse_t* tvbparse_init(tvbuff_t* tvb,
1209 const int offset,
1210 int len,
1211 void* data,
1212 const tvbparse_wanted_t* ignore) {
1213 tvbparse_t* tt = (tvbparse_t *)ep_alloc(sizeof(tvbparse_t));
1215 #ifdef TVBPARSE_DEBUG
1216 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_TT) g_warning("tvbparse_init: offset=%i len=%i",offset,len);
1217 #endif
1220 tt->tvb = tvb;
1221 tt->offset = offset;
1222 len = (len == -1) ? (int) tvb_length(tvb) : len;
1223 tt->end_offset = offset + len;
1224 tt->data = data;
1225 tt->ignore = ignore;
1226 return tt;
1229 gboolean tvbparse_reset(tvbparse_t* tt,
1230 const int offset,
1231 int len) {
1233 #ifdef TVBPARSE_DEBUG
1234 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_TT) g_warning("tvbparse_init: offset=%i len=%i",offset,len);
1235 #endif
1237 len = (len == -1) ? (int) tvb_length(tt->tvb) : len;
1239 if( tvb_length_remaining(tt->tvb, offset) >= len) {
1240 tt->offset = offset;
1241 tt->end_offset = offset + len;
1242 return TRUE;
1243 } else {
1244 return FALSE;
1248 guint tvbparse_curr_offset(tvbparse_t* tt) {
1249 return tt->offset;
1252 static void execute_callbacks(tvbparse_t* tt, tvbparse_elem_t* curr) {
1253 ep_stack_t stack = ep_stack_new();
1255 while (curr) {
1256 if(curr->wanted->before) {
1257 #ifdef TVBPARSE_DEBUG
1258 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CB) g_warning("execute_callbacks: BEFORE: id=%i offset=%i len=%i",curr->id,curr->offset,curr->len);
1259 #endif
1260 curr->wanted->before(tt->data, curr->wanted->data, curr);
1263 if(curr->sub) {
1264 ep_stack_push(stack,curr);
1265 curr = curr->sub;
1266 continue;
1267 } else {
1268 #ifdef TVBPARSE_DEBUG
1269 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CB) g_warning("execute_callbacks: AFTER: id=%i offset=%i len=%i",curr->id,curr->offset,curr->len);
1270 #endif
1271 if(curr->wanted->after) curr->wanted->after(tt->data, curr->wanted->data, curr);
1274 curr = curr->next;
1276 while( !curr && ep_stack_peek(stack) ) {
1277 curr = (tvbparse_elem_t *)ep_stack_pop(stack);
1278 #ifdef TVBPARSE_DEBUG
1279 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CB) g_warning("execute_callbacks: AFTER: id=%i offset=%i len=%i",curr->id,curr->offset,curr->len);
1280 #endif
1281 if( curr->wanted->after ) curr->wanted->after(tt->data, curr->wanted->data, curr);
1282 curr = curr->next;
1288 gboolean tvbparse_peek(tvbparse_t* tt,
1289 const tvbparse_wanted_t* wanted) {
1290 tvbparse_elem_t* tok = NULL;
1291 int consumed;
1292 int offset = tt->offset;
1294 #ifdef TVBPARSE_DEBUG
1295 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) g_warning("tvbparse_peek: ENTER offset=%i",offset);
1296 #endif
1298 offset += ignore_fcn(tt,offset);
1300 #ifdef TVBPARSE_DEBUG
1301 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) g_warning("tvbparse_peek: after ignore offset=%i",offset);
1302 #endif
1304 consumed = wanted->condition(tt,offset,wanted,&tok);
1306 if (consumed >= 0) {
1307 #ifdef TVBPARSE_DEBUG
1308 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) g_warning("tvbparse_peek: GOT len=%i",consumed);
1309 #endif
1310 return TRUE;
1311 } else {
1312 #ifdef TVBPARSE_DEBUG
1313 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) g_warning("tvbparse_peek: NOT GOT");
1314 #endif
1315 return FALSE;
1320 tvbparse_elem_t* tvbparse_get(tvbparse_t* tt,
1321 const tvbparse_wanted_t* wanted) {
1322 tvbparse_elem_t* tok = NULL;
1323 int consumed;
1324 int offset = tt->offset;
1326 #ifdef TVBPARSE_DEBUG
1327 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) g_warning("tvbparse_get: ENTER offset=%i",offset);
1328 #endif
1330 offset += ignore_fcn(tt,offset);
1332 #ifdef TVBPARSE_DEBUG
1333 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) g_warning("tvbparse_get: after ignore offset=%i",offset);
1334 #endif
1336 consumed = wanted->condition(tt,offset,wanted,&tok);
1338 if (consumed >= 0) {
1339 #ifdef TVBPARSE_DEBUG
1340 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) g_warning("tvbparse_get: GOT len=%i",consumed);
1341 #endif
1342 execute_callbacks(tt,tok);
1343 tt->offset = offset + consumed;
1344 #ifdef TVBPARSE_DEBUG
1345 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) g_warning("tvbparse_get: DONE offset=%i", tt->offset);
1346 #endif
1347 return tok;
1348 } else {
1349 return NULL;
1355 tvbparse_elem_t* tvbparse_find(tvbparse_t* tt, const tvbparse_wanted_t* wanted) {
1356 tvbparse_elem_t* tok = NULL;
1357 int len = 0;
1358 int offset = tt->offset;
1359 int target_offset = offset -1;
1361 #ifdef TVBPARSE_DEBUG
1362 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) g_warning("tvbparse_get: ENTER offset=%i", tt->offset);
1363 #endif
1365 do {
1366 len = wanted->condition(tt, target_offset+1, wanted, &tok);
1367 } while(len < 0 && ++target_offset < tt->end_offset);
1369 if (len >= 0) {
1370 #ifdef TVBPARSE_DEBUG
1371 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) g_warning("tvbparse_get: FOUND offset=%i len=%i", target_offset,len);
1372 #endif
1373 execute_callbacks(tt,tok);
1374 tt->offset = target_offset + len;
1376 #ifdef TVBPARSE_DEBUG
1377 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) g_warning("tvbparse_get: DONE offset=%i", tt->offset);
1378 #endif
1379 return tok;
1380 } else {
1381 #ifdef TVBPARSE_DEBUG
1382 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) g_warning("tvbparse_get: NOT FOUND");
1383 #endif
1384 return NULL;
1388 struct _elem_tree_stack_frame {
1389 proto_tree* tree;
1390 tvbparse_elem_t* elem;
1393 void tvbparse_tree_add_elem(proto_tree* tree, tvbparse_elem_t* curr) {
1394 ep_stack_t stack = ep_stack_new();
1395 struct _elem_tree_stack_frame* frame = (struct _elem_tree_stack_frame *)ep_alloc(sizeof(struct _elem_tree_stack_frame));
1396 proto_item* pi;
1397 frame->tree = tree;
1398 frame->elem = curr;
1400 while (curr) {
1401 pi = proto_tree_add_text(frame->tree,curr->tvb,curr->offset,curr->len,"%s",tvb_format_text(curr->tvb,curr->offset,curr->len));
1403 if(curr->sub) {
1404 frame->elem = curr;
1405 ep_stack_push(stack,frame);
1406 frame = (struct _elem_tree_stack_frame *)ep_alloc(sizeof(struct _elem_tree_stack_frame));
1407 frame->tree = proto_item_add_subtree(pi,0);
1408 curr = curr->sub;
1409 continue;
1412 curr = curr->next;
1414 while( !curr && ep_stack_peek(stack) ) {
1415 frame = (struct _elem_tree_stack_frame *)ep_stack_pop(stack);
1416 curr = frame->elem->next;