f6950e75fa5b74e16c8f8687306e22d226c877d1
[obnox/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 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@ethereal.com>
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 typedef enum _tvbparse_wanted_type_t {
40         TVBPARSE_WANTED_NONE, /* currently unused */
41         
42         /* simple tokens */
43         TVBPARSE_WANTED_SIMPLE_CHAR, /* just one matching char */
44         TVBPARSE_WANTED_SIMPLE_CHARS, /* a sequence of matching chars */
45         TVBPARSE_WANTED_SIMPLE_NOT_CHAR, /* one non matching char */ 
46         TVBPARSE_WANTED_SIMPLE_NOT_CHARS, /* a sequence of non matching chars */
47         TVBPARSE_WANTED_SIMPLE_STRING, /* a string */
48         TVBPARSE_WANTED_SIMPLE_CASESTRING, /* a caseless string */
49         TVBPARSE_WANTED_UNTIL, /* all the characters until the first matching token */
50         
51         /* composed tokens */
52         TVBPARSE_WANTED_SET_ONEOF, /* one of the given types */
53         TVBPARSE_WANTED_SET_SEQ, /* an exact sequence of tokens of the given types */
54         TVBPARSE_WANTED_CARDINALITY, /* one or more tokens of the given type */ 
55     TVBPARSE_WANTED_HANDLE,  /* a handle to another one */
56     
57 } tvbparse_type_t;
58
59 struct _tvbparse_t {
60         tvbuff_t* tvb;
61         int offset;
62         int max_len;
63         void* data;
64         const tvbparse_wanted_t* ignore;
65         guint depth;
66 };
67
68 struct _tvbparse_wanted_t {
69         int id;
70         tvbparse_type_t type;
71         
72         union {
73         const gchar* str;
74         guint val;
75         struct _tvbparse_wanted_t** handle;
76     } control;
77     
78         int len;
79         
80         guint min;
81         guint max;
82         
83         const void* data;
84         tvbparse_action_t before;
85         tvbparse_action_t after;
86         
87         GPtrArray* elems;
88 };
89
90
91 tvbparse_wanted_t* tvbparse_char(int id,
92                                                   const gchar* chr,
93                                                   const void* data,
94                                                   tvbparse_action_t before_cb,
95                                                   tvbparse_action_t after_cb) {
96         tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
97         
98         w->id = id;
99         w->type = TVBPARSE_WANTED_SIMPLE_CHAR;
100         w->control.str = chr;
101         w->len = 1;
102         w->min = 0;
103         w->max = 0;
104         w->data = data;
105         w->before = before_cb;
106         w->after = after_cb;
107         w->elems = g_ptr_array_new();
108         
109         return w;
110 }
111
112 tvbparse_wanted_t* tvbparse_chars(int id,
113                                                                   guint min_len,
114                                                                   guint max_len,
115                                                                   const gchar* chr,
116                                                                   const void* data,
117                                                                   tvbparse_action_t before_cb,
118                                                                   tvbparse_action_t after_cb) {
119         tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
120         
121         w->id = id;
122         w->type = TVBPARSE_WANTED_SIMPLE_CHARS;
123         w->control.str = chr;
124         w->len = 0;
125         w->min = min_len ? min_len : 1;
126         w->max = max_len ? max_len : G_MAXINT;
127         w->data = data;
128         w->before = before_cb;
129         w->after = after_cb;
130         w->elems = g_ptr_array_new();
131         
132         return w;
133 }
134
135 tvbparse_wanted_t* tvbparse_not_char(int id,
136                                                           const gchar* chr,
137                                                           const void* data,
138                                                           tvbparse_action_t before_cb,
139                                                           tvbparse_action_t after_cb) {
140         tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
141         
142         w->id = id;
143         w->type = TVBPARSE_WANTED_SIMPLE_NOT_CHAR;
144         w->control.str = chr;
145         w->len = 0;
146         w->min = 0;
147         w->max = 0;
148         w->data = data;
149         w->before = before_cb;
150         w->after = after_cb;
151         w->elems = g_ptr_array_new();
152         
153         return w;
154 }
155
156 tvbparse_wanted_t* tvbparse_not_chars(int id,
157                                                                           guint min_len,
158                                                                           guint max_len,
159                                                                           const gchar* chr,
160                                                                           const void* data,
161                                                                           tvbparse_action_t before_cb,
162                                                                           tvbparse_action_t after_cb){
163         tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
164         
165         w->id = id;
166         w->type = TVBPARSE_WANTED_SIMPLE_NOT_CHARS;
167         w->control.str = chr;
168         w->len = 0;
169         w->min = min_len ? min_len : 1;
170         w->max = max_len ? max_len : G_MAXINT;
171         w->data = data;
172         w->before = before_cb;
173         w->after = after_cb;
174         w->elems = g_ptr_array_new();
175         
176         return w;
177 }
178
179
180 tvbparse_wanted_t* tvbparse_string(int id,
181                                                                    const gchar* str,
182                                                                    const void* data,
183                                                                    tvbparse_action_t before_cb,
184                                                                    tvbparse_action_t after_cb) {
185         tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
186         
187         w->id = id;
188         w->type = TVBPARSE_WANTED_SIMPLE_STRING;
189         w->control.str = str;
190         w->len = strlen(str);
191         w->min = 0;
192         w->max = 0;
193         w->data = data;
194         w->before = before_cb;
195         w->after = after_cb;
196         w->elems = g_ptr_array_new();
197         
198         return w;
199 }
200
201 tvbparse_wanted_t* tvbparse_casestring(int id,
202                                                                    const gchar* str,
203                                                                    const void* data,
204                                                                    tvbparse_action_t before_cb,
205                                                                    tvbparse_action_t after_cb) {
206         tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
207         
208         w->id = id;
209         w->type = TVBPARSE_WANTED_SIMPLE_CASESTRING;
210         w->control.str = str;
211         w->len = strlen(str);
212         w->min = 0;
213         w->max = 0;
214         w->data = data;
215         w->before = before_cb;
216         w->after = after_cb;
217         w->elems = g_ptr_array_new();
218         
219         return w;
220 }
221
222
223 tvbparse_wanted_t* tvbparse_set_oneof(int id,
224                                                            const void* data, 
225                                                            tvbparse_action_t before_cb,
226                                                            tvbparse_action_t after_cb,
227                                                            ...) {
228         tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
229         tvbparse_t* el;
230         va_list ap;
231         
232         w->id = id;
233         w->type = TVBPARSE_WANTED_SET_ONEOF;
234         w->control.val = 0;
235         w->len = 0;
236         w->min = 0;
237         w->max = 0;
238         w->data = data;
239         w->before = before_cb;
240         w->after = after_cb;
241         w->elems = g_ptr_array_new();
242         
243         va_start(ap,after_cb);
244         
245         while(( el = va_arg(ap,tvbparse_t*) )) {
246                 g_ptr_array_add(w->elems,el);
247         };
248         
249         va_end(ap);
250         
251         return w;
252 }
253
254 tvbparse_wanted_t* tvbparse_set_seq(int id,
255                                                          const void* data,
256                                                          tvbparse_action_t before_cb,
257                                                          tvbparse_action_t after_cb,
258                                                          ...) {
259         tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
260         tvbparse_wanted_t*  el = NULL;
261         va_list ap;
262         
263         w->id = id;
264         w->type = TVBPARSE_WANTED_SET_SEQ;
265         w->control.val = 0;
266         w->len = 0;
267         w->min = 0;
268         w->max = 0;
269         w->data = data;
270         w->before = before_cb;
271         w->after = after_cb;
272         w->elems = g_ptr_array_new();
273         
274         va_start(ap,after_cb);
275         
276         while(( el = va_arg(ap,tvbparse_wanted_t*) )) {
277                 g_ptr_array_add(w->elems,el);
278         };
279         
280         va_end(ap);
281         return w;
282 }
283
284
285 tvbparse_wanted_t* tvbparse_some(int id,
286                                                                  guint from,
287                                                                  guint to,
288                                                                  const void* data,
289                                                                  tvbparse_action_t before_cb,
290                                                                  tvbparse_action_t after_cb,
291                                                                  const tvbparse_wanted_t* el) {
292         
293         tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
294         
295         g_assert(from <= to);
296         
297         w->id = id;
298         w->type = TVBPARSE_WANTED_CARDINALITY;
299         w->control.val = 0;
300         w->len = 0;
301         w->min = from;
302         w->max = to;
303         w->data = data;
304         w->before = before_cb;
305         w->after = after_cb;
306         w->elems = g_ptr_array_new();
307         
308         g_ptr_array_add(w->elems,(gpointer)el);
309         
310         return w;
311 }
312
313 tvbparse_wanted_t* tvbparse_until(int id,
314                                                    const void* data,
315                                                    tvbparse_action_t before_cb,
316                                                    tvbparse_action_t after_cb,
317                                                    const tvbparse_wanted_t* el,
318                                                    int op_mode) {
319         tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
320         
321         w->id = id;
322         w->type = TVBPARSE_WANTED_UNTIL;
323         
324         w->control.val = op_mode;
325         
326         w->len = 0;
327         w->min = 0;
328         w->max = 0;
329         w->data = data;
330         w->before = before_cb;
331         w->after = after_cb;
332         w->elems = g_ptr_array_new();
333         
334         g_ptr_array_add(w->elems,(gpointer)el);
335         
336         return w;
337 }
338
339 tvbparse_wanted_t* tvbparse_handle(tvbparse_wanted_t** handle) {
340         tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
341         
342         w->id = 0;
343         w->type = TVBPARSE_WANTED_HANDLE;
344         
345         w->control.handle = handle;
346         
347         w->len = 0;
348         w->min = 0;
349         w->max = 0;
350         w->data = NULL;
351         w->before = NULL;
352         w->after = NULL;
353         w->elems = NULL;
354         
355         return w;
356 }
357
358
359 tvbparse_wanted_t* tvbparse_quoted(int id,
360                                                                    const void* data,
361                                                                    tvbparse_action_t before_cb,
362                                                                    tvbparse_action_t after_cb,
363                                                                    char quote,
364                                                                    char esc) {
365         
366         gchar* esc_quot = g_strdup_printf("%c%c",esc,quote);
367         gchar* quot = g_strdup_printf("%c",quote);
368         tvbparse_wanted_t* want_quot = tvbparse_char(-1,quot,NULL,NULL,NULL);
369         
370         return tvbparse_set_oneof(id, data, before_cb, after_cb,
371                                                           tvbparse_set_seq(-1, NULL, NULL, NULL,
372                                                                                            want_quot,
373                                                                                            tvbparse_set_seq(-1,NULL,NULL,NULL,
374                                                                                                                                 tvbparse_set_oneof(-1, NULL, NULL, NULL,
375                                                                                                                                                                    tvbparse_string(-1,esc_quot,NULL,NULL,NULL),
376                                                                                                                                                                    tvbparse_not_chars(-1,0,0,quot,NULL,NULL,NULL),
377                                                                                                                                                                    NULL),
378                                                                                                                                 NULL),
379                                                                                            want_quot,
380                                                                                            NULL),
381                                                           tvbparse_set_seq(-1, NULL, NULL, NULL,
382                                                                                            want_quot,
383                                                                                            want_quot,
384                                                                                            NULL),                                                                                                               
385                                                           NULL);
386         
387 }
388
389 void tvbparse_shrink_token_cb(void* tvbparse_data _U_,
390                                                           const void* wanted_data _U_,
391                                                           tvbparse_elem_t* tok) {
392         tok->offset += 1;
393         tok->len -= 2;
394 }
395
396 tvbparse_t* tvbparse_init(tvbuff_t* tvb,
397                                                   int offset,
398                                                   int len,
399                                                   void* data,
400                                                   const tvbparse_wanted_t* ignore) {
401         tvbparse_t* tt = ep_alloc(sizeof(tvbparse_t));
402         
403         tt->tvb = tvb;
404         tt->offset = offset;
405         tt->max_len = (len == -1) ? (int) tvb_length(tvb) : len;
406         tt->data = data;
407         tt->ignore = ignore;
408         tt->depth = 0;
409         return tt;
410 }
411
412 gboolean tvbparse_reset(tvbparse_t* tt,
413                                                 int offset,
414                                                 int len) {
415         
416         len = (len == -1) ? (int) tvb_length(tt->tvb) : len;
417         
418         if( tvb_length_remaining(tt->tvb, offset) >= len) {
419                 tt->offset = offset;
420                 tt->max_len = len;
421                 tt->depth = 0;
422                 return TRUE;
423         } else {
424                 tt->depth = 0;
425                 return FALSE;
426         }
427 }
428
429 static tvbparse_elem_t* new_tok(tvbparse_t* tt,
430                                                            int id,
431                                                            int offset,
432                                                            int len,
433                                                            const tvbparse_wanted_t* wanted) {
434         tvbparse_elem_t* tok = ep_alloc(sizeof(tvbparse_elem_t));
435         
436         tok->tvb = tt->tvb;
437         tok->id = id;
438         tok->offset = offset;
439         tok->len = len;
440         tok->data = NULL;
441         tok->sub = NULL;
442         tok->next = NULL;
443         tok->wanted = wanted;
444         tok->last = tok;
445         
446         return tok;
447 }
448
449 guint tvbparse_curr_offset(tvbparse_t* tt) {
450     return tt->offset;
451 }
452 guint tvbparse_len_left(tvbparse_t* tt) {
453     return tt->max_len;
454 }
455
456 tvbparse_elem_t* tvbparse_get(tvbparse_t* tt,
457                                                                   const tvbparse_wanted_t* wanted) {
458         tvbparse_elem_t* tok = NULL;
459         int save_offset = tt->offset;
460         int save_len = tt->max_len;
461         
462         tt->depth++;
463         
464         if (tt->ignore && tt->ignore != wanted) {
465                 tvbparse_wanted_t* save = (void*)tt->ignore;
466                 tt->ignore = NULL;
467                 while ( tvbparse_get(tt,save) )  {
468                         ;
469                 }
470                 tt->ignore = save;
471         }
472         
473         switch(wanted->type) {
474                 case TVBPARSE_WANTED_NONE:
475                         goto reject;
476                 case TVBPARSE_WANTED_SIMPLE_NOT_CHAR:
477                 {
478                         gchar c, t;
479                         guint i;
480                         gboolean not_matched = FALSE;
481                         
482                         if (! tt->max_len )
483                                 goto reject;
484                         
485                         t = (gchar) tvb_get_guint8(tt->tvb,tt->offset);
486                         
487                         for(i = 0; (c = wanted->control.str[i]) && tt->max_len; i++) {
488                                 if ( c == t ) {
489                                         not_matched = TRUE;
490                                 }
491                         }
492                         
493                         if (not_matched) {
494                                 goto reject;
495                         } else {
496                                 tt->offset++;
497                                 tt->max_len--;
498                                 tok =  new_tok(tt,wanted->id,tt->offset-1,1,wanted);
499                                 goto accept;
500                         }
501                 }
502                 case TVBPARSE_WANTED_SIMPLE_CHAR:
503                 {
504                         gchar c,t;
505                         guint i;
506                         
507                         if (! tt->max_len )
508                                 goto reject;
509                         
510                         t = (gchar) tvb_get_guint8(tt->tvb,tt->offset);
511                         
512                         for(i = 0; (c = wanted->control.str[i]) && tt->max_len; i++) {
513                                 if ( c == t ) {
514                                         tt->offset++;
515                                         tt->max_len--;
516                                         tok =  new_tok(tt,wanted->id,tt->offset-1,1,wanted);
517                                         goto accept;
518                                 }
519                         }
520                         goto reject;
521                 }
522                 case TVBPARSE_WANTED_SIMPLE_NOT_CHARS:
523                 {
524                         gchar c, t;
525                         guint i;
526                         guint offset = tt->offset;
527                         guint length = 0;
528                         
529                         while( tt->max_len && length < wanted->max) {
530                                 gboolean not_matched = FALSE;
531                                 t = (gchar) tvb_get_guint8(tt->tvb,tt->offset);
532                                 i = 0;
533                                 
534                                 while ( (c = wanted->control.str[i]) && tt->max_len ) {
535                                         
536                                         if (c == t) {
537                                                 not_matched = TRUE;
538                                         }
539                                         
540                                         i++;
541                                 }
542                                 
543                                 if ( not_matched )
544                                         break;
545
546                                 length++;
547                                 tt->offset++;
548                                 tt->max_len--;
549                         };
550                         
551                         if ( length < wanted->min ) {
552                                 goto reject;
553                         } else {
554                                 tok = new_tok(tt,wanted->id,offset,length,wanted);
555                                 goto accept;                    
556                         }
557                 }
558                 case TVBPARSE_WANTED_SIMPLE_CHARS:
559                 {
560                         gchar c, t;
561                         guint i;
562                         guint offset = tt->offset;
563                         guint length = 0;
564                         
565                         while( tt->max_len && length < wanted->max) {
566                                 gboolean matched = FALSE;
567                                 t = (gchar) tvb_get_guint8(tt->tvb,tt->offset);
568                                 i = 0;
569                                 
570                                 while ( (c = wanted->control.str[i]) && tt->max_len ) {
571                                         
572                                         if (c == t) {
573                                                 matched = TRUE;
574                                                 break;
575                                         }
576                                         
577                                         i++;
578                                 }
579                                 
580                                 if (! matched )
581                                         break;
582                                 
583                                 length++;
584                                 tt->offset++;
585                                 tt->max_len--;
586                         };
587                         
588                         if (length < wanted->min) {
589                                 goto reject;
590                         } else {
591                                 tok = new_tok(tt,wanted->id,offset,length,wanted);
592                                 goto accept;                    
593                         }
594                 }
595                 case TVBPARSE_WANTED_SIMPLE_STRING:
596                 {
597                         if ( tvb_strneql(tt->tvb, tt->offset, wanted->control.str, wanted->len) == 0 ) {
598                                 int offset = tt->offset;
599                                 tt->offset += wanted->len;
600                                 tt->max_len -= wanted->len;
601                                 tok = new_tok(tt,wanted->id,offset,wanted->len,wanted);
602                                 goto accept;
603                         } else {
604                                 goto reject;
605                         }
606                 }
607                 case TVBPARSE_WANTED_SIMPLE_CASESTRING:
608                 {
609                         if ( tvb_strncaseeql(tt->tvb, tt->offset, wanted->control.str, wanted->len) == 0 ) {
610                                 int offset = tt->offset;
611                                 tt->offset += wanted->len;
612                                 tt->max_len -= wanted->len;
613                                 tok = new_tok(tt,wanted->id,offset,wanted->len,wanted);
614                                 goto accept;
615                         } else {
616                                 goto reject;
617                         }
618                 }
619                 case TVBPARSE_WANTED_SET_ONEOF:
620                 {
621                         guint i;
622                         
623                         for(i=0; i < wanted->elems->len; i++) {
624                                 tvbparse_wanted_t* w = g_ptr_array_index(wanted->elems,i);
625                                 tvbparse_elem_t* new = tvbparse_get(tt, w);
626                                 
627                                 if (new) {
628                                         tok = new_tok(tt, wanted->id, new->offset, new->len, wanted);
629                                         tok->sub = new;
630                                         goto accept;                    
631                                 }
632                         }
633                         goto reject;
634                 }
635                 case TVBPARSE_WANTED_SET_SEQ:
636                 {
637                         guint i;
638                         
639                         for(i=0; i < wanted->elems->len; i++) {
640                                 tvbparse_wanted_t* w = g_ptr_array_index(wanted->elems,i);
641                                 tvbparse_elem_t* new = tvbparse_get(tt, w);
642                                 
643                                 if (new) {
644                                         if (tok) {
645                                                 tok->len = (new->offset - tok->offset) + new->len;
646                                                 tok->sub->last->next = new;
647                                                 tok->sub->last = new;
648                                         } else {
649                                                 tok = new_tok(tt, wanted->id, new->offset, new->len, wanted);
650                                                 tok->sub = new;
651                                         }
652                                 } else {
653                                         goto reject;
654                                 }
655                                 
656                         }
657                         
658                         goto accept;                    
659                 }
660                 case TVBPARSE_WANTED_CARDINALITY:
661                 {
662                         guint got_so_far = 0;
663                         tvbparse_wanted_t* w = g_ptr_array_index(wanted->elems,0);
664                         
665             if ( wanted->min == 0 ) {
666                 new_tok(tt,wanted->id,tt->offset,0,wanted);
667             }
668             
669                         while (got_so_far < wanted->max) {
670                                 tvbparse_elem_t* new = tvbparse_get(tt, w);
671                                 
672                                 if(new) {
673                                         if (tok) {
674                                                 tok->len = (new->offset - tok->offset) + new->len;
675                                                 tok->sub->last->next = new;
676                                                 tok->sub->last = new;
677                                         } else {
678                                                 tok = new_tok(tt, wanted->id, new->offset, new->len, wanted);
679                                                 tok->sub = new;
680                                         }
681                                 } else {
682                                         break;
683                                 }
684                                 
685                                 got_so_far++;
686                         }
687                         
688                         if(got_so_far < wanted->min) {
689                                 goto reject;
690                         }
691                         
692                         goto accept;                    
693                 }
694                 case TVBPARSE_WANTED_UNTIL:
695                 {
696                         int offset = tt->offset;
697                         tvbparse_wanted_t* w = g_ptr_array_index(wanted->elems,0);
698                         tvbparse_elem_t* new = tvbparse_find(tt, w);
699                         
700                         if (new) {
701                                 tok = new;
702                                 
703                                 switch (wanted->control.val) {
704                     case TP_UNTIL_INCLUDE:
705                         tok->len = (tok->offset - offset) + tok->len;
706                         break;
707                     case TP_UNTIL_LEAVE:
708                         tt->offset -= tok->len;
709                         tt->max_len += tok->len;
710                         /* fall through */
711                     case TP_UNTIL_SPEND:
712                         tok->len = (tok->offset - offset);
713                         break;
714                     default:
715                         DISSECTOR_ASSERT_NOT_REACHED();
716                                 }
717                                 
718                                 tok->offset = offset;
719                                 tok->id = wanted->id;
720                                 tok->next = NULL;
721                                 tok->last = tok;
722                                 tok->wanted = wanted;
723                                 
724                                 goto accept;
725                         } else {
726                                 goto reject;
727                         }
728                 }
729         case TVBPARSE_WANTED_HANDLE:
730         {
731             tok = tvbparse_get(tt, *(wanted->control.handle));
732             if (tok) {
733                 goto accept;
734             } else {
735                 goto reject;
736             }
737         }
738         }
739         
740         DISSECTOR_ASSERT_NOT_REACHED();
741         return NULL;
742         
743 accept:
744                 if (tok) {
745                         if( tt->depth == 1 ) {
746                                 GPtrArray* stack = g_ptr_array_new();
747                                 tvbparse_elem_t* curr = tok;
748                                 
749                                 while (curr) {
750                                         
751                                         if(curr->wanted->before) {
752                                                 curr->wanted->before(tt->data, curr->wanted->data, curr);
753                                         }
754                                         
755                                         if(curr->sub) {
756                                                 g_ptr_array_add(stack,curr);
757                                                 curr = curr->sub;
758                                                 continue;
759                                         } else {
760                                                 if(curr->wanted->after) curr->wanted->after(tt->data, curr->wanted->data, curr);
761                                         }
762                                         
763                                         curr = curr->next;
764                                         
765                                         while( !curr && stack->len ) {
766                                                 curr = g_ptr_array_remove_index_fast(stack,stack->len - 1);
767                                                 if( curr->wanted->after ) curr->wanted->after(tt->data, curr->wanted->data, curr);
768                                                 curr = curr->next;
769                                         }
770                                         
771                                 }
772                                 
773                                 g_ptr_array_free(stack,TRUE);
774                         }
775                         
776                         tt->depth--;
777                         return tok; 
778                 }
779         
780 reject:
781                 tt->offset = save_offset;
782         tt->max_len = save_len;
783         tt->depth--;
784         return NULL;
785                                 
786 }
787
788
789 tvbparse_elem_t* tvbparse_find(tvbparse_t* tt, const tvbparse_wanted_t* wanted) {
790         int save_offset = tt->offset;
791         int save_len = tt->max_len;
792         tvbparse_elem_t* tok = NULL;
793         
794         while ( tvb_length_remaining(tt->tvb,tt->offset) >= wanted->len ) {
795                 if (( tok = tvbparse_get(tt, wanted) )) {
796                         return tok;
797                 }
798                 tt->offset++;
799                 tt->max_len--;
800         }
801         
802         tt->offset = save_offset;
803         tt->max_len = save_len;
804         
805         return NULL;
806 }
807
808 struct _elem_tree_stack_frame {
809     proto_tree* tree;
810     tvbparse_elem_t* elem;
811 };
812
813 void tvbparse_tree_add_elem(proto_tree* tree, tvbparse_elem_t* curr) {
814     GPtrArray* stack = g_ptr_array_new();
815     struct _elem_tree_stack_frame* frame = ep_alloc(sizeof(struct _elem_tree_stack_frame));
816     proto_item* pi;
817     frame->tree = tree;
818     frame->elem = curr;
819     
820     while (curr) {
821         pi = proto_tree_add_text(frame->tree,curr->tvb,curr->offset,curr->len,"%s",tvb_format_text(curr->tvb,curr->offset,curr->len));
822         
823         if(curr->sub) {
824             frame->elem = curr;
825             g_ptr_array_add(stack,frame);
826             frame = ep_alloc(sizeof(struct _elem_tree_stack_frame));
827             frame->tree = proto_item_add_subtree(pi,0);
828             curr = curr->sub;
829             continue;
830         }
831         
832         curr = curr->next;
833         
834         while( !curr && stack->len ) {
835             frame = g_ptr_array_remove_index_fast(stack,stack->len - 1);
836             curr = frame->elem->next;
837         }
838         
839     }
840     
841     g_ptr_array_free(stack,TRUE);
842 }
843