INSTALL: add reference to pet/README
[ppn.git] / yaml.cc
blobbd3e4a28388a43ea55c9c77f466aab3008787b3a
1 #include <assert.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <string>
6 extern "C" {
7 #define st_delete STUPID_PROTOTYPING_st_delete
8 #define st_insert STUPID_PROTOTYPING_st_insert
9 #include <syck.h>
10 #include <isa/yll.h>
11 #undef st_delete
12 #undef st_insert
13 int st_delete( register st_table *, register char **, char **value );
14 int st_insert( register st_table *, register char *, char * );
17 #ifndef HAVE_STRNDUP
18 extern "C" char *strndup(const char *s, size_t n);
19 #endif
21 #include <isa/yaml.h>
23 using std::string;
24 using std::vector;
26 namespace yaml
29 bool emitter::anchor_handled(serialize *s)
31 if (anchors.find(s) != anchors.end()) {
32 yll_emitter_alias(e, anchors[s]);
33 return true;
35 if (refs[s] > 1)
36 anchors[s] = yll_emitter_anchor(e);
37 return false;
40 void serialize::collect_references(refset& refs)
42 refs[this] = 1;
45 void serialize::free()
47 refset references;
48 collect_references(references);
49 refset::iterator i;
50 for (i = references.begin(); i != references.end(); ++i) {
51 if (i->first != this)
52 delete i->first;
56 SyckNode* serialize::bad_anchor_handler(SyckParser *p, char *a)
58 SyckNode * n = syck_new_str(a, scalar_none);
59 serialize_p s = new bad_anchor();
61 anchor_map *anchors = (anchor_map *) p->bonus;
63 n->id = syck_add_sym(p, (char *)s);
65 anchors->add(s, n->id);
67 return n;
70 // We may need to replace inside the replacers as well XXX
71 serialize * anchor_map::replace(SYMID id, serialize *replacement)
73 serialize *orig;
74 st_delete( p->syms, (char **)&id, (char **)&orig );
75 assert(anchors[orig].first == id);
77 vector<replacer_base *> & replacements = anchors[orig].second;
78 anchors[replacement].first = id;
79 vector<replacer_base *> & new_replacements = anchors[replacement].second;
80 for (int i=0; i < replacements.size(); ++i) {
81 replacements[i]->with(replacement);
82 new_replacements.push_back(replacements[i]);
84 anchors.erase(orig);
85 st_insert( p->syms, (char *)id, (char *)replacement );
86 return orig;
89 anchor_map::~anchor_map()
91 map<serialize *, rep_pair >::iterator i;
92 for (i = anchors.begin(); i != anchors.end(); ++i) {
93 for (int j=0; j < i->second.second.size(); ++j) {
94 delete i->second.second[j];
99 SYMID serialize::syck_handler(SyckParser *p, SyckNode *n)
101 serialize_p s = 0;
102 anchor_map *anchors = (anchor_map *) p->bonus;
104 if (n->type_id) {
105 if (s_desc().find(string(n->type_id)) != s_desc().end())
106 s = (s_desc())[n->type_id]->create(anchors->user);
108 if (!s) {
109 switch (n->kind) {
110 case syck_str_kind:
111 s = str::create(anchors->user);
112 break;
113 case syck_map_kind:
114 s = dict::create();
115 break;
116 case syck_seq_kind:
117 s = seq<serialize>::create();
118 break;
119 default:
120 assert(0);
124 SYMID id = (n->id == 0) ? syck_add_sym(p, (char *)s) : 0;
126 if (id && n->anchor) {
127 anchors->add(s, id);
130 if (s)
131 s->init(p,n);
133 // bad anchor
134 if (n->id != 0) {
135 serialize *anchor = anchors->replace(n->id, s);
136 delete anchor;
137 return n->id;
140 return id;
143 serialize *serialize::Load(SyckParser *parser, const type_info *type,
144 void *user)
146 SYMID v;
147 serialize_p y = NULL;
149 anchor_map anchors(parser, user);
150 parser->bonus = &anchors;
151 syck_parser_handler(parser, syck_handler);
152 syck_parser_bad_anchor_handler(parser, bad_anchor_handler);
153 syck_parser_implicit_typing( parser, 1 );
154 v = syck_parse(parser);
155 syck_lookup_sym(parser, v, (char **)&y);
157 if (type && y) {
158 if (*type != typeid(*y)) {
159 description *desc = t_desc()[type];
160 assert(desc);
161 y = desc->convert(&anchors, y, type);
165 syck_free_parser(parser);
167 return y;
170 serialize_p serialize::Load(char *str, const type_info *type, void *user)
172 SyckParser *parser = syck_new_parser();
173 syck_parser_str_auto(parser, str, NULL);
174 return Load(parser, type, user);
177 serialize_p Load(char *str, const type_info *type, void *user)
179 return serialize::Load(str, type, user);
182 serialize_p serialize::Load(FILE *fp, const type_info *type, void *user)
184 SyckParser *parser = syck_new_parser();
185 syck_parser_file(parser, fp, NULL);
186 return Load(parser, type, user);
189 serialize_p Load(FILE *fp, const type_info *type, void *user)
191 return serialize::Load(fp, type, user);
194 void serialize::syck_output_handler(YllEmitter *p, char *s, long len)
198 void serialize::Dump(FILE *out)
200 emitter e;
201 e.e->out = out;
202 collect_references(e.refs);
203 yll_emitter_handler(e.e, syck_output_handler);
204 Dump(e);
207 void serialize::register_type(const char * type, const type_info *ti,
208 description * c)
210 s_desc()[type] = c;
211 t_desc()[ti] = c;
214 void str::register_type()
216 static description str_d = { create, NULL, &typeid(str) };
217 serialize::register_type("str", &typeid(str), &str_d);
218 serialize::register_type("int", &typeid(str), &str_d);
221 serialize *str::create(void *user)
223 return new str;
226 void str::init(SyckParser *p, SyckNode *n)
228 s = string(n->data.str->ptr, n->data.str->len);
231 at_init register_str(str::register_type);
233 void integer::register_type()
235 static description integer_d = { create, NULL, &typeid(integer) };
236 integer_d.convert = convert;
237 serialize::register_type("integer", &typeid(integer), &integer_d);
240 serialize *integer::create(void *user)
242 return new integer;
245 void integer::init(SyckParser *p, SyckNode *n)
247 char *s = strndup(n->data.str->ptr, n->data.str->len);
248 v = atoi(s);
249 ::free(s);
252 serialize_p integer::convert (anchor_map * am, serialize * s, const type_info *type)
254 str *st = dynamic_cast<str *>(s);
255 integer *i = NULL;
257 if (st) {
258 i = new integer;
259 i->v = atoi(st->s.c_str());
262 delete s;
264 return i;
267 at_init register_integer(integer::register_type);
269 serialize_p dict::create()
271 dict *d = new dict;
272 return d;
275 static void dict_init(sermap& d, SyckParser *p, SyckNode *n)
277 anchor_map *anchors = (anchor_map *) p->bonus;
278 for (int i = 0; i < n->data.pairs->idx; i++) {
279 str *key;
280 serialize *val;
281 SYMID oidk = syck_map_read( n, map_key, i );
282 syck_lookup_sym( p, oidk, (char **)&key );
283 SYMID oidv = syck_map_read( n, map_value, i );
284 syck_lookup_sym( p, oidv, (char **)&val );
285 d[key->s] = val;
286 delete key;
288 // In a second iteration, since we wouldn't want the
289 // memory locations to change for the replacer
290 map<string,serialize_p>::iterator i;
291 for (i = d.begin(); i != d.end(); ++i) {
292 if (anchors->is_anchor(i->second)) {
293 anchors->replace(i->second, new replacer<serialize>(i->second));
298 void dict::init(SyckParser *p, SyckNode *n)
300 d = new map<string,serialize_p>;
301 dict_init(*d, p, n);
304 static void dict_collect(sermap& d, refset& refs)
306 map<string,serialize_p>::iterator i;
307 for (i = d.begin(); i != d.end(); ++i) {
308 serialize *el = i->second;
309 if (refs.find(el) == refs.end())
310 el->collect_references(refs);
311 else
312 ++refs[el];
316 void dict::collect_references(refset& refs)
318 serialize::collect_references(refs);
319 dict_collect(*d, refs);
322 static void dict_dump(sermap& d, emitter& e)
324 map<string,serialize_p>::iterator i;
325 for (i = d.begin(); i != d.end(); ++i) {
326 yll_emitter_write_string(e.e, i->first.c_str());
327 if (i->second)
328 i->second->Dump(e);
329 else
330 yll_emitter_write_null(e.e);
334 void dict::dump(emitter& e)
336 yll_emitter_start_map(e.e);
337 dict_dump(*d, e);
338 yll_emitter_end_map(e.e);
341 void structure::init(SyckParser *p, SyckNode *n)
343 switch (n->kind) {
344 case syck_map_kind:
345 d = new map<string,serialize_p>;
346 dict_init(*d, p, n);
347 anchor_map *anchors = (anchor_map *) p->bonus;
348 fill_fields(anchors);
349 break;
353 void structure::fill_fields(anchor_map *am)
355 struct_description * sd = (struct_description *)(t_desc())[&typeid(*this)];
357 map<string,serialize_p>::iterator i;
358 for (i = d->begin(); i != d->end(); ) {
359 map<string,serialize_p>::iterator j = i++;
360 if (sd->m.find(j->first) != sd->m.end()) {
361 serialize *el = j->second;
363 if (sd->m[j->first]->set(am, this, j->second))
364 d->erase(j);
369 serialize_p structure::convert (anchor_map * am,
370 serialize * s, const type_info *type)
372 dict * d = dynamic_cast<dict *>(s);
373 structure * c = NULL;
375 if (d) {
376 c = dynamic_cast<structure *>(t_desc()[type]->create(am->user));
377 assert(t_desc().find(type) != t_desc().end());
379 if (am->is_anchor(s)) {
380 serialize *anchor = am->replace(s, c);
381 assert(anchor == s);
384 c->d = d->d;
385 d->d = NULL;
387 c->fill_fields(am);
390 delete s;
392 return c;
395 void structure::collect_references(refset& refs)
397 serialize::collect_references(refs);
398 if (d)
399 dict_collect(*d, refs);
400 struct_description * sd = (struct_description *)(t_desc())[&typeid(*this)];
401 fieldmap::iterator j;
402 for (j = sd->m.begin(); j != sd->m.end(); ++j) {
403 sd->m[j->first]->collect(this, refs);
407 void structure::dump(emitter& e)
409 yll_emitter_start_map(e.e);
411 struct_description * sd = (struct_description *)(t_desc())[&typeid(*this)];
412 fieldmap::iterator j;
413 for (j = sd->m.begin(); j != sd->m.end(); ++j) {
414 if (sd->m[j->first]->is_empty(this))
415 continue;
417 yll_emitter_write_string(e.e, j->first.c_str());
418 sd->m[j->first]->dump(this, e);
420 if (d)
421 dict_dump(*d, e);
423 yll_emitter_end_map(e.e);
426 void structure::register_type(const char * type, const type_info *ti,
427 description * c)
429 if (!c->convert)
430 c->convert = convert;
431 c->type = ti;
432 serialize::register_type(type, ti, c);
435 bool ptr_field::set(anchor_map *am, structure * c, serialize *& el)
437 map<const type_info *, description*>& desc = serialize::t_desc();
438 serialize * new_el = el;
440 if (*desc[type]->type != typeid(*el))
441 new_el = desc[type]->convert(am, el, type);
443 if (new_el) {
444 c->*pos = new_el;
445 if (am->is_anchor(el)) {
446 am->replace(el, new replacer_base(el),
447 new replacer<serialize>((c->*pos)));
451 return el != NULL;
454 void ptr_field::collect(structure * c, refset& refs)
456 serialize *el = c->*pos;
457 if (!el)
458 return;
460 if (refs.find(el) == refs.end())
461 el->collect_references(refs);
462 else
463 ++refs[el];
466 void ptr_field::dump(structure * c, emitter& e)
468 serialize *el = c->*pos;
469 if (el)
470 el->Dump(e);
471 else
472 yll_emitter_write_null(e.e);
475 bool int_field::set(anchor_map *am, structure * c, serialize *& el)
477 c->*pos = atoi(((str*)el)->s.c_str());
478 delete el;
480 return true;
483 void int_field::collect(structure * c, refset& refs)
487 void int_field::dump(structure * c, emitter& e)
489 yll_emitter_write_int(e.e, c->*pos);