1 | /****************************************************************************** |
---|
2 | * Copyright (c) 2005 Eric Petit |
---|
3 | * |
---|
4 | * Permission is hereby granted, free of charge, to any person obtaining a |
---|
5 | * copy of this software and associated documentation files (the "Software"), |
---|
6 | * to deal in the Software without restriction, including without limitation |
---|
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
---|
8 | * and/or sell copies of the Software, and to permit persons to whom the |
---|
9 | * Software is furnished to do so, subject to the following conditions: |
---|
10 | * |
---|
11 | * The above copyright notice and this permission notice shall be included in |
---|
12 | * all copies or substantial portions of the Software. |
---|
13 | * |
---|
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
---|
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
---|
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
---|
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
---|
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
---|
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
---|
20 | * DEALINGS IN THE SOFTWARE. |
---|
21 | *****************************************************************************/ |
---|
22 | |
---|
23 | #include "transmission.h" |
---|
24 | |
---|
25 | #define LIST_SIZE 20 |
---|
26 | |
---|
27 | int _tr_bencLoad( char * buf, benc_val_t * val, char ** end ) |
---|
28 | { |
---|
29 | char * p, * foo; |
---|
30 | |
---|
31 | if( !end ) |
---|
32 | { |
---|
33 | /* So we only have to check once */ |
---|
34 | end = &foo; |
---|
35 | } |
---|
36 | |
---|
37 | val->begin = buf; |
---|
38 | |
---|
39 | if( buf[0] == 'i' ) |
---|
40 | { |
---|
41 | /* Integer: i1242e */ |
---|
42 | val->type = TYPE_INT; |
---|
43 | val->val.i = strtoll( &buf[1], &p, 10 ); |
---|
44 | |
---|
45 | if( p == &buf[1] || p[0] != 'e' ) |
---|
46 | { |
---|
47 | return 1; |
---|
48 | } |
---|
49 | |
---|
50 | val->end = p + 1; |
---|
51 | } |
---|
52 | else if( buf[0] == 'l' || buf[0] == 'd' ) |
---|
53 | { |
---|
54 | /* List: l<item1><item2>e |
---|
55 | Dict: d<string1><item1><string2><item2>e |
---|
56 | A dictionary is just a special kind of list with an even |
---|
57 | count of items, and where even items are strings. */ |
---|
58 | char * cur; |
---|
59 | char is_dict; |
---|
60 | char str_expected; |
---|
61 | |
---|
62 | is_dict = ( buf[0] == 'd' ); |
---|
63 | val->type = is_dict ? TYPE_DICT : TYPE_LIST; |
---|
64 | val->val.l.alloc = LIST_SIZE; |
---|
65 | val->val.l.count = 0; |
---|
66 | val->val.l.vals = malloc( LIST_SIZE * sizeof( benc_val_t ) ); |
---|
67 | cur = &buf[1]; |
---|
68 | str_expected = 1; |
---|
69 | while( cur[0] != 'e' ) |
---|
70 | { |
---|
71 | if( val->val.l.count == val->val.l.alloc ) |
---|
72 | { |
---|
73 | /* We need a bigger boat */ |
---|
74 | val->val.l.alloc += LIST_SIZE; |
---|
75 | val->val.l.vals = realloc( val->val.l.vals, |
---|
76 | val->val.l.alloc * sizeof( benc_val_t ) ); |
---|
77 | } |
---|
78 | if( tr_bencLoad( cur, &val->val.l.vals[val->val.l.count], &p ) ) |
---|
79 | { |
---|
80 | return 1; |
---|
81 | } |
---|
82 | if( is_dict && str_expected && |
---|
83 | val->val.l.vals[val->val.l.count].type != TYPE_STR ) |
---|
84 | { |
---|
85 | return 1; |
---|
86 | } |
---|
87 | str_expected = !str_expected; |
---|
88 | |
---|
89 | val->val.l.count++; |
---|
90 | cur = p; |
---|
91 | } |
---|
92 | |
---|
93 | if( is_dict && ( val->val.l.count & 1 ) ) |
---|
94 | { |
---|
95 | return 1; |
---|
96 | } |
---|
97 | |
---|
98 | val->end = cur + 1; |
---|
99 | } |
---|
100 | else |
---|
101 | { |
---|
102 | /* String: 12:whateverword */ |
---|
103 | val->type = TYPE_STR; |
---|
104 | val->val.s.i = strtol( buf, &p, 10 ); |
---|
105 | |
---|
106 | if( p == buf || p[0] != ':' ) |
---|
107 | { |
---|
108 | return 1; |
---|
109 | } |
---|
110 | |
---|
111 | val->val.s.s = malloc( val->val.s.i + 1 ); |
---|
112 | val->val.s.s[val->val.s.i] = 0; |
---|
113 | memcpy( val->val.s.s, p + 1, val->val.s.i ); |
---|
114 | |
---|
115 | val->end = p + 1 + val->val.s.i; |
---|
116 | } |
---|
117 | |
---|
118 | *end = val->end; |
---|
119 | |
---|
120 | return 0; |
---|
121 | } |
---|
122 | |
---|
123 | static void __bencPrint( benc_val_t * val, int space ) |
---|
124 | { |
---|
125 | int i; |
---|
126 | |
---|
127 | for( i = 0; i < space; i++ ) |
---|
128 | { |
---|
129 | fprintf( stderr, " " ); |
---|
130 | } |
---|
131 | |
---|
132 | switch( val->type ) |
---|
133 | { |
---|
134 | case TYPE_INT: |
---|
135 | fprintf( stderr, "int: %lld\n", val->val.i ); |
---|
136 | break; |
---|
137 | |
---|
138 | case TYPE_STR: |
---|
139 | fprintf( stderr, "%s\n", val->val.s.s ); |
---|
140 | break; |
---|
141 | |
---|
142 | case TYPE_LIST: |
---|
143 | fprintf( stderr, "list\n" ); |
---|
144 | for( i = 0; i < val->val.l.count; i++ ) |
---|
145 | __bencPrint( &val->val.l.vals[i], space + 1 ); |
---|
146 | break; |
---|
147 | |
---|
148 | case TYPE_DICT: |
---|
149 | fprintf( stderr, "dict\n" ); |
---|
150 | for( i = 0; i < val->val.l.count; i++ ) |
---|
151 | __bencPrint( &val->val.l.vals[i], space + 1 ); |
---|
152 | break; |
---|
153 | } |
---|
154 | } |
---|
155 | |
---|
156 | void tr_bencPrint( benc_val_t * val ) |
---|
157 | { |
---|
158 | __bencPrint( val, 0 ); |
---|
159 | } |
---|
160 | |
---|
161 | void tr_bencFree( benc_val_t * val ) |
---|
162 | { |
---|
163 | int i; |
---|
164 | |
---|
165 | switch( val->type ) |
---|
166 | { |
---|
167 | case TYPE_INT: |
---|
168 | break; |
---|
169 | |
---|
170 | case TYPE_STR: |
---|
171 | if( val->val.s.s ) |
---|
172 | { |
---|
173 | free( val->val.s.s ); |
---|
174 | } |
---|
175 | break; |
---|
176 | |
---|
177 | case TYPE_LIST: |
---|
178 | case TYPE_DICT: |
---|
179 | for( i = 0; i < val->val.l.count; i++ ) |
---|
180 | { |
---|
181 | tr_bencFree( &val->val.l.vals[i] ); |
---|
182 | } |
---|
183 | free( val->val.l.vals ); |
---|
184 | break; |
---|
185 | } |
---|
186 | } |
---|
187 | |
---|
188 | benc_val_t * tr_bencDictFind( benc_val_t * val, char * key ) |
---|
189 | { |
---|
190 | int i; |
---|
191 | if( val->type != TYPE_DICT ) |
---|
192 | { |
---|
193 | return NULL; |
---|
194 | } |
---|
195 | |
---|
196 | for( i = 0; i < val->val.l.count; i += 2 ) |
---|
197 | { |
---|
198 | if( !strcmp( val->val.l.vals[i].val.s.s, key ) ) |
---|
199 | { |
---|
200 | return &val->val.l.vals[i+1]; |
---|
201 | } |
---|
202 | } |
---|
203 | |
---|
204 | return NULL; |
---|
205 | } |
---|