name change
[metze/wireshark/wip.git] / epan / tvbparse.c
1 /* tvbparse.c
2 *
3 * Copyright 2005, Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
4 *
5 * $Id$
6 *
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
10 *
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.
15
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.
20
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 */
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include <stdlib.h>
31 #include <string.h>
32 #include <glib.h>
33
34 #include <epan/emem.h>
35 #include <epan/proto.h>
36 #include <epan/packet_info.h>
37 #include <epan/tvbparse.h>
38
39
40 #define TVBPARSE_DEBUG_ALL 0xffffffff
41
42 /*#define TVBPARSE_DEBUG_ 0x80000000
43 #define TVBPARSE_DEBUG_ 0x40000000
44 #define TVBPARSE_DEBUG_ 0x20000000
45 #define TVBPARSE_DEBUG_ 0x10000000*/
46
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 /*#define TVBPARSE_DEBUG_ 0x00010000
59 #define TVBPARSE_DEBUG_ 0x00008000
60 #define TVBPARSE_DEBUG_ 0x00004000
61 #define TVBPARSE_DEBUG_ 0x00002000
62 #define TVBPARSE_DEBUG_ 0x00001000*/
63
64 #define TVBPARSE_DEBUG_TT 0x00000800
65 #define TVBPARSE_DEBUG_CB 0x00000400
66 #define TVBPARSE_DEBUG_GET 0x00000200
67 #define TVBPARSE_DEBUG_FIND 0x00000100
68 #define TVBPARSE_DEBUG_NEWTOK 0x00000080
69 #define TVBPARSE_DEBUG_IGNORE 0x00000040
70 #define TVBPARSE_DEBUG_PEEK 0x00000020
71 /*#define TVBPARSE_DEBUG_ 0x00000010
72 #define TVBPARSE_DEBUG_ 0x00000008
73 #define TVBPARSE_DEBUG_ 0x00000004
74 #define TVBPARSE_DEBUG_ 0x00000002
75 #define TVBPARSE_DEBUG_ 0x00000001*/
76
77 /*
78 #define TVBPARSE_DEBUG (TVBPARSE_DEBUG_SOME)
79 */
80
81 static tvbparse_elem_t* new_tok(tvbparse_t* tt,
82                                 int id,
83                                 int offset,
84                                 int len,
85                                 const tvbparse_wanted_t* wanted) {
86         tvbparse_elem_t* tok;
87     
88 #ifdef TVBPARSE_DEBUG
89     if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NEWTOK) g_warning("new_tok: id=%i offset=%u len=%u",id,offset,len);
90 #endif
91
92     tok = ep_alloc(sizeof(tvbparse_elem_t));
93
94         tok->tvb = tt->tvb;
95         tok->id = id;
96         tok->offset = offset;
97         tok->len = len;
98         tok->data = NULL;
99         tok->sub = NULL;
100         tok->next = NULL;
101         tok->wanted = wanted;
102         tok->last = tok;
103         
104         return tok;
105 }
106
107 static int ignore(tvbparse_t* tt,int offset) {
108     int len = 0;
109     int consumed;
110     tvbparse_elem_t* ignored = NULL;
111     
112     if (!tt->ignore) return 0;
113     
114 #ifdef TVBPARSE_DEBUG
115     if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_IGNORE) g_warning("ignore: enter");
116 #endif
117     
118     while ((consumed = tt->ignore->condition(tt,offset,tt->ignore,&ignored)) > 0) {
119         len += consumed;
120         offset += consumed;
121 #ifdef TVBPARSE_DEBUG
122         if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_IGNORE) g_warning("ignore: consumed=%i",consumed);
123 #endif
124         
125     }
126
127 #ifdef TVBPARSE_DEBUG
128     if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_IGNORE) g_warning("ignore: len=%i",len);
129 #endif
130     
131     return len;
132 }
133
134
135 static int cond_char (tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
136     gchar c,t;
137     guint i;
138
139 #ifdef TVBPARSE_DEBUG
140     if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHAR) g_warning("cond_char: control='%s'",wanted->control.str);
141 #endif
142     
143     if ( offset + 1 > tt->end_offset )
144         return -1;
145     
146     t = (gchar) tvb_get_guint8(tt->tvb,offset);
147     
148     for(i = 0; (c = wanted->control.str[i]) && offset <= tt->end_offset; i++) {
149         if ( c == t ) {
150             *tok =  new_tok(tt,wanted->id,offset,1,wanted);
151 #ifdef TVBPARSE_DEBUG
152             if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHAR) g_warning("cond_char: GOT: '%c'",c);
153 #endif
154             return 1;
155         }
156     }
157     
158     return -1;
159 }
160
161 tvbparse_wanted_t* tvbparse_char(int id,
162                                  const gchar* chr,
163                                  const void* data,
164                                  tvbparse_action_t before_cb,
165                                  tvbparse_action_t after_cb) {
166         tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
167         
168     w->condition = cond_char;
169     w->id = id;
170         w->control.str = chr;
171         w->len = 1;
172         w->data = data;
173         w->before = before_cb;
174         w->after = after_cb;
175         
176         return w;
177 }
178
179 static int cond_chars (tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
180     guint length = 0;
181     int start = offset;
182     int left = tt->end_offset - offset;
183     
184 #ifdef TVBPARSE_DEBUG
185     if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHARS) g_warning("cond_chars: control='%s'",wanted->control.str);
186 #endif
187     
188     if ( offset + (int)wanted->min > tt->end_offset )
189         return -1;
190
191     left = left < (int) wanted->max ? left :  (int) wanted->max;
192
193     while( left > 0 ) {
194         gchar t = (gchar) tvb_get_guint8(tt->tvb,offset++);
195         gchar c;
196         guint i = 0;
197         
198         while ( (c = wanted->control.str[i++]) ) {
199             if (c == t) goto next_char;
200         }
201         
202         break;
203         
204 next_char:
205         length++;
206         left--;
207     };
208     
209     if (length < wanted->min) {
210         return  -1;
211     } else {
212         *tok = new_tok(tt,wanted->id,start,length,wanted);
213 #ifdef TVBPARSE_DEBUG
214         if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CHARS) g_warning("cond_chars: GOT len=%i",length);
215 #endif
216         return length;                  
217     }
218 }
219
220 tvbparse_wanted_t* tvbparse_chars(int id,
221                                                                   guint min_len,
222                                                                   guint max_len,
223                                                                   const gchar* chr,
224                                                                   const void* data,
225                                                                   tvbparse_action_t before_cb,
226                                                                   tvbparse_action_t after_cb) {
227         tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
228         
229     w->condition = cond_chars;
230     w->id = id;
231         w->control.str = chr;
232         w->min = min_len ? min_len : 1;
233         w->max = max_len ? max_len : G_MAXINT/2;
234         w->data = data;
235         w->before = before_cb;
236         w->after = after_cb;
237         
238         return w;
239 }
240
241
242 static int cond_not_char(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
243     gchar c, t;
244     guint i;
245     gboolean not_matched = FALSE;
246
247 #ifdef TVBPARSE_DEBUG
248     if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NOT_CHAR) g_warning("cond_not_char: control='%s'",wanted->control.str);
249 #endif
250     
251     if (! offset < tt->end_offset ) {
252         return -1;
253     }
254     
255     t = (gchar) tvb_get_guint8(tt->tvb,offset);
256     
257     for(i = 0; (c = wanted->control.str[i]); i++) {
258         if ( c == t ) {
259             not_matched = TRUE;
260         }
261     }
262     
263     if (not_matched) {
264         return -1;
265     } else {
266         *tok =  new_tok(tt,wanted->id,offset,1,wanted);
267 #ifdef TVBPARSE_DEBUG
268         if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NOT_CHAR) g_warning("cond_not_char: GOT='%c'",t);
269 #endif        
270         return 1;
271     }
272 }
273
274 tvbparse_wanted_t* tvbparse_not_char(int id,
275                                      const gchar* chr,
276                                      const void* data,
277                                      tvbparse_action_t before_cb,
278                                      tvbparse_action_t after_cb) {
279         tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
280         
281     w->condition = cond_not_char;
282     w->id = id;
283         w->control.str = chr;
284         w->data = data;
285         w->before = before_cb;
286         w->after = after_cb;
287         
288         return w;
289 }
290
291 static int cond_not_chars(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
292     guint length = 0;
293     int left = tt->end_offset - offset;
294     int start = offset;
295
296 #ifdef TVBPARSE_DEBUG
297     if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NOT_CHARS) g_warning("cond_not_chars: control='%s'",wanted->control.str);
298 #endif
299     
300     if ( offset + (int)wanted->min > tt->end_offset )
301         return -1;
302
303     if (left < (int)wanted->min)
304         return -1;
305
306     left = left <= (int)wanted->max ? left :  (int)wanted->max;
307
308     while( left > 0 ) {
309         gchar c;
310         gchar t = (gchar) tvb_get_guint8(tt->tvb,offset);
311         guint i = 0;
312         
313         while ( (c = wanted->control.str[i++]) ) {
314             if (c == t) goto end_not_chars;
315         }
316         
317         offset++;
318         length++;
319         left--;
320     }
321 end_not_chars:
322     
323     if ( length < wanted->min ) {
324         return -1;
325     } else {
326         *tok = new_tok(tt,wanted->id,start,length,wanted);
327 #ifdef TVBPARSE_DEBUG
328         if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_NOT_CHARS) g_warning("cond_not_chars: GOT len=%i",length);
329 #endif        
330         return length;
331     }
332 }
333
334 tvbparse_wanted_t* tvbparse_not_chars(int id,
335                                                                           guint min_len,
336                                                                           guint max_len,
337                                                                           const gchar* chr,
338                                                                           const void* data,
339                                                                           tvbparse_action_t before_cb,
340                                                                           tvbparse_action_t after_cb){
341         tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
342         
343     w->condition = cond_not_chars;
344     w->id = id;
345         w->control.str = chr;
346         w->len = 0;
347         w->min = min_len ? min_len : 1;
348         w->max = max_len ? max_len : G_MAXINT/2;
349         w->data = data;
350         w->before = before_cb;
351         w->after = after_cb;
352         
353         return w;
354 }
355
356
357 static int cond_string(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
358     int len = wanted->len;
359 #ifdef TVBPARSE_DEBUG
360     if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_STRING) g_warning("cond_string: control='%s'",wanted->control.str);
361 #endif
362     
363     if ( offset + wanted->len > tt->end_offset )
364         return -1;
365
366     if ( tvb_strneql(tt->tvb, offset, wanted->control.str, len) == 0 ) {
367         *tok = new_tok(tt,wanted->id,offset,len,wanted);
368 #ifdef TVBPARSE_DEBUG
369         if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_STRING) g_warning("cond_string: GOT len=%i",len);
370 #endif        
371         return len;
372     } else {
373         return -1;
374     }
375 }
376
377 tvbparse_wanted_t* tvbparse_string(int id,
378                                                                    const gchar* str,
379                                                                    const void* data,
380                                                                    tvbparse_action_t before_cb,
381                                                                    tvbparse_action_t after_cb) {
382         tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
383         
384     w->condition = cond_string;
385     w->id = id;
386         w->control.str = str;
387         w->len = strlen(str);
388         w->data = data;
389         w->before = before_cb;
390         w->after = after_cb;
391         
392         return w;
393 }
394
395 static int cond_casestring(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
396     int len = wanted->len;
397 #ifdef TVBPARSE_DEBUG
398     if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CASESTRING) g_warning("cond_casestring: control='%s'",wanted->control.str);
399 #endif
400     
401     if ( offset + len > tt->end_offset )
402         return -1;
403
404     if ( tvb_strncaseeql(tt->tvb, offset, wanted->control.str, len) == 0 ) {
405         *tok = new_tok(tt,wanted->id,offset,len,wanted);
406 #ifdef TVBPARSE_DEBUG
407         if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CASESTRING) g_warning("cond_casestring: GOT len=%i",len);
408 #endif                
409         return len;
410     } else {
411         *tok = NULL;
412         return -1;
413     }
414 }
415
416 tvbparse_wanted_t* tvbparse_casestring(int id,
417                                        const gchar* str,
418                                        const void* data,
419                                        tvbparse_action_t before_cb,
420                                        tvbparse_action_t after_cb) {
421         tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
422         
423     w->condition = cond_casestring;
424     w->id = id;
425         w->control.str = str;
426         w->len = strlen(str);
427         w->data = data;
428         w->before = before_cb;
429         w->after = after_cb;
430         
431         return w;
432 }
433
434 static int cond_one_of(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
435     guint i;
436 #ifdef TVBPARSE_DEBUG
437     if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_ONEOF) g_warning("cond_one_of: START");
438 #endif
439     
440     if ( offset > tt->end_offset )
441         return -1;
442
443     for(i=0; i < wanted->control.elems->len; i++) {
444         tvbparse_wanted_t* w = g_ptr_array_index(wanted->control.elems,i);
445         tvbparse_elem_t* new = NULL;
446         int curr_len;
447         
448         if ( offset + w->len > tt->end_offset )
449             return -1;
450         
451         curr_len = w->condition(tt, offset, w,  &new);
452
453         if (curr_len >= 0) {
454             *tok = new_tok(tt, wanted->id, new->offset, new->len, wanted);
455             (*tok)->sub = new;
456 #ifdef TVBPARSE_DEBUG
457             if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_ONEOF) g_warning("cond_one_of: GOT len=%i",curr_len);
458 #endif
459             return curr_len;                    
460         }
461     }
462
463     return -1;
464 }
465
466 tvbparse_wanted_t* tvbparse_set_oneof(int id,
467                                       const void* data, 
468                                       tvbparse_action_t before_cb,
469                                       tvbparse_action_t after_cb,
470                                       ...) {
471         tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
472         tvbparse_t* el;
473         va_list ap;
474         
475     w->condition = cond_one_of;
476     w->id = id;
477         w->data = data;
478         w->before = before_cb;
479         w->after = after_cb;
480         w->control.elems = g_ptr_array_new();
481         
482         va_start(ap,after_cb);
483         
484         while(( el = va_arg(ap,tvbparse_t*) )) {
485                 g_ptr_array_add(w->control.elems,el);
486         };
487         
488         va_end(ap);
489         
490         return w;
491 }
492
493 static int cond_hash(tvbparse_t* tt, int offset, const tvbparse_wanted_t* wanted, tvbparse_elem_t** tok) {
494     int key_len;
495     gchar* key = NULL;
496     tvbparse_elem_t* key_elem = NULL;
497     tvbparse_wanted_t* value_wanted = NULL;
498     int value_len;
499     tvbparse_elem_t* value_elem = NULL;
500     int tot_len;
501     
502 #ifdef TVBPARSE_DEBUG
503     if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_HASH) g_warning("cond_hash: START");
504 #endif
505     
506     tvbparse_elem_t* ret_tok;
507     if ( offset > tt->end_offset )
508         return -1;
509     
510     key_len = wanted->control.hash.key->condition(tt, offset, wanted->control.hash.key,  &key_elem);
511
512     if (key_len < 0) 
513         return -1;
514     
515     key = tvb_get_ephemeral_string(key_elem->tvb,key_elem->offset,key_elem->len);
516 #ifdef TVBPARSE_DEBUG
517     if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_HASH) g_warning("cond_hash: got key='%s'",key);
518 #endif
519     
520     if ((value_wanted = g_hash_table_lookup(wanted->control.hash.table,key))) {
521         value_len = value_wanted->condition(tt, offset + key_len, value_wanted,  &value_elem);
522     } else if (wanted->control.hash.other) {
523         value_len = wanted->control.hash.other->condition(tt, offset+key_len, wanted->control.hash.other,  &value_elem);
524         if (value_len < 0) 
525             return -1;
526     } else {
527         return -1;
528     }
529
530     tot_len = key_len + value_len;
531     
532     ret_tok = new_tok(tt, value_elem->id, offset, tot_len, wanted);
533     ret_tok->sub = key_elem;
534     ret_tok->sub->last->next = value_elem;
535     
536     *tok = ret_tok;
537 #ifdef TVBPARSE_DEBUG
538     if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_HASH) g_warning("cond_hash: GOT len=%i",tot_len);
539 #endif
540     
541     return tot_len;
542 }
543
544 tvbparse_wanted_t* tvbparse_hashed(int id,
545                                    const void* data, 
546                                    tvbparse_action_t before_cb,
547                                    tvbparse_action_t after_cb,
548                                    tvbparse_wanted_t* key,
549                                    tvbparse_wanted_t* other,
550                                    ...) {
551         tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
552     gchar* name;
553         tvbparse_wanted_t* el;
554         va_list ap;
555         
556     w->condition = cond_hash;
557     w->id = id;
558         w->data = data;
559         w->before = before_cb;
560         w->after = after_cb;
561         w->control.hash.table = g_hash_table_new(g_str_hash,g_str_equal);
562         w->control.hash.key = key;
563     w->control.hash.other = other;
564     
565         va_start(ap,other);
566         
567         while(( name = va_arg(ap,gchar*) )) {
568         el = va_arg(ap,tvbparse_wanted_t*);
569                 g_hash_table_insert(w->control.hash.table,name,el);
570         }
571         
572         va_end(ap);
573         
574         return w;
575 }
576
577 void tvbparse_hashed_add(tvbparse_wanted_t* w, ...) {
578     tvbparse_wanted_t* el;
579         va_list ap;
580     gchar* name;
581     
582     va_start(ap,w);
583         
584         while (( name = va_arg(ap,gchar*) )) {
585         el = va_arg(ap,tvbparse_wanted_t*);
586                 g_hash_table_insert(w->control.hash.table,name,el);
587         }
588         
589         va_end(ap);
590 }    
591
592 static int cond_seq(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
593     guint i;
594     int len = 0;
595     int start = offset;
596     tvbparse_elem_t* ret_tok = NULL;
597     
598     if ( offset > tt->end_offset )
599         return -1;
600 #ifdef TVBPARSE_DEBUG
601     if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SEQ) g_warning("cond_seq: START");
602 #endif
603     
604     for(i=0; i < wanted->control.elems->len; i++) {
605         tvbparse_wanted_t* w = g_ptr_array_index(wanted->control.elems,i);
606         tvbparse_elem_t* new = NULL;
607
608         if ( offset + w->len > tt->end_offset )
609             return -1;
610         
611         
612         len = w->condition(tt, offset, w, &new);
613         
614         if (len >= 0) {
615             if (ret_tok) {
616                 ret_tok->len = (new->offset - ret_tok->offset) + new->len;
617                 ret_tok->sub->last->next = new;
618                 ret_tok->sub->last = new;
619             } else {
620                 ret_tok = new_tok(tt, wanted->id, new->offset, new->len, wanted);
621                 ret_tok->sub = new;
622                 new->last = new;
623             }
624         } else {
625             return -1;
626         }
627         
628         offset += len;
629         offset += ignore(tt,offset);
630     }
631
632     *tok = ret_tok;
633     
634 #ifdef TVBPARSE_DEBUG
635     if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SEQ) g_warning("cond_seq: GOT len=%i",offset - start);
636 #endif
637     
638     return offset - start;                      
639 }
640
641
642 tvbparse_wanted_t* tvbparse_set_seq(int id,
643                                     const void* data,
644                                     tvbparse_action_t before_cb,
645                                     tvbparse_action_t after_cb,
646                                     ...) {
647         tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
648         tvbparse_wanted_t*  el = NULL;
649         va_list ap;
650         
651     w->condition = cond_seq;
652     w->id = id;
653         w->data = data;
654         w->before = before_cb;
655         w->after = after_cb;
656         w->control.elems = g_ptr_array_new();
657         
658         va_start(ap,after_cb);
659         
660         while(( el = va_arg(ap,tvbparse_wanted_t*) )) {
661                 g_ptr_array_add(w->control.elems,el);
662         };
663         
664         va_end(ap);
665         return w;
666 }
667
668 static int cond_some(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
669     guint got_so_far = 0;
670     int start = offset;
671     tvbparse_elem_t* ret_tok = NULL;
672 #ifdef TVBPARSE_DEBUG
673     if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SOME) g_warning("cond_some: START");
674 #endif
675     
676     if ( offset > tt->end_offset )
677         return -1;
678     
679     if ( wanted->min == 0 ) {
680         ret_tok = new_tok(tt,wanted->id,tt->offset,0,wanted);
681     }
682     
683     while (got_so_far < wanted->max) {
684         tvbparse_elem_t* new = NULL;
685         int consumed;
686         
687         if ( offset > tt->end_offset )
688             return -1;
689         
690         consumed = wanted->control.subelem->condition(tt, offset, wanted->control.subelem, &new);
691         
692         if(consumed >= 0) {
693             if (ret_tok) {
694                 ret_tok->len = (new->offset - ret_tok->offset) + new->len;
695                 
696                 if (ret_tok->sub) {
697                     ret_tok->sub->last->next = new;
698                     ret_tok->sub->last = new;
699                 } else {
700                     ret_tok->sub = new;                            
701                 }
702             } else {
703                 ret_tok = new_tok(tt, wanted->id, new->offset, new->len, wanted);
704                 ret_tok->sub = new;
705             }
706         } else {
707             break;
708         }
709         
710         offset += consumed;
711         got_so_far++;
712     }
713     
714 #ifdef TVBPARSE_DEBUG
715     if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SOME) g_warning("cond_some: got num=%u",got_so_far);
716 #endif
717     
718     if(got_so_far < wanted->min) {
719         return -1;
720     }
721     
722     *tok = ret_tok;
723 #ifdef TVBPARSE_DEBUG
724     if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_SOME) g_warning("cond_some: GOT len=%i",offset - start);
725 #endif
726     return offset - start;
727 }
728
729 tvbparse_wanted_t* tvbparse_some(int id,
730                                                                  guint from,
731                                                                  guint to,
732                                                                  const void* data,
733                                                                  tvbparse_action_t before_cb,
734                                                                  tvbparse_action_t after_cb,
735                                                                  const tvbparse_wanted_t* el) {
736         
737         tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
738         
739         g_assert(from <= to);
740         
741     w->condition = cond_some;
742     w->id = id;
743         w->min = from;
744         w->max = to;
745         w->data = data;
746         w->before = before_cb;
747         w->after = after_cb;
748         w->control.subelem = el;
749         
750         return w;
751 }
752
753
754 static int cond_until(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
755     tvbparse_elem_t* new = NULL;
756     int len = 0;
757     int target_offset = offset;
758 #ifdef TVBPARSE_DEBUG
759     if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) g_warning("cond_until: START");
760 #endif
761     
762     if ( offset + wanted->control.until.subelem->len > tt->end_offset )
763         return -1;
764     
765     do {
766         len = wanted->control.until.subelem->condition(tt, target_offset++, wanted->control.until.subelem,  &new);
767     } while(len < 0  && target_offset+1 < tt->end_offset);
768     
769     if (len >= 0) {
770         
771         new->id = wanted->id;
772         new->next = NULL;
773         new->last = NULL;
774         new->wanted = wanted;
775         new->offset = offset;
776         
777         (*tok) = new;        
778         
779         switch (wanted->control.until.mode) {
780             case TP_UNTIL_INCLUDE:
781                 new->len = target_offset - offset - 1 + len;
782 #ifdef TVBPARSE_DEBUG
783                 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) g_warning("cond_until: GOT len=%i",target_offset - offset -1 + len);
784 #endif
785                 return target_offset - offset -1 + len;
786             case TP_UNTIL_SPEND:
787                 new->len = target_offset - offset - 1;
788 #ifdef TVBPARSE_DEBUG
789                 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) g_warning("cond_until: GOT len=%i",target_offset - offset -1 + len);
790 #endif
791                 return target_offset - offset - 1 + len;
792             case TP_UNTIL_LEAVE:
793                 new->len = target_offset - offset - 1;
794 #ifdef TVBPARSE_DEBUG
795                 if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_UNTIL) g_warning("cond_until: GOT len=%i",target_offset - offset -1);
796 #endif                
797                 return target_offset - offset -1;
798             default:
799                 DISSECTOR_ASSERT_NOT_REACHED();
800                 return -1;
801         }
802         
803     } else {
804         return -1;
805     }
806 }
807
808 tvbparse_wanted_t* tvbparse_until(int id,
809                                   const void* data,
810                                   tvbparse_action_t before_cb,
811                                   tvbparse_action_t after_cb,
812                                   const tvbparse_wanted_t* el,
813                                   until_mode_t until_mode) {
814         tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
815         
816     w->condition = cond_until;
817     w->control.until.mode = until_mode;
818         w->control.until.subelem = el;
819     w->id = id;
820         w->data = data;
821         w->before = before_cb;
822         w->after = after_cb;
823         
824         return w;
825 }
826
827 static int cond_handle(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
828     tvbparse_wanted_t* w = *(wanted->control.handle);
829     int len = w->condition(tt, offset, w,  tok);
830
831     if (len >= 0) {
832         return len;
833     } else {
834         return -1;
835     }
836 }
837
838 tvbparse_wanted_t* tvbparse_handle(tvbparse_wanted_t** handle) {
839         tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
840         
841     w->condition = cond_handle;
842         w->control.handle = handle;
843         
844         return w;
845 }
846
847 static int cond_end(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted _U_, tvbparse_elem_t** tok) {
848     if (offset == tt->end_offset) {
849         *tok = new_tok(tt,wanted->id,offset,0,wanted);
850         return 0;
851     } else {
852         return -1;
853     }
854 }
855
856 tvbparse_wanted_t* tvbparse_end_of_buffer(int id,
857                                const void* data,
858                                tvbparse_action_t before_cb,
859                                tvbparse_action_t after_cb) {
860     tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
861         
862     w->id = id;
863     w->condition = cond_end;
864         w->after = after_cb;
865     w->before = before_cb;
866     w->data = data;
867         return w;
868     
869 }
870
871
872 #if 0
873 /* these extract binary values */
874
875 static int cond_ft(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted, tvbparse_elem_t** tok) {
876     guint len = 0;
877
878     if ( offset + wanted->len > tt->end_offset )
879         return -1;
880
881     if (wanted->len) {
882         return wanted->len;
883     } else if (wanted->control.ftenum == FT_STRINGZ) {
884             if (( len = tvb_find_guint8(tt->tvb,offset,tt->end_offset - offset,'\0') >= 0 )) {
885                 *tok = new_tok(tt,wanted->id,offset,len,wanted);
886                 return len;
887             } else {
888                 return -1;
889             }
890     } else {
891         return -2;
892     }
893 }
894
895 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 };
896
897 tvbparse_wanted_t* tvbparse_ft(int id,
898                                const void* data,
899                                tvbparse_action_t before_cb,
900                                tvbparse_action_t after_cb,
901                                enum ftenum ftenum) {
902     gint len = ft_lens[ftenum];
903     
904     if (len >= 0) {
905         tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
906         
907         w->id = id;
908         w->condition = cond_ft;
909         w->len = len;
910         w->control.ftenum = ftenum;
911         w->after = after_cb;
912         w->before = before_cb;
913         w->data = data;
914         
915         return w;
916     } else {
917         g_assert(! "unsupported ftenum" );
918         return NULL;
919     }
920 }    
921
922 static int cond_ft_comp(tvbparse_t* tt, int offset, const tvbparse_wanted_t * wanted _U_, tvbparse_elem_t** tok) {
923     void* l = wanted->control.number.extract(tt->tvb,offset);
924     const void* r = &(wanted->control.number.value);
925     
926     if ( offset + wanted->len > tt->end_offset )
927         return -1;
928
929     if ( wanted->control.number.comp(&l,&r) ) {
930         *tok = new_tok(tt,wanted->id,offset,wanted->len,wanted);
931         return wanted->len;
932     } else {
933         return -1;
934     }
935 }
936
937 static gboolean comp_gt_i(void* lp, const void* rp) { return ( *((gint64*)lp) > *((gint64*)rp) ); }
938 static gboolean comp_ge_i(void* lp, const void* rp) { return ( *((gint64*)lp) >= *((gint64*)rp) ); }
939 static gboolean comp_eq_i(void* lp, const void* rp) { return ( *((gint64*)lp) == *((gint64*)rp) ); }
940 static gboolean comp_ne_i(void* lp, const void* rp) { return ( *((gint64*)lp) != *((gint64*)rp) ); }
941 static gboolean comp_le_i(void* lp, const void* rp) { return ( *((gint64*)lp) <= *((gint64*)rp) ); }
942 static gboolean comp_lt_i(void* lp, const void* rp) { return ( *((gint64*)lp) < *((gint64*)rp) ); }
943
944 static gboolean comp_gt_u(void* lp, const void* rp) { return ( *((guint64*)lp) > *((guint64*)rp) ); }
945 static gboolean comp_ge_u(void* lp, const void* rp) { return ( *((guint64*)lp) >= *((guint64*)rp) ); }
946 static gboolean comp_eq_u(void* lp, const void* rp) { return ( *((guint64*)lp) == *((guint64*)rp) ); }
947 static gboolean comp_ne_u(void* lp, const void* rp) { return ( *((guint64*)lp) != *((guint64*)rp) ); }
948 static gboolean comp_le_u(void* lp, const void* rp) { return ( *((guint64*)lp) <= *((guint64*)rp) ); }
949 static gboolean comp_lt_u(void* lp, const void* rp) { return ( *((guint64*)lp) < *((guint64*)rp) ); }
950
951 static gboolean comp_gt_f(void* lp, const void* rp) { return ( *((gdouble*)lp) > *((gdouble*)rp) ); }
952 static gboolean comp_ge_f(void* lp, const void* rp) { return ( *((gdouble*)lp) >= *((gdouble*)rp) ); }
953 static gboolean comp_eq_f(void* lp, const void* rp) { return ( *((gdouble*)lp) == *((gdouble*)rp) ); }
954 static gboolean comp_ne_f(void* lp, const void* rp) { return ( *((gdouble*)lp) != *((gdouble*)rp) ); }
955 static gboolean comp_le_f(void* lp, const void* rp) { return ( *((gdouble*)lp) <= *((gdouble*)rp) ); }
956 static gboolean comp_lt_f(void* lp, const void* rp) { return ( *((gdouble*)lp) < *((gdouble*)rp) ); }
957
958 static void* extract_u8(tvbuff_t* tvb, guint offset) {
959     guint64* p = ep_new(guint64);
960     *p = tvb_get_guint8(tvb,offset);
961     return p;
962 }
963
964 static void* extract_uns(tvbuff_t* tvb, guint offset) {
965     guint64* p = ep_new(guint64);
966     *p = tvb_get_ntohs(tvb,offset);
967     return p;
968 }
969
970 static void* extract_un24(tvbuff_t* tvb, guint offset) {
971     guint64* p = ep_new(guint64);
972     *p = tvb_get_ntoh24(tvb,offset);
973     return p;
974 }
975
976 static void* extract_unl(tvbuff_t* tvb, guint offset) {
977     guint64* p = ep_new(guint64);
978     *p = tvb_get_ntohl(tvb,offset);
979     return p;
980 }
981
982 static void* extract_un64(tvbuff_t* tvb, guint offset) {
983     guint64* p = ep_new(guint64);
984     *p = tvb_get_ntoh64(tvb,offset);
985     return p;
986 }
987
988 static void* extract_ules(tvbuff_t* tvb, guint offset) {
989     guint64* p = ep_new(guint64);
990     *p = tvb_get_letohs(tvb,offset);
991     return p;
992 }
993
994 static void* extract_ule24(tvbuff_t* tvb, guint offset) {
995     guint64* p = ep_new(guint64);
996     *p = tvb_get_letoh24(tvb,offset);
997     return p;
998 }
999
1000 static void* extract_ulel(tvbuff_t* tvb, guint offset) {
1001     guint64* p = ep_new(guint64);
1002     *p = tvb_get_letohl(tvb,offset);
1003     return p;
1004 }
1005
1006 static void* extract_ule64(tvbuff_t* tvb, guint offset) {
1007     guint64* p = ep_new(guint64);
1008     *p = tvb_get_letoh64(tvb,offset);
1009     return p;
1010 }
1011
1012 static void* extract_ins(tvbuff_t* tvb, guint offset) {
1013     guint64* p = ep_new(guint64);
1014     *p = tvb_get_ntohs(tvb,offset);
1015     return p;
1016 }
1017
1018 static void* extract_in24(tvbuff_t* tvb, guint offset) {
1019     guint64* p = ep_new(guint64);
1020     *p = tvb_get_ntoh24(tvb,offset);
1021     return p;
1022 }
1023
1024 static void* extract_inl(tvbuff_t* tvb, guint offset) {
1025     guint64* p = ep_new(guint64);
1026     *p = tvb_get_ntohl(tvb,offset);
1027     return p;
1028 }
1029
1030 static void* extract_in64(tvbuff_t* tvb, guint offset) {
1031     guint64* p = ep_new(guint64);
1032     *p = tvb_get_ntoh64(tvb,offset);
1033     return p;
1034 }
1035
1036 static void* extract_iles(tvbuff_t* tvb, guint offset) {
1037     guint64* p = ep_new(guint64);
1038     *p = tvb_get_letohs(tvb,offset);
1039     return p;
1040 }
1041
1042 static void* extract_ile24(tvbuff_t* tvb, guint offset) {
1043     guint64* p = ep_new(guint64);
1044     *p = tvb_get_letoh24(tvb,offset);
1045     return p;
1046 }
1047
1048 static void* extract_ilel(tvbuff_t* tvb, guint offset) {
1049     guint64* p = ep_new(guint64);
1050     *p = tvb_get_letohl(tvb,offset);
1051     return p;
1052 }
1053
1054 static void* extract_ile64(tvbuff_t* tvb, guint offset) {
1055     guint64* p = ep_new(guint64);
1056     *p = tvb_get_letoh64(tvb,offset);
1057     return p;
1058 }
1059
1060 static void* extract_inf(tvbuff_t* tvb, guint offset) {
1061     gdouble* p = ep_new(gdouble);
1062     *p = tvb_get_ntohieee_float(tvb,offset);
1063     return p;
1064 }
1065
1066 static void* extract_ind(tvbuff_t* tvb, guint offset) {
1067     gdouble* p = ep_new(gdouble);
1068     *p = tvb_get_ntohieee_double(tvb,offset);
1069     return p;
1070 }
1071
1072 static void* extract_ilef(tvbuff_t* tvb, guint offset) {
1073     gdouble* p = ep_new(gdouble);
1074     *p = tvb_get_letohieee_float(tvb,offset);
1075     return p;
1076 }
1077
1078 static void* extract_iled(tvbuff_t* tvb, guint offset) {
1079     gdouble* p = ep_new(gdouble);
1080     *p = tvb_get_letohieee_double(tvb,offset);
1081     return p;
1082 }
1083
1084
1085
1086 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};
1087 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};
1088 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};
1089
1090 static gboolean (**comps[])(void*, const void*) = {comps_u,comps_i,comps_f};
1091
1092 static void* (*extract_n[])(tvbuff_t* tvb, guint offset)  =  {  NULL, NULL, NULL, extract_u8, extract_uns, extract_un24, extract_unl, extract_un64, extract_u8, extract_ins, extract_in24, extract_inl, extract_in64, extract_inf, extract_ind, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,NULL, NULL };
1093 static void* (*extract_le[])(tvbuff_t* tvb, guint offset)  =  { NULL, NULL, NULL, extract_u8, extract_ules, extract_ule24, extract_ulel, extract_ule64, extract_u8, extract_iles, extract_ile24, extract_ilel, extract_ile64, extract_ilef, extract_iled, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,NULL, NULL };
1094
1095 static void* (**extracts[])(tvbuff_t* tvb, guint offset) = { extract_n, extract_le};
1096
1097
1098 tvbparse_wanted_t* tvbparse_ft_numcmp(int id,
1099                                      const void* data,
1100                                      tvbparse_action_t before_cb,
1101                                      tvbparse_action_t after_cb,
1102                                      enum ftenum ftenum,
1103                                      int little_endian,
1104                                      enum ft_cmp_op ft_cmp_op,
1105                                      ... ) {
1106         tvbparse_wanted_t* w = g_malloc0(sizeof(tvbparse_wanted_t));
1107     va_list ap;
1108     
1109     va_start(ap,ft_cmp_op);
1110     
1111     switch (ftenum) {
1112         case FT_UINT8:
1113         case FT_UINT16:
1114         case FT_UINT24:
1115         case FT_UINT32:
1116             w->control.number.comp = comps[0][ft_cmp_op];
1117             w->control.number.value.u = va_arg(ap,guint32);
1118             break;
1119         case FT_UINT64:
1120             w->control.number.comp = comps[0][ft_cmp_op];
1121             w->control.number.value.u = va_arg(ap,guint64);
1122             break;
1123         case FT_INT8:
1124         case FT_INT16:
1125         case FT_INT24:
1126         case FT_INT32:
1127             w->control.number.comp = comps[1][ft_cmp_op];
1128             w->control.number.value.i = va_arg(ap,gint32);
1129             break;            
1130         case FT_INT64:
1131             w->control.number.comp = comps[1][ft_cmp_op];
1132             w->control.number.value.i = va_arg(ap,gint64);
1133             break;            
1134         case FT_FLOAT:
1135         case FT_DOUBLE:
1136             w->control.number.comp = comps[1][ft_cmp_op];
1137             w->control.number.value.i = va_arg(ap,gdouble);
1138             break;
1139         default:
1140             g_assert(! "comparision unsupported");
1141     }
1142
1143     w->control.number.extract = extracts[little_endian][ftenum];
1144
1145     g_assert(w->control.number.extract && "extraction unsupported");
1146     
1147     w->id = id;
1148     w->condition = cond_ft_comp;
1149     w->after = after_cb;
1150     w->before = before_cb;
1151     w->data = data;
1152
1153     return w;
1154 }
1155
1156 #endif
1157
1158
1159 tvbparse_wanted_t* tvbparse_quoted(int id,
1160                                                                    const void* data,
1161                                                                    tvbparse_action_t before_cb,
1162                                                                    tvbparse_action_t after_cb,
1163                                                                    char quote,
1164                                                                    char esc) {
1165         
1166         gchar* esc_quot = g_strdup_printf("%c%c",esc,quote);
1167         gchar* quot = g_strdup_printf("%c",quote);
1168         tvbparse_wanted_t* want_quot = tvbparse_char(-1,quot,NULL,NULL,NULL);
1169         
1170         return tvbparse_set_oneof(id, data, before_cb, after_cb,
1171                               tvbparse_set_seq(-1, NULL, NULL, NULL,
1172                                                want_quot,
1173                                                tvbparse_set_seq(-1,NULL,NULL,NULL,
1174                                                                 tvbparse_set_oneof(-1, NULL, NULL, NULL,
1175                                                                                    tvbparse_string(-1,esc_quot,NULL,NULL,NULL),
1176                                                                                    tvbparse_not_chars(-1,0,0,quot,NULL,NULL,NULL),
1177                                                                                    NULL),
1178                                                                 NULL),
1179                                                want_quot,
1180                                                NULL),
1181                               tvbparse_set_seq(-1, NULL, NULL, NULL,
1182                                                want_quot,
1183                                                want_quot,
1184                                                NULL),
1185                               NULL);
1186 }
1187
1188 void tvbparse_shrink_token_cb(void* tvbparse_data _U_,
1189                                                           const void* wanted_data _U_,
1190                                                           tvbparse_elem_t* tok) {
1191         tok->offset += 1;
1192         tok->len -= 2;
1193 }
1194
1195 tvbparse_t* tvbparse_init(tvbuff_t* tvb,
1196                                                   int offset,
1197                                                   int len,
1198                                                   void* data,
1199                                                   const tvbparse_wanted_t* ignore) {
1200         tvbparse_t* tt = ep_alloc(sizeof(tvbparse_t));
1201         
1202 #ifdef TVBPARSE_DEBUG
1203     if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_TT) g_warning("tvbparse_init: offset=%i len=%i",offset,len);
1204 #endif                
1205     
1206     
1207         tt->tvb = tvb;
1208         tt->offset = offset;
1209         len = (len == -1) ? (int) tvb_length(tvb) : len;
1210     tt->end_offset = offset + len;
1211         tt->data = data;
1212         tt->ignore = ignore;
1213         return tt;
1214 }
1215
1216 gboolean tvbparse_reset(tvbparse_t* tt,
1217                                                 int offset,
1218                                                 int len) {
1219         
1220 #ifdef TVBPARSE_DEBUG
1221     if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_TT) g_warning("tvbparse_init: offset=%i len=%i",offset,len);
1222 #endif                
1223     
1224         len = (len == -1) ? (int) tvb_length(tt->tvb) : len;
1225         
1226         if( tvb_length_remaining(tt->tvb, offset) >= len) {
1227                 tt->offset = offset;
1228                 tt->end_offset = offset + len;
1229                 return TRUE;
1230         } else {
1231                 return FALSE;
1232         }
1233 }
1234
1235 guint tvbparse_curr_offset(tvbparse_t* tt) {
1236     return tt->offset;
1237 }
1238
1239 static void execute_callbacks(tvbparse_t* tt, tvbparse_elem_t* curr) {
1240     ep_stack_t stack = ep_stack_new();
1241     
1242     while (curr) {
1243         if(curr->wanted->before) {
1244 #ifdef TVBPARSE_DEBUG
1245             if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CB) g_warning("execute_callbacks: BEFORE: id=%i offset=%i len=%i",curr->id,curr->offset,curr->len);
1246 #endif                            
1247             curr->wanted->before(tt->data, curr->wanted->data, curr);
1248         }
1249         
1250         if(curr->sub) {
1251             ep_stack_push(stack,curr);
1252             curr = curr->sub;
1253             continue;
1254         } else {
1255 #ifdef TVBPARSE_DEBUG
1256             if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CB) g_warning("execute_callbacks: AFTER: id=%i offset=%i len=%i",curr->id,curr->offset,curr->len);
1257 #endif                            
1258             if(curr->wanted->after) curr->wanted->after(tt->data, curr->wanted->data, curr);
1259         }
1260         
1261         curr = curr->next;
1262         
1263         while( !curr && ep_stack_peek(stack) ) {
1264             curr = ep_stack_pop(stack);
1265 #ifdef TVBPARSE_DEBUG
1266             if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_CB) g_warning("execute_callbacks: AFTER: id=%i offset=%i len=%i",curr->id,curr->offset,curr->len);
1267 #endif                            
1268             if( curr->wanted->after ) curr->wanted->after(tt->data, curr->wanted->data, curr);
1269             curr = curr->next;
1270         }
1271     }
1272
1273 }
1274
1275 gboolean tvbparse_peek(tvbparse_t* tt,
1276                               const tvbparse_wanted_t* wanted) {
1277         tvbparse_elem_t* tok = NULL;
1278         int consumed;
1279     int offset = tt->offset;
1280     
1281 #ifdef TVBPARSE_DEBUG
1282     if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) g_warning("tvbparse_peek: ENTER offset=%i",offset);
1283 #endif                            
1284     
1285     offset += ignore(tt,offset);
1286     
1287 #ifdef TVBPARSE_DEBUG
1288     if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) g_warning("tvbparse_peek: after ignore offset=%i",offset);
1289 #endif                            
1290     
1291     consumed = wanted->condition(tt,offset,wanted,&tok);
1292     
1293     if (consumed >= 0) {
1294 #ifdef TVBPARSE_DEBUG
1295         if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) g_warning("tvbparse_peek: GOT len=%i",consumed);
1296 #endif                            
1297         return TRUE;
1298     } else {
1299 #ifdef TVBPARSE_DEBUG
1300         if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_PEEK) g_warning("tvbparse_peek: NOT GOT");
1301 #endif                            
1302         return FALSE;
1303     }
1304     
1305 }
1306
1307 tvbparse_elem_t* tvbparse_get(tvbparse_t* tt,
1308                               const tvbparse_wanted_t* wanted) {
1309         tvbparse_elem_t* tok = NULL;
1310         int consumed;
1311     int offset = tt->offset;
1312     
1313 #ifdef TVBPARSE_DEBUG
1314     if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) g_warning("tvbparse_get: ENTER offset=%i",offset);
1315 #endif                            
1316     
1317     offset += ignore(tt,offset);
1318
1319 #ifdef TVBPARSE_DEBUG
1320     if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) g_warning("tvbparse_get: after ignore offset=%i",offset);
1321 #endif                            
1322     
1323     consumed = wanted->condition(tt,offset,wanted,&tok);
1324
1325     if (consumed >= 0) {
1326 #ifdef TVBPARSE_DEBUG
1327         if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) g_warning("tvbparse_get: GOT len=%i",consumed);
1328 #endif                            
1329         execute_callbacks(tt,tok);
1330         tt->offset = offset + consumed;
1331 #ifdef TVBPARSE_DEBUG
1332         if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_GET) g_warning("tvbparse_get: DONE offset=%i", tt->offset);
1333 #endif                            
1334         return tok; 
1335     } else {
1336         return NULL;
1337     }
1338             
1339 }
1340
1341
1342 tvbparse_elem_t* tvbparse_find(tvbparse_t* tt, const tvbparse_wanted_t* wanted) {
1343         tvbparse_elem_t* tok = NULL;
1344     int len = 0;
1345     int offset = tt->offset;
1346     int target_offset = offset -1;
1347
1348 #ifdef TVBPARSE_DEBUG
1349     if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) g_warning("tvbparse_get: ENTER offset=%i", tt->offset);
1350 #endif                            
1351     
1352     do {
1353         len = wanted->condition(tt, target_offset+1, wanted,  &tok);
1354     } while(len < 0  && ++target_offset < tt->end_offset);
1355
1356     if (len >= 0) {
1357 #ifdef TVBPARSE_DEBUG
1358         if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) g_warning("tvbparse_get: FOUND offset=%i len=%i", target_offset,len);
1359 #endif                            
1360                 execute_callbacks(tt,tok);
1361         tt->offset = target_offset + len;
1362
1363 #ifdef TVBPARSE_DEBUG
1364         if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) g_warning("tvbparse_get: DONE offset=%i", tt->offset);
1365 #endif                            
1366         return tok;
1367     } else {
1368 #ifdef TVBPARSE_DEBUG
1369         if (TVBPARSE_DEBUG & TVBPARSE_DEBUG_FIND) g_warning("tvbparse_get: NOT FOUND");
1370 #endif                            
1371         return NULL;
1372     }
1373 }
1374
1375 struct _elem_tree_stack_frame {
1376     proto_tree* tree;
1377     tvbparse_elem_t* elem;
1378 };
1379
1380 void tvbparse_tree_add_elem(proto_tree* tree, tvbparse_elem_t* curr) {
1381     ep_stack_t stack = ep_stack_new();
1382     struct _elem_tree_stack_frame* frame = ep_alloc(sizeof(struct _elem_tree_stack_frame));
1383     proto_item* pi;
1384     frame->tree = tree;
1385     frame->elem = curr;
1386     
1387     while (curr) {
1388         pi = proto_tree_add_text(frame->tree,curr->tvb,curr->offset,curr->len,"%s",tvb_format_text(curr->tvb,curr->offset,curr->len));
1389         
1390         if(curr->sub) {
1391             frame->elem = curr;
1392             ep_stack_push(stack,frame);
1393             frame = ep_alloc(sizeof(struct _elem_tree_stack_frame));
1394             frame->tree = proto_item_add_subtree(pi,0);
1395             curr = curr->sub;
1396             continue;
1397         }
1398         
1399         curr = curr->next;
1400         
1401         while( !curr && ep_stack_peek(stack) ) {
1402             frame = ep_stack_pop(stack);
1403             curr = frame->elem->next;
1404         }
1405         
1406     }
1407 }
1408