Bencoding parser in C
1 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <ctype.h> 5 #include <sys/types.h> 6 7 #define BUFSIZE 256 8 9 typedef enum BType { 10 Nothing = 0, 11 BString, 12 BInt, 13 BList, 14 BDict 15 } BType; 16 17 struct Bencoding; 18 19 typedef struct ListNode { 20 struct Bencoding *cargo; 21 struct ListNode *next; 22 } ListNode; 23 24 typedef struct DictNode { 25 char *key; 26 struct Bencoding *value; 27 struct DictNode *next; 28 } DictNode; 29 30 typedef struct Bencoding { 31 BType type; 32 union { 33 long long val; // used when type == BInt 34 ListNode *list; // used when type == BList 35 char *str; // used when type == BString 36 DictNode *dict; 37 } cargo; // data 38 } Bencoding; 39 40 Bencoding* parse_bencoding(); 41 42 Bencoding* new_bencoding() 43 { 44 return malloc(sizeof(Bencoding)); 45 } 46 47 ListNode* new_listnode() 48 { 49 return malloc(sizeof(ListNode)); 50 } 51 52 DictNode* new_dictnode() 53 { 54 return malloc(sizeof(DictNode)); 55 } 56 57 Bencoding* new_bint(int val) 58 { 59 Bencoding *b = new_bencoding(); 60 b->type = BInt; 61 b->cargo.val = val; 62 return b; 63 } 64 65 Bencoding* new_blist(ListNode *l) 66 { 67 Bencoding *b = new_bencoding(); 68 b->type = BList; 69 b->cargo.list = l; 70 return b; 71 } 72 73 Bencoding* new_bstring(char *s, int len) 74 { 75 Bencoding *b = new_bencoding(); 76 b->type = BString; 77 b->cargo.str = s; 78 return b; 79 } 80 81 Bencoding* new_bdict(DictNode *d) 82 { 83 Bencoding *b = new_bencoding(); 84 b->type = BDict; 85 b->cargo.dict = d; 86 return b; 87 } 88 89 void failed() 90 { 91 printf("Parse FAILED\n"); 92 exit(1); 93 } 94 95 char buf[BUFSIZE]; 96 int pos = 0; 97 int buf_lim = 0; 98 99 char reloadBuffer() 100 { 101 buf_lim = fread(buf, 1, BUFSIZE, stdin); 102 pos = 0; 103 } 104 105 void checkBufReady() 106 { 107 if (pos >= buf_lim) 108 reloadBuffer(); 109 } 110 111 char peekChar() 112 { 113 checkBufReady(); 114 return buf[pos]; 115 } 116 117 char getChar() 118 { 119 checkBufReady(); 120 return buf[pos++]; 121 } 122 123 void matchChar(char c) 124 { 125 if (getChar() != c) 126 failed(); 127 } 128 129 Bencoding* parse_int() 130 { 131 matchChar('i'); 132 long long val = 0; 133 while (isdigit(peekChar())) 134 val = val*10 + (getChar() - '0'); 135 matchChar('e'); 136 137 return new_bint(val); 138 } 139 140 Bencoding* parse_list() 141 { 142 matchChar('l'); 143 ListNode l; 144 ListNode *c = &l; 145 while (peekChar() != 'e') { 146 c->next = new_listnode(); 147 c = c->next; 148 c->cargo = parse_bencoding(); 149 c->next = 0; 150 } 151 matchChar('e'); 152 return new_blist(l.next); 153 } 154 155 Bencoding* parse_string() 156 { 157 int len = 0; 158 while (isdigit(peekChar())) 159 len = len*10 + (getChar() - '0'); 160 matchChar(':'); 161 char *s = malloc(sizeof(char)*(len+1)); 162 int i; 163 for (i = 0; i < len; ++i) 164 s[i] = getChar(); 165 s[len] = 0; 166 return new_bstring(s, len+1); 167 } 168 169 Bencoding* parse_dict() 170 { 171 matchChar('d'); 172 DictNode d; 173 DictNode *c = &d; 174 while (peekChar() != 'e') { 175 c->next = new_dictnode(); 176 c = c->next; 177 Bencoding *s = parse_string(); 178 c->key = s->cargo.str; 179 free(s); 180 c->value = parse_bencoding(); 181 c->next = 0; 182 } 183 matchChar('e'); 184 return new_bdict(d.next); 185 } 186 187 Bencoding* parse_bencoding() 188 { 189 char c = peekChar(); 190 switch (c) { 191 case 'd': return parse_dict(); 192 case 'l': return parse_list(); 193 case 'i': return parse_int(); 194 default: return parse_string(); 195 } 196 } 197 198 void print_indent(int indent) 199 { 200 int i; 201 for (i = 0; i < indent; ++i) 202 printf(" "); 203 } 204 205 206 void print_bencoding(Bencoding *b, int indent) 207 { 208 print_indent(indent); 209 switch (b->type) { 210 case BInt: 211 printf("%lld\n", b->cargo.val); 212 break; 213 case BList: 214 printf("[\n"); 215 ListNode *c = b->cargo.list; 216 while (c) { 217 print_bencoding(c->cargo, indent+1); 218 c = c->next; 219 } 220 print_indent(indent); 221 printf("]\n"); 222 break; 223 case BString: 224 printf("%s\n", b->cargo.str); 225 break; 226 case BDict: 227 printf("{\n"); 228 DictNode *d = b->cargo.dict; 229 while (d) { 230 print_indent(indent+1); 231 printf("%s ==>\n", d->key); 232 print_bencoding(d->value, indent+2); 233 d = d->next; 234 } 235 print_indent(indent); 236 printf("}\n"); 237 break; 238 } 239 } 240 241 int main(int argc, char *argv[]) 242 { 243 Bencoding* b = parse_bencoding(); 244 245 print_bencoding(b, 0); 246 247 return 0; 248 }