├── 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 | --------------------------------------------------------------------------------