├── gen
├── daegen.bat
├── daegen.sh
├── daegen_vs2010.vcxproj
├── make.c
├── makefile
├── src
│ ├── gen.c
│ ├── gen.h
│ ├── main.c
│ ├── xsd.c
│ ├── xsd.h
│ ├── xsdparse.c
│ └── xsdparse.h
└── template
│ ├── dae.c
│ └── dae.h
├── include
├── dae.h
└── daeu.h
├── libdae_vs2010.vcxproj
├── make.c
├── makefile
├── readme.txt
├── src
├── dae.c
└── daeu.c
└── unlicense.txt
/gen/daegen.bat:
--------------------------------------------------------------------------------
1 | bin\daegen collada_schema_1_5.xsd template\dae.c ..\src\dae.c
2 | bin\daegen collada_schema_1_5.xsd template\dae.h ..\include\dae.h
3 |
--------------------------------------------------------------------------------
/gen/daegen.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | bin/daegen collada_schema_1_5.xsd template/dae.c ../src/dae.c
3 | bin/daegen collada_schema_1_5.xsd template/dae.h ../include/dae.h
4 |
--------------------------------------------------------------------------------
/gen/daegen_vs2010.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 |
14 |
15 |
16 |
17 | daegen
18 | {FCC97DB3-BFAF-4DF6-A807-841C4D58B9C2}
19 | daegen
20 | Win32Proj
21 |
22 |
23 |
24 | Application
25 | MultiByte
26 | true
27 |
28 |
29 | Application
30 | MultiByte
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | <_ProjectFileVersion>10.0.30319.1
44 | $(ProjectDir)bin/
45 | $(ProjectDir)objd/
46 | $(ProjectDir)bin/
47 | $(ProjectDir)obj/
48 | $(ProjectName)d
49 |
50 |
51 |
52 | Disabled
53 | ../../../extern/expat/lib;%(AdditionalIncludeDirectories)
54 | WIN32;_CONSOLE;_CRT_SECURE_NO_WARNINGS;XML_STATIC;_DEBUG;%(PreprocessorDefinitions)
55 | true
56 |
57 |
58 | EnableFastChecks
59 | MultiThreadedDebug
60 | false
61 |
62 |
63 | $(IntDir)
64 | Level3
65 | EditAndContinue
66 | CompileAsC
67 |
68 |
69 | $(OutDir)$(TargetName)$(TargetExt)
70 | Console
71 | ../../../extern/expat/win32/bin/Release/libexpatMT.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
72 | true
73 |
74 |
75 |
76 |
77 | MaxSpeed
78 | true
79 | ../../../extern/expat/lib;%(AdditionalIncludeDirectories)
80 | WIN32;_CONSOLE;_CRT_SECURE_NO_WARNINGS;XML_STATIC;NDEBUG;%(PreprocessorDefinitions)
81 |
82 |
83 | MultiThreaded
84 | true
85 | false
86 |
87 |
88 | $(IntDir)
89 | Level3
90 | ProgramDatabase
91 | CompileAsC
92 |
93 |
94 | Console
95 | ../../../extern/expat/win32/bin/Release/libexpatMT.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
96 |
97 |
98 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/gen/make.c:
--------------------------------------------------------------------------------
1 | #include "src/main.c"
2 | #include "src/gen.c"
3 | #include "src/xsdparse.c"
4 | #include "src/xsd.c"
5 |
--------------------------------------------------------------------------------
/gen/makefile:
--------------------------------------------------------------------------------
1 | EXE=bin/daegen
2 | EXED=bin/daegend
3 | OBJS=obj/make.o
4 | OBJSD=objd/make.o
5 | INCLUDES= -I../../extern/expat/lib
6 | LIBS= -L../../extern/expat/.libs -lexpat
7 | CC=gcc
8 | CCFLAGS=-Wall -msse -O3 -fno-exceptions -DNDEBUG -DXML_STATIC $(INCLUDES)
9 | CCFLAGSD=-Wall -msse -O0 -ggdb2 -fno-exceptions -D_DEBUG -DXML_STATIC $(INCLUDES)
10 | LD=gcc
11 | LDFLAGS=$(LIBS)
12 |
13 | $(EXE): obj bin $(OBJS)
14 | $(LD) $(OBJS) $(LDFLAGS) -o $(EXE)
15 |
16 | $(EXED): objd bin $(OBJSD)
17 | $(LD) $(OBJSD) $(LDFLAGS) -o $(EXED)
18 |
19 | obj:
20 | mkdir obj
21 |
22 | objd:
23 | mkdir objd
24 |
25 | bin:
26 | mkdir bin
27 |
28 | obj/make.o : make.c
29 | $(CC) $(CCFLAGS) -c $< -o $@
30 |
31 | objd/make.o : make.c
32 | $(CC) $(CCFLAGSD) -c $< -o $@
33 |
34 | all: $(EXE) $(EXED)
35 |
36 | clean:
37 | rm -rf $(EXE) $(EXED) obj objd
38 |
39 | debug: $(EXED)
40 |
41 | release: $(EXE)
42 |
--------------------------------------------------------------------------------
/gen/src/gen.c:
--------------------------------------------------------------------------------
1 | #include "gen.h"
2 | #include
3 | #include
4 | #include
5 |
6 | //****************************************************************************
7 | static void gen_str_alphanumeric(
8 | char* dst,
9 | const char* src,
10 | size_t n)
11 | {
12 | char* end = dst + n - 1;
13 | while(dst != end && *src != '\0')
14 | {
15 | char ch = *src;
16 | *dst = (isalnum(ch)) ? ch : '_';
17 | ++src;
18 | ++dst;
19 | }
20 | *dst = '\0';
21 | }
22 |
23 | //****************************************************************************
24 | static void gen_str_upper(
25 | char* dst,
26 | const char* src,
27 | size_t n)
28 | {
29 | char* end = dst + n - 1;
30 | while(dst != end && *src != '\0')
31 | {
32 | *dst = toupper(*src);
33 | ++src;
34 | ++dst;
35 | }
36 | assert(dst != end);
37 | *dst = '\0';
38 | }
39 |
40 | //****************************************************************************
41 | static void gen_cname_id(
42 | char* dst,
43 | const char* src,
44 | size_t n)
45 | {
46 | if(n > 7)
47 | {
48 | const char* colon = strchr(src, ':');
49 | if(colon != NULL)
50 | {
51 | // strip out namespaces
52 | src = colon + 1;
53 | }
54 | strcpy(dst, "dae_ID_");
55 | gen_str_alphanumeric(dst + 7, src, n - 7);
56 | gen_str_upper(dst + 7, dst + 7, n - 7);
57 | }
58 | else if(n > 0)
59 | {
60 | *dst = '\0';
61 | }
62 | }
63 |
64 | //****************************************************************************
65 | static void gen_cname_attrib(
66 | char* dst,
67 | const char* src,
68 | size_t n)
69 | {
70 | if(n > 3)
71 | {
72 | strcpy(dst, "at_");
73 | gen_str_alphanumeric(dst + 3, src, n - 3);
74 | }
75 | else if(n > 0)
76 | {
77 | *dst = '\0';
78 | }
79 | }
80 |
81 | //****************************************************************************
82 | static void gen_cname_elem(
83 | char* dst,
84 | const char* src,
85 | size_t n)
86 | {
87 | if(n > 3)
88 | {
89 | strcpy(dst, "el_");
90 | gen_str_alphanumeric(dst + 3, src, n - 3);
91 | }
92 | else if(n > 0)
93 | {
94 | *dst = '\0';
95 | }
96 | }
97 |
98 | //****************************************************************************
99 | static const char* gen_cname_nativeid(
100 | xsd_schema* schema,
101 | const char* src)
102 | {
103 | const char* nativeid = NULL;
104 | while(src != NULL)
105 | {
106 | xsd_type* t;
107 | if(!strcmp(src, xsd_DATA_BOOL))
108 | {
109 | nativeid = "dae_NATIVE_BOOL32";
110 | }
111 | else if(!strcmp(src, xsd_DATA_HEX))
112 | {
113 | nativeid = "dae_NATIVE_HEX8";
114 | }
115 | else if(!strcmp(src, xsd_DATA_FLOAT))
116 | {
117 | nativeid = "dae_NATIVE_FLOAT";
118 | }
119 | else if(!strcmp(src, xsd_DATA_INT8))
120 | {
121 | nativeid = "dae_NATIVE_INT8";
122 | }
123 | else if(!strcmp(src, xsd_DATA_INT16))
124 | {
125 | nativeid = "dae_NATIVE_INT16";
126 | }
127 | else if(!strcmp(src, xsd_DATA_STRING))
128 | {
129 | nativeid = "dae_NATIVE_STRING";
130 | }
131 | else if(!strcmp(src, xsd_DATA_INT32))
132 | {
133 | nativeid = "dae_NATIVE_INT32";
134 | }
135 | else if(!strcmp(src, xsd_DATA_UINT8))
136 | {
137 | nativeid = "dae_NATIVE_UINT8";
138 | }
139 | else if(!strcmp(src, xsd_DATA_UINT16))
140 | {
141 | nativeid = "dae_NATIVE_UINT16";
142 | }
143 | else if(!strcmp(src, xsd_DATA_UINT32))
144 | {
145 | nativeid = "dae_NATIVE_UINT32";
146 | }
147 | if(nativeid != NULL)
148 | {
149 | break;
150 | }
151 | t = xsd_find_type(schema, src);
152 | src = t->base;
153 | }
154 | return nativeid;
155 | }
156 |
157 | static const char* gen_cname_native(
158 | const char* src)
159 | {
160 | const char* cname = NULL;
161 | if(!strcmp(src, xsd_DATA_BOOL))
162 | {
163 | cname = "int";
164 | }
165 | else if(!strcmp(src, xsd_DATA_HEX))
166 | {
167 | cname = "unsigned char";
168 | }
169 | else if(!strcmp(src, xsd_DATA_FLOAT))
170 | {
171 | cname = "float";
172 | }
173 | else if(!strcmp(src, xsd_DATA_INT8))
174 | {
175 | cname = "char";
176 | }
177 | else if(!strcmp(src, xsd_DATA_INT16))
178 | {
179 | cname = "short";
180 | }
181 | else if(!strcmp(src, xsd_DATA_STRING))
182 | {
183 | cname = "char*";
184 | }
185 | else if(!strcmp(src, xsd_DATA_INT32))
186 | {
187 | cname = "int";
188 | }
189 | else if(!strcmp(src, xsd_DATA_UINT8))
190 | {
191 | cname = "unsigned char";
192 | }
193 | else if(!strcmp(src, xsd_DATA_UINT16))
194 | {
195 | cname = "unsigned short";
196 | }
197 | else if(!strcmp(src, xsd_DATA_UINT32))
198 | {
199 | cname = "unsigned int";
200 | }
201 | return cname;
202 | }
203 |
204 | //****************************************************************************
205 | static void gen_cname_type(
206 | char* dst,
207 | const char* src,
208 | size_t n)
209 | {
210 | const char* native = gen_cname_native(src);
211 | if(native != NULL)
212 | {
213 | strncpy(dst, native, n);
214 | dst[n - 1] = '\0';
215 | }
216 | else
217 | {
218 | if(n > 4)
219 | {
220 | const char* colon = strchr(src, ':');
221 | if(colon != NULL)
222 | {
223 | // strip out namespaces
224 | src = colon + 1;
225 | }
226 | strcpy(dst, "dae_");
227 | gen_str_alphanumeric(dst + 4, src, n - 4);
228 | }
229 | else if(n > 0)
230 | {
231 | *dst = '\0';
232 | }
233 | }
234 | }
235 |
236 | //****************************************************************************
237 | static void gen_print_structmember(
238 | FILE* fp,
239 | xsd_type* t,
240 | const char* name,
241 | int min,
242 | int max,
243 | int useptr)
244 | {
245 | char tcn[128];
246 | gen_cname_type(tcn, t->name, sizeof(tcn) - 1);
247 | if(useptr)
248 | {
249 | strcat(tcn, "*");
250 | }
251 | if((max == 1 || max == xsd_UNSET))
252 | {
253 | fprintf(fp," %s %s;\n", tcn, name);
254 | }
255 | else if(max == xsd_UNBOUNDED)
256 | {
257 | // variable sized list
258 | fprintf(fp," struct\n");
259 | fprintf(fp," {\n");
260 | fprintf(fp," %s* values;\n", tcn);
261 | fprintf(fp," size_t size;\n");
262 | fprintf(fp," } %s;\n", name);
263 | }
264 | else
265 | {
266 | // fixed size array
267 | fprintf(fp," %s %s[%i];\n", tcn, name, max);
268 | }
269 | }
270 |
271 | //****************************************************************************
272 | void gen_print_typeids(
273 | FILE* fp,
274 | xsd_schema* schema)
275 | {
276 | xsd_type** titr = schema->types;
277 | xsd_type** tend = titr + schema->numtypes;
278 | fprintf(fp,"enum dae_obj_typeid_e\n");
279 | fprintf(fp,"{\n");
280 | while(titr != tend)
281 | {
282 | xsd_type* t = *titr;
283 | xsd_type** previtr = schema->types;
284 | char idcn[128];
285 | gen_cname_id(idcn, t->name, sizeof(idcn));
286 | // check for duplicates
287 | while(previtr != titr)
288 | {
289 | xsd_type* prev = *previtr;
290 | char prevcn[128];
291 | gen_cname_id(prevcn, prev->name, sizeof(prevcn));
292 | if(strcmp(prevcn, idcn) == 0)
293 | {
294 | break;
295 | }
296 | ++previtr;
297 | }
298 | if(previtr == titr)
299 | {
300 | fprintf(fp," %s,\n", idcn);
301 | }
302 | ++titr;
303 | }
304 | fprintf(fp," dae_ID_INVALID = -1\n");
305 | fprintf(fp,"};\n");
306 | }
307 |
308 | //****************************************************************************
309 | void gen_print_typedefs(
310 | FILE* fp,
311 | xsd_schema* schema)
312 | {
313 | xsd_type** titr = schema->types;
314 | xsd_type** tend = titr + schema->numtypes;
315 | while(titr != tend)
316 | {
317 | xsd_type* t = *titr;
318 | if(gen_cname_native(t->name) == NULL)
319 | {
320 | // only generate typedefs for non-native types
321 | char tcn[128];
322 | gen_cname_type(tcn, t->name, sizeof(tcn));
323 | if(t->baserelation == xsd_BASE_RENAME)
324 | {
325 | char basecn[128];
326 | gen_cname_type(basecn, t->base, sizeof(basecn));
327 | fprintf(fp, "typedef %s %s;\n", basecn, tcn);
328 | }
329 | else if(t->hascomplex)
330 | {
331 | // if the type has complex content, generate a struct for it
332 | if(t->complex.numattribs > 0 || !t->anycontent)
333 | {
334 | fprintf(fp,"typedef struct %s_s %s;\n", tcn, tcn);
335 | }
336 | else
337 | {
338 | // if any child content is allowed, and there are no
339 | // attribs, then there is nothing to define in a struct
340 | // define as void*
341 | fprintf(fp,"typedef void* %s;\n", tcn);
342 | }
343 | }
344 | else if(t->hassimple)
345 | {
346 | // if the type is simple, generate a primitive typedef for it
347 | char cdata[128];
348 | int max;
349 | gen_cname_type(cdata, t->simple.itemtype, sizeof(cdata));
350 | max=(t->simple.maxoccurs!=xsd_UNSET) ? t->simple.maxoccurs:1;
351 | assert(!t->anycontent);
352 | if(max == 1)
353 | {
354 | // single component
355 | fprintf(fp,"typedef %s %s;\n", cdata, tcn);
356 | }
357 | else if(max == xsd_UNBOUNDED)
358 | {
359 | // list, need a struct
360 | fprintf(fp,"typedef struct %s_s %s;\n", tcn, tcn);
361 | }
362 | else
363 | {
364 | // array
365 | fprintf(fp,"typedef %s %s[%i];\n", cdata, tcn, max);
366 | }
367 | }
368 | else
369 | {
370 | // if the type has no content, define as void*
371 | fprintf(fp,"typedef void* %s;\n", tcn);
372 | }
373 | }
374 | ++titr;
375 | }
376 | }
377 |
378 | //****************************************************************************
379 | static int gen_is_struct(
380 | xsd_type* t)
381 | {
382 | int isstruct = 0;
383 | if(t->hascomplex)
384 | {
385 | isstruct = t->complex.numattribs > 0 || t->complex.numelements > 0;
386 | }
387 | else if(t->hassimple)
388 | {
389 | isstruct = t->simple.maxoccurs == xsd_UNBOUNDED;
390 | }
391 | return isstruct;
392 | }
393 |
394 | //****************************************************************************
395 | void gen_print_structs(
396 | FILE* fp,
397 | xsd_schema* schema)
398 | {
399 | xsd_type** titr = schema->types;
400 | xsd_type** tend = titr + schema->numtypes;
401 | while(titr != tend)
402 | {
403 | xsd_type* t = *titr;
404 | int needstruct = 0;
405 | if(t->baserelation == xsd_BASE_RENAME)
406 | {
407 | // special case, renames get typedefed as base type
408 | needstruct = 0;
409 | }
410 | else
411 | {
412 | needstruct = gen_is_struct(t);
413 | }
414 | if(needstruct)
415 | {
416 | xsd_attrib** atitr = t->complex.attribs;
417 | xsd_attrib** atend = atitr + t->complex.numattribs;
418 | xsd_element** elitr = t->complex.elements;
419 | xsd_element** elend = elitr + t->complex.numelements;
420 | char tcn[128];
421 | assert(!t->isbuiltin);
422 | gen_cname_type(tcn, t->name, sizeof(tcn));
423 | fprintf(fp,"struct %s_s\n", tcn);
424 | fprintf(fp,"{\n");
425 | while(atitr != atend)
426 | {
427 | xsd_attrib* at = *atitr;
428 | xsd_type* tat = xsd_find_type(schema,at->type);
429 | const char* item = tat->simple.itemtype;
430 | int min = (at->required) ? 1 : 0;
431 | int max = 1;
432 | char atcn[128];
433 | gen_cname_attrib(atcn, at->name, sizeof(atcn));
434 | gen_print_structmember(fp, tat, atcn, min, max, 1);
435 | if (!tat->hassimple || gen_cname_nativeid(schema,item)==NULL)
436 | {
437 | fprintf(fp,"#error unrecogonized attribute type\n");
438 | }
439 | ++atitr;
440 | }
441 | while(elitr != elend)
442 | {
443 | xsd_element* el = *elitr;
444 | if(el->type != NULL)
445 | {
446 | xsd_element** inrelitr = t->complex.elements;
447 | int isduplicate = 0;
448 | // make sure there are no other elements with the same name
449 | // only export duplicated elements once to the struct def
450 | while(inrelitr != elitr)
451 | {
452 | xsd_element* inrel = *inrelitr;
453 | if(!strcmp(el->name,inrel->name))
454 | {
455 | isduplicate = 1;
456 | break;
457 | }
458 | ++inrelitr;
459 | }
460 | if(!isduplicate)
461 | {
462 | xsd_type* tel = xsd_find_type(schema,el->type);
463 | int min = el->minoccurs;
464 | int max = el->maxoccurs;
465 | char elcn[128];
466 | gen_cname_elem(elcn, el->name, sizeof(elcn));
467 | gen_print_structmember(fp, tel, elcn, min, max, 1);
468 | }
469 | }
470 | ++elitr;
471 | }
472 | if(t->hassimple)
473 | {
474 | xsd_type* titem = xsd_find_type(schema, t->simple.itemtype);
475 | int min = t->simple.minoccurs;
476 | int max = t->simple.maxoccurs;
477 | gen_print_structmember(fp, titem, "data", min, max, 0);
478 | }
479 | fprintf(fp,"};\n");
480 | fprintf(fp,"\n");
481 | }
482 | ++titr;
483 | }
484 | }
485 |
486 | //****************************************************************************
487 | void gen_print_schema(
488 | FILE* fp,
489 | xsd_schema* schema)
490 | {
491 | xsd_type** titr;
492 | xsd_type** tend;
493 | fprintf(fp,"static void dae_build_schema(\n");
494 | fprintf(fp," dae_obj_typedef** types_out,\n");
495 | fprintf(fp," unsigned* numtypes_out)\n");
496 | fprintf(fp,"{\n");
497 | fprintf(fp," static dae_obj_typedef s_types[%i];\n",
498 | (int) schema->numtypes);
499 | fprintf(fp," dae_obj_typedef* t = s_types;\n");
500 | titr = schema->types;
501 | tend = titr + schema->numtypes;
502 | while(titr != tend)
503 | {
504 | xsd_type* t = *titr;
505 | char idcn[128];
506 | char tcn[128];
507 | gen_cname_id(idcn, t->name, sizeof(idcn));
508 | gen_cname_type(tcn, t->name, sizeof(tcn));
509 | fprintf(fp," t->name = \"%s\";\n", t->name);
510 | fprintf(fp," t->size = sizeof(%s);\n", tcn);
511 | fprintf(fp," t->flags= 0");
512 | if(t->anycontent)
513 | {
514 | fprintf(fp," | dae_XSD_ANY");
515 | }
516 | fprintf(fp,";\n");
517 | fprintf(fp," t->objtypeid = %s;\n", idcn);
518 | if(t->hassimple)
519 | {
520 | const char* dtcid;
521 | int min;
522 | int max;
523 | // exported data type should always be a native
524 | dtcid = gen_cname_nativeid(schema, t->simple.itemtype);
525 | min = (t->simple.minoccurs!=xsd_UNSET) ? t->simple.minoccurs : 1;
526 | max = (t->simple.maxoccurs!=xsd_UNSET) ? t->simple.maxoccurs : 1;
527 | if(gen_is_struct(t))
528 | {
529 | fprintf(fp," t->dataoffset=offsetof(%s,data);\n",tcn);
530 | }
531 | else
532 | {
533 | fprintf(fp," t->dataoffset=0;\n");
534 | }
535 | fprintf(fp," t->datatypeid=%s;\n", dtcid);
536 | fprintf(fp," t->datamin=%i;\n", min);
537 | fprintf(fp," t->datamax=%i;\n", max);
538 | }
539 | else
540 | {
541 | fprintf(fp," t->datatypeid=dae_ID_INVALID;\n");
542 | }
543 | if(t->hascomplex && t->complex.numattribs > 0)
544 | {
545 | xsd_attrib** atitr = t->complex.attribs;
546 | xsd_attrib** atend = atitr + t->complex.numattribs;
547 | int numats = t->complex.numattribs;
548 | fprintf(fp," {\n");
549 | fprintf(fp," static dae_obj_memberdef attribs[%i];\n", numats);
550 | fprintf(fp," dae_obj_memberdef* at = attribs;\n");
551 | while(atitr != atend)
552 | {
553 | xsd_attrib* at = *atitr;
554 | const char* deflt = at->deflt;
555 | char atcn[128];
556 | char attcid[128];
557 | int req;
558 | gen_cname_attrib(atcn, at->name, sizeof(atcn));
559 | gen_cname_id(attcid, at->type, sizeof(attcid));
560 | req = (at->required!=xsd_UNSET) ? at->required : 0;
561 | fprintf(fp," at->name=\"%s\";\n", at->name);
562 | fprintf(fp," at->offset=offsetof(%s,%s);\n",tcn,atcn);
563 | fprintf(fp," at->objtypeid=%s;\n", attcid);
564 | fprintf(fp," at->min=%i;\n", req);
565 | fprintf(fp," at->max=1;\n");
566 | if(deflt != NULL)
567 | {
568 | fprintf(fp," at->deflt=\"%s\";\n",deflt);
569 | }
570 | fprintf(fp," ++at;\n");
571 | ++atitr;
572 | }
573 | fprintf(fp," t->attribs = attribs;\n");
574 | fprintf(fp," t->numattribs = %i;\n", numats);
575 | fprintf(fp," }\n");
576 | }
577 | if(t->hascomplex && t->complex.numelements > 0)
578 | {
579 | xsd_element** elitr = t->complex.elements;
580 | xsd_element** elend = elitr + t->complex.numelements;
581 | int numels = t->complex.numelements;
582 | fprintf(fp," {\n");
583 | fprintf(fp," static dae_obj_memberdef elems[%i];\n",numels);
584 | fprintf(fp," dae_obj_memberdef* el = elems;\n");
585 | while(elitr != elend)
586 | {
587 | xsd_element* el = *elitr;
588 | char elcn[128];
589 | char eltcid[128];
590 | int min;
591 | int max;
592 | gen_cname_elem(elcn, el->name, sizeof(elcn));
593 | gen_cname_id(eltcid, el->type, sizeof(eltcid));
594 | min = (el->minoccurs!=xsd_UNSET) ? el->minoccurs : 1;
595 | max = (el->maxoccurs!=xsd_UNSET) ? el->maxoccurs : 1;
596 | fprintf(fp," el->name=\"%s\";\n", el->name);
597 | fprintf(fp," el->offset=offsetof(%s,%s);\n",tcn,elcn);
598 | fprintf(fp," el->objtypeid=%s;\n", eltcid);
599 | fprintf(fp," el->min=%i;\n", min);
600 | fprintf(fp," el->max=%i;\n", max);
601 | fprintf(fp," el->seq=%i;\n", el->seq);
602 | fprintf(fp," ++el;\n");
603 | ++elitr;
604 | }
605 |
606 | fprintf(fp," t->elems = elems;\n");
607 | fprintf(fp," t->numelems = %i;\n", numels);
608 | fprintf(fp," }\n");
609 | }
610 | fprintf(fp," ++t;\n");
611 | ++titr;
612 | }
613 | fprintf(fp," *types_out = s_types;\n");
614 | fprintf(fp," *numtypes_out = sizeof(s_types)/sizeof(*s_types);\n");
615 | fprintf(fp,"}\n");
616 | }
617 |
--------------------------------------------------------------------------------
/gen/src/gen.h:
--------------------------------------------------------------------------------
1 | #ifndef GEN_H_
2 | #define GEN_H_
3 |
4 | #include "xsd.h"
5 | #include
6 |
7 | void gen_print_typeids(
8 | FILE* fp,
9 | xsd_schema* schema);
10 |
11 | void gen_print_typedefs(
12 | FILE* fp,
13 | xsd_schema* schema);
14 |
15 | void gen_print_structs(
16 | FILE* fp,
17 | xsd_schema* schema);
18 |
19 | void gen_print_schema(
20 | FILE* fp,
21 | xsd_schema* schema);
22 |
23 | #endif // GEN_H_
24 |
--------------------------------------------------------------------------------
/gen/src/main.c:
--------------------------------------------------------------------------------
1 | #include "xsdparse.h"
2 | #include "gen.h"
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #define TYPEIDS_BGN "/*GEN_TYPEIDS_BGN*/"
10 | #define TYPEIDS_END "/*GEN_TYPEIDS_END*/"
11 | #define TYPEDEFS_BGN "/*GEN_TYPEDEFS_BGN*/"
12 | #define TYPEDEFS_END "/*GEN_TYPEDEFS_END*/"
13 | #define STRUCTS_BGN "/*GEN_STRUCTS_BGN*/"
14 | #define STRUCTS_END "/*GEN_STRUCTS_END*/"
15 | #define SCHEMA_BGN "/*GEN_SCHEMA_BGN*/"
16 | #define SCHEMA_END "/*GEN_SCHEMA_END*/"
17 |
18 | int main(
19 | int argc,
20 | char** argv)
21 | {
22 | if(argc == 4)
23 | {
24 | FILE* fpx = fopen(argv[1], "rb");
25 | FILE* fpi = fopen(argv[2], "rb");
26 | FILE* fpo = fopen(argv[3], "wb");
27 | if(fpx != NULL && fpi != NULL && fpo != NULL)
28 | {
29 | xsd_schema schema;
30 | char* data;
31 | size_t size;
32 | size_t readsize;
33 | int err;
34 | xsd_create_schema(&schema);
35 | {
36 | xsdparse_state st;
37 | XML_Parser xml;
38 | // initialize the xsd state data
39 | memset(&st, 0, sizeof(st));
40 | st.schema = &schema;
41 | // create expat parser
42 | xml = XML_ParserCreate(NULL);
43 | // read schema file
44 | fseek(fpx, 0, SEEK_END);
45 | size = ftell(fpx);
46 | fseek(fpx, 0, SEEK_SET);
47 | data = (char*) XML_GetBuffer(xml, size);
48 | readsize = fread(data, 1, size, fpx);
49 | if(readsize == size)
50 | {
51 | // parse schema xml
52 | XML_SetElementHandler(
53 | xml,
54 | xsdparse_startelement,
55 | xsdparse_endelement);
56 | XML_SetUserData(xml, &st);
57 | XML_ParseBuffer(xml, size, 1);
58 | // add hacks
59 | xsdparse_hacks(&schema);
60 | // validate and format schema
61 | err = xsd_validate_schema(&schema);
62 | assert(err == 0);
63 | xsd_flatten_schema(&schema);
64 | err = xsd_validate_schema(&schema);
65 | assert(err == 0);
66 | xsd_remove_unreferenced_types(&schema);
67 | err = xsd_validate_schema(&schema);
68 | assert(err == 0);
69 | free(st.stack);
70 | }
71 | else
72 | {
73 | err = -1;
74 | assert(0);
75 | }
76 | // clean up expat parser
77 | XML_ParserFree(xml);
78 | }
79 | data = NULL;
80 | if(err == 0)
81 | {
82 | size = 0;
83 | fseek(fpi, 0, SEEK_END);
84 | size = ftell(fpi);
85 | fseek(fpi, 0, SEEK_SET);
86 | if(size > 0)
87 | {
88 | data = (char*) malloc(sizeof(*data) * (size+1));
89 | if(fread(data, 1, size, fpi) != size)
90 | {
91 | free(data);
92 | data = NULL;
93 | size = 0;
94 | }
95 | }
96 | }
97 | if(data != NULL)
98 | {
99 | char* itr = data;
100 | int writing = 1;
101 | itr[size] = '\0';
102 | while(*itr != '\0')
103 | {
104 | if(!strncmp(itr, TYPEIDS_BGN, sizeof(TYPEIDS_BGN)-1))
105 | {
106 | gen_print_typeids(fpo, &schema);
107 | writing = 0;
108 | itr += sizeof(TYPEIDS_BGN);
109 | }
110 | else if(!strncmp(itr, TYPEIDS_END, sizeof(TYPEIDS_END)-1))
111 | {
112 | writing = 1;
113 | itr += sizeof(TYPEIDS_END);
114 | }
115 | else if(!strncmp(itr,TYPEDEFS_BGN,sizeof(TYPEDEFS_BGN)-1))
116 | {
117 | gen_print_typedefs(fpo, &schema);
118 | writing = 0;
119 | itr += sizeof(TYPEDEFS_BGN);
120 | }
121 | else if(!strncmp(itr,TYPEDEFS_END,sizeof(TYPEDEFS_END)-1))
122 | {
123 | writing = 1;
124 | itr += sizeof(TYPEDEFS_END);
125 | }
126 | else if(!strncmp(itr, STRUCTS_BGN, sizeof(STRUCTS_BGN)-1))
127 | {
128 | gen_print_structs(fpo, &schema);
129 | writing = 0;
130 | itr += sizeof(STRUCTS_BGN);
131 | }
132 | else if(!strncmp(itr, STRUCTS_END, sizeof(STRUCTS_END)-1))
133 | {
134 | writing = 1;
135 | itr += sizeof(STRUCTS_END);
136 | }
137 | else if(!strncmp(itr, SCHEMA_BGN, sizeof(SCHEMA_BGN)-1))
138 | {
139 | gen_print_schema(fpo, &schema);
140 | writing = 0;
141 | itr += sizeof(SCHEMA_BGN);
142 | }
143 | else if(!strncmp(itr, SCHEMA_END, sizeof(SCHEMA_END)-1))
144 | {
145 | writing = 1;
146 | itr += sizeof(SCHEMA_END);
147 | }
148 | else
149 | {
150 | if(writing)
151 | {
152 | fwrite(itr, 1, 1, fpo);
153 | }
154 | ++itr;
155 | }
156 | }
157 | free(data);
158 | }
159 | xsd_destroy_schema(&schema);
160 | }
161 | if(fpx != NULL)
162 | {
163 | fclose(fpx);
164 | }
165 | else
166 | {
167 | printf("error: could not open file \"%s\"\n", argv[1]);
168 | }
169 | if(fpi != NULL)
170 | {
171 | fclose(fpi);
172 | }
173 | else
174 | {
175 | printf("error: could not open file \"%s\"\n", argv[2]);
176 | }
177 | if(fpo != NULL)
178 | {
179 | fclose(fpo);
180 | }
181 | else
182 | {
183 | printf("error: could not open file \"%s\"\n", argv[3]);
184 | }
185 | }
186 | else
187 | {
188 | printf("usage: daegen <_output file>\n");
189 | }
190 | return EXIT_SUCCESS;
191 | }
192 |
--------------------------------------------------------------------------------
/gen/src/xsd.c:
--------------------------------------------------------------------------------
1 | #include "xsd.h"
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | //****************************************************************************
8 | static xsd_attrib* xsd_add_attrib(
9 | xsd_schema* schema,
10 | xsd_attrib*** arrayref,
11 | size_t* sizeref,
12 | const char* name,
13 | const char* type,
14 | const char* ref,
15 | const char* deflt,
16 | int required)
17 | {
18 | enum { CHUNK = 16 };
19 | xsd_attrib* at = (xsd_attrib*) calloc(1, sizeof(*at));
20 | size_t n = *sizeref;
21 | size_t cap = (n + CHUNK-1) & ~(CHUNK-1);
22 | size_t ncap = (n + CHUNK) & ~(CHUNK-1);
23 | if(ncap > cap)
24 | {
25 | *arrayref = (xsd_attrib**) realloc(*arrayref, ncap * sizeof(at));
26 | }
27 | (*arrayref)[n] = at;
28 | *sizeref = (*sizeref) + 1;
29 | at->name = xsd_strdup(name);
30 | at->type = xsd_strdup(type);
31 | at->ref = xsd_strdup(ref);
32 | at->deflt = xsd_strdup(deflt);
33 | at->required = required;
34 | return at;
35 | }
36 |
37 | //****************************************************************************
38 | static xsd_element* xsd_add_element(
39 | xsd_schema* schema,
40 | xsd_element*** arrayref,
41 | size_t* sizeref,
42 | const char* name,
43 | const char* type,
44 | const char* ref,
45 | int minoccurs,
46 | int maxoccurs,
47 | int seq)
48 | {
49 | enum { CHUNK = 16 };
50 | xsd_element** elements = *arrayref;
51 | xsd_element* el = (xsd_element*) calloc(1, sizeof(*el));
52 | size_t n = *sizeref;
53 | size_t cap = (n + CHUNK-1) & ~(CHUNK-1);
54 | size_t ncap = (n + CHUNK) & ~(CHUNK-1);
55 | if(ncap > cap)
56 | {
57 | elements = (xsd_element**) realloc(elements, ncap * sizeof(el));
58 | *arrayref = elements;
59 | }
60 | el->name = xsd_strdup(name);
61 | el->type = xsd_strdup(type);
62 | el->ref = xsd_strdup(ref);
63 | el->minoccurs = minoccurs;
64 | el->maxoccurs = maxoccurs;
65 | el->seq = seq;
66 | // sort element into correct sequence order
67 | while(n > 0 && elements[n-1]->seq > seq)
68 | {
69 | elements[n] = elements[n-1];
70 | --n;
71 | }
72 | elements[n] = el;
73 | *sizeref = (*sizeref) + 1;
74 | return el;
75 | }
76 |
77 | //****************************************************************************
78 | static xsd_group* xsd_add_group(
79 | xsd_schema* schema,
80 | xsd_group*** arrayref,
81 | size_t* sizeref,
82 | const char* name,
83 | const char* ref,
84 | int seq)
85 | {
86 | enum { CHUNK = 16 };
87 | xsd_group** groups = *arrayref;
88 | xsd_group* grp = (xsd_group*) calloc(1, sizeof(*grp));
89 | size_t n = *sizeref;
90 | size_t cap = (n + CHUNK-1) & ~(CHUNK-1);
91 | size_t ncap = (n + CHUNK) & ~(CHUNK-1);
92 | if(ncap > cap)
93 | {
94 | groups = (xsd_group**) realloc(groups, ncap * sizeof(grp));
95 | *arrayref = groups;
96 | }
97 | grp->name = xsd_strdup(name);
98 | grp->ref = xsd_strdup(ref);
99 | grp->seq = seq;
100 | // sort element into correct sequence order
101 | while(n > 0 && groups[n-1]->seq > seq)
102 | {
103 | groups[n] = groups[n-1];
104 | --n;
105 | }
106 | groups[n] = grp;
107 | *sizeref = (*sizeref) + 1;
108 | return grp;
109 | }
110 |
111 | //****************************************************************************
112 | static void xsd_destroy_attribs(
113 | xsd_attrib** attribs,
114 | size_t numattribs)
115 | {
116 | xsd_attrib** atitr = attribs;
117 | xsd_attrib** atend = atitr + numattribs;
118 | while(atitr != atend)
119 | {
120 | xsd_attrib* at = *atitr;
121 | free(at->name);
122 | free(at->type);
123 | free(at->ref);
124 | free(at->deflt);
125 | free(at);
126 | ++atitr;
127 | }
128 | free(attribs);
129 | }
130 |
131 | //****************************************************************************
132 | static void xsd_destroy_elements(
133 | xsd_element** elements,
134 | size_t numelements)
135 | {
136 | xsd_element** elitr = elements;
137 | xsd_element** elend = elitr + numelements;
138 | while(elitr != elend)
139 | {
140 | xsd_element* el = *elitr;
141 | free(el->name);
142 | free(el->type);
143 | free(el->ref);
144 | free(el);
145 | ++elitr;
146 | }
147 | free(elements);
148 | }
149 |
150 | //****************************************************************************
151 | static void xsd_destroy_groups(
152 | xsd_group** groups,
153 | size_t numgroups)
154 | {
155 | xsd_group** grpitr = groups;
156 | xsd_group** grpend = grpitr + numgroups;
157 | while(grpitr != grpend)
158 | {
159 | xsd_group* grp = *grpitr;
160 | free(grp->name);
161 | free(grp->ref);
162 | xsd_destroy_elements(grp->elements, grp->numelements);
163 | free(grp);
164 | ++grpitr;
165 | }
166 | free(groups);
167 | }
168 |
169 | //****************************************************************************
170 | static void xsd_destroy_type(
171 | xsd_type* t)
172 | {
173 | if(t->hassimple)
174 | {
175 | free(t->simple.itemtype);
176 | }
177 | if(t->hascomplex)
178 | {
179 | xsd_destroy_attribs(t->complex.attribs, t->complex.numattribs);
180 | xsd_destroy_elements(t->complex.elements, t->complex.numelements);
181 | xsd_destroy_groups(t->complex.groups, t->complex.numgroups);
182 | }
183 | free(t->name);
184 | free(t->base);
185 | free(t);
186 | }
187 |
188 | //****************************************************************************
189 | static void xsd_flatten_attribs(
190 | xsd_schema* schema)
191 | {
192 | // expandes all attrib references within type defintions into attrib defs
193 | xsd_type** titr = schema->types;
194 | xsd_type** tend = titr + schema->numtypes;
195 | while(titr != tend)
196 | {
197 | xsd_type* t = *titr;
198 | if(t->hascomplex)
199 | {
200 | xsd_attrib** atitr = t->complex.attribs;
201 | xsd_attrib** atend = atitr + t->complex.numattribs;
202 | while(atitr != atend)
203 | {
204 | xsd_attrib* at = *atitr;
205 | xsd_attrib* atref = NULL;
206 | char* ref = at->ref;
207 | while(ref != NULL)
208 | {
209 | atref = xsd_find_attrib(schema, ref);
210 | assert(atref != NULL);
211 | ref = atref->ref;
212 | }
213 | if(atref != NULL)
214 | {
215 | at->name = xsd_strdup(atref->name);
216 | at->type = xsd_strdup(atref->type);
217 | at->deflt = xsd_strdup(atref->deflt);
218 | free(at->ref);
219 | at->ref = NULL;
220 | }
221 | ++atitr;
222 | }
223 | }
224 | ++titr;
225 | }
226 | }
227 |
228 | //****************************************************************************
229 | static void xsd_flatten_elements(
230 | xsd_schema* schema)
231 | {
232 | // replaces all element refs within groups and types with element defs
233 | xsd_element** elitr;
234 | xsd_element** elend;
235 | xsd_group** grpitr;
236 | xsd_group** grpend;
237 | xsd_type** titr;
238 | xsd_type** tend;
239 | grpitr = schema->groups;
240 | grpend = grpitr + schema->numgroups;
241 | while(grpitr != grpend)
242 | {
243 | xsd_group* grp = *grpitr;
244 | elitr = grp->elements;
245 | elend = elitr + grp->numelements;
246 | while(elitr != elend)
247 | {
248 | xsd_element* el = *elitr;
249 | xsd_element* elref = NULL;
250 | char* ref = el->ref;
251 | while(ref != NULL)
252 | {
253 | elref = xsd_find_element(schema, ref);
254 | assert(elref != NULL);
255 | ref = elref->ref;
256 | }
257 | if(elref != NULL)
258 | {
259 | el->name = xsd_strdup(elref->name);
260 | el->type = xsd_strdup(elref->type);
261 | free(el->ref);
262 | el->ref = NULL;
263 | }
264 | ++elitr;
265 | }
266 | ++grpitr;
267 | }
268 | titr = schema->types;
269 | tend = titr + schema->numtypes;
270 | while(titr != tend)
271 | {
272 | xsd_type* t = *titr;
273 | if(t->hascomplex)
274 | {
275 | elitr = t->complex.elements;
276 | elend = elitr + t->complex.numelements;
277 | while(elitr != elend)
278 | {
279 | xsd_element* el = *elitr;
280 | xsd_element* elref = NULL;
281 | char* ref = el->ref;
282 | while(ref != NULL)
283 | {
284 | elref = xsd_find_element(schema, ref);
285 | assert(elref != NULL);
286 | ref = elref->ref;
287 | }
288 | if(elref != NULL)
289 | {
290 | el->name = xsd_strdup(elref->name);
291 | el->type = xsd_strdup(elref->type);
292 | free(el->ref);
293 | el->ref = NULL;
294 | }
295 | ++elitr;
296 | }
297 | grpitr = t->complex.groups;
298 | grpend = grpitr + t->complex.numgroups;
299 | while(grpitr != grpend)
300 | {
301 | xsd_group* grp = *grpitr;
302 | elitr = grp->elements;
303 | elend = elitr + grp->numelements;
304 | while(elitr != elend)
305 | {
306 | xsd_element* el = *elitr;
307 | xsd_element* elref = NULL;
308 | char* ref = el->ref;
309 | while(ref != NULL)
310 | {
311 | elref = xsd_find_element(schema, ref);
312 | assert(elref != NULL);
313 | ref = elref->ref;
314 | }
315 | if(elref != NULL)
316 | {
317 | el->name = xsd_strdup(elref->name);
318 | el->type = xsd_strdup(elref->type);
319 | free(el->ref);
320 | el->ref = NULL;
321 | }
322 | ++elitr;
323 | }
324 | ++grpitr;
325 | }
326 | }
327 | ++titr;
328 | }
329 | }
330 |
331 | //****************************************************************************
332 | static void xsd_flatten_groups(
333 | xsd_schema* schema)
334 | {
335 | // expandes all groups within type defintions into elements
336 | xsd_type** titr = schema->types;
337 | xsd_type** tend = titr + schema->numtypes;
338 | while(titr != tend)
339 | {
340 | xsd_type* t = *titr;
341 | xsd_group** grpitr;
342 | xsd_group** grpend;
343 | xsd_element** elitr;
344 | xsd_element** elend;
345 | // offset the sequence numbers of all the groups
346 | grpitr = t->complex.groups;
347 | grpend = grpitr + t->complex.numgroups;
348 | while(grpitr != grpend)
349 | {
350 | xsd_group* grp = *grpitr;
351 | xsd_group** inrgrpitr = t->complex.groups;
352 | xsd_group** inrgrpend = inrgrpitr + t->complex.numgroups;
353 | while(inrgrpitr != inrgrpend)
354 | {
355 | xsd_group* inrgrp = *inrgrpitr;
356 | if(grp->seq > inrgrp->seq)
357 | {
358 | // if the group instance is a reference, the sequence
359 | // number of the instance comes from the reference
360 | if(inrgrp->ref != NULL)
361 | {
362 | // the number of sequenced elements in the group
363 | // comes from the reference target
364 | inrgrp = xsd_find_group(schema, inrgrp->ref);
365 | assert(inrgrp != NULL);
366 | }
367 | grp->seq += inrgrp->seqmax;
368 | }
369 | ++inrgrpitr;
370 | }
371 | ++grpitr;
372 | }
373 | // offset the sequence numbers of all the existing elements
374 | elitr = t->complex.elements;
375 | elend = elitr + t->complex.numelements;
376 | while(elitr != elend)
377 | {
378 | xsd_element* el = *elitr;
379 | xsd_group** inrgrpitr = t->complex.groups;
380 | xsd_group** inrgrpend = inrgrpitr + t->complex.numgroups;
381 | while(inrgrpitr != inrgrpend)
382 | {
383 | xsd_group* inrgrp = *inrgrpitr;
384 | if(el->seq > inrgrp->seq)
385 | {
386 | // if the group instance is a reference, the sequence
387 | // number of the instance comes from the reference
388 | if(inrgrp->ref != NULL)
389 | {
390 | // the number of sequenced elements in the group
391 | // comes from the reference target
392 | inrgrp = xsd_find_group(schema, inrgrp->ref);
393 | assert(inrgrp != NULL);
394 | }
395 | el->seq += inrgrp->seqmax;
396 | }
397 | ++inrgrpitr;
398 | }
399 | ++elitr;
400 | }
401 | grpitr = t->complex.groups;
402 | grpend = grpitr + t->complex.numgroups;
403 | while(grpitr != grpend)
404 | {
405 | xsd_group* grp = *grpitr;
406 | int seqoffset = grp->seq; // save before resolving reference
407 | if(grp->ref != NULL)
408 | {
409 | grp = xsd_find_group(schema, grp->ref);
410 | assert(grp != NULL);
411 | }
412 | elitr = grp->elements;
413 | elend = elitr + grp->numelements;
414 | while(elitr != elend)
415 | {
416 | xsd_element* el = *elitr;
417 | xsd_add_element_to_type(
418 | schema,
419 | t,
420 | el->name,
421 | el->type,
422 | el->ref,
423 | el->minoccurs,
424 | el->maxoccurs,
425 | seqoffset + el->seq);
426 | ++elitr;
427 | }
428 | ++grpitr;
429 | }
430 | xsd_destroy_groups(t->complex.groups, t->complex.numgroups);
431 | t->complex.groups = NULL;
432 | t->complex.numgroups = 0;
433 | ++titr;
434 | }
435 | xsd_destroy_groups(schema->groups, schema->numgroups);
436 | schema->groups = NULL;
437 | schema->numgroups = 0;
438 | }
439 |
440 | //****************************************************************************
441 | static void xsd_flatten_relation(
442 | xsd_schema* schema,
443 | xsd_type* t,
444 | xsd_type* tbase)
445 | {
446 | // relation type should never be set to rename until after type is
447 | // flattened
448 | assert(t->baserelation != xsd_BASE_RENAME);
449 | if(tbase->hassimple)
450 | {
451 | // copy simple content from base type
452 | t->simple.itemtype=xsd_strdup(tbase->simple.itemtype);
453 | if(t->simple.minoccurs == xsd_UNSET)
454 | {
455 | t->simple.minoccurs = tbase->simple.minoccurs;
456 | }
457 | if(t->simple.maxoccurs == xsd_UNSET)
458 | {
459 | t->simple.maxoccurs = tbase->simple.maxoccurs;
460 | }
461 | t->hassimple = 1;
462 | }
463 | if(tbase->hascomplex && tbase->complex.numattribs > 0)
464 | {
465 | // copy attributes from base type
466 | xsd_attrib** atitr = tbase->complex.attribs;
467 | xsd_attrib** atend = atitr+tbase->complex.numattribs;
468 | while(atitr != atend)
469 | {
470 | xsd_attrib* at = *atitr;
471 | xsd_add_attrib_to_type(
472 | schema,
473 | t,
474 | at->name,
475 | at->type,
476 | at->ref,
477 | at->deflt,
478 | at->required);
479 | ++atitr;
480 | }
481 | t->hascomplex = 1;
482 | }
483 | if(tbase->hascomplex && t->baserelation == xsd_BASE_EXTEND)
484 | {
485 | // only copy groups and elements if relationship is extends
486 | xsd_group** grpitr;
487 | xsd_group** grpend;
488 | xsd_element** elitr;
489 | xsd_element** elend;
490 | // offset sequence number of all child groups
491 | grpitr = t->complex.groups;
492 | grpend = grpitr + t->complex.numgroups;
493 | while(grpitr != grpend)
494 | {
495 | xsd_group* grp = *grpitr;
496 | grp->seq += tbase->complex.seqmax;
497 | ++grpitr;
498 | }
499 | // offset sequence number of all child elements
500 | elitr = t->complex.elements;
501 | elend = elitr + t->complex.numelements;
502 | while(elitr != elend)
503 | {
504 | xsd_element* el = *elitr;
505 | el->seq += tbase->complex.seqmax;
506 | ++elitr;
507 | }
508 | // add base type groups
509 | grpitr = tbase->complex.groups;
510 | grpend = grpitr + tbase->complex.numgroups;
511 | while(grpitr != grpend)
512 | {
513 | xsd_group* grp = *grpitr;
514 | xsd_group* cgrp = xsd_add_group_to_type(
515 | schema,
516 | t,
517 | grp->name,
518 | grp->ref,
519 | grp->seq);
520 | // copy base group elements to child group
521 | elitr = grp->elements;
522 | elend = elitr + grp->numelements;
523 | while(elitr != elend)
524 | {
525 | xsd_element* el = *elitr;
526 | xsd_add_element_to_group(
527 | schema,
528 | cgrp,
529 | el->name,
530 | el->type,
531 | el->ref,
532 | el->minoccurs,
533 | el->maxoccurs,
534 | el->seq);
535 | ++elitr;
536 | }
537 | ++grpitr;
538 | }
539 | // add base type elements
540 | elitr = tbase->complex.elements;
541 | elend = elitr + tbase->complex.numelements;
542 | while(elitr != elend)
543 | {
544 | xsd_element* el = *elitr;
545 | xsd_add_element_to_type(
546 | schema,
547 | t,
548 | el->name,
549 | el->type,
550 | el->ref,
551 | el->minoccurs,
552 | el->maxoccurs,
553 | el->seq);
554 | ++elitr;
555 | }
556 | t->hascomplex = 1;
557 | t->anycontent = tbase->anycontent;
558 | }
559 | }
560 |
561 | //****************************************************************************
562 | static int xsd_is_rename(
563 | xsd_schema* schema,
564 | xsd_type* t)
565 | {
566 | xsd_type* tbase = NULL;
567 | int rename = 0;
568 | if(t->baserelation != xsd_BASE_NONE)
569 | {
570 | rename = 1;
571 | tbase = xsd_find_type(schema, t->base);
572 | assert(tbase != NULL);
573 | if(t->hassimple)
574 | {
575 | if(t->simple.itemtype != NULL)
576 | {
577 | if(tbase->simple.itemtype != NULL)
578 | {
579 | if(strcmp(t->simple.itemtype, tbase->simple.itemtype))
580 | {
581 | rename = 0;
582 | }
583 | }
584 | else
585 | {
586 | rename = 0;
587 | }
588 | }
589 | if(t->simple.minoccurs != xsd_UNSET)
590 | {
591 | if(t->simple.minoccurs != tbase->simple.minoccurs)
592 | {
593 | rename = 0;
594 | }
595 | }
596 | if(t->simple.maxoccurs != xsd_UNSET)
597 | {
598 | if(t->simple.maxoccurs != tbase->simple.maxoccurs)
599 | {
600 | rename = 0;
601 | }
602 | }
603 | }
604 | if(t->hascomplex)
605 | {
606 | if (t->complex.numattribs != 0)
607 | {
608 | rename = 0;
609 | }
610 | if(t->complex.numgroups != 0)
611 | {
612 | rename = 0;
613 | }
614 | if(t->complex.numelements != 0)
615 | {
616 | rename = 0;
617 | }
618 | if(t->anycontent && !tbase->anycontent)
619 | {
620 | rename = 0;
621 | }
622 | }
623 | }
624 | else if(t->hassimple && !t->hascomplex)
625 | {
626 | // no base type, but it's simple
627 | // flatten it if it does not deviate from primitive types
628 | assert(t->simple.itemtype != NULL);
629 | if(t->simple.minoccurs==xsd_UNSET || t->simple.minoccurs==1)
630 | {
631 | if(t->simple.maxoccurs==xsd_UNSET || t->simple.maxoccurs==1)
632 | {
633 | if(strcmp(t->name, t->simple.itemtype))
634 | {
635 | // replace it if it is not the primitive definition
636 | tbase = xsd_find_type(schema, t->simple.itemtype);
637 | rename = 1;
638 | }
639 | }
640 | }
641 | }
642 | return rename;
643 | }
644 |
645 | //****************************************************************************
646 | static void xsd_replace(
647 | xsd_schema* schema,
648 | const char* src,
649 | const char* target)
650 | {
651 | xsd_type** titr = schema->types;
652 | xsd_type** tend = titr + schema->numtypes;
653 | xsd_attrib** atitr;
654 | xsd_attrib** atend;
655 | xsd_group** grpitr;
656 | xsd_group** grpend;
657 | xsd_element** elitr;
658 | xsd_element** elend;
659 | // replace matching top level attribs with target type
660 | atitr = schema->attribs;
661 | atend = atitr + schema->numattribs;
662 | while(atitr != atend)
663 | {
664 | xsd_attrib* at = *atitr;
665 | if(at->type != NULL && !strcmp(at->type,src))
666 | {
667 | free(at->type);
668 | at->type = xsd_strdup(target);
669 | }
670 | ++atitr;
671 | }
672 | // replace matching top level elements with target type
673 | elitr = schema->elements;
674 | elend = elitr + schema->numelements;
675 | while(elitr != elend)
676 | {
677 | xsd_element* el = *elitr;
678 | if(el->type != NULL && !strcmp(el->type,src))
679 | {
680 | free(el->type);
681 | el->type = xsd_strdup(target);
682 | }
683 | ++elitr;
684 | }
685 | // replace matching group elements with target type
686 | grpitr = schema->groups;
687 | grpend = grpitr + schema->numgroups;
688 | while(grpitr != grpend)
689 | {
690 | xsd_group* grp = *grpitr;
691 | elitr = grp->elements;
692 | elend = elitr + grp->numelements;
693 | while(elitr != elend)
694 | {
695 | xsd_element* el = *elitr;
696 | if(el->type != NULL && !strcmp(el->type,src))
697 | {
698 | free(el->type);
699 | el->type = xsd_strdup(target);
700 | }
701 | ++elitr;
702 | }
703 | ++grpitr;
704 | }
705 | while(titr != tend)
706 | {
707 | xsd_type* t = *titr;
708 | if(t->base != NULL)
709 | {
710 | if(!strcmp(t->base,src))
711 | {
712 | free(t->base);
713 | t->base = xsd_strdup(target);
714 | }
715 | }
716 | if(t->hassimple)
717 | {
718 | char* itemtype = t->simple.itemtype;
719 | if(itemtype != NULL && !strcmp(itemtype, src))
720 | {
721 | free(t->simple.itemtype);
722 | t->simple.itemtype = xsd_strdup(target);
723 | }
724 | }
725 | if(t->hascomplex)
726 | {
727 | // replace matching attribs with target type
728 | atitr = t->complex.attribs;
729 | atend = atitr + t->complex.numattribs;
730 | while(atitr != atend)
731 | {
732 | xsd_attrib* at = *atitr;
733 | if(at->type != NULL && !strcmp(at->type,src))
734 | {
735 | free(at->type);
736 | at->type = xsd_strdup(target);
737 | }
738 | ++atitr;
739 | }
740 | // replace matching elements with target type
741 | elitr = t->complex.elements;
742 | elend = elitr + t->complex.numelements;
743 | while(elitr != elend)
744 | {
745 | xsd_element* el = *elitr;
746 | if(el->type != NULL && !strcmp(el->type,src))
747 | {
748 | free(el->type);
749 | el->type = xsd_strdup(target);
750 | }
751 | ++elitr;
752 | }
753 | // replace matching group elements with target type
754 | grpitr = t->complex.groups;
755 | grpend = grpitr + t->complex.numgroups;
756 | while(grpitr != grpend)
757 | {
758 | xsd_group* grp = *grpitr;
759 | elitr = grp->elements;
760 | elend = elitr + grp->numelements;
761 | while(elitr != elend)
762 | {
763 | xsd_element* el = *elitr;
764 | if(el->type != NULL && !strcmp(el->type,src))
765 | {
766 | free(el->type);
767 | el->type = xsd_strdup(target);
768 | }
769 | ++elitr;
770 | }
771 | ++grpitr;
772 | }
773 | }
774 | ++titr;
775 | }
776 | }
777 |
778 | //****************************************************************************
779 | static void xsd_flatten_types(
780 | xsd_schema* schema)
781 | {
782 | // expands child types to include all inherited properties from base type
783 | int changed; // controls outer loop
784 | int done; // redundant correctness check
785 | do
786 | {
787 | // this is an iterative process that must be repeated until
788 | // no changes are made
789 | xsd_type** titr = schema->types;
790 | xsd_type** tend = titr + schema->numtypes;
791 | changed = 0;
792 | done = 1;
793 | while(titr != tend)
794 | {
795 | xsd_type* t = *titr;
796 | xsd_base_relation rel = t->baserelation;
797 | int isrename = xsd_is_rename(schema, t);
798 | if(rel == xsd_BASE_EXTEND || rel == xsd_BASE_RESTRICTION)
799 | {
800 | done = 0;
801 | }
802 | if (rel == xsd_BASE_EXTEND ||
803 | rel == xsd_BASE_RESTRICTION ||
804 | (rel != xsd_BASE_RENAME && isrename))
805 | {
806 | // only process type if its base has already been flattened
807 | xsd_type* tbase;
808 | xsd_base_relation baserel;
809 | if(t->baserelation != xsd_BASE_NONE)
810 | {
811 | tbase = xsd_find_type(schema, t->base);
812 | }
813 | else
814 | {
815 | // it's possible that the type did not specify a base,
816 | // but was a non-array simple type that did not specify
817 | // any attributes. in that case, it's treated as a rename
818 | tbase = xsd_find_type(schema, t->simple.itemtype);
819 | }
820 | baserel = tbase->baserelation;
821 | assert(tbase != NULL);
822 | if (baserel != xsd_BASE_EXTEND &&
823 | baserel != xsd_BASE_RESTRICTION &&
824 | (baserel==xsd_BASE_RENAME||!xsd_is_rename(schema,tbase)))
825 | {
826 | // copy all members of the base down to the child type
827 | xsd_flatten_relation(schema, t, tbase);
828 | if(isrename)
829 | {
830 | // type has no unique content that differs from the
831 | // base, so treat it as a rename
832 | if(!t->isanonymous)
833 | {
834 | // if the type was explicity defined, keep it, but
835 | // flatten the relationship and mark as a rename
836 | t->baserelation = xsd_BASE_RENAME;
837 | assert(tbase != NULL);
838 | if(t->base == NULL)
839 | {
840 | t->base = xsd_strdup(tbase->name);
841 | }
842 | }
843 | else
844 | {
845 | // if it was an implicitly defined type, replace
846 | // all references to it with the base type and
847 | // remove it completely
848 | xsd_replace(schema, t->name, tbase->name);
849 | xsd_remove_type(schema,(int)(titr-schema->types));
850 | }
851 | }
852 | else
853 | {
854 | // remove relationship
855 | free(t->base);
856 | t->base = NULL;
857 | t->baserelation = xsd_BASE_NONE;
858 | }
859 | // indicate change occurred
860 | changed = 1;
861 | // need to break the loop because iterator may be invalid
862 | break;
863 | }
864 | }
865 | ++titr;
866 | }
867 | }
868 | while(changed);
869 | // there should not be any extend or restriction inheritence remaining
870 | if(done == 0)
871 | {
872 | assert(0);
873 | }
874 | }
875 |
876 | //****************************************************************************
877 | static void xsd_predefine_types(
878 | xsd_schema* schema)
879 | {
880 | xsd_type* t;
881 | t = xsd_add_type(schema, xsd_DATA_BOOL);
882 | t->isbuiltin = 1;
883 | t->hassimple = 1;
884 | t->simple.itemtype = xsd_strdup(xsd_DATA_BOOL);
885 | t->simple.minoccurs = 1;
886 | t->simple.maxoccurs = 1;
887 | t = xsd_add_type(schema, xsd_DATA_HEX);
888 | t->isbuiltin = 1;
889 | t->hassimple = 1;
890 | t->simple.itemtype = xsd_strdup(xsd_DATA_HEX);
891 | t->simple.minoccurs = 1;
892 | t->simple.maxoccurs = 1;
893 | t = xsd_add_type(schema, xsd_DATA_FLOAT);
894 | t->isbuiltin = 1;
895 | t->hassimple = 1;
896 | t->simple.itemtype = xsd_strdup(xsd_DATA_FLOAT);
897 | t->simple.minoccurs = 1;
898 | t->simple.maxoccurs = 1;
899 | t = xsd_add_type(schema, xsd_DATA_INT8);
900 | t->isbuiltin = 1;
901 | t->hassimple = 1;
902 | t->simple.itemtype = xsd_strdup(xsd_DATA_INT8);
903 | t->simple.minoccurs = 1;
904 | t->simple.maxoccurs = 1;
905 | t = xsd_add_type(schema, xsd_DATA_INT16);
906 | t->isbuiltin = 1;
907 | t->hassimple = 1;
908 | t->simple.itemtype = xsd_strdup(xsd_DATA_INT16);
909 | t->simple.minoccurs = 1;
910 | t->simple.maxoccurs = 1;
911 | t = xsd_add_type(schema, xsd_DATA_INT32);
912 | t->isbuiltin = 1;
913 | t->hassimple = 1;
914 | t->simple.itemtype = xsd_strdup(xsd_DATA_INT32);
915 | t->simple.minoccurs = 1;
916 | t->simple.maxoccurs = 1;
917 | t = xsd_add_type(schema, xsd_DATA_STRING);
918 | t->isbuiltin = 1;
919 | t->hassimple = 1;
920 | t->simple.itemtype = xsd_strdup(xsd_DATA_STRING);
921 | t->simple.minoccurs = 1;
922 | t->simple.maxoccurs = 1;
923 | t = xsd_add_type(schema, xsd_DATA_UINT8);
924 | t->isbuiltin = 1;
925 | t->hassimple = 1;
926 | t->simple.itemtype = xsd_strdup(xsd_DATA_UINT8);
927 | t->simple.minoccurs = 1;
928 | t->simple.maxoccurs = 1;
929 | t = xsd_add_type(schema, xsd_DATA_UINT16);
930 | t->isbuiltin = 1;
931 | t->hassimple = 1;
932 | t->simple.itemtype = xsd_strdup(xsd_DATA_UINT16);
933 | t->simple.minoccurs = 1;
934 | t->simple.maxoccurs = 1;
935 | t = xsd_add_type(schema, xsd_DATA_UINT32);
936 | t->isbuiltin = 1;
937 | t->hassimple = 1;
938 | t->simple.itemtype = xsd_strdup(xsd_DATA_UINT32);
939 | t->simple.minoccurs = 1;
940 | t->simple.maxoccurs = 1;
941 | // add redefines of base types
942 | t = xsd_add_type(schema, "xs:anyURI");
943 | t->isbuiltin = 1;
944 | t->base = xsd_strdup(xsd_DATA_STRING);
945 | t->baserelation = xsd_BASE_RESTRICTION;
946 | t = xsd_add_type(schema, "xs:dateTime");
947 | t->isbuiltin = 1;
948 | t->base = xsd_strdup(xsd_DATA_STRING);
949 | t->baserelation = xsd_BASE_RESTRICTION;
950 | t = xsd_add_type(schema, "xs:double");
951 | t->isbuiltin = 1;
952 | t->base = xsd_strdup(xsd_DATA_FLOAT);
953 | t->baserelation = xsd_BASE_RESTRICTION;
954 | t = xsd_add_type(schema, "xs:ID");
955 | t->isbuiltin = 1;
956 | t->base = xsd_strdup(xsd_DATA_STRING);
957 | t->baserelation = xsd_BASE_RESTRICTION;
958 | t = xsd_add_type(schema, "xs:IDREF");
959 | t->isbuiltin = 1;
960 | t->base = xsd_strdup(xsd_DATA_STRING);
961 | t->baserelation = xsd_BASE_RESTRICTION;
962 | t = xsd_add_type(schema, "xs:integer");
963 | t->isbuiltin = 1;
964 | t->base = xsd_strdup(xsd_DATA_INT32);
965 | t->baserelation = xsd_BASE_RESTRICTION;
966 | t = xsd_add_type(schema, "xs:long");
967 | t->isbuiltin = 1;
968 | t->base = xsd_strdup(xsd_DATA_INT32);
969 | t->baserelation = xsd_BASE_RESTRICTION;
970 | t = xsd_add_type(schema, "xs:Name");
971 | t->isbuiltin = 1;
972 | t->base = xsd_strdup(xsd_DATA_STRING);
973 | t->baserelation = xsd_BASE_RESTRICTION;
974 | t = xsd_add_type(schema, "xs:NCName");
975 | t->isbuiltin = 1;
976 | t->base = xsd_strdup(xsd_DATA_STRING);
977 | t->baserelation = xsd_BASE_RESTRICTION;
978 | t = xsd_add_type(schema, "xs:NMTOKEN");
979 | t->isbuiltin = 1;
980 | t->base = xsd_strdup(xsd_DATA_STRING);
981 | t->baserelation = xsd_BASE_RESTRICTION;
982 | t = xsd_add_type(schema, "xs:nonNegativeInteger");
983 | t->isbuiltin = 1;
984 | t->base = xsd_strdup(xsd_DATA_UINT32);
985 | t->baserelation = xsd_BASE_RESTRICTION;
986 | t = xsd_add_type(schema, "xs:positiveInteger");
987 | t->isbuiltin = 1;
988 | t->base = xsd_strdup(xsd_DATA_UINT32);
989 | t->baserelation = xsd_BASE_RESTRICTION;
990 | t = xsd_add_type(schema, "xs:token");
991 | t->isbuiltin = 1;
992 | t->base = xsd_strdup(xsd_DATA_STRING);
993 | t->baserelation = xsd_BASE_RESTRICTION;
994 | t = xsd_add_type(schema, "xs:unsignedLong");
995 | t->isbuiltin = 1;
996 | t->base = xsd_strdup(xsd_DATA_UINT32);
997 | t->baserelation = xsd_BASE_RESTRICTION;
998 | // additional misc types
999 | t = xsd_add_type(schema, "xs:IDREFS");
1000 | t->isbuiltin = 1;
1001 | t->hassimple = 1;
1002 | t->simple.itemtype = xsd_strdup("xs:ID");
1003 | t->simple.minoccurs = 0;
1004 | t->simple.maxoccurs = -1;
1005 | // top level attribs
1006 | xsd_add_attrib_global(schema, "xml:base", "xs:anyURI", NULL, NULL, 0);
1007 | // top level elements
1008 | }
1009 |
1010 | //****************************************************************************
1011 | static int xsd_validate_attrib(
1012 | xsd_schema* schema,
1013 | xsd_attrib** list,
1014 | size_t listsize,
1015 | xsd_attrib* at)
1016 | {
1017 | int result = 0;
1018 | if(at->name != NULL)
1019 | {
1020 | // make sure all attributes in the list have a unique name
1021 | xsd_attrib** atitr = list;
1022 | xsd_attrib** atend = atitr + listsize;
1023 | while(atitr != atend)
1024 | {
1025 | xsd_attrib* atother = *atitr;
1026 | if(atother != at)
1027 | {
1028 | if(atother->name != NULL && !strcmp(atother->name, at->name))
1029 | {
1030 | // name must be unique
1031 | assert(0);
1032 | result = -1;
1033 | break;
1034 | }
1035 | }
1036 | ++atitr;
1037 | }
1038 | }
1039 | if(at->type != NULL)
1040 | {
1041 | xsd_type* attype = xsd_find_type(schema, at->type);
1042 | if(at->name == NULL)
1043 | {
1044 | // must have a name
1045 | assert(0);
1046 | result = -1;
1047 | }
1048 | if(attype != NULL)
1049 | {
1050 | if(attype->hascomplex)
1051 | {
1052 | // make sure the attribute type is not complex
1053 | assert(0);
1054 | result = -1;
1055 | }
1056 | }
1057 | else
1058 | {
1059 | // make sure the attribute type actually exists
1060 | assert(0);
1061 | result = -1;
1062 | }
1063 | }
1064 | else if(at->ref != NULL)
1065 | {
1066 | xsd_attrib* atref = xsd_find_attrib(schema, at->ref);
1067 | if(atref == NULL)
1068 | {
1069 | // make sure the referenced attribute exists
1070 | assert(0);
1071 | result = -1;
1072 | }
1073 | }
1074 | else
1075 | {
1076 | // make sure the attribute has a type or ref
1077 | assert(0);
1078 | result = -1;
1079 | }
1080 | return result;
1081 | }
1082 |
1083 | //****************************************************************************
1084 | static int xsd_validate_element(
1085 | xsd_schema* schema,
1086 | xsd_element** list,
1087 | size_t listsize,
1088 | xsd_element* el)
1089 | {
1090 | int result = 0;
1091 | if(el->name != NULL)
1092 | {
1093 | // make sure all elements in the list have a unique name
1094 | xsd_element** elitr = list;
1095 | xsd_element** elend = elitr + listsize;
1096 | while(elitr != elend)
1097 | {
1098 | xsd_element* elother = *elitr;
1099 | if(elother != el)
1100 | {
1101 | if(elother->name != NULL && !strcmp(elother->name, el->name))
1102 | {
1103 | if(el->type == NULL || elother->type == NULL)
1104 | {
1105 | // must have types
1106 | assert(0);
1107 | result = -1;
1108 | break;
1109 | }
1110 | if(strcmp(el->type, elother->type))
1111 | {
1112 | // must have same type
1113 | // this is artificial constraint not imposed by schema
1114 | // but required for code generation
1115 | assert(0);
1116 | result = -1;
1117 | break;
1118 | }
1119 | }
1120 | }
1121 | ++elitr;
1122 | }
1123 | }
1124 | if(el->type != NULL)
1125 | {
1126 | xsd_type* eltype = xsd_find_type(schema, el->type);
1127 | if(el->name == NULL)
1128 | {
1129 | // must have a name
1130 | assert(0);
1131 | result = -1;
1132 | }
1133 | if(eltype == NULL)
1134 | {
1135 | // make sure the element type exists
1136 | assert(0);
1137 | result = -1;
1138 | }
1139 | }
1140 | else if(el->ref != NULL)
1141 | {
1142 | xsd_element* elref = xsd_find_element(schema, el->ref);
1143 | if(elref == NULL)
1144 | {
1145 | // make sure the referenced element exists
1146 | assert(0);
1147 | result = -1;
1148 | }
1149 | }
1150 | else
1151 | {
1152 | assert(0);
1153 | result = -1;
1154 | }
1155 | return result;
1156 | }
1157 |
1158 | //****************************************************************************
1159 | static int xsd_validate_group(
1160 | xsd_schema* schema,
1161 | xsd_group** list,
1162 | size_t listsize,
1163 | xsd_group* grp)
1164 | {
1165 | int result = 0;
1166 | if(grp->name != NULL)
1167 | {
1168 | // make sure all groups in the list have a unique name
1169 | xsd_group** grpitr = list;
1170 | xsd_group** grpend = grpitr + listsize;
1171 | while(grpitr != grpend)
1172 | {
1173 | xsd_group* grpother = *grpitr;
1174 | if(grpother != grp)
1175 | {
1176 | if(grpother->name!=NULL && !strcmp(grpother->name,grp->name))
1177 | {
1178 | // name must be unique
1179 | assert(0);
1180 | result = -1;
1181 | break;
1182 | }
1183 | }
1184 | ++grpitr;
1185 | }
1186 | }
1187 | if(grp->ref != NULL)
1188 | {
1189 | xsd_group* grpref = xsd_find_group(schema, grp->ref);
1190 | if(grpref == NULL)
1191 | {
1192 | // make sure the referenced group exists
1193 | assert(0);
1194 | result = -1;
1195 | }
1196 | if(grp->numelements > 0)
1197 | {
1198 | // references should not define elements themselves
1199 | assert(0);
1200 | result = -1;
1201 | }
1202 | }
1203 | else
1204 | {
1205 | xsd_element** elitr = grp->elements;
1206 | xsd_element** elend = elitr + grp->numelements;
1207 | while(elitr != elend && result == 0)
1208 | {
1209 | result = xsd_validate_element(
1210 | schema,
1211 | grp->elements,
1212 | grp->numelements,
1213 | *elitr);
1214 | ++elitr;
1215 | }
1216 | }
1217 | return result;
1218 | }
1219 |
1220 |
1221 | //****************************************************************************
1222 | xsd_attrib* xsd_add_attrib_global(
1223 | xsd_schema* schema,
1224 | const char* name,
1225 | const char* type,
1226 | const char* ref,
1227 | const char* deflt,
1228 | int required)
1229 | {
1230 | return xsd_add_attrib(
1231 | schema,
1232 | &schema->attribs,
1233 | &schema->numattribs,
1234 | name,
1235 | type,
1236 | ref,
1237 | deflt,
1238 | required);
1239 | }
1240 |
1241 | //****************************************************************************
1242 | xsd_attrib* xsd_add_attrib_to_type(
1243 | xsd_schema* schema,
1244 | xsd_type* t,
1245 | const char* name,
1246 | const char* type,
1247 | const char* ref,
1248 | const char* deflt,
1249 | int required)
1250 | {
1251 | assert(t->hascomplex);
1252 | return xsd_add_attrib(
1253 | schema,
1254 | &t->complex.attribs,
1255 | &t->complex.numattribs,
1256 | name,
1257 | type,
1258 | ref,
1259 | deflt,
1260 | required);
1261 | }
1262 |
1263 | //****************************************************************************
1264 | xsd_element* xsd_add_element_global(
1265 | xsd_schema* schema,
1266 | const char* name,
1267 | const char* type,
1268 | const char* ref,
1269 | int minoccurs,
1270 | int maxoccurs)
1271 | {
1272 | return xsd_add_element(
1273 | schema,
1274 | &schema->elements,
1275 | &schema->numelements,
1276 | name,
1277 | type,
1278 | ref,
1279 | minoccurs,
1280 | maxoccurs,
1281 | 0);
1282 | }
1283 |
1284 | //****************************************************************************
1285 | xsd_element* xsd_add_element_to_group(
1286 | xsd_schema* schema,
1287 | xsd_group* grp,
1288 | const char* name,
1289 | const char* type,
1290 | const char* ref,
1291 | int minoccurs,
1292 | int maxoccurs,
1293 | int seq)
1294 | {
1295 | if(seq > grp->seqmax)
1296 | {
1297 | grp->seqmax = seq;
1298 | }
1299 | return xsd_add_element(
1300 | schema,
1301 | &grp->elements,
1302 | &grp->numelements,
1303 | name,
1304 | type,
1305 | ref,
1306 | minoccurs,
1307 | maxoccurs,
1308 | seq);
1309 | }
1310 |
1311 | //****************************************************************************
1312 | xsd_element* xsd_add_element_to_type(
1313 | xsd_schema* schema,
1314 | xsd_type* t,
1315 | const char* name,
1316 | const char* type,
1317 | const char* ref,
1318 | int minoccurs,
1319 | int maxoccurs,
1320 | int seq)
1321 | {
1322 | assert(t->hascomplex);
1323 | if(seq > t->complex.seqmax)
1324 | {
1325 | t->complex.seqmax = seq;
1326 | }
1327 | return xsd_add_element(
1328 | schema,
1329 | &t->complex.elements,
1330 | &t->complex.numelements,
1331 | name,
1332 | type,
1333 | ref,
1334 | minoccurs,
1335 | maxoccurs,
1336 | seq);
1337 | }
1338 |
1339 | //****************************************************************************
1340 | xsd_group* xsd_add_group_global(
1341 | xsd_schema* schema,
1342 | const char* name,
1343 | const char* ref)
1344 | {
1345 | return xsd_add_group(
1346 | schema,
1347 | &schema->groups,
1348 | &schema->numgroups,
1349 | name,
1350 | ref,
1351 | 0);
1352 | }
1353 |
1354 | //****************************************************************************
1355 | xsd_group* xsd_add_group_to_type(
1356 | xsd_schema* schema,
1357 | xsd_type* t,
1358 | const char* name,
1359 | const char* ref,
1360 | int seq)
1361 | {
1362 | assert(t->hascomplex);
1363 | if(seq > t->complex.seqmax)
1364 | {
1365 | t->complex.seqmax = seq;
1366 | }
1367 | return xsd_add_group(
1368 | schema,
1369 | &t->complex.groups,
1370 | &t->complex.numgroups,
1371 | name,
1372 | ref,
1373 | seq);
1374 | }
1375 |
1376 | //****************************************************************************
1377 | xsd_type* xsd_add_type(
1378 | xsd_schema* schema,
1379 | const char* name)
1380 | {
1381 | enum { CHUNK = 1024 };
1382 | xsd_type* t = (xsd_type*) calloc(1, sizeof(*t));
1383 | size_t n = schema->numtypes;
1384 | size_t cap = (n + CHUNK-1) & ~(CHUNK-1);
1385 | size_t ncap = (n + CHUNK) & ~(CHUNK-1);
1386 | if(ncap > cap)
1387 | {
1388 | schema->types = (xsd_type**) realloc(schema->types, ncap*sizeof(t));
1389 | }
1390 | schema->types[n] = t;
1391 | ++schema->numtypes;
1392 | t->name = xsd_strdup(name);
1393 | t->simple.minoccurs = xsd_UNSET;
1394 | t->simple.maxoccurs = xsd_UNSET;
1395 | return t;
1396 | }
1397 |
1398 | //****************************************************************************
1399 | void xsd_create_schema(
1400 | xsd_schema* schema_out)
1401 | {
1402 | memset(schema_out, 0, sizeof(*schema_out));
1403 | xsd_predefine_types(schema_out);
1404 | }
1405 |
1406 | //****************************************************************************
1407 | void xsd_destroy_schema(
1408 | xsd_schema* schema)
1409 | {
1410 | xsd_type** titr = schema->types;
1411 | xsd_type** tend = titr + schema->numtypes;
1412 | xsd_destroy_attribs(schema->attribs, schema->numattribs);
1413 | xsd_destroy_elements(schema->elements, schema->numelements);
1414 | xsd_destroy_groups(schema->groups, schema->numgroups);
1415 | while(titr != tend)
1416 | {
1417 | xsd_type* t = *titr;
1418 | xsd_destroy_type(t);
1419 | ++titr;
1420 | }
1421 | free(schema->types);
1422 | }
1423 |
1424 | //****************************************************************************
1425 | xsd_attrib* xsd_find_attrib(
1426 | xsd_schema* schema,
1427 | const char* name)
1428 | {
1429 | xsd_attrib* result = NULL;
1430 | xsd_attrib** atitr = schema->attribs;
1431 | xsd_attrib** atend = atitr + schema->numattribs;
1432 | while(atitr != atend)
1433 | {
1434 | xsd_attrib* at = *atitr;
1435 | if(!strcmp(at->name, name))
1436 | {
1437 | result = at;
1438 | break;
1439 | }
1440 | ++atitr;
1441 | }
1442 | return result;
1443 | }
1444 |
1445 | //****************************************************************************
1446 | xsd_element* xsd_find_element(
1447 | xsd_schema* schema,
1448 | const char* name)
1449 | {
1450 | xsd_element* result = NULL;
1451 | xsd_element** elitr = schema->elements;
1452 | xsd_element** elend = elitr + schema->numelements;
1453 | while(elitr != elend)
1454 | {
1455 | xsd_element* el = *elitr;
1456 | if(!strcmp(el->name, name))
1457 | {
1458 | result = el;
1459 | break;
1460 | }
1461 | ++elitr;
1462 | }
1463 | return result;
1464 | }
1465 |
1466 | //****************************************************************************
1467 | xsd_group* xsd_find_group(
1468 | xsd_schema* schema,
1469 | const char* name)
1470 | {
1471 | xsd_group* result = NULL;
1472 | xsd_group** grpitr = schema->groups;
1473 | xsd_group** grpend = grpitr + schema->numgroups;
1474 | while(grpitr != grpend)
1475 | {
1476 | xsd_group* grp = *grpitr;
1477 | if(!strcmp(grp->name, name))
1478 | {
1479 | result = grp;
1480 | break;
1481 | }
1482 | ++grpitr;
1483 | }
1484 | return result;
1485 | }
1486 |
1487 | //****************************************************************************
1488 | xsd_type* xsd_find_type(
1489 | xsd_schema* schema,
1490 | const char* name)
1491 | {
1492 | xsd_type* result = NULL;
1493 | xsd_type** titr = schema->types;
1494 | xsd_type** tend = titr + schema->numtypes;
1495 | while(titr != tend)
1496 | {
1497 | xsd_type* t = *titr;
1498 | if(!strcmp(t->name, name))
1499 | {
1500 | result = t;
1501 | break;
1502 | }
1503 | ++titr;
1504 | }
1505 | return result;
1506 | }
1507 |
1508 | //****************************************************************************
1509 | void xsd_flatten_schema(
1510 | xsd_schema* schema)
1511 | {
1512 | xsd_flatten_attribs(schema);
1513 | xsd_flatten_elements(schema);
1514 | xsd_flatten_groups(schema);
1515 | xsd_flatten_types(schema);
1516 | }
1517 |
1518 | //****************************************************************************
1519 | void xsd_remove_type(
1520 | xsd_schema* schema,
1521 | size_t index)
1522 | {
1523 | xsd_type* t = schema->types[index];
1524 | xsd_type** titr = schema->types + index;
1525 | xsd_type** tend = schema->types + schema->numtypes - 1;
1526 | xsd_destroy_type(t);
1527 | while(titr != tend)
1528 | {
1529 | *titr = titr[1];
1530 | ++titr;
1531 | }
1532 | --schema->numtypes;
1533 | }
1534 |
1535 | //****************************************************************************
1536 | void xsd_remove_unreferenced_types(
1537 | xsd_schema* schema)
1538 | {
1539 | // culls types that are not referenced by anything
1540 | int changed;
1541 | do
1542 | {
1543 | // this is an iterative process that must be repeated until
1544 | // no changes are made
1545 | xsd_type** titr = schema->types + schema->numtypes - 1;
1546 | xsd_type** tend = schema->types - 1;
1547 | changed = 0;
1548 | while(titr != tend)
1549 | {
1550 | // loop backward, removing from end
1551 | xsd_type* t = *titr;
1552 | char* type = t->name;
1553 | xsd_attrib** atitr;
1554 | xsd_attrib** atend;
1555 | xsd_element** elitr;
1556 | xsd_element** elend;
1557 | xsd_group** grpitr;
1558 | xsd_group** grpend;
1559 | xsd_type** inrtitr;
1560 | xsd_type** inrtend;
1561 | int remove = 1;
1562 | // look for top level attributes that reference t
1563 | atitr = schema->attribs;
1564 | atend = atitr + schema->numattribs;
1565 | while(atitr != atend && remove)
1566 | {
1567 | xsd_attrib* at = *atitr;
1568 | if(at->type != NULL && !strcmp(at->type, type))
1569 | {
1570 | remove = 0;
1571 | break;
1572 | }
1573 | ++atitr;
1574 | }
1575 | // look for top level elements that reference t
1576 | elitr = schema->elements;
1577 | elend = elitr + schema->numelements;
1578 | while(elitr != elend && remove)
1579 | {
1580 | xsd_element* el = *elitr;
1581 | if(el->type != NULL && !strcmp(el->type, type))
1582 | {
1583 | remove = 0;
1584 | break;
1585 | }
1586 | ++elitr;
1587 | }
1588 | // look for top level groups that reference t
1589 | grpitr = schema->groups;
1590 | grpend = grpitr + schema->numgroups;
1591 | while(grpitr != grpend && remove)
1592 | {
1593 | xsd_group* grp = *grpitr;
1594 | elitr = grp->elements;
1595 | elend = elitr + grp->numelements;
1596 | while(elitr != elend && remove)
1597 | {
1598 | xsd_element* el = *elitr;
1599 | if(el->type != NULL && !strcmp(el->type, type))
1600 | {
1601 | remove = 0;
1602 | break;
1603 | }
1604 | ++elitr;
1605 | }
1606 | ++grpitr;
1607 | }
1608 | // look for types that reference t
1609 | inrtitr = schema->types;
1610 | inrtend = inrtitr + schema->numtypes;
1611 | while(inrtitr != inrtend && remove)
1612 | {
1613 | xsd_type* inrt = *inrtitr;
1614 | if(inrt != t)
1615 | {
1616 | if(inrt->base != NULL)
1617 | {
1618 | if(!strcmp(inrt->base, type))
1619 | {
1620 | remove = 0;
1621 | break;
1622 | }
1623 | }
1624 | if(inrt->hassimple)
1625 | {
1626 | if(inrt->simple.itemtype != NULL)
1627 | {
1628 | if(!strcmp(inrt->simple.itemtype, type))
1629 | {
1630 | remove = 0;
1631 | break;
1632 | }
1633 | }
1634 | }
1635 | if(inrt->hascomplex)
1636 | {
1637 | // look for attributes that reference t
1638 | atitr = inrt->complex.attribs;
1639 | atend = atitr + inrt->complex.numattribs;
1640 | while(atitr != atend && remove)
1641 | {
1642 | xsd_attrib* at = *atitr;
1643 | if(at->type != NULL && !strcmp(at->type, type))
1644 | {
1645 | remove = 0;
1646 | break;
1647 | }
1648 | ++atitr;
1649 | }
1650 | // look for elements that reference t
1651 | elitr = inrt->complex.elements;
1652 | elend = elitr + inrt->complex.numelements;
1653 | while(elitr != elend && remove)
1654 | {
1655 | xsd_element* el = *elitr;
1656 | if(el->type != NULL && !strcmp(el->type, type))
1657 | {
1658 | remove = 0;
1659 | break;
1660 | }
1661 | ++elitr;
1662 | }
1663 | // look for groups that reference t
1664 | grpitr = inrt->complex.groups;
1665 | grpend = grpitr + inrt->complex.numgroups;
1666 | while(grpitr != grpend && remove)
1667 | {
1668 | xsd_group* grp = *grpitr;
1669 | elitr = grp->elements;
1670 | elend = elitr + grp->numelements;
1671 | while(elitr != elend && remove)
1672 | {
1673 | xsd_element* el = *elitr;
1674 | if(el->type!=NULL && !strcmp(el->type,type))
1675 | {
1676 | remove = 0;
1677 | break;
1678 | }
1679 | ++elitr;
1680 | }
1681 | ++grpitr;
1682 | }
1683 | }
1684 | }
1685 | ++inrtitr;
1686 | }
1687 | if(remove)
1688 | {
1689 | xsd_remove_type(schema, (int) (titr - schema->types));
1690 | changed = 1;
1691 | }
1692 | --titr;
1693 | }
1694 | }
1695 | while(changed);
1696 | }
1697 |
1698 | //****************************************************************************
1699 | char* xsd_strdup(
1700 | const char* str)
1701 | {
1702 | char* dup = NULL;
1703 | if(str != NULL && *str != '\0')
1704 | {
1705 | size_t sz = strlen(str) + 1;
1706 | dup = (char*) malloc(sz);
1707 | memcpy(dup, str, sz);
1708 | }
1709 | return dup;
1710 | }
1711 |
1712 | //****************************************************************************
1713 | int xsd_validate_schema(
1714 | xsd_schema* schema)
1715 | {
1716 | int result = 0;
1717 | xsd_attrib** atitr;
1718 | xsd_attrib** atend;
1719 | xsd_element** elitr;
1720 | xsd_element** elend;
1721 | xsd_group** grpitr;
1722 | xsd_group** grpend;
1723 | xsd_type** titr;
1724 | xsd_type** tend;
1725 | // validate top level attributes
1726 | atitr = schema->attribs;
1727 | atend = atitr + schema->numattribs;
1728 | while(atitr != atend && result == 0)
1729 | {
1730 | result = xsd_validate_attrib(
1731 | schema,
1732 | schema->attribs,
1733 | schema->numattribs,
1734 | *atitr);
1735 | ++atitr;
1736 | }
1737 | // validate top level elements
1738 | elitr = schema->elements;
1739 | elend = elitr + schema->numelements;
1740 | if(elitr != NULL)
1741 | {
1742 | while(elitr != elend && result == 0)
1743 | {
1744 | result = xsd_validate_element(
1745 | schema,
1746 | schema->elements,
1747 | schema->numelements,
1748 | *elitr);
1749 | ++elitr;
1750 | }
1751 | }
1752 | else
1753 | {
1754 | // should have at least one top level element
1755 | assert(0);
1756 | result = -1;
1757 | }
1758 | // validate top level groups
1759 | grpitr = schema->groups;
1760 | grpend = grpitr + schema->numgroups;
1761 | while(grpitr != grpend && result == 0)
1762 | {
1763 | result = xsd_validate_group(
1764 | schema,
1765 | schema->groups,
1766 | schema->numgroups,
1767 | *grpitr);
1768 | ++grpitr;
1769 | }
1770 | // validate types
1771 | titr = schema->types;
1772 | tend = titr + schema->numtypes;
1773 | while(titr != tend && result == 0)
1774 | {
1775 | xsd_type* t = *titr;
1776 | xsd_type** inrtitr = schema->types;
1777 | xsd_type** inrtend = inrtitr + schema->numtypes;
1778 | const char* base = t->base;
1779 | while(inrtitr != inrtend)
1780 | {
1781 | // search for items with duplicate type names
1782 | xsd_type* inrt = *inrtitr;
1783 | if(inrt != t && !strcmp(inrt->name, t->name))
1784 | {
1785 | assert(0);
1786 | result = -1;
1787 | break;
1788 | }
1789 | ++inrtitr;
1790 | }
1791 | if(t->hassimple)
1792 | {
1793 | if(t->simple.itemtype == NULL && base == NULL)
1794 | {
1795 | // make sure that it actually does have simple content
1796 | assert(0);
1797 | result = -1;
1798 | }
1799 | }
1800 | if(t->hascomplex)
1801 | {
1802 | atitr = t->complex.attribs;
1803 | atend = atitr + t->complex.numattribs;
1804 | while(atitr != atend && result == 0)
1805 | {
1806 | result = xsd_validate_attrib(
1807 | schema,
1808 | t->complex.attribs,
1809 | t->complex.numattribs,
1810 | *atitr);
1811 | ++atitr;
1812 | }
1813 | elitr = t->complex.elements;
1814 | elend = elitr + t->complex.numelements;
1815 | while(elitr != elend && result == 0)
1816 | {
1817 | result = xsd_validate_element(
1818 | schema,
1819 | t->complex.elements,
1820 | t->complex.numelements,
1821 | *elitr);
1822 | ++elitr;
1823 | }
1824 | grpitr = t->complex.groups;
1825 | grpend = grpitr + t->complex.numgroups;
1826 | while(grpitr != grpend)
1827 | {
1828 | result = xsd_validate_group(
1829 | schema,
1830 | t->complex.groups,
1831 | t->complex.numgroups,
1832 | *grpitr);
1833 | ++grpitr;
1834 | }
1835 | }
1836 | ++titr;
1837 | }
1838 | return result;
1839 | }
1840 |
--------------------------------------------------------------------------------
/gen/src/xsd.h:
--------------------------------------------------------------------------------
1 | #ifndef XSD_H_
2 | #define XSD_H_
3 |
4 | #include
5 |
6 | #define xsd_DATA_NONE NULL
7 | #define xsd_DATA_BOOL "xs:boolean"
8 | #define xsd_DATA_HEX "xs:hexBinary"
9 | #define xsd_DATA_FLOAT "xs:float"
10 | #define xsd_DATA_INT8 "xs:byte"
11 | #define xsd_DATA_INT16 "xs:short"
12 | #define xsd_DATA_INT32 "xs:int"
13 | #define xsd_DATA_STRING "xs:string"
14 | #define xsd_DATA_UINT8 "xs:unsignedByte"
15 | #define xsd_DATA_UINT16 "xs:unsignedShort"
16 | #define xsd_DATA_UINT32 "xs:unsignedInt"
17 |
18 | enum
19 | {
20 | xsd_UNBOUNDED = -1,
21 | xsd_UNSET = -2
22 | };
23 |
24 | enum xsd_base_relation_e
25 | {
26 | xsd_BASE_NONE,
27 | xsd_BASE_EXTEND,
28 | xsd_BASE_RESTRICTION,
29 | xsd_BASE_RENAME
30 | };
31 |
32 | typedef enum xsd_base_relation_e xsd_base_relation;
33 | typedef struct xsd_attrib_s xsd_attrib;
34 | typedef struct xsd_element_s xsd_element;
35 | typedef struct xsd_group_s xsd_group;
36 | typedef struct xsd_type_s xsd_type;
37 | typedef struct xsd_schema_s xsd_schema;
38 |
39 | struct xsd_attrib_s
40 | {
41 | char* name;
42 | char* type;
43 | char* ref;
44 | char* deflt;
45 | int required;
46 | };
47 |
48 | struct xsd_element_s
49 | {
50 | char* name;
51 | char* ref;
52 | char* type;
53 | int minoccurs;
54 | int maxoccurs;
55 | int seq;
56 | };
57 |
58 | struct xsd_group_s
59 | {
60 | char* name;
61 | char* ref;
62 | xsd_element** elements;
63 | size_t numelements;
64 | int seqmax;
65 | int seq;
66 | };
67 |
68 | struct xsd_type_s
69 | {
70 | char* name;
71 | char* base;
72 | xsd_base_relation baserelation;
73 | char isanonymous;
74 | char isbuiltin;
75 | char hassimple;
76 | char hascomplex;
77 | char anycontent;
78 | struct
79 | {
80 | char* itemtype;
81 | int minoccurs;
82 | int maxoccurs;
83 | } simple;
84 | struct
85 | {
86 | xsd_attrib** attribs;
87 | xsd_element** elements;
88 | xsd_group** groups;
89 | size_t numattribs;
90 | size_t numelements;
91 | size_t numgroups;
92 | int seqmax;
93 | } complex;
94 | };
95 |
96 | struct xsd_schema_s
97 | {
98 | /// top level attributes
99 | xsd_attrib** attribs;
100 | /// top level elements
101 | xsd_element** elements;
102 | /// top level groups
103 | xsd_group** groups;
104 | /// list of types defined by schema
105 | xsd_type** types;
106 | size_t numattribs;
107 | size_t numelements;
108 | size_t numgroups;
109 | size_t numtypes;
110 | };
111 |
112 | //****************************************************************************
113 |
114 | xsd_attrib* xsd_add_attrib_global(
115 | xsd_schema* schema,
116 | const char* name,
117 | const char* type,
118 | const char* ref,
119 | const char* deflt,
120 | int required);
121 |
122 | xsd_attrib* xsd_add_attrib_to_type(
123 | xsd_schema* schema,
124 | xsd_type* t,
125 | const char* name,
126 | const char* type,
127 | const char* ref,
128 | const char* deflt,
129 | int required);
130 |
131 | xsd_element* xsd_add_element_global(
132 | xsd_schema* schema,
133 | const char* name,
134 | const char* type,
135 | const char* ref,
136 | int minoccurs,
137 | int maxoccurs);
138 |
139 | xsd_element* xsd_add_element_to_group(
140 | xsd_schema* schema,
141 | xsd_group* grp,
142 | const char* name,
143 | const char* type,
144 | const char* ref,
145 | int minoccurs,
146 | int maxoccurs,
147 | int seq);
148 |
149 | xsd_element* xsd_add_element_to_type(
150 | xsd_schema* schema,
151 | xsd_type* t,
152 | const char* name,
153 | const char* type,
154 | const char* ref,
155 | int minoccurs,
156 | int maxoccurs,
157 | int seq);
158 |
159 | xsd_group* xsd_add_group_global(
160 | xsd_schema* schema,
161 | const char* name,
162 | const char* ref);
163 |
164 | xsd_group* xsd_add_group_to_type(
165 | xsd_schema* schema,
166 | xsd_type* t,
167 | const char* name,
168 | const char* ref,
169 | int seq);
170 |
171 | xsd_type* xsd_add_type(
172 | xsd_schema* schema,
173 | const char* name);
174 |
175 | void xsd_create_schema(
176 | xsd_schema* schema_out);
177 |
178 | void xsd_destroy_schema(
179 | xsd_schema* schema);
180 |
181 | xsd_attrib* xsd_find_attrib(
182 | xsd_schema* schema,
183 | const char* name);
184 |
185 | xsd_element* xsd_find_element(
186 | xsd_schema* schema,
187 | const char* name);
188 |
189 | xsd_group* xsd_find_group(
190 | xsd_schema* schema,
191 | const char* name);
192 |
193 | xsd_type* xsd_find_type(
194 | xsd_schema* schema,
195 | const char* name);
196 |
197 | void xsd_flatten_schema(
198 | xsd_schema* schema);
199 |
200 | void xsd_remove_type(
201 | xsd_schema* schema,
202 | size_t index);
203 |
204 | void xsd_remove_unreferenced_types(
205 | xsd_schema* schema);
206 |
207 | char* xsd_strdup(
208 | const char* str);
209 |
210 | int xsd_validate_schema(
211 | xsd_schema* schema);
212 |
213 | #endif // XSD_H_
214 |
--------------------------------------------------------------------------------
/gen/src/xsdparse.c:
--------------------------------------------------------------------------------
1 | #include "xsdparse.h"
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | //****************************************************************************
8 | static void xsdparse_pop(
9 | xsdparse_state* st)
10 | {
11 | assert(st->stacksize > 0);
12 | --st->stacksize;
13 | }
14 |
15 | //****************************************************************************
16 | static void xsdparse_push(
17 | xsdparse_state* st,
18 | const xsdparse_node* nd)
19 | {
20 | enum { CHUNK = 16 };
21 | size_t n = st->stacksize;
22 | size_t cap = (n + CHUNK - 1) & ~(CHUNK-1);
23 | size_t ncap = (n + CHUNK) & ~(CHUNK-1);
24 | if(ncap > cap)
25 | {
26 | st->stack = (xsdparse_node*) realloc(st->stack, ncap*sizeof(*nd));
27 | }
28 | st->stack[n] = *nd;
29 | ++st->stacksize;
30 | }
31 |
32 | //****************************************************************************
33 | static int xsdparse_attribute(
34 | const xsdparse_state* st,
35 | const xsdparse_node* parent,
36 | xsd_schema* schema,
37 | xsdparse_node* nd,
38 | const char** att)
39 | {
40 | int success = 0;
41 | const char* name = NULL;
42 | const char* ref = NULL;
43 | const char* type = NULL;
44 | const char* deflt = NULL;
45 | int required = xsd_UNSET;
46 | while(*att != NULL)
47 | {
48 | if(!strcmp(att[0], "default"))
49 | {
50 | deflt = att[1];
51 | }
52 | else if(!strcmp(att[0], "name"))
53 | {
54 | name = att[1];
55 | }
56 | else if(!strcmp(att[0], "ref"))
57 | {
58 | ref = att[1];
59 | }
60 | else if(!strcmp(att[0], "type"))
61 | {
62 | type = att[1];
63 | }
64 | else if(!strcmp(att[0], "use"))
65 | {
66 | if(!strcmp(att[1], "required"))
67 | {
68 | required = 1;
69 | }
70 | }
71 | att += 2;
72 | }
73 | if((name != NULL && type != NULL) || (ref != NULL))
74 | {
75 | if(nd->type != NULL)
76 | {
77 | xsd_add_attrib_to_type(schema,nd->type,name,type,ref,deflt,required);
78 | }
79 | else
80 | {
81 | xsd_add_attrib_global(schema,name,type,ref,deflt,required);
82 | }
83 | success = 1;
84 | }
85 | return success;
86 | }
87 |
88 | //****************************************************************************
89 | static int xsdparse_choice(
90 | const xsdparse_state* st,
91 | const xsdparse_node* parent,
92 | xsd_schema* schema,
93 | xsdparse_node* nd,
94 | const char** att)
95 | {
96 | int min = xsd_UNSET;
97 | int max = xsd_UNSET;
98 | while(*att != NULL)
99 | {
100 | if(!strcmp(att[0], "maxOccurs"))
101 | {
102 | const char* val = att[1];
103 | if(!strcmp(val, "unbounded"))
104 | {
105 | max = xsd_UNBOUNDED;
106 | }
107 | else
108 | {
109 | sscanf(val, "%i", &max);
110 | }
111 | }
112 | if(!strcmp(att[0], "minOccurs"))
113 | {
114 | const char* val = att[1];
115 | sscanf(val, "%i", &min);
116 | }
117 | att += 2;
118 | }
119 | nd->inseq = 0;
120 | nd->min = min;
121 | nd->max = max;
122 | return 1;
123 | }
124 |
125 | //****************************************************************************
126 | static int xsdparse_complextype(
127 | const xsdparse_state* st,
128 | const xsdparse_node* parent,
129 | xsd_schema* schema,
130 | xsdparse_node* nd,
131 | const char** att)
132 | {
133 | int success = 0;
134 | const char* name = NULL;
135 | while(*att != NULL)
136 | {
137 | if(!strcmp(att[0], "name"))
138 | {
139 | name = att[1];
140 | }
141 | att += 2;
142 | }
143 | if(name != NULL)
144 | {
145 | xsd_type* t = xsd_add_type(schema, name);
146 | t->hascomplex = 1;
147 | memset(nd, 0, sizeof(*nd));
148 | nd->type = t;
149 | success = 1;
150 | }
151 | else if(nd->element != NULL && nd->element->type == NULL)
152 | {
153 | // inside element with anonymous type
154 | char* containername = NULL;
155 | xsd_element* el = nd->element;
156 | xsd_type* t;
157 | if(nd->group != NULL && nd->group->name != NULL)
158 | {
159 | containername = nd->group->name;
160 | }
161 | else if(nd->type != NULL && nd->type->name != NULL)
162 | {
163 | containername = nd->type->name;
164 | }
165 | if(containername != NULL)
166 | {
167 | // inside a group or type definition
168 | // derive new type name from container name and element name
169 | size_t ndsz = strlen(containername);
170 | size_t elsz = strlen(el->name);
171 | char* name = (char*) malloc(ndsz + 1 + elsz + 1);
172 | strcpy(name, containername);
173 | name[ndsz] = '_';
174 | strcpy(name + ndsz + 1, el->name);
175 | t = xsd_add_type(schema, name);
176 | free(name);
177 | }
178 | else
179 | {
180 | // top level element
181 | // derive type name from element name
182 | t = xsd_add_type(schema, el->name);
183 | }
184 | t->isanonymous = 1;
185 | t->hascomplex = 1;
186 | el->type = xsd_strdup(t->name);
187 | memset(nd, 0, sizeof(*nd));
188 | nd->type = t;
189 | success = 1;
190 | }
191 | return success;
192 | }
193 |
194 | //****************************************************************************
195 | static int xsdparse_element(
196 | const xsdparse_state* st,
197 | const xsdparse_node* parent,
198 | xsd_schema* schema,
199 | xsdparse_node* nd,
200 | const char** att)
201 | {
202 | int success = 0;
203 | const char* name = NULL;
204 | const char* type = NULL;
205 | const char* ref = NULL;
206 | int max = parent->max;
207 | int min = parent->min;
208 | while(*att != NULL)
209 | {
210 | if(!strcmp(att[0], "maxOccurs"))
211 | {
212 | const char* val = att[1];
213 | if(!strcmp(val, "unbounded"))
214 | {
215 | max = xsd_UNBOUNDED;
216 | }
217 | else
218 | {
219 | sscanf(val, "%i", &max);
220 | }
221 | }
222 | if(!strcmp(att[0], "minOccurs"))
223 | {
224 | const char* val = att[1];
225 | sscanf(val, "%i", &min);
226 | }
227 | if(!strcmp(att[0], "name"))
228 | {
229 | name = att[1];
230 | }
231 | else if(!strcmp(att[0], "ref"))
232 | {
233 | ref = att[1];
234 | }
235 | else if(!strcmp(att[0], "type"))
236 | {
237 | type = att[1];
238 | }
239 | att += 2;
240 | }
241 | if(name != NULL || ref != NULL)
242 | {
243 | xsd_element* el;
244 | if(nd->group != NULL)
245 | {
246 | xsd_group* grp = nd->group;
247 | int seq = nd->seq;
248 | el=xsd_add_element_to_group(schema,grp,name,type,ref,min,max,seq);
249 | if(nd->inseq)
250 | {
251 | ++nd->seq;
252 | }
253 | }
254 | else if(nd->type != NULL)
255 | {
256 | xsd_type* t = nd->type;
257 | int seq = nd->seq;
258 | el = xsd_add_element_to_type(schema,t,name,type,ref,min,max,seq);
259 | if(nd->inseq)
260 | {
261 | ++nd->seq;
262 | }
263 | }
264 | else
265 | {
266 | if(name != NULL && type != NULL)
267 | {
268 | xsd_type* tsrc = xsd_find_type(schema, type);
269 | xsd_type* t = xsd_add_type(schema, name);
270 | t->base = xsd_strdup(type);
271 | t->baserelation = xsd_BASE_RESTRICTION;
272 | if(tsrc != NULL)
273 | {
274 | t->hascomplex = tsrc->hascomplex;
275 | t->hassimple = tsrc->hassimple;
276 | }
277 | type = name;
278 | }
279 | el = xsd_add_element_global(schema,name,type,ref,min,max);
280 | }
281 | nd->element = el;
282 | success = 1;
283 | }
284 | return success;
285 | }
286 |
287 | //****************************************************************************
288 | static int xsdparse_extension(
289 | const xsdparse_state* st,
290 | const xsdparse_node* parent,
291 | xsd_schema* schema,
292 | xsdparse_node* nd,
293 | const char** att)
294 | {
295 | int success = 0;
296 | if(nd->type != NULL)
297 | {
298 | const char* base = NULL;
299 | while(*att != NULL)
300 | {
301 | if(!strcmp(att[0], "base"))
302 | {
303 | base = att[1];
304 | }
305 | att += 2;
306 | }
307 | if(base != NULL)
308 | {
309 | nd->type->base = xsd_strdup(base);
310 | nd->type->baserelation = xsd_BASE_EXTEND;
311 | success = 1;
312 | }
313 | }
314 | return success;
315 | }
316 |
317 | //****************************************************************************
318 | static int xsdparse_group(
319 | const xsdparse_state* st,
320 | const xsdparse_node* parent,
321 | xsd_schema* schema,
322 | xsdparse_node* nd,
323 | const char** att)
324 | {
325 | int success = 0;
326 | const char* name = NULL;
327 | const char* ref = NULL;
328 | while(*att != NULL)
329 | {
330 | if(!strcmp(att[0], "name"))
331 | {
332 | name = att[1];
333 | }
334 | if(!strcmp(att[0], "ref"))
335 | {
336 | ref = att[1];
337 | }
338 | att += 2;
339 | }
340 | if(name != NULL || ref != NULL)
341 | {
342 | xsd_group* grp;
343 | if(nd->type != NULL)
344 | {
345 | xsd_type* t = nd->type;
346 | int seq = nd->seq;
347 | grp = xsd_add_group_to_type(schema, t, name, ref, seq);
348 | if(nd->inseq)
349 | {
350 | ++nd->seq;
351 | }
352 | }
353 | else
354 | {
355 | grp = xsd_add_group_global(schema, name, ref);
356 | }
357 | nd->group = grp;
358 | success = 1;
359 | }
360 | return success;
361 | }
362 |
363 | //****************************************************************************
364 | static int xsdparse_import(
365 | const xsdparse_state* st,
366 | const xsdparse_node* parent,
367 | xsd_schema* schema,
368 | xsdparse_node* nd,
369 | const char** att)
370 | {
371 | int success = 0;
372 | const char* ns = NULL;
373 | while(*att != NULL)
374 | {
375 | if(!strcmp(att[0], "namespace"))
376 | {
377 | ns = att[1];
378 | }
379 | att += 2;
380 | }
381 | if(ns != NULL)
382 | {
383 | if(!strcmp(ns, "http://www.w3.org/1998/Math/MathML"))
384 | {
385 | // MathML import, define math element and type with any content
386 | xsd_type* t;
387 | t = xsd_add_type(schema, "math:math");
388 | t->hascomplex = 1;
389 | t->anycontent = 1;
390 | xsd_add_element_global(schema,"math:math","math:math",NULL,0,-1);
391 | }
392 | success = 1;
393 | }
394 | return success;
395 | }
396 |
397 | //****************************************************************************
398 | static int xsdparse_list(
399 | const xsdparse_state* st,
400 | const xsdparse_node* parent,
401 | xsd_schema* schema,
402 | xsdparse_node* nd,
403 | const char** att)
404 | {
405 | int success = 0;
406 | if(nd->type != NULL && nd->type->hassimple)
407 | {
408 | xsd_type* t = nd->type;
409 | const char* itemtype = NULL;
410 | while(*att != NULL)
411 | {
412 | if(!strcmp(att[0], "itemType"))
413 | {
414 | itemtype = att[1];
415 | }
416 | att += 2;
417 | }
418 | if(itemtype != NULL)
419 | {
420 | t->simple.itemtype = xsd_strdup(itemtype);
421 | t->simple.minoccurs = 0;
422 | t->simple.maxoccurs = xsd_UNBOUNDED;
423 | success = 1;
424 | }
425 | }
426 | return success;
427 | }
428 |
429 | //****************************************************************************
430 | static int xsdparse_restriction(
431 | const xsdparse_state* st,
432 | const xsdparse_node* parent,
433 | xsd_schema* schema,
434 | xsdparse_node* nd,
435 | const char** att)
436 | {
437 | int success = 0;
438 | if(nd->type != NULL)
439 | {
440 | const char* base = NULL;
441 | while(*att != NULL)
442 | {
443 | if(!strcmp(att[0], "base"))
444 | {
445 | base = att[1];
446 | }
447 | att += 2;
448 | }
449 | if(base != NULL)
450 | {
451 | nd->type->base = xsd_strdup(base);
452 | nd->type->baserelation = xsd_BASE_RESTRICTION;
453 | success = 1;
454 | }
455 | }
456 | return success;
457 | }
458 |
459 | //****************************************************************************
460 | static int xsdparse_sequence(
461 | const xsdparse_state* st,
462 | const xsdparse_node* parent,
463 | xsd_schema* schema,
464 | xsdparse_node* nd,
465 | const char** att)
466 | {
467 | int min = xsd_UNSET;
468 | int max = xsd_UNSET;
469 | while(*att != NULL)
470 | {
471 | if(!strcmp(att[0], "maxOccurs"))
472 | {
473 | const char* val = att[1];
474 | if(!strcmp(val, "unbounded"))
475 | {
476 | max = xsd_UNBOUNDED;
477 | }
478 | else
479 | {
480 | sscanf(val, "%i", &max);
481 | }
482 | }
483 | if(!strcmp(att[0], "minOccurs"))
484 | {
485 | const char* val = att[1];
486 | sscanf(val, "%i", &min);
487 | }
488 | att += 2;
489 | }
490 | nd->inseq = 1;
491 | nd->min = min;
492 | nd->max = max;
493 | return 1;
494 | }
495 |
496 | //****************************************************************************
497 | static int xsdparse_simpletype(
498 | const xsdparse_state* st,
499 | const xsdparse_node* parent,
500 | xsd_schema* schema,
501 | xsdparse_node* nd,
502 | const char** att)
503 | {
504 | int success = 0;
505 | const char* name = NULL;
506 | while(*att != NULL)
507 | {
508 | if(!strcmp(att[0], "name"))
509 | {
510 | name = att[1];
511 | }
512 | att += 2;
513 | }
514 | if(name != NULL)
515 | {
516 | xsd_type* t = xsd_add_type(schema, name);
517 | t->hassimple = 1;
518 | memset(nd, 0, sizeof(*nd));
519 | nd->type = t;
520 | success = 1;
521 | }
522 | else if(nd->element != NULL && nd->element->type == NULL)
523 | {
524 | // inside element with anonymous type
525 | xsd_element* el = nd->element;
526 | xsd_type* t;
527 | if(nd->type != NULL)
528 | {
529 | // inside a type definition
530 | // derive new type with name from parent type and element
531 | size_t ndsz = strlen(nd->type->name);
532 | size_t elsz = strlen(el->name);
533 | char* name = (char*) malloc(ndsz + 1 + elsz + 1);
534 | strcpy(name, nd->type->name);
535 | name[ndsz] = '_';
536 | strcpy(name + ndsz + 1, el->name);
537 | t = xsd_add_type(schema, name);
538 | t->isanonymous = 1;
539 | free(name);
540 | }
541 | else
542 | {
543 | // top level element
544 | // derive type name from element name
545 | t = xsd_add_type(schema, el->name);
546 | }
547 | t->hassimple = 1;
548 | el->type = xsd_strdup(t->name);
549 | memset(nd, 0, sizeof(*nd));
550 | nd->type = t;
551 | success = 1;
552 | }
553 | return success;
554 | }
555 |
556 | //****************************************************************************
557 | static int xsdparse_union(
558 | const xsdparse_state* st,
559 | const xsdparse_node* parent,
560 | xsd_schema* schema,
561 | xsdparse_node* nd,
562 | const char** att)
563 | {
564 | int success = 0;
565 | if(nd->type != NULL && nd->type->hassimple)
566 | {
567 | xsd_type* t = nd->type;
568 | const char* membertypes = NULL;
569 | while(*att != NULL)
570 | {
571 | if(!strcmp(att[0], "memberTypes"))
572 | {
573 | membertypes = att[1];
574 | }
575 | att += 2;
576 | }
577 | if(membertypes != NULL && t->simple.itemtype == NULL)
578 | {
579 | // for now, make all unions strings that the client can parse
580 | t->simple.itemtype = xsd_strdup(xsd_DATA_STRING);
581 | success = 1;
582 | }
583 | }
584 | return success;
585 | }
586 |
587 | //****************************************************************************
588 | void xsdparse_startelement(
589 | void* userdata,
590 | const char* el,
591 | const char** att)
592 | {
593 | xsdparse_state* st = (xsdparse_state*) userdata;
594 | xsd_schema* schema = st->schema;
595 | xsdparse_node* parent;
596 | xsdparse_node nd;
597 | int success;
598 | if(st->stacksize > 0)
599 | {
600 | parent = st->stack + st->stacksize - 1;
601 | nd = *parent;
602 | nd.childseq = 0;
603 | }
604 | else
605 | {
606 | parent = NULL;
607 | memset(&nd, 0, sizeof(nd));
608 | }
609 | success = 0;
610 | if(!strcmp(el, "xs:annotation"))
611 | {
612 | success = 1;
613 | }
614 | else if(!strcmp(el, "xs:any"))
615 | {
616 | if(nd.type != NULL)
617 | {
618 | nd.type->anycontent = 1;
619 | success = 1;
620 | }
621 | }
622 | else if(!strcmp(el, "xs:appinfo"))
623 | {
624 | success = 1;
625 | }
626 | else if(!strcmp(el, "xs:attribute"))
627 | {
628 | success = xsdparse_attribute(st, parent, schema, &nd, att);
629 | }
630 | else if(!strcmp(el, "xs:choice"))
631 | {
632 | success = xsdparse_choice(st, parent, schema, &nd, att);
633 | }
634 | else if(!strcmp(el, "xs:complexContent"))
635 | {
636 | if(nd.type != NULL && nd.type->hascomplex)
637 | {
638 | success = 1;
639 | }
640 | }
641 | else if(!strcmp(el, "xs:complexType"))
642 | {
643 | success = xsdparse_complextype(st, parent, schema, &nd, att);
644 | }
645 | else if(!strcmp(el, "xs:documentation"))
646 | {
647 | success = 1;
648 | }
649 | else if(!strcmp(el, "xs:element"))
650 | {
651 | success = xsdparse_element(st, parent, schema, &nd, att);
652 | }
653 | else if(!strcmp(el, "xs:enumeration"))
654 | {
655 | success = 1;
656 | }
657 | else if(!strcmp(el, "xs:extension"))
658 | {
659 | success = xsdparse_extension(st, parent, schema, &nd, att);
660 | }
661 | else if(!strcmp(el, "xs:group"))
662 | {
663 | success = xsdparse_group(st, parent, schema, &nd, att);
664 | }
665 | else if(!strcmp(el, "xs:import"))
666 | {
667 | success = xsdparse_import(st, parent, schema, &nd, att);
668 | }
669 | else if(!strcmp(el, "xs:list"))
670 | {
671 | success = xsdparse_list(st, parent, schema, &nd, att);
672 | }
673 | else if(!strcmp(el, "xs:maxExclusive"))
674 | {
675 | success = 1;
676 | }
677 | else if(!strcmp(el, "xs:maxInclusive"))
678 | {
679 | success = 1;
680 | }
681 | else if(!strcmp(el, "xs:maxLength"))
682 | {
683 | if(nd.type != NULL && !nd.type->hascomplex)
684 | {
685 | xsd_type* t = nd.type;
686 | const char* value = NULL;
687 | while(*att != NULL)
688 | {
689 | if(!strcmp(att[0], "value"))
690 | {
691 | value = att[1];
692 | }
693 | att += 2;
694 | }
695 | if(value != NULL)
696 | {
697 | int i;
698 | if(sscanf(value, "%i", &i) == 1)
699 | {
700 | t->simple.maxoccurs = i;
701 | success = 1;
702 | }
703 | }
704 | }
705 | }
706 | else if(!strcmp(el, "xs:minExclusive"))
707 | {
708 | success = 1;
709 | }
710 | else if(!strcmp(el, "xs:minInclusive"))
711 | {
712 | success = 1;
713 | }
714 | else if(!strcmp(el, "xs:minLength"))
715 | {
716 | if(nd.type != NULL && !nd.type->hascomplex)
717 | {
718 | xsd_type* t = nd.type;
719 | const char* value = NULL;
720 | while(*att != NULL)
721 | {
722 | if(!strcmp(att[0], "value"))
723 | {
724 | value = att[1];
725 | }
726 | att += 2;
727 | }
728 | if(value != NULL)
729 | {
730 | int i;
731 | if(sscanf(value, "%i", &i) == 1)
732 | {
733 | t->simple.minoccurs = i;
734 | success = 1;
735 | }
736 | }
737 | }
738 | }
739 | else if(!strcmp(el, "xs:pattern"))
740 | {
741 | success = 1;
742 | }
743 | else if(!strcmp(el, "xs:restriction"))
744 | {
745 | success = xsdparse_restriction(st, parent, schema, &nd, att);
746 | }
747 | else if(!strcmp(el, "xs:schema"))
748 | {
749 | if(st->stacksize == 0)
750 | {
751 | success = 1;
752 | }
753 | }
754 | else if(!strcmp(el, "xs:sequence"))
755 | {
756 | success = xsdparse_sequence(st, parent, schema, &nd, att);
757 | }
758 | else if(!strcmp(el, "xs:simpleContent"))
759 | {
760 | nd.type->hassimple = 1;
761 | success = 1;
762 | }
763 | else if(!strcmp(el, "xs:simpleType"))
764 | {
765 | success = xsdparse_simpletype(st, parent, schema, &nd, att);
766 | }
767 | else if(!strcmp(el, "xs:union"))
768 | {
769 | success = xsdparse_union(st, parent, schema, &nd, att);
770 | }
771 | xsdparse_push(st, &nd);
772 | if(success == 0)
773 | {
774 | assert(0);
775 | }
776 | }
777 |
778 | //****************************************************************************
779 | void xsdparse_endelement(
780 | void* userdata,
781 | const char* el)
782 | {
783 | xsdparse_state* st = (xsdparse_state*) userdata;
784 | xsd_schema* schema = st->schema;
785 | xsdparse_node* nd = st->stack + st->stacksize - 1;
786 | assert(st->stacksize > 0);
787 | if(!strcmp(el, "xs:element"))
788 | {
789 | xsd_element* el = nd->element;
790 | if(el->name != NULL && el->ref == NULL && el->type == NULL)
791 | {
792 | // this is a hack to make sure that if the element has no type
793 | // definition, an empty one exists for it
794 | xsd_type* t;
795 | if(nd->type != NULL)
796 | {
797 | // inside a type definition
798 | // derive new type with name from parent type and element
799 | size_t ndsz = strlen(nd->type->name);
800 | size_t elsz = strlen(el->name);
801 | char* name = (char*) malloc(ndsz + 1 + elsz + 1);
802 | strcpy(name, nd->type->name);
803 | name[ndsz] = '_';
804 | strcpy(name + ndsz + 1, el->name);
805 | t = xsd_add_type(schema, name);
806 | free(name);
807 | }
808 | else
809 | {
810 | // top level element
811 | // derive type name from element name
812 | t = xsd_add_type(schema, el->name);
813 | }
814 | el->type = xsd_strdup(t->name);
815 | }
816 | }
817 | if(st->stacksize > 1)
818 | {
819 | xsdparse_node* parent = nd - 1;
820 | if ((nd->type!=NULL && parent->type==nd->type) ||
821 | (nd->group!=NULL && parent->group==nd->group))
822 | {
823 | // only propagate child sequences up to parent if they share
824 | // the same type or group definition
825 | // update the counter of maximum child sequence to parent
826 | if(parent->childseq < nd->childseq)
827 | {
828 | parent->childseq = nd->childseq;
829 | }
830 | if(parent->childseq < nd->seq)
831 | {
832 | parent->childseq = nd->seq;
833 | }
834 | // if the parent node is part of a sequence, its next node must
835 | // be ordered after all the its previous children
836 | if(parent->inseq)
837 | {
838 | parent->seq = parent->childseq;
839 | }
840 | }
841 | }
842 | xsdparse_pop(st);
843 | }
844 |
845 | //****************************************************************************
846 | void xsdparse_hacks(
847 | xsd_schema* schema)
848 | {
849 | // add backward compatibility for 1.4.1 to common materials
850 | xsd_type* newparamt = xsd_find_type(schema, "fx_common_newparam_type");
851 | xsd_type* sampt = xsd_find_type(schema, "fx_sampler2D_type");
852 | if(newparamt != NULL)
853 | {
854 | xsd_type* surft = xsd_add_type(schema, "fx_surface_common_type");
855 | surft->hascomplex = 1;
856 | xsd_add_attrib_to_type(schema,surft,"type","xs:token",NULL,NULL,1);
857 | xsd_add_element_to_type(
858 | schema,
859 | surft,
860 | "init_from",
861 | "image_type_init_from",
862 | NULL,
863 | 0,
864 | -1,
865 | 0);
866 | xsd_add_element_to_type(
867 | schema,
868 | newparamt,
869 | "surface",
870 | "fx_surface_common_type",
871 | NULL,
872 | 0,
873 | 1,
874 | 0);
875 | }
876 | if(sampt != NULL)
877 | {
878 | if(sampt->base != NULL)
879 | {
880 | sampt->baserelation = xsd_BASE_EXTEND;
881 | }
882 | xsd_add_element_to_type(
883 | schema,
884 | sampt,
885 | "source",
886 | "xs:NCName",
887 | NULL,
888 | 0,
889 | 1,
890 | 0);
891 | }
892 | }
893 |
--------------------------------------------------------------------------------
/gen/src/xsdparse.h:
--------------------------------------------------------------------------------
1 | #ifndef XSDPARSE_H_
2 | #define XSDPARSE_H_
3 |
4 | #include "xsd.h"
5 |
6 | //****************************************************************************
7 |
8 | typedef struct xsdparse_node_s xsdparse_node;
9 | typedef struct xsdparse_state_s xsdparse_state;
10 |
11 | //****************************************************************************
12 |
13 | struct xsdparse_node_s
14 | {
15 | xsd_type* type;
16 | xsd_group* group;
17 | xsd_attrib* attrib;
18 | xsd_element* element;
19 | int min;
20 | int max;
21 | int inseq;
22 | int seq;
23 | int childseq;
24 | };
25 |
26 | struct xsdparse_state_s
27 | {
28 | xsdparse_node* stack;
29 | int stacksize;
30 | xsd_schema* schema;
31 | };
32 |
33 | //****************************************************************************
34 |
35 | void xsdparse_startelement(
36 | void* userdata,
37 | const char* el,
38 | const char** att);
39 |
40 | void xsdparse_endelement(
41 | void* userdata,
42 | const char* el);
43 |
44 |
45 | /**
46 | * @details Manually alter the schema for compatibility purposes
47 | */
48 | void xsdparse_hacks(
49 | xsd_schema* schema);
50 |
51 | #endif // XSDPARSE_H_
52 |
--------------------------------------------------------------------------------
/gen/template/dae.c:
--------------------------------------------------------------------------------
1 | /**
2 | * @brief libdae source
3 | * @author Thomas Atwood (tatwood.net)
4 | * @date 2011
5 | * @copyright unlicense / public domain
6 | ****************************************************************************/
7 | #include "dae.h"
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | #define dae_GET_HEADER(pobj_) \
15 | ((dae_obj_header*) (((ptrdiff_t) pobj_)-((sizeof(dae_obj_header)+7)&~7)))
16 |
17 | #define dae_GET_PTR(phdr_) \
18 | ((dae_obj_ptr) (((ptrdiff_t) phdr_)+((sizeof(dae_obj_header)+7)&~7)))
19 |
20 | enum dae_obj_memberdeftype_e
21 | {
22 | dae_MEMBER_ATTRIB,
23 | dae_MEMBER_ELEM
24 | };
25 |
26 | enum dae_obj_flags_e
27 | {
28 | dae_XSD_ANY = 1 << 0,
29 | };
30 |
31 | typedef enum dae_obj_memberdeftype_e dae_obj_memberdeftype;
32 | typedef enum dae_obj_flags_e dae_obj_flags;
33 |
34 | typedef struct dae_obj_memberdef_s dae_obj_memberdef;
35 | typedef struct dae_obj_typedef_s dae_obj_typedef;
36 | typedef struct dae_obj_vector_s dae_obj_vector;
37 | typedef struct dae_obj_list_s dae_obj_list;
38 | typedef struct dae_obj_header_s dae_obj_header;
39 |
40 | struct dae_obj_memberdef_s
41 | {
42 | const char* name;
43 | const char* deflt;
44 | unsigned offset;
45 | short objtypeid;
46 | short min;
47 | short max;
48 | short seq;
49 | };
50 |
51 | struct dae_obj_typedef_s
52 | {
53 | const char* name;
54 | dae_obj_memberdef* attribs;
55 | dae_obj_memberdef* elems;
56 | unsigned flags;
57 | unsigned size;
58 | unsigned dataoffset;
59 | short objtypeid;
60 | short datatypeid;
61 | unsigned short numattribs;
62 | unsigned short numelems;
63 | short datamin;
64 | short datamax;
65 | };
66 |
67 | struct dae_obj_vector_s
68 | {
69 | void* values;
70 | size_t size;
71 | };
72 |
73 | struct dae_obj_list_s
74 | {
75 | dae_obj_header* head;
76 | dae_obj_header* tail;
77 | };
78 |
79 | struct dae_obj_header_s
80 | {
81 | dae_obj_header* parent;
82 | dae_obj_list* parentlist;
83 | const dae_obj_memberdef* memberdef;
84 | const char* membername;
85 | int structindex;
86 | const dae_obj_typedef* def;
87 | dae_obj_list attribs;
88 | dae_obj_list elems;
89 | dae_obj_header* prev;
90 | dae_obj_header* next;
91 | };
92 |
93 | static void dae_free(
94 | void* ptr);
95 |
96 | static char* dae_strdup(
97 | const char* str);
98 |
99 | static dae_obj_ptr dae_create_obj(
100 | const dae_obj_typedef* def);
101 |
102 | static dae_obj_ptr dae_add_obj(
103 | dae_obj_header* parenthdr,
104 | dae_obj_list* parentlist,
105 | const dae_obj_memberdef* memberdef,
106 | const char* membername,
107 | const dae_obj_typedef* childdef,
108 | size_t childsize);
109 |
110 | static void dae_destroy_obj(
111 | dae_obj_header* hdr);
112 |
113 | static size_t dae_convert_string_floats(
114 | const char* str,
115 | float* floats_out);
116 |
117 | static size_t dae_convert_string_int8s(
118 | const char* str,
119 | char* ints_out);
120 |
121 | static size_t dae_convert_string_int16s(
122 | const char* str,
123 | short* ints_out);
124 |
125 | static size_t dae_convert_string_int32s(
126 | const char* str,
127 | int* ints_out);
128 |
129 | static size_t dae_convert_string_uint8s(
130 | const char* str,
131 | unsigned char* ints_out);
132 |
133 | static size_t dae_convert_string_uint32s(
134 | const char* str,
135 | unsigned* ints_out);
136 |
137 | static size_t dae_convert_string_words(
138 | const char* str,
139 | char** strings_out);
140 |
141 | static size_t dae_count_string_floats(
142 | const char* str);
143 |
144 | static size_t dae_count_string_int8s(
145 | const char* str);
146 |
147 | static size_t dae_count_string_int16s(
148 | const char* str);
149 |
150 | static size_t dae_count_string_int32s(
151 | const char* str);
152 |
153 | static size_t dae_count_string_uint8s(
154 | const char* str);
155 |
156 | static size_t dae_count_string_uint32s(
157 | const char* str);
158 |
159 | static size_t dae_count_string_words(
160 | const char* str);
161 |
162 | static void dae_get_schema(
163 | dae_obj_typedef** types,
164 | unsigned* numtypes);
165 |
166 | static dae_obj_typedef* dae_get_type(
167 | unsigned objtypeid);
168 |
169 | static dae_obj_typedef* dae_find_type(
170 | const char* name);
171 |
172 | //****************************************************************************
173 | /*GEN_SCHEMA_BGN*/
174 | static void dae_build_schema(
175 | dae_obj_typedef** types_out,
176 | unsigned* numtypes_out)
177 | {
178 | }
179 | /*GEN_SCHEMA_END*/
180 |
181 | //****************************************************************************
182 | static void dae_free(void* ptr)
183 | {
184 | free(ptr);
185 | }
186 |
187 | //****************************************************************************
188 | static char* dae_strdup(
189 | const char* str)
190 | {
191 | char* dup = NULL;
192 | if(str != NULL && *str != '\0')
193 | {
194 | size_t sz = strlen(str) + 1;
195 | dup = (char*) malloc(sz);
196 | memcpy(dup, str, sz);
197 | }
198 | return dup;
199 | }
200 |
201 | //****************************************************************************
202 | static dae_obj_ptr dae_create_obj(
203 | const dae_obj_typedef* def)
204 | {
205 | size_t objsize = (def != NULL) ? def->size : sizeof(char*);
206 | size_t bufsize = ((ptrdiff_t) dae_GET_PTR(0)) + objsize;
207 | dae_obj_header* hdr = (dae_obj_header*) malloc(bufsize);
208 | dae_obj_ptr obj = dae_GET_PTR(hdr);
209 | memset(hdr, 0, bufsize);
210 | hdr->structindex = -1;
211 | hdr->def = def;
212 | return obj;
213 | }
214 |
215 | //****************************************************************************
216 | static dae_obj_ptr dae_add_obj(
217 | dae_obj_header* parenthdr,
218 | dae_obj_list* parentlist,
219 | const dae_obj_memberdef* memberdef,
220 | const char* membername,
221 | const dae_obj_typedef* childdef,
222 | size_t childsize)
223 | {
224 | void* parentobj = dae_GET_PTR(parenthdr);
225 | void* childobj = dae_create_obj(childdef);
226 | dae_obj_header* childhdr = dae_GET_HEADER(childobj);
227 | // initialize header information
228 | childhdr->parent = parenthdr;
229 | childhdr->parentlist = parentlist;
230 | childhdr->memberdef = memberdef;
231 | // add element to parent's header
232 | childhdr->prev = parentlist->tail;
233 | childhdr->next = NULL;
234 | if(parentlist->tail != NULL)
235 | {
236 | parentlist->tail->next = childhdr;
237 | }
238 | else
239 | {
240 | parentlist->head = childhdr;
241 | }
242 | parentlist->tail = childhdr;
243 | // add element to parent's struct
244 | if(memberdef != NULL)
245 | {
246 | int offset = memberdef->offset;
247 | int max = memberdef->max;
248 | if(max == 1)
249 | {
250 | // single instance pointer
251 | void** mbr = (void**) (((ptrdiff_t) parentobj)+offset);
252 | if(*mbr == NULL)
253 | {
254 | childhdr->structindex = 0;
255 | *mbr = childobj;
256 | }
257 | }
258 | else if(max < 0)
259 | {
260 | // variable sized vector
261 | dae_obj_vector* vec;
262 | void** buf;
263 | size_t i;
264 | vec = (dae_obj_vector*) (((ptrdiff_t) parentobj)+offset);
265 | i = vec->size;
266 | childhdr->structindex = i;
267 | buf = (void**) realloc(vec->values, (i+1) * sizeof(*buf));
268 | buf[i] = childobj;
269 | vec->values = buf;
270 | ++vec->size;
271 | }
272 | else
273 | {
274 | // fixed length array
275 | void** mbr = (void**) (((ptrdiff_t) parentobj)+offset);
276 | void** mbritr = mbr;
277 | void** mbrend = mbritr + max;
278 | while(mbritr != mbrend)
279 | {
280 | if(*mbritr == NULL)
281 | {
282 | childhdr->structindex = (int) (mbritr - mbr);
283 | *mbritr = childobj;
284 | break;
285 | }
286 | ++mbritr;
287 | }
288 | }
289 | // if member definition exists, re-use name string from definition
290 | childhdr->membername = memberdef->name;
291 | }
292 | else
293 | {
294 | // if no member definition exists, need to make a copy of name string
295 | childhdr->membername = dae_strdup(membername);
296 | }
297 | return (dae_obj_ptr) childobj;
298 | }
299 |
300 | //****************************************************************************
301 | static void dae_destroy_obj(
302 | dae_obj_header* hdr)
303 | {
304 | dae_obj_header* itr = hdr;
305 | while(1)
306 | {
307 | dae_obj_header* next;
308 | // move down to bottom of tree
309 | while(itr->elems.head != NULL)
310 | {
311 | itr = itr->elems.head;
312 | }
313 | while(itr->attribs.head != NULL)
314 | {
315 | itr = itr->attribs.head;
316 | }
317 | if(itr->next != NULL)
318 | {
319 | next = itr->next;
320 | }
321 | else
322 | {
323 | next = itr->parent;
324 | if(itr->parentlist != NULL)
325 | {
326 | itr->parentlist->head = NULL;
327 | itr->parentlist->tail = NULL;
328 | }
329 | }
330 | if(itr->attribs.head == NULL && itr->elems.head == NULL)
331 | {
332 | void* obj = dae_GET_PTR(itr);
333 | dae_obj_typeid datatype = dae_ID_INVALID;
334 | int datamax;
335 | size_t dataoff;
336 | if(itr->memberdef == NULL)
337 | {
338 | // if the object had a member definition, the member name
339 | // was derived from the def and does not need to be freed.
340 | // otherwise, it does
341 | dae_free((char*) itr->membername);
342 | }
343 | if(itr->def != NULL)
344 | {
345 | // clean up struct members
346 | const dae_obj_typedef* def = itr->def;
347 | const dae_obj_memberdef* mbritr = def->elems;
348 | const dae_obj_memberdef* mbrend = mbritr + def->numelems;
349 | while(mbritr != mbrend)
350 | {
351 | if(mbritr->max < 0)
352 | {
353 | // if the struct member is a variable sized vector
354 | // the buffer needs to be freed.
355 | dae_obj_vector* vec;
356 | size_t off;
357 | off = mbritr->offset;
358 | vec = (dae_obj_vector*) (((ptrdiff_t) obj) + off);
359 | if(vec->values != NULL)
360 | {
361 | dae_free(vec->values);
362 | // set buffer to NULL to prevent multiple free as
363 | // multiple element definitions may reference it
364 | vec->values = NULL;
365 | }
366 | }
367 | ++mbritr;
368 | }
369 | datatype = (dae_obj_typeid) def->datatypeid;
370 | datamax = def->datamax;
371 | dataoff = def->dataoffset;
372 | }
373 | else
374 | {
375 | datatype = dae_ID_STRING;
376 | datamax = 1;
377 | dataoff = 0;
378 | }
379 | if(datatype != dae_ID_INVALID)
380 | {
381 | if(datamax == -1)
382 | {
383 | // if it's a variable sized vector, free the buffer
384 | dae_obj_vector* vec;
385 | vec = (dae_obj_vector*) (((ptrdiff_t) obj) + dataoff);
386 | if(datatype == dae_ID_STRING)
387 | {
388 | // if it's a vector of strings, all the strings need
389 | // to be freed individually
390 | char** sitr = (char**) vec->values;
391 | char** send = sitr + vec->size;
392 | while(sitr != send)
393 | {
394 | dae_free(*sitr);
395 | ++sitr;
396 | }
397 | }
398 | dae_free(vec->values);
399 | }
400 | else if(datatype == dae_ID_STRING)
401 | {
402 | // single or fixed size array of strings
403 | char** sitr = (char**) (((ptrdiff_t) obj) + dataoff);
404 | char** send = sitr + datamax;
405 | while(sitr != send)
406 | {
407 | dae_free(*sitr);
408 | ++sitr;
409 | }
410 | }
411 | }
412 | dae_free(itr);
413 | if(itr == hdr)
414 | {
415 | // if the freed item was the selected object, stop
416 | break;
417 | }
418 | itr = next;
419 | }
420 | }
421 | }
422 |
423 | //****************************************************************************
424 | static size_t dae_convert_string_floats(
425 | const char* str,
426 | float* floats_out)
427 | {
428 | // parses the string into an array of floats
429 | // the array must be large enough to hold the result of
430 | // dae_count_float_string
431 | size_t n = 0;
432 | while(*str != '\0')
433 | {
434 | float f = 0.0f;
435 | // move past any leading whitespace
436 | while(*str != '\0' && isspace(*str))
437 | {
438 | ++str;
439 | }
440 | // attempt to convert string word to float
441 | if(sscanf(str, "%f", &f) == 1)
442 | {
443 | floats_out[n] = f;
444 | ++n;
445 | }
446 | else
447 | {
448 | break;
449 | }
450 | // find the next set of whitespace
451 | while(*str != '\0' && !isspace(*str))
452 | {
453 | ++str;
454 | }
455 | }
456 | return n;
457 | }
458 |
459 | //****************************************************************************
460 | static size_t dae_convert_string_int8s(
461 | const char* str,
462 | char* ints_out)
463 | {
464 | // counts the number of ints that can be parsed from the string
465 | size_t n = 0;
466 | while(*str != '\0')
467 | {
468 | int i = 0;
469 | // move past any leading whitespace
470 | while(*str != '\0' && isspace(*str))
471 | {
472 | ++str;
473 | }
474 | // attempt to convert string word to int
475 | if(sscanf(str, "%i", &i) == 1)
476 | {
477 | ints_out[n] = (char) i;
478 | ++n;
479 | }
480 | else
481 | {
482 | break;
483 | }
484 | // find the next set of whitespace
485 | while(*str != '\0' && !isspace(*str))
486 | {
487 | ++str;
488 | }
489 | }
490 | return n;
491 | }
492 |
493 | //****************************************************************************
494 | static size_t dae_convert_string_int16s(
495 | const char* str,
496 | short* ints_out)
497 | {
498 | // counts the number of ints that can be parsed from the string
499 | size_t n = 0;
500 | while(*str != '\0')
501 | {
502 | int i = 0;
503 | // move past any leading whitespace
504 | while(*str != '\0' && isspace(*str))
505 | {
506 | ++str;
507 | }
508 | // attempt to convert string word to int
509 | if(sscanf(str, "%i", &i) == 1)
510 | {
511 | ints_out[n] = (short) i;
512 | ++n;
513 | }
514 | else
515 | {
516 | break;
517 | }
518 | // find the next set of whitespace
519 | while(*str != '\0' && !isspace(*str))
520 | {
521 | ++str;
522 | }
523 | }
524 | return n;
525 | }
526 |
527 | //****************************************************************************
528 | static size_t dae_convert_string_int32s(
529 | const char* str,
530 | int* ints_out)
531 | {
532 | // counts the number of ints that can be parsed from the string
533 | size_t n = 0;
534 | while(*str != '\0')
535 | {
536 | int i = 0;
537 | // move past any leading whitespace
538 | while(*str != '\0' && isspace(*str))
539 | {
540 | ++str;
541 | }
542 | // attempt to convert string word to int
543 | if(sscanf(str, "%i", &i) == 1)
544 | {
545 | ints_out[n] = i;
546 | ++n;
547 | }
548 | else
549 | {
550 | break;
551 | }
552 | // find the next set of whitespace
553 | while(*str != '\0' && !isspace(*str))
554 | {
555 | ++str;
556 | }
557 | }
558 | return n;
559 | }
560 |
561 | //****************************************************************************
562 | static size_t dae_convert_string_uint8s(
563 | const char* str,
564 | unsigned char* ints_out)
565 | {
566 | // counts the number of ints that can be parsed from the string
567 | size_t n = 0;
568 | while(*str != '\0')
569 | {
570 | unsigned i = 0;
571 | // move past any leading whitespace
572 | while(*str != '\0' && isspace(*str))
573 | {
574 | ++str;
575 | }
576 | // attempt to convert string word to int
577 | if(sscanf(str, "%i", &i) == 1)
578 | {
579 | ints_out[n] = (unsigned char) i;
580 | ++n;
581 | }
582 | else
583 | {
584 | break;
585 | }
586 | // find the next set of whitespace
587 | while(*str != '\0' && !isspace(*str))
588 | {
589 | ++str;
590 | }
591 | }
592 | return n;
593 | }
594 |
595 | //****************************************************************************
596 | static size_t dae_convert_string_uint32s(
597 | const char* str,
598 | unsigned* ints_out)
599 | {
600 | // counts the number of ints that can be parsed from the string
601 | size_t n = 0;
602 | while(*str != '\0')
603 | {
604 | unsigned i = 0;
605 | // move past any leading whitespace
606 | while(*str != '\0' && isspace(*str))
607 | {
608 | ++str;
609 | }
610 | // attempt to convert string word to int
611 | if(sscanf(str, "%u", &i) == 1)
612 | {
613 | ints_out[n] = i;
614 | ++n;
615 | }
616 | else
617 | {
618 | break;
619 | }
620 | // find the next set of whitespace
621 | while(*str != '\0' && !isspace(*str))
622 | {
623 | ++str;
624 | }
625 | }
626 | return n;
627 | }
628 |
629 | //****************************************************************************
630 | static size_t dae_convert_string_words(
631 | const char* str,
632 | char** strings_out)
633 | {
634 | size_t n = 0;
635 | while(*str != '\0')
636 | {
637 | size_t len = 0;
638 | // move past any leading whitespace
639 | while(*str != '\0' && isspace(*str))
640 | {
641 | ++str;
642 | }
643 | // determine length of trimmed word
644 | while(str[len] != '\0' && !isspace(str[len]))
645 | {
646 | ++len;
647 | }
648 | // duplicate trimmed word
649 | if(len > 0)
650 | {
651 | char* dup = (char*) malloc(len + 1);
652 | memcpy(dup, str, len);
653 | dup[len] = '\0';
654 | strings_out[n] = dup;
655 | ++n;
656 | }
657 | // find the next set of whitespace
658 | str += len;
659 | }
660 | return n;
661 | }
662 |
663 | //****************************************************************************
664 | static size_t dae_count_string_floats(
665 | const char* str)
666 | {
667 | // counts the number of floats that can be parsed from the string
668 | size_t n = 0;
669 | while(*str != '\0')
670 | {
671 | float f = 0.0f;
672 | // move past any leading whitespace
673 | while(*str != '\0' && isspace(*str))
674 | {
675 | ++str;
676 | }
677 | // attempt to convert string word to float
678 | if(sscanf(str, "%f", &f) == 1)
679 | {
680 | ++n;
681 | }
682 | else
683 | {
684 | break;
685 | }
686 | // find the next set of whitespace
687 | while(*str != '\0' && !isspace(*str))
688 | {
689 | ++str;
690 | }
691 | }
692 | return n;
693 | }
694 |
695 | //****************************************************************************
696 | static size_t dae_count_string_int8s(
697 | const char* str)
698 | {
699 | return dae_count_string_int32s(str);
700 | }
701 |
702 | //****************************************************************************
703 | static size_t dae_count_string_int16s(
704 | const char* str)
705 | {
706 | return dae_count_string_int32s(str);
707 | }
708 |
709 | //****************************************************************************
710 | static size_t dae_count_string_int32s(
711 | const char* str)
712 | {
713 | // counts the number of ints that can be parsed from the string
714 | size_t n = 0;
715 | while(*str != '\0')
716 | {
717 | int i = 0;
718 | // move past any leading whitespace
719 | while(*str != '\0' && isspace(*str))
720 | {
721 | ++str;
722 | }
723 | // attempt to convert string word to int
724 | if(sscanf(str, "%i", &i) == 1)
725 | {
726 | ++n;
727 | }
728 | else
729 | {
730 | break;
731 | }
732 | // find the next set of whitespace
733 | while(*str != '\0' && !isspace(*str))
734 | {
735 | ++str;
736 | }
737 | }
738 | return n;
739 | }
740 |
741 | //****************************************************************************
742 | static size_t dae_count_string_uint8s(
743 | const char* str)
744 | {
745 | return dae_count_string_uint32s(str);
746 | }
747 |
748 | //****************************************************************************
749 | static size_t dae_count_string_uint32s(
750 | const char* str)
751 | {
752 | // counts the number of ints that can be parsed from the string
753 | size_t n = 0;
754 | while(*str != '\0')
755 | {
756 | int i = 0;
757 | // move past any leading whitespace
758 | while(*str != '\0' && isspace(*str))
759 | {
760 | ++str;
761 | }
762 | // attempt to convert string word to int
763 | if(sscanf(str, "%u", &i) == 1)
764 | {
765 | ++n;
766 | }
767 | else
768 | {
769 | break;
770 | }
771 | // find the next set of whitespace
772 | while(*str != '\0' && !isspace(*str))
773 | {
774 | ++str;
775 | }
776 | }
777 | return n;
778 | }
779 |
780 | //****************************************************************************
781 | static size_t dae_count_string_words(
782 | const char* str)
783 | {
784 | size_t n = 0;
785 | while(*str != '\0')
786 | {
787 | size_t len = 0;
788 | // move past any leading whitespace
789 | while(*str != '\0' && isspace(*str))
790 | {
791 | ++str;
792 | }
793 | // determine length of trimmed word
794 | while(str[len] != '\0' && !isspace(str[len]))
795 | {
796 | ++len;
797 | }
798 | // count it
799 | if(len > 0)
800 | {
801 | ++n;
802 | }
803 | // find the next set of whitespace
804 | str += len;
805 | }
806 | return n;
807 | }
808 |
809 | //****************************************************************************
810 | static void dae_get_schema(
811 | dae_obj_typedef** types,
812 | unsigned* numtypes)
813 | {
814 | static dae_obj_typedef* s_types;
815 | static unsigned s_numtypes;
816 | if(s_types == NULL)
817 | {
818 | dae_build_schema(&s_types, &s_numtypes);
819 | }
820 | *types = s_types;
821 | *numtypes = s_numtypes;
822 | }
823 |
824 | //****************************************************************************
825 | static dae_obj_typedef* dae_get_type(
826 | unsigned objtypeid)
827 | {
828 | dae_obj_typedef* types;
829 | unsigned numtypes;
830 | dae_get_schema(&types, &numtypes);
831 | return (objtypeid < numtypes) ? types + objtypeid : NULL;
832 | }
833 |
834 | //****************************************************************************
835 | static dae_obj_typedef* dae_find_type(
836 | const char* name)
837 | {
838 | dae_obj_typedef* result = NULL;
839 | dae_obj_typedef* titr;
840 | dae_obj_typedef* tend;
841 | unsigned numtypes;
842 | dae_get_schema(&titr, &numtypes);
843 | tend = titr + numtypes;
844 | while(titr != tend)
845 | {
846 | if(!strcmp(titr->name, name))
847 | {
848 | result = titr;
849 | break;
850 | }
851 | ++titr;
852 | }
853 | return result;
854 | }
855 |
856 | //****************************************************************************
857 | dae_obj_ptr dae_add_attrib(
858 | dae_obj_ptr parent,
859 | const char* name,
860 | const char* value)
861 | {
862 | dae_obj_header* parenthdr = dae_GET_HEADER(parent);
863 | const dae_obj_typedef* parentdef = parenthdr->def;
864 | const dae_obj_memberdef* at = NULL;
865 | const dae_obj_typedef* def = NULL;
866 | dae_obj_ptr obj = NULL;
867 | if(parentdef != NULL)
868 | {
869 | // predefined content type
870 | // need to find a predefined attribute
871 | dae_obj_memberdef* atitr = parentdef->attribs;
872 | dae_obj_memberdef* atend = atitr + parentdef->numattribs;
873 | while(atitr != atend)
874 | {
875 | if(!strcmp(name, atitr->name))
876 | {
877 | at = atitr;
878 | def = dae_get_type(atitr->objtypeid);
879 | break;
880 | }
881 | ++atitr;
882 | }
883 | }
884 | else
885 | {
886 | // undefined type, assume all attributes are strings
887 | def = dae_get_type(dae_ID_STRING);
888 | }
889 | if(def != NULL)
890 | {
891 | obj = dae_add_obj(
892 | parenthdr,
893 | &parenthdr->attribs,
894 | at,
895 | name,
896 | def,
897 | def->size);
898 | if(value == NULL && at != NULL)
899 | {
900 | value = at->deflt;
901 | }
902 | if(value != NULL)
903 | {
904 | dae_set_string(obj, value);
905 | }
906 | }
907 | return obj;
908 | }
909 |
910 | //****************************************************************************
911 | dae_obj_ptr dae_add_element(
912 | dae_obj_ptr parent,
913 | const char* name)
914 | {
915 | dae_obj_header* parenthdr = dae_GET_HEADER(parent);
916 | const dae_obj_typedef* parentdef = parenthdr->def;
917 | const dae_obj_memberdef* el = NULL;
918 | const dae_obj_typedef* def = NULL;
919 | dae_obj_ptr obj = NULL;
920 | if(parentdef!=NULL && (parentdef->flags&dae_XSD_ANY)==0)
921 | {
922 | // predefined content type
923 | // need to find a predefined element
924 | dae_obj_memberdef* elitr = parentdef->elems;
925 | dae_obj_memberdef* elend = elitr + parentdef->numelems;
926 | while(elitr != elend)
927 | {
928 | if(!strcmp(name, elitr->name))
929 | {
930 | el = elitr;
931 | def = dae_get_type(elitr->objtypeid);
932 | break;
933 | }
934 | ++elitr;
935 | }
936 | }
937 | else
938 | {
939 | // any element content is allowed
940 | def = dae_find_type(name);
941 | }
942 | if(parentdef == NULL || parentdef->datamax == 0)
943 | {
944 | obj = dae_add_obj(
945 | parenthdr,
946 | &parenthdr->elems,
947 | el,
948 | name,
949 | def,
950 | (def != NULL) ? def->size : 0);
951 | }
952 | else
953 | {
954 | assert(0);
955 | }
956 | return obj;
957 | }
958 |
959 | //****************************************************************************
960 | dae_COLLADA* dae_create()
961 | {
962 | const dae_obj_typedef* def = dae_get_type(dae_ID_COLLADA);
963 | return (dae_COLLADA*) dae_create_obj(def);
964 | }
965 |
966 | //****************************************************************************
967 | void dae_destroy(
968 | dae_COLLADA* doc)
969 | {
970 | dae_destroy_obj(dae_GET_HEADER(doc));
971 | }
972 |
973 | //****************************************************************************
974 | size_t dae_get_data(
975 | dae_obj_ptr obj,
976 | dae_native_typeid* type_out,
977 | void** data_out,
978 | size_t* datalen_out)
979 | {
980 | size_t datalen = 0;
981 | const dae_obj_typedef* def = dae_GET_HEADER(obj)->def;
982 | if(def != NULL)
983 | {
984 | void* data = (void*) (((ptrdiff_t) obj) + def->dataoffset);
985 | if(def->datamax >= 0)
986 | {
987 | // fixed size array
988 | datalen = def->datamax;
989 | }
990 | else
991 | {
992 | // dynamically sized vector
993 | dae_obj_vector* vec = (dae_obj_vector*) data;
994 | data = vec->values;
995 | datalen = vec->size;
996 | }
997 | *type_out = (dae_native_typeid) def->datatypeid;
998 | *data_out = data;
999 | *datalen_out = datalen;
1000 | }
1001 | return datalen;
1002 | }
1003 |
1004 | //****************************************************************************
1005 | dae_obj_ptr dae_get_first_attrib(
1006 | dae_obj_ptr obj)
1007 | {
1008 | dae_obj_header* childhdr = dae_GET_HEADER(obj)->attribs.head;
1009 | return (childhdr != NULL) ? dae_GET_PTR(childhdr) : NULL;
1010 | }
1011 |
1012 | //****************************************************************************
1013 | dae_obj_ptr dae_get_first_element(
1014 | dae_obj_ptr obj)
1015 | {
1016 | dae_obj_header* childhdr = dae_GET_HEADER(obj)->elems.head;
1017 | return (childhdr != NULL) ? dae_GET_PTR(childhdr) : NULL;
1018 | }
1019 |
1020 | //****************************************************************************
1021 | const char* dae_get_name(
1022 | dae_obj_ptr obj)
1023 | {
1024 | return dae_GET_HEADER(obj)->membername;
1025 | }
1026 |
1027 | //****************************************************************************
1028 | dae_obj_ptr dae_get_next(
1029 | dae_obj_ptr obj)
1030 | {
1031 | dae_obj_header* nexthdr = dae_GET_HEADER(obj)->next;
1032 | return (nexthdr != NULL) ? dae_GET_PTR(nexthdr) : NULL;
1033 | }
1034 |
1035 | //****************************************************************************
1036 | dae_obj_ptr dae_get_parent(
1037 | dae_obj_ptr child)
1038 | {
1039 | dae_obj_header* parenthdr = dae_GET_HEADER(child)->parent;
1040 | return (parenthdr != NULL) ? dae_GET_PTR(parenthdr) : NULL;
1041 | }
1042 |
1043 | //****************************************************************************
1044 | dae_obj_typeid dae_get_typeid(
1045 | dae_obj_ptr obj)
1046 | {
1047 | const dae_obj_typedef* def = dae_GET_HEADER(obj)->def;
1048 | return (def != NULL) ? (dae_obj_typeid) def->objtypeid : dae_ID_INVALID;
1049 | }
1050 |
1051 | //****************************************************************************
1052 | void dae_set_string(
1053 | dae_obj_ptr obj,
1054 | const char* data)
1055 | {
1056 | dae_obj_header* hdr = dae_GET_HEADER(obj);
1057 | const dae_obj_typedef* def = hdr->def;
1058 | dae_native_typeid datatype = dae_NATIVE_STRING;
1059 | int dataoffset = -1;
1060 | int max;
1061 | if(def != NULL)
1062 | {
1063 | if(def->datatypeid != dae_ID_INVALID)
1064 | {
1065 | datatype = (dae_native_typeid) def->datatypeid;
1066 | dataoffset = def->dataoffset;
1067 | max = def->datamax;
1068 | }
1069 | }
1070 | else
1071 | {
1072 | // if this is a generic element with no type definition, make it a
1073 | // pointer to a string
1074 | datatype = dae_NATIVE_STRING;
1075 | dataoffset = 0;
1076 | max = 1;
1077 | }
1078 | if(dataoffset >= 0)
1079 | {
1080 | if(max == 1)
1081 | {
1082 | void* p = (void*) (((ptrdiff_t) obj) + dataoffset);
1083 | // trim leading space
1084 | while(*data != '\0' && isspace(*data))
1085 | {
1086 | ++data;
1087 | }
1088 | switch(datatype)
1089 | {
1090 | case dae_NATIVE_BOOL32:
1091 | // TODO
1092 | break;
1093 | case dae_NATIVE_HEX8:
1094 | // TODO
1095 | break;
1096 | case dae_NATIVE_FLOAT:
1097 | {
1098 | float f = 0;
1099 | if(sscanf(data, "%f", &f) == 1)
1100 | {
1101 | float* fp = (float*) p;
1102 | *fp = (float) f;
1103 | }
1104 | }
1105 | break;
1106 | case dae_NATIVE_INT8:
1107 | {
1108 | int i = 0;
1109 | if(sscanf(data, "%i", &i) == 1)
1110 | {
1111 | char* ip = (char*) p;
1112 | *ip = (char) i;
1113 | }
1114 | }
1115 | break;
1116 | case dae_NATIVE_INT16:
1117 | {
1118 | int i = 0;
1119 | if(sscanf(data, "%i", &i) == 1)
1120 | {
1121 | short* ip = (short*) p;
1122 | *ip = (short) i;
1123 | }
1124 | }
1125 | break;
1126 | case dae_NATIVE_INT32:
1127 | {
1128 | int i = 0;
1129 | if(sscanf(data, "%i", &i) == 1)
1130 | {
1131 | int* ip = (int*) p;
1132 | *ip = (int) i;
1133 | }
1134 | }
1135 | break;
1136 | case dae_NATIVE_STRING:
1137 | {
1138 | // TODO: free old pointer?
1139 | size_t len = 0;
1140 | // trim trailing space
1141 | while(data[len] != '\0' && !isspace(data[len]))
1142 | {
1143 | ++len;
1144 | }
1145 | if(len > 0)
1146 | {
1147 | char** sp = (char**) p;
1148 | char* dup = (char*) malloc(len + 1);
1149 | memcpy(dup, data, len);
1150 | dup[len] = '\0';
1151 | *sp = dup;
1152 | }
1153 | }
1154 | break;
1155 | case dae_NATIVE_UINT8:
1156 | {
1157 | unsigned i = 0;
1158 | if(sscanf(data, "%u", &i) == 1)
1159 | {
1160 | unsigned char* ip = (unsigned char*) p;
1161 | *ip = (unsigned char) i;
1162 | }
1163 | }
1164 | break;
1165 | case dae_NATIVE_UINT32:
1166 | {
1167 | unsigned i = 0;
1168 | if(sscanf(data, "%u", &i) == 1)
1169 | {
1170 | unsigned* ip = (unsigned *) p;
1171 | *ip = (unsigned) i;
1172 | }
1173 | }
1174 | break;
1175 | default:
1176 | assert(0);
1177 | break;
1178 | }
1179 | }
1180 | else if(max == -1)
1181 | {
1182 | dae_obj_vector* vec;
1183 | vec = (dae_obj_vector*) (((ptrdiff_t) obj) + dataoffset);
1184 | switch(datatype)
1185 | {
1186 | case dae_NATIVE_BOOL32:
1187 | // TODO
1188 | break;
1189 | case dae_NATIVE_HEX8:
1190 | // TODO
1191 | break;
1192 | case dae_NATIVE_FLOAT:
1193 | {
1194 | size_t n = dae_count_string_floats(data);
1195 | if(n > 0)
1196 | {
1197 | float* fv = (float*) vec->values;
1198 | if(n > vec->size)
1199 | {
1200 | fv = (float*) realloc(fv, n*sizeof(*fv));
1201 | vec->values = fv;
1202 | }
1203 | vec->size = dae_convert_string_floats(data, fv);
1204 | }
1205 | }
1206 | break;
1207 | case dae_NATIVE_INT8:
1208 | {
1209 | size_t n = dae_count_string_int8s(data);
1210 | if(n > 0)
1211 | {
1212 | char* iv = (char*) vec->values;
1213 | if(n > vec->size)
1214 | {
1215 | iv = (char*) realloc(iv, n*sizeof(*iv));
1216 | vec->values = iv;
1217 | }
1218 | vec->size = dae_convert_string_int8s(data, iv);
1219 | }
1220 | }
1221 | break;
1222 | case dae_NATIVE_INT16:
1223 | {
1224 | size_t n = dae_count_string_int16s(data);
1225 | if(n > 0)
1226 | {
1227 | short* iv = (short*) vec->values;
1228 | if(n > vec->size)
1229 | {
1230 | iv = (short*) realloc(iv, n*sizeof(*iv));
1231 | vec->values = iv;
1232 | }
1233 | vec->size = dae_convert_string_int16s(data, iv);
1234 | }
1235 | }
1236 | break;
1237 | case dae_NATIVE_INT32:
1238 | {
1239 | size_t n = dae_count_string_int32s(data);
1240 | if(n > 0)
1241 | {
1242 | int* iv = (int*) vec->values;
1243 | if(n > vec->size)
1244 | {
1245 | iv = (int*) realloc(iv, n*sizeof(*iv));
1246 | vec->values = iv;
1247 | }
1248 | vec->size = dae_convert_string_int32s(data, iv);
1249 | }
1250 | }
1251 | break;
1252 | case dae_NATIVE_STRING:
1253 | {
1254 | size_t n = dae_count_string_words(data);
1255 | if(n > 0)
1256 | {
1257 | // TODO: free old pointers?
1258 | char** sv = (char**) vec->values;
1259 | if(n > vec->size)
1260 | {
1261 | sv = (char**) realloc(sv, n*sizeof(*sv));
1262 | vec->values = sv;
1263 | }
1264 | vec->size = dae_convert_string_words(data, sv);
1265 | }
1266 | }
1267 | break;
1268 | case dae_NATIVE_UINT8:
1269 | {
1270 | size_t n = dae_count_string_uint8s(data);
1271 | if(n > 0)
1272 | {
1273 | unsigned char* iv = (unsigned char*) vec->values;
1274 | if(n > vec->size)
1275 | {
1276 | iv = (unsigned char*) realloc(iv, n*sizeof(*iv));
1277 | vec->values = iv;
1278 | }
1279 | vec->size = dae_convert_string_uint8s(data, iv);
1280 | }
1281 | }
1282 | break;
1283 | case dae_NATIVE_UINT32:
1284 | {
1285 | size_t n = dae_count_string_uint32s(data);
1286 | if(n > 0)
1287 | {
1288 | unsigned* iv = (unsigned*) vec->values;
1289 | if(n > vec->size)
1290 | {
1291 | iv = (unsigned*) realloc(iv, n*sizeof(*iv));
1292 | vec->values = iv;
1293 | }
1294 | vec->size = dae_convert_string_uint32s(data, iv);
1295 | }
1296 | }
1297 | break;
1298 | default:
1299 | assert(0);
1300 | break;
1301 | }
1302 | }
1303 | else
1304 | {
1305 | // fixed size array
1306 | void* ar = (void*) (((ptrdiff_t) obj) + dataoffset);
1307 | switch(datatype)
1308 | {
1309 | case dae_NATIVE_BOOL32:
1310 | // TODO
1311 | break;
1312 | case dae_NATIVE_HEX8:
1313 | // TODO
1314 | break;
1315 | case dae_NATIVE_FLOAT:
1316 | {
1317 | int n = dae_count_string_floats(data);
1318 | if(n == max)
1319 | {
1320 | float* fv = (float*) ar;
1321 | dae_convert_string_floats(data, fv);
1322 | }
1323 | }
1324 | break;
1325 | case dae_NATIVE_INT8:
1326 | {
1327 | int n = dae_count_string_int8s(data);
1328 | if(n == max)
1329 | {
1330 | char* iv = (char*) ar;
1331 | dae_convert_string_int8s(data, iv);
1332 | }
1333 | }
1334 | break;
1335 | case dae_NATIVE_INT16:
1336 | {
1337 | int n = dae_count_string_int16s(data);
1338 | if(n == max)
1339 | {
1340 | short* iv = (short*) ar;
1341 | dae_convert_string_int16s(data, iv);
1342 | }
1343 | }
1344 | break;
1345 | case dae_NATIVE_INT32:
1346 | {
1347 | int n = dae_count_string_int32s(data);
1348 | if(n == max)
1349 | {
1350 | int* iv = (int*) ar;
1351 | dae_convert_string_int32s(data, iv);
1352 | }
1353 | }
1354 | break;
1355 | case dae_NATIVE_STRING:
1356 | {
1357 | int n = dae_count_string_words(data);
1358 | if(n == max)
1359 | {
1360 | // TODO: free old pointers?
1361 | char** sv = (char**) ar;
1362 | dae_convert_string_words(data, sv);
1363 | }
1364 | }
1365 | break;
1366 | case dae_NATIVE_UINT8:
1367 | {
1368 | int n = dae_count_string_uint8s(data);
1369 | if(n == max)
1370 | {
1371 | unsigned char* iv = (unsigned char*) ar;
1372 | dae_convert_string_uint8s(data, iv);
1373 | }
1374 | }
1375 | break;
1376 | case dae_NATIVE_UINT32:
1377 | {
1378 | int n = dae_count_string_uint32s(data);
1379 | if(n == max)
1380 | {
1381 | unsigned* iv = (unsigned*)ar;
1382 | dae_convert_string_uint32s(data, iv);
1383 | }
1384 | }
1385 | break;
1386 | default:
1387 | assert(0);
1388 | break;
1389 | }
1390 | }
1391 | }
1392 | }
1393 |
--------------------------------------------------------------------------------
/gen/template/dae.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @brief libdae header
3 | * @author Thomas Atwood (tatwood.net)
4 | * @date 2011
5 | * @copyright unlicense / public domain
6 | ****************************************************************************/
7 | #ifndef DAE_H_
8 | #define DAE_H_
9 |
10 | #include
11 |
12 | //****************************************************************************
13 | // enums
14 |
15 | /*GEN_TYPEIDS_BGN*/
16 | enum dae_obj_typeid_e
17 | {
18 | dae_ID_BOOLEAN,
19 | dae_ID_HEXBINARY,
20 | dae_ID_FLOAT,
21 | dae_ID_BYTE,
22 | dae_ID_SHORT,
23 | dae_ID_INT,
24 | dae_ID_STRING,
25 | dae_ID_UNSIGNEDBYTE,
26 | dae_ID_UNSIGNEDINT,
27 | dae_ID_COLLADA,
28 | dae_ID_INVALID = -1
29 | };
30 | /*GEN_TYPEIDS_END*/
31 |
32 | enum dae_native_typeid_e
33 | {
34 | /// can be evaluated as int32_t
35 | dae_NATIVE_BOOL32 = dae_ID_BOOLEAN,
36 | /// can be evaluated as uint8_t
37 | dae_NATIVE_HEX8 = dae_ID_HEXBINARY,
38 | /// can be evaluated as float
39 | dae_NATIVE_FLOAT = dae_ID_FLOAT,
40 | /// can be evaluated as int8_t
41 | dae_NATIVE_INT8 = dae_ID_BYTE,
42 | /// can be evaluated as int16_t
43 | dae_NATIVE_INT16 = dae_ID_SHORT,
44 | /// can be evaluated as int32_t
45 | dae_NATIVE_INT32 = dae_ID_INT,
46 | /// can be evaluated as char*
47 | dae_NATIVE_STRING = dae_ID_STRING,
48 | /// can be evaluated as uint8_t
49 | dae_NATIVE_UINT8 = dae_ID_UNSIGNEDBYTE,
50 | /// can be evaluated as uint32_t
51 | dae_NATIVE_UINT32 = dae_ID_UNSIGNEDINT
52 | };
53 |
54 | //****************************************************************************
55 | // typedefs
56 |
57 | typedef enum dae_native_typeid_e dae_native_typeid;
58 | typedef enum dae_obj_typeid_e dae_obj_typeid;
59 |
60 | typedef void* dae_obj_ptr;
61 |
62 | /*GEN_TYPEDEFS_BGN*/
63 | typedef struct dae_COLLADA_S dae_COLLADA;
64 | /*GEN_TYPEDEFS_END*/
65 |
66 | //****************************************************************************
67 | // structs
68 |
69 | /*GEN_STRUCTS_BGN*/
70 | /*GEN_STRUCTS_END*/
71 |
72 | //****************************************************************************
73 | // functions
74 |
75 | #ifdef __cplusplus
76 | extern "C" {
77 | #endif // __cplusplus
78 |
79 | dae_obj_ptr dae_add_attrib(
80 | dae_obj_ptr parent,
81 | const char* name,
82 | const char* value);
83 |
84 | dae_obj_ptr dae_add_element(
85 | dae_obj_ptr parent,
86 | const char* name);
87 |
88 | dae_COLLADA* dae_create();
89 |
90 | void dae_destroy(
91 | dae_COLLADA* doc);
92 |
93 | size_t dae_get_data(
94 | dae_obj_ptr obj,
95 | dae_native_typeid* type_out,
96 | void** data_out,
97 | size_t* datalen_out);
98 |
99 | dae_obj_ptr dae_get_first_attrib(
100 | dae_obj_ptr obj);
101 |
102 | dae_obj_ptr dae_get_first_element(
103 | dae_obj_ptr obj);
104 |
105 | const char* dae_get_name(
106 | dae_obj_ptr obj);
107 |
108 | dae_obj_ptr dae_get_next(
109 | dae_obj_ptr obj);
110 |
111 | dae_obj_ptr dae_get_parent(
112 | dae_obj_ptr child);
113 |
114 | dae_obj_typeid dae_get_typeid(
115 | dae_obj_ptr obj);
116 |
117 | void dae_set_string(
118 | dae_obj_ptr obj,
119 | const char* data);
120 |
121 | #ifdef __cplusplus
122 | }
123 | #endif // __cplusplus
124 |
125 | #endif // DAE_H_
126 |
127 |
--------------------------------------------------------------------------------
/include/daeu.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @brief libdae utility header
3 | * @details These utility functions are written using only the external API.
4 | * They are provided as a convenience, but their functionality
5 | * could be replicated without access to the library internals.
6 | * @author Thomas Atwood (tatwood.net)
7 | * @date 2011
8 | * @copyright unlicense / public domain
9 | ****************************************************************************/
10 | #ifndef DAEU_H_
11 | #define DAEU_H_
12 |
13 | #include "dae.h"
14 |
15 | typedef struct daeu_xml_parser_s* daeu_xml_parser;
16 |
17 | #ifdef __cplusplus
18 | extern "C" {
19 | #endif // __cplusplus
20 |
21 | void daeu_calc_transform_matrix(
22 | dae_obj_ptr obj,
23 | float* mtx_out);
24 |
25 | void daeu_lookat_to_matrix(
26 | const dae_lookat_type* lookat,
27 | float* mtx_out);
28 |
29 | void daeu_rotate_to_matrix(
30 | const dae_rotate_type* rotate,
31 | float* mtx_out);
32 |
33 | void daeu_scale_to_matrix(
34 | const dae_scale_type* scale,
35 | float* mtx_out);
36 |
37 | void daeu_translate_to_matrix(
38 | const dae_translate_type* translate,
39 | float* mtx_out);
40 |
41 | /**
42 | * @details This function can be used to perform a sid search that targets an
43 | * element and possibly a data component within that element. For example, if
44 | * the search string is "node_0/translate.X", this function will set the
45 | * output parameters so that obj_out points to the object with id "translate"
46 | * within "node_0", and dataindex_out will be set to 0, representing an index
47 | * to the first float value in the data array of
48 | * "translate". The data_out parameter is optional.
49 | * @param obj_out out param that will be filled with target object
50 | * @param data_out optional out param that will be filled with the array index
51 | * of the target data component referenced by the search string. If no
52 | * component was specified, or it does not exist, it will be set to -1
53 | * @return The number of outputs found: 2 if both the object and data target
54 | * were found, 1 if only an object target was found, and 0 if no
55 | * targets were found.
56 | */
57 | int daeu_search_sid(
58 | dae_obj_ptr searchroot,
59 | const char* ref,
60 | dae_obj_ptr* obj_out,
61 | int* dataindex_out);
62 |
63 | dae_obj_ptr daeu_search_uri(
64 | dae_obj_ptr searchroot,
65 | const char* uri);
66 |
67 | void daeu_xml_chardata(
68 | void *userdata,
69 | const char *s,
70 | int len);
71 |
72 | void daeu_xml_create(
73 | dae_COLLADA* root,
74 | daeu_xml_parser* parser_out);
75 |
76 | void daeu_xml_destroy(
77 | daeu_xml_parser parser);
78 |
79 | void daeu_xml_endelement(
80 | void* userdata,
81 | const char* el);
82 |
83 | void daeu_xml_startelement(
84 | void* userdata,
85 | const char* el,
86 | const char** att);
87 |
88 | #ifdef __cplusplus
89 | }
90 | #endif // __cplusplus
91 |
92 | #endif // DAEU_H_
93 |
--------------------------------------------------------------------------------
/libdae_vs2010.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 |
14 |
15 |
16 |
17 | libdae
18 | {262EE279-87D3-4C94-8625-B20613779B74}
19 | libdae
20 | Win32Proj
21 |
22 |
23 |
24 | StaticLibrary
25 | MultiByte
26 | true
27 |
28 |
29 | StaticLibrary
30 | MultiByte
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | <_ProjectFileVersion>10.0.30319.1
44 | $(ProjectDir)lib/
45 | $(ProjectDir)objd/
46 | $(ProjectDir)lib/
47 | $(ProjectDir)obj/
48 | $(ProjectName)d
49 |
50 |
51 |
52 | Disabled
53 | include;%(AdditionalIncludeDirectories)
54 | WIN32;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions)
55 | true
56 |
57 |
58 | EnableFastChecks
59 | MultiThreadedDebug
60 | false
61 |
62 |
63 | $(IntDir)
64 | Level3
65 | EditAndContinue
66 | CompileAsC
67 |
68 |
69 | $(OutDir)$(TargetName)$(TargetExt)
70 | Console
71 | ../../extern/expat/libexpatMT.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
72 | true
73 |
74 |
75 |
76 |
77 | MaxSpeed
78 | true
79 | include;%(AdditionalIncludeDirectories)
80 | WIN32;_CRT_SECURE_NO_WARNINGS;NDEBUG;%(PreprocessorDefinitions)
81 |
82 |
83 | MultiThreaded
84 | true
85 | false
86 |
87 |
88 | $(IntDir)
89 | Level3
90 | ProgramDatabase
91 | CompileAsC
92 |
93 |
94 | Console
95 | ../../extern/expat/libexpatMT.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
96 |
97 |
98 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/make.c:
--------------------------------------------------------------------------------
1 | #include "src/dae.c"
2 | #include "src/daeu.c"
3 |
--------------------------------------------------------------------------------
/makefile:
--------------------------------------------------------------------------------
1 | LIB=lib/libdae.a
2 | LIBD=lib/libdaed.a
3 | OBJS=obj/make.o
4 | OBJSD=objd/make.o
5 | INCLUDES=-Iinclude
6 | CC=gcc
7 | CCFLAGS=-Wall -O3 -fno-exceptions -DNDEBUG $(INCLUDES)
8 | CCFLAGSD=-Wall -O0 -ggdb2 -fno-exceptions -DDEBUG $(INCLUDES)
9 | AR=ar
10 | ARFLAGS=rs
11 |
12 | $(LIB): obj lib $(OBJS)
13 | $(AR) $(ARFLAGS) $@ $(OBJS)
14 |
15 | $(LIBD): obj lib $(OBJSD)
16 | $(AR) $(ARFLAGS) $@ $(OBJSD)
17 |
18 | obj:
19 | mkdir obj
20 |
21 | objd:
22 | mkdir objd
23 |
24 | lib:
25 | mkdir lib
26 |
27 | obj/make.o : make.c
28 | $(CC) $(CCFLAGS) -c $< -o $@
29 |
30 | objd/make.o : make.c
31 | $(CC) $(CCFLAGSD) -c $< -o $@
32 |
33 | all: $(LIB) $(LIBD)
34 |
35 | clean:
36 | rm -rf lib/libdae.a lib/libdaed.a obj
37 |
38 |
--------------------------------------------------------------------------------
/readme.txt:
--------------------------------------------------------------------------------
1 | libdae
2 | ======
3 |
4 | Auto generated C library for processing COLLADA files based on the XSD schema
5 |
6 | author: Thomas Atwood (tatwood.net)
7 | date: 2011
8 | license: see UNLICENSE.txt
9 |
10 | Description
11 | ===========
12 |
13 | One of the goals of this project is to be as easy as possible to setup and
14 | build. Technically, only one C file is required to build and link with this
15 | library. If ./src/dae.c is linked into an application, and dae.h is in the
16 | include path, no additional setup is required. Realistically, any project
17 | using this library will also need an XML parser. No dependencies exist on any
18 | particular XML parser, but utility functions are provided that are designed to
19 | interact with a SAX parser. Specifically, even though they do not depend on
20 | expat, they are written so they can be plugged directly into expat without any
21 | glue.
22 |
23 | Unfortunately, due to differences in the type names and the methodology used
24 | to define types between the 1.4.1 xsd and 1.5 xsd, the apis generated from
25 | the two different versions of the spec are not compatible. The spec themselves
26 | are defined to be backwards compatible, so code generated from the 1.5 xsd may
27 | be used to parse xml exported using the 1.4.1 spec.
28 |
29 | Code generated from the 1.5 spec is included by default.
30 |
31 | Building
32 | ========
33 |
34 | ./include/dae.h - auto generated header for public API
35 | ./include/daeu.h - public API definition of optional utility functions
36 | ./src/dae.c - auto generated implementation of public API
37 | ./src/daeu.c - implementation of optional utility functions
38 |
39 | add ./include to the include search path
40 | add ./src/dae.c and optionally ./src/daeu.c as build dependencies
41 |
42 | Usage
43 | =====
44 |
45 | Assuming that an expat XML_Parser with the variable name "expat" was created
46 | and given a data buffer containing COLLADA xml, the following code will parse
47 | it into a dae_COLLADA struct:
48 |
49 | dae_COLLADA* collada = dae_create();
50 | daeu_xml_parser daeparser;
51 | daeu_xml_create(collada, &daeparser);
52 | XML_SetElementHandler(
53 | expat,
54 | daeu_xml_startelement,
55 | daeu_xml_endelement);
56 | XML_SetCharacterDataHandler(expat, daeu_xml_chardata);
57 | XML_SetUserData(expat, daeparser);
58 | if(XML_ParseBuffer(expat, size, 1) != XML_STATUS_OK)
59 | {
60 | err = -1;
61 | }
62 | daeu_xml_destroy(parser);
63 |
64 | When finished with the document, destroy it as follows:
65 |
66 | dae_destroy(collada);
67 |
68 | Code Generation
69 | ===============
70 |
71 | The source code generation project is in the directory ./gen. The binary will
72 | regenerate source code given a path to the XSD schema and a template input
73 | file. For example, if the schema file "collada_schema_1_5.xsd" was placed
74 | inside the gen folder, dae.c and dae.h could be generated as follows:
75 |
76 | cd gen
77 | bin/daegen collada_schema_1_5.xsd template/dae.c ../src/dae.c
78 | bin/daegen collada_schema_1_5.xsd template/dae.h ../include/dae.h
79 |
--------------------------------------------------------------------------------
/src/daeu.c:
--------------------------------------------------------------------------------
1 | /**
2 | * @brief libdae utility source
3 | * @author Thomas Atwood (tatwood.net)
4 | * @date 2011
5 | * @copyright unlicense / public domain
6 | ****************************************************************************/
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | struct daeu_xml_parser_s
15 | {
16 | dae_COLLADA* root;
17 | dae_obj_ptr current;
18 | struct
19 | {
20 | char* str;
21 | size_t len;
22 | size_t cap;
23 | } chardata;
24 | };
25 |
26 | //****************************************************************************
27 | static void daeu_cross3(
28 | const float* a,
29 | const float* b,
30 | float* out)
31 | {
32 | out[0] = a[1]*b[2]-a[2]*b[1];
33 | out[1] = a[2]*b[0]-a[0]*b[2];
34 | out[2] = a[0]*b[1]-a[1]*b[0];
35 | }
36 |
37 | //****************************************************************************
38 | static void daeu_normalize4(
39 | const float* a,
40 | float* out)
41 | {
42 | float d = sqrtf(a[0]*a[0] + a[1]*a[1] + a[2]*a[2] + a[3]*a[3]);
43 | if(d > 0.000001f)
44 | {
45 | d = 1.0f/d;
46 | out[0] = a[0]*d; out[1] = a[1]*d; out[2] = a[2]*d; out[3] = a[3]*d;
47 | }
48 | }
49 |
50 | //****************************************************************************
51 | static void daeu_matrix_identity(
52 | float* out)
53 | {
54 | out[ 0] = 1.0f; out[ 1] = 0.0f; out[ 2] = 0.0f; out[ 3] = 0.0f;
55 | out[ 4] = 0.0f; out[ 5] = 1.0f; out[ 6] = 0.0f; out[ 7] = 0.0f;
56 | out[ 8] = 0.0f; out[ 9] = 0.0f; out[10] = 1.0f; out[11] = 0.0f;
57 | out[12] = 0.0f; out[13] = 0.0f; out[14] = 0.0f; out[15] = 1.0f;
58 | }
59 |
60 |
61 | //****************************************************************************
62 | static void daeu_matrix_multiply(
63 | const float* a,
64 | const float* b,
65 | float* out)
66 | {
67 | #define daeu_MATRIXMUL_COMP(r_, c_) \
68 | out[(r_)*4 + (c_)] = \
69 | a[(r_)*4+0]*b[0*4+(c_)] + \
70 | a[(r_)*4+1]*b[1*4+(c_)] + \
71 | a[(r_)*4+2]*b[2*4+(c_)] + \
72 | a[(r_)*4+3]*b[3*4+(c_)]
73 | daeu_MATRIXMUL_COMP(0,0);
74 | daeu_MATRIXMUL_COMP(0,1);
75 | daeu_MATRIXMUL_COMP(0,2);
76 | daeu_MATRIXMUL_COMP(0,3);
77 | daeu_MATRIXMUL_COMP(1,0);
78 | daeu_MATRIXMUL_COMP(1,1);
79 | daeu_MATRIXMUL_COMP(1,2);
80 | daeu_MATRIXMUL_COMP(1,3);
81 | daeu_MATRIXMUL_COMP(2,0);
82 | daeu_MATRIXMUL_COMP(2,1);
83 | daeu_MATRIXMUL_COMP(2,2);
84 | daeu_MATRIXMUL_COMP(2,3);
85 | daeu_MATRIXMUL_COMP(3,0);
86 | daeu_MATRIXMUL_COMP(3,1);
87 | daeu_MATRIXMUL_COMP(3,2);
88 | daeu_MATRIXMUL_COMP(3,3);
89 | #undef daeu_MATRIXMUL_COMP
90 | }
91 |
92 | //****************************************************************************
93 | void daeu_lookat_to_matrix(
94 | const dae_lookat_type* lookat,
95 | float* mtx_out)
96 | {
97 | const float* vp = lookat->data + 0;
98 | const float* vi = lookat->data + 3;
99 | const float* vup = lookat->data + 6;
100 | float mtxrot[16];
101 | float mtxtrans[16];
102 | float* s = mtxrot + 0;
103 | float* u = mtxrot + 4;
104 | float* f = mtxrot + 8;
105 | // calculate rotation
106 | daeu_matrix_identity(mtxrot);
107 | f[0]=vp[0]-vi[0]; f[1]=vp[1]-vi[1]; f[2]=vp[2]-vi[2]; f[3]=0.0f;
108 | daeu_normalize4(f, f);
109 | daeu_cross3(vup, f, s);
110 | s[3] = 0.0f;
111 | daeu_normalize4(s, s);
112 | daeu_cross3(f, s, u);
113 | u[3] = 0.0f;
114 | daeu_normalize4(u, u);
115 | // calculate translation
116 | daeu_matrix_identity(mtxtrans);
117 | mtxtrans[3] = -vp[0]; mtxtrans[7] = -vp[1]; mtxtrans[11] = -vp[2];
118 | daeu_matrix_multiply(mtxrot, mtxtrans, mtx_out);
119 | }
120 |
121 | //****************************************************************************
122 | void daeu_rotate_to_matrix(
123 | const dae_rotate_type* rotate,
124 | float* mtx_out)
125 | {
126 | const float* axis = rotate->data;
127 | float rad = rotate->data[3] * (3.14159265f/180.0f);
128 | float c = cosf(rad);
129 | float s = sinf(rad);
130 | mtx_out[ 0] = axis[0]*axis[0]*(1.0f-c) + c;
131 | mtx_out[ 1] = axis[0]*axis[1]*(1.0f-c) - axis[2]*s;
132 | mtx_out[ 2] = axis[0]*axis[2]*(1.0f-c) + axis[1]*s;
133 | mtx_out[ 3] = 0.0f;
134 | mtx_out[ 4] = axis[1]*axis[0]*(1.0f-c) + axis[2]*s;
135 | mtx_out[ 5] = axis[1]*axis[1]*(1.0f-c) + c;
136 | mtx_out[ 6] = axis[1]*axis[2]*(1.0f-c) - axis[0]*s;
137 | mtx_out[ 7] = 0.0f;
138 | mtx_out[ 8] = axis[2]*axis[0]*(1.0f-c) - axis[1]*s;
139 | mtx_out[ 9] = axis[2]*axis[1]*(1.0f-c) + axis[0]*s;
140 | mtx_out[10] = axis[2]*axis[2]*(1.0f-c) + c;
141 | mtx_out[11] = 0.0f;
142 | mtx_out[12] = 0.0f;
143 | mtx_out[13] = 0.0f;
144 | mtx_out[14] = 0.0f;
145 | mtx_out[15] = 1.0f;
146 | }
147 |
148 | //****************************************************************************
149 | void daeu_scale_to_matrix(
150 | const dae_scale_type* scale,
151 | float* mtx_out)
152 | {
153 | daeu_matrix_identity(mtx_out);
154 | mtx_out[ 0] = scale->data[0];
155 | mtx_out[ 5] = scale->data[1];
156 | mtx_out[10] = scale->data[2];
157 | }
158 |
159 | //****************************************************************************
160 | void daeu_translate_to_matrix(
161 | const dae_translate_type* translate,
162 | float* mtx_out)
163 | {
164 | daeu_matrix_identity(mtx_out);
165 | mtx_out[ 3] = translate->data[0];
166 | mtx_out[ 7] = translate->data[1];
167 | mtx_out[11] = translate->data[2];
168 | }
169 |
170 | //****************************************************************************
171 | void daeu_calc_transform_matrix(
172 | dae_obj_ptr obj,
173 | float* mtx_out)
174 | {
175 | float mtxa[16];
176 | float mtxb[16];
177 | dae_obj_ptr el;
178 |
179 | daeu_matrix_identity(mtx_out);
180 | el = dae_get_first_element(obj);
181 | while(el != NULL)
182 | {
183 | int istransform = 1;
184 | dae_obj_typeid eltype = dae_get_typeid(el);
185 | memcpy(mtxa, mtx_out, sizeof(mtxa));
186 | daeu_matrix_identity(mtxb);
187 | switch(eltype)
188 | {
189 | case dae_ID_LOOKAT_TYPE:
190 | daeu_lookat_to_matrix((dae_lookat_type*) el, mtxb);
191 | break;
192 | case dae_ID_MATRIX_TYPE:
193 | memcpy(mtxb, ((dae_matrix_type*) el)->data, sizeof(mtxb));
194 | break;
195 | case dae_ID_ROTATE_TYPE:
196 | daeu_rotate_to_matrix((dae_rotate_type*) el, mtxb);
197 | break;
198 | case dae_ID_SCALE_TYPE:
199 | daeu_scale_to_matrix((dae_scale_type*) el, mtxb);
200 | break;
201 | case dae_ID_SKEW_TYPE:
202 | // TODO support SKEW
203 | assert(0);
204 | break;
205 | case dae_ID_TRANSLATE_TYPE:
206 | daeu_translate_to_matrix((dae_translate_type*) el, mtxb);
207 | break;
208 | default:
209 | istransform = 0;
210 | break;
211 | }
212 | if(istransform)
213 | {
214 | daeu_matrix_multiply(mtxa, mtxb, mtx_out);
215 | }
216 | el = dae_get_next(el);
217 | }
218 | }
219 |
220 | //****************************************************************************
221 | dae_obj_ptr daeu_find_attrib(
222 | dae_obj_ptr obj,
223 | const char* name)
224 | {
225 | dae_obj_ptr at = NULL;
226 | dae_obj_ptr itr = dae_get_first_attrib(obj);
227 | while(itr != NULL)
228 | {
229 | const char* itname = dae_get_name(itr);
230 | if(!strcmp(itname, name))
231 | {
232 | at = itr;
233 | break;
234 | }
235 | itr = dae_get_next(itr);
236 | }
237 | return at;
238 | }
239 |
240 | //****************************************************************************
241 | int daeu_search_sid(
242 | dae_obj_ptr searchroot,
243 | const char* ref,
244 | dae_obj_ptr* obj_out,
245 | int* dataindex_out)
246 | {
247 | const char* sep = "/.(";
248 | size_t result = 0;
249 | int isrootless = 0;
250 | int ismatch = 0;
251 | if(dataindex_out != NULL)
252 | {
253 | *dataindex_out = -1;
254 | }
255 | if(*ref == '.')
256 | {
257 | // relative to the current element
258 | ismatch = 1;
259 | ++ref;
260 | }
261 | else if(*ref == '/')
262 | {
263 | // a child element
264 | ++ref;
265 | }
266 | else
267 | {
268 | // the root of the path has not been found yet
269 | assert(strpbrk(ref, sep) != ref);
270 | isrootless = 1;
271 | }
272 | if(!ismatch)
273 | {
274 | // check to see if this is the current item in the path
275 | const char* atnames[] = { "sid", "id" };
276 | size_t i;
277 | for(i = 0; i < sizeof(atnames)/sizeof(*atnames); ++i)
278 | {
279 | dae_obj_ptr at = daeu_find_attrib(searchroot, atnames[i]);
280 | if(at != NULL)
281 | {
282 | dae_native_typeid attype;
283 | void* ataddr;
284 | size_t atsize;
285 | if(dae_get_data(at, &attype, &ataddr, &atsize) > 0)
286 | {
287 | // compare the attribute value against the search key
288 | const char* atval = *((char**) ataddr);
289 | if(attype == dae_NATIVE_STRING && atval != NULL)
290 | {
291 | const char* end = strpbrk(ref, sep);
292 | size_t len;
293 | len = (end!=NULL) ? (size_t)(end-ref) : strlen(ref);
294 | ismatch = !memcmp(atval,ref,len) && atval[len]=='\0';
295 | if(ismatch)
296 | {
297 | *obj_out = searchroot;
298 | isrootless = 0;
299 | ref += len;
300 | ++result;
301 | break;
302 | }
303 | }
304 | }
305 | }
306 | }
307 | }
308 | if(ismatch || isrootless)
309 | {
310 | // if this item was in the path, or the path root has not been found
311 | if(*ref == '.')
312 | {
313 | // referencing a component of the current element
314 | dae_native_typeid datatype;
315 | float* data;
316 | size_t datalen;
317 | ++ref;
318 | if(dae_get_data(searchroot,&datatype,(void**)&data,&datalen) != 0)
319 | {
320 | if(datatype == dae_NATIVE_FLOAT && dataindex_out != NULL)
321 | {
322 | int i = -1;
323 | switch(*ref)
324 | {
325 | case 'A':
326 | // ANGLE or A (ALPHA)
327 | if(!strcmp(ref, "ANGLE") || ref[1] == '\0'){ i = 3; }
328 | break;
329 | case 'B':
330 | // B (BLUE)
331 | if(ref[1] == '\0') { i = 2; }
332 | break;
333 | case 'G':
334 | // G (GREEN)
335 | if(ref[1] == '\0') { i = 1; }
336 | break;
337 | case 'P':
338 | if(ref[1] == '\0') { i = 2; }
339 | break;
340 | case 'Q':
341 | if(ref[1] == '\0') { i = 3; }
342 | break;
343 | case 'R':
344 | if(ref[1] == '\0') { i = 0; }
345 | break;
346 | case 'S':
347 | if(ref[1] == '\0') { i = 0; }
348 | break;
349 | case 'T':
350 | // NOTE: not handling 'TIME'
351 | if(ref[1] == '\0') { i = 1; }
352 | break;
353 | case 'U':
354 | if(ref[1] == '\0') { i = 0; }
355 | break;
356 | case 'V':
357 | if(ref[1] == '\0') { i = 1; }
358 | break;
359 | case 'W':
360 | if(ref[1] == '\0') { i = 3; }
361 | break;
362 | case 'X':
363 | if(ref[1] == '\0') { i = 0; }
364 | break;
365 | case 'Y':
366 | if(ref[1] == '\0') { i = 1; }
367 | break;
368 | case 'Z':
369 | if(ref[1] == '\0') { i = 2; }
370 | break;
371 | }
372 | if(i >= 0)
373 | {
374 | if(i < (int) datalen)
375 | {
376 | *dataindex_out = i;
377 | ++result;
378 | }
379 | }
380 | }
381 | }
382 | }
383 | else if(*ref == '(')
384 | {
385 | // referencing a component of the current element by index
386 | dae_native_typeid datatype;
387 | float* data;
388 | size_t datalen;
389 | ++ref;
390 | if(dae_get_data(searchroot,&datatype,(void**)&data,&datalen) != 0)
391 | {
392 | if(datatype == dae_NATIVE_FLOAT && dataindex_out != NULL)
393 | {
394 | int i = 0;
395 | if(sscanf(ref,"%d",&i) == 1)
396 | {
397 | if(i >= 0)
398 | {
399 | if(i < (int) datalen)
400 | {
401 | *dataindex_out = i;
402 | ++result;
403 | }
404 | }
405 | }
406 | }
407 | }
408 | }
409 | else if(*ref == '/' || isrootless)
410 | {
411 | // traverse children
412 | dae_obj_ptr elem = dae_get_first_element(searchroot);
413 | while(elem != NULL)
414 | {
415 | result = daeu_search_sid(elem, ref, obj_out, dataindex_out);
416 | if(result != 0)
417 | {
418 | break;
419 | }
420 | elem = dae_get_next(elem);
421 | }
422 | }
423 | }
424 | return result;
425 | }
426 |
427 | //****************************************************************************
428 | dae_obj_ptr daeu_search_uri(
429 | dae_obj_ptr searchroot,
430 | const char* uri)
431 | {
432 | const char* key = uri + 1;
433 | dae_obj_ptr result = NULL;
434 | dae_obj_ptr itr = searchroot;
435 | assert(*uri == '#');
436 | do
437 | {
438 | dae_obj_ptr at;
439 | dae_obj_ptr next;
440 | // attempt to find the id attribute for this object
441 | at = daeu_find_attrib(itr, "id");
442 | if(at != NULL)
443 | {
444 | // attempt the get the attribute value
445 | dae_native_typeid attype;
446 | void* ataddr;
447 | size_t atsize;
448 | if(dae_get_data(at, &attype, &ataddr, &atsize))
449 | {
450 | const char* atval = *((char**) ataddr);
451 | if(attype == dae_NATIVE_STRING && atval != NULL)
452 | {
453 | // compare the attribute value against the search key
454 | if(!strcmp(atval, key))
455 | {
456 | // found match
457 | result = itr;
458 | break;
459 | }
460 | }
461 | }
462 | }
463 | // attempt to traverse children
464 | next = dae_get_first_element(itr);
465 | while(next == NULL)
466 | {
467 | // if no children exist, attempt to move to next sibling
468 | next = dae_get_next(itr);
469 | if(next == NULL)
470 | {
471 | // if a sibling did not exist, attempt to move up to the
472 | // parent's sibling.
473 | next = dae_get_parent(itr);
474 | if(next != searchroot)
475 | {
476 | // only move to the parent's sibling if not at the root
477 | itr = next;
478 | next = dae_get_next(next);
479 | }
480 | }
481 | }
482 | itr = next;
483 | }
484 | while(itr != searchroot);
485 | return result;
486 | }
487 |
488 | //****************************************************************************
489 | void daeu_xml_chardata(
490 | void *userdata,
491 | const char *s,
492 | int len)
493 | {
494 | daeu_xml_parser parser = (daeu_xml_parser) userdata;
495 | char* chars = parser->chardata.str;
496 | size_t off = parser->chardata.len;
497 | size_t cap = parser->chardata.cap;
498 | if((off + len + 1) > cap)
499 | {
500 | cap = (off + len + 1024) & ~1023;
501 | chars = (char*) realloc(chars, cap * sizeof(*chars));
502 | parser->chardata.str = chars;
503 | parser->chardata.cap = cap;
504 | }
505 | memcpy(chars + off, s, len);
506 | chars[off + len] = '\0';
507 | parser->chardata.len += len;
508 | }
509 |
510 | //****************************************************************************
511 | void daeu_xml_create(
512 | dae_COLLADA* root,
513 | daeu_xml_parser* parser_out)
514 | {
515 | daeu_xml_parser parser = (daeu_xml_parser) malloc(sizeof(*parser));
516 | memset(parser, 0, sizeof(*parser));
517 | parser->root = root;
518 | *parser_out = parser;
519 | }
520 |
521 | //****************************************************************************
522 | void daeu_xml_destroy(
523 | daeu_xml_parser parser)
524 | {
525 | free(parser->chardata.str);
526 | free(parser);
527 | }
528 |
529 | //****************************************************************************
530 | void daeu_xml_endelement(
531 | void* userdata,
532 | const char* el)
533 | {
534 | daeu_xml_parser parser = (daeu_xml_parser) userdata;
535 | if(parser->current != NULL)
536 | {
537 | if(parser->chardata.len > 0)
538 | {
539 | dae_obj_ptr obj = parser->current;
540 | if(dae_get_typeid(obj) == dae_ID_IMAGE_TYPE_INIT_FROM)
541 | {
542 | // this is a hack for compatibility with the maya exporter.
543 | // it places the init_from character data directly within the
544 | // init_from instead of within a ref element per the spec
545 | obj = dae_add_element(obj, "ref");
546 | }
547 | dae_set_string(obj, parser->chardata.str);
548 | }
549 | parser->current = dae_get_parent(parser->current);
550 | }
551 | }
552 |
553 | //****************************************************************************
554 | void daeu_xml_startelement(
555 | void* userdata,
556 | const char* el,
557 | const char** att)
558 | {
559 | daeu_xml_parser parser = (daeu_xml_parser) userdata;
560 | dae_obj_ptr parent = parser->current;
561 | dae_obj_ptr obj = NULL;
562 | if(parent == NULL)
563 | {
564 | if(!strcmp(el, "COLLADA"))
565 | {
566 | obj = parser->root;
567 | }
568 | }
569 | else
570 | {
571 | obj = dae_add_element(parent, el);
572 | }
573 | if(obj != NULL)
574 | {
575 | while(att[0] != NULL && att[1] != NULL)
576 | {
577 | dae_add_attrib(obj, att[0], att[1]);
578 | att += 2;
579 | }
580 | parser->current = obj;
581 | }
582 | else
583 | {
584 | assert(0);
585 | }
586 | parser->chardata.len = 0;
587 | }
588 |
--------------------------------------------------------------------------------
/unlicense.txt:
--------------------------------------------------------------------------------
1 | This is free and unencumbered software released into the public domain.
2 |
3 | Anyone is free to copy, modify, publish, use, compile, sell, or
4 | distribute this software, either in source code form or as a compiled
5 | binary, for any purpose, commercial or non-commercial, and by any
6 | means.
7 |
8 | In jurisdictions that recognize copyright laws, the author or authors
9 | of this software dedicate any and all copyright interest in the
10 | software to the public domain. We make this dedication for the benefit
11 | of the public at large and to the detriment of our heirs and
12 | successors. We intend this dedication to be an overt act of
13 | relinquishment in perpetuity of all present and future rights to this
14 | software under copyright law.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------