core/class.c

Go to the documentation of this file.
00001 
00046 #include "class.h"
00047 #include "output.h"
00048 #include "convert.h"
00049 #include "module.h"
00050 #include "exception.h"
00051 #include "timestamp.h"
00052 
00053 /* IMPORTANT: this list must match PROPERTYTYPE enum in class.h */
00054 static struct s_property_specs { 
00058     char *name; 
00059     unsigned int size; 
00060     int (*data_to_string)(char *,int,void*,PROPERTY*); 
00061     int (*string_to_data)(char *,void*,PROPERTY*); 
00062 } property_type[] = {
00063     {"void", 0, convert_from_void,convert_to_void},
00064     {"double", sizeof(double), convert_from_double,convert_to_double},
00065     {"complex", sizeof(complex), convert_from_complex,convert_to_complex},
00066     {"enumeration",sizeof(long), convert_from_enumeration,convert_to_enumeration},
00067     {"set",sizeof(int64), convert_from_set,convert_to_set},
00068     {"int16", sizeof(int16), convert_from_int16,convert_to_int16},
00069     {"int32", sizeof(int32), convert_from_int32,convert_to_int32},
00070     {"int64", sizeof(int64), convert_from_int64,convert_to_int64},
00071     {"char8", sizeof(char8), convert_from_char8,convert_to_char8},
00072     {"char32", sizeof(char32), convert_from_char32,convert_to_char32},
00073     {"char256", sizeof(char256), convert_from_char256,convert_to_char256},
00074     {"char1024", sizeof(char1024), convert_from_char1024,convert_to_char1024},
00075     {"object", sizeof(OBJECT*), convert_from_object,convert_to_object},
00076     {"delegated", -1, convert_from_delegated, convert_to_delegated},
00077     {"bool", sizeof(unsigned int), convert_from_boolean, convert_to_boolean},
00078     {"timestamp", sizeof(int64), convert_from_timestamp_stub, convert_to_timestamp_stub},
00079     {"double_array", sizeof(double), convert_from_double_array, convert_to_double_array},
00080     {"complex_array", sizeof(complex), convert_from_complex_array, convert_to_complex_array},
00081 };
00082 
00083 /* property map */
00084 PROPERTY *first_property = NULL;
00085 PROPERTY *last_property = NULL;
00086 
00087 /* object class list */
00088 OBJECTTYPE last_object_type = 0;
00089 static CLASS *first_class = NULL;
00090 static CLASS *last_class = NULL;
00091 
00111 PROPERTY *class_get_first_property(CLASS *oclass) 
00112 {
00113     if (oclass==NULL)
00114         return first_property;
00115     else
00116         return oclass->pmap;
00117 }
00118 
00122 PROPERTY *class_get_next_property(PROPERTY *prop)
00123 {
00124     if (prop->next!=NULL && prop->otype==prop->next->otype)
00125         return prop->next;
00126     else
00127         return NULL;
00128 }
00129 
00133 unsigned long property_size(PROPERTY *prop)
00134 {
00135     if (prop && prop->ptype>_PT_FIRST && prop->ptype<_PT_LAST)
00136         return property_type[prop->ptype].size;
00137     else
00138         return 0;
00139 }
00144 PROPERTY *class_find_property(CLASS *oclass,        
00145                               PROPERTYNAME name)    
00146 {
00147     PROPERTY *prop;
00148     for (prop=oclass->pmap; prop!=NULL && prop->otype==oclass->type; prop=prop->next)
00149     {
00150         if (strcmp(name,prop->name)==0)
00151             return prop;
00152     }
00153     return NULL;
00154 }
00155 
00159 CLASS *class_get_last_class(void)
00160 {
00161     return last_class;
00162 }
00163 
00167 unsigned int class_get_count(void)
00168 {
00169     return last_object_type;
00170 }
00171 
00175 char *class_get_property_typename(PROPERTYTYPE type) 
00176 {
00177     if (type<=_PT_FIRST || type>=_PT_LAST)
00178         return "##UNDEF##";
00179     else 
00180         return property_type[type].name;
00181 }
00182 
00186 PROPERTYTYPE class_get_propertytype_from_typename(char *name) 
00187 {
00188     int i;
00189     for (i=0; i<sizeof(property_type)/sizeof(property_type[0]); i++)
00190     {
00191         if (strcmp(property_type[i].name,name)==0)
00192             return i;
00193     }
00194     return PT_void;
00195 }
00196 
00201 int class_string_to_property(PROPERTY *prop, 
00202                              void *addr,        
00203                              char *value)       
00204 {
00205     if (prop->ptype==PT_delegated)
00206     {
00207         output_error("unable to convert to delegated property value");
00208         return 0;
00209     }
00210     else if (prop->ptype > _PT_FIRST && prop->ptype < _PT_LAST)
00211         return (*property_type[prop->ptype].string_to_data)(value,addr,prop);
00212     else
00213         return 0;
00214 }
00215 
00220 int class_property_to_string(PROPERTY *prop, 
00221                              void *addr,        
00222                              char *value,       
00223                              int size)          
00224 {
00225     if (prop->ptype==PT_delegated)
00226     {
00227         output_error("unable to convert from delegated property value");
00228         return 0;
00229     }
00230     else if (prop->ptype>_PT_FIRST && prop->ptype<_PT_LAST)
00231         return (*property_type[prop->ptype].data_to_string)(value,size,addr,prop);
00232     else
00233         return 0;
00234 }
00235 
00236 
00243 CLASS *class_register(MODULE *module,           
00244                       CLASSNAME name,           
00245                       PASSCONFIG passconfig)    
00246 {
00247     CLASS *oclass = class_get_class_from_classname(name);
00248     MODULE *mod = NULL;
00249 
00250     /* check the property list */
00251     int a = sizeof(property_type);
00252     int b = sizeof(property_type[0]);
00253     int c = _PT_LAST - _PT_FIRST - 1;
00254 
00255     if (_PT_LAST-_PT_FIRST-1!=sizeof(property_type)/sizeof(property_type[0]))
00256     {
00257         output_fatal("property_type[] in class.c has an incorrect number of members");
00258         exit(1);
00259     }
00260     if (oclass!=NULL)
00261     {
00262         if(strcmp(oclass->module->name, module->name) == 0){
00263             output_error("module %s cannot register class %s, it is already registered by module %s", module->name,name,oclass->module->name);
00264             return NULL;
00265         } else {
00266             output_verbose("module %s is registering a 2nd class %s, previous one in module %s", module->name, name, oclass->module->name);
00267         }
00268     }
00269     if (strlen(name)>=sizeof(oclass->name) )
00270     {
00271         errno = E2BIG;
00272         return 0;
00273     }
00274     oclass = (CLASS*)malloc(sizeof(CLASS));
00275     if (oclass==NULL)
00276     {
00277         errno = ENOMEM;
00278         return 0;
00279     }
00280     oclass->module = module;
00281     oclass->type = ++last_object_type;
00282     strncpy(oclass->name,name,sizeof(oclass->name));
00283     oclass->next = NULL;
00284     oclass->pmap = NULL;
00285     oclass->fmap = NULL;
00286     oclass->sync = NULL;
00287     oclass->create = NULL;
00288     oclass->passconfig = passconfig;
00289     oclass->profiler.numobjs=0;
00290     oclass->profiler.count=0;
00291     oclass->profiler.clocks=0;
00292     if (first_class==NULL)
00293         first_class = oclass;
00294     else
00295         last_class->next = oclass;
00296     last_class = oclass;
00297     output_verbose("class %s registered ok", name);
00298     return oclass;
00299 }
00300 
00305 CLASS *class_get_first_class(void)
00306 {
00307     return first_class;
00308 }
00309 
00314 CLASS *class_get_class_from_objecttype(OBJECTTYPE type) 
00315 {
00316     CLASS *oclass;
00317     for (oclass=first_class; oclass!=NULL; oclass=oclass->next)
00318     {
00319         if (oclass->type==type)
00320             return oclass;
00321     }
00322     return NULL;
00323 }
00324 
00328 char *class_get_classname_from_objecttype(OBJECTTYPE type) 
00329 {
00330     CLASS *oclass;
00331     for (oclass=first_class; oclass!=NULL; oclass=oclass->next)
00332     {
00333         if (oclass->type==type)
00334             return oclass->name;
00335     }
00336     return NULL;
00337 }
00338 
00343 CLASS *class_get_class_from_classname_in_module(char *name, MODULE *mod){
00344     CLASS *oclass = NULL;
00345     if(name == NULL) return NULL;
00346     if(mod == NULL) return NULL;
00347     for (oclass=first_class; oclass!=NULL; oclass=oclass->next)
00348     {
00349         if(oclass->module == (MODULE *)mod)
00350             if(strcmp(oclass->name,name)==0)
00351                 return oclass;
00352     }
00353     return NULL;
00354 }
00355 
00360 CLASS *class_get_class_from_classname(char *name) 
00361 {
00362     CLASS *oclass = NULL;
00363     MODULE *mod = NULL;
00364     char *ptr = NULL;
00365     char temp[1024]; /* we get access violations when name is from another DLL. -mh */
00366     strcpy(temp, name);
00367     ptr = strchr(temp, '.');
00368     if(ptr != NULL){    /* check module for the class */
00369         ptr[0] = 0;
00370         ++ptr;
00371         mod = module_find(temp);
00372         if(mod == NULL){
00373             output_verbose("could not search for '%s.%s', module not loaded", name, ptr);
00374             return NULL;
00375         }
00376         for (oclass=first_class; oclass!=NULL; oclass=oclass->next)
00377         {
00378             if(oclass->module == mod)
00379                 if(strcmp(oclass->name,ptr)==0)
00380                     return oclass;
00381         }
00382         return NULL;
00383     }
00384     for (oclass=first_class; oclass!=NULL; oclass=oclass->next)
00385     {
00386         if (strcmp(oclass->name,name)==0)
00387             return oclass;
00388     }
00389     return NULL;
00390 }
00391 
00395 OBJECTTYPE class_get_classtype_from_classname(char *name) 
00396 {
00397     CLASS *oclass;
00398     for (oclass=first_class; oclass!=NULL; oclass=oclass->next)
00399     {
00400         if (strcmp(oclass->name,name)==0)
00401             return oclass->type;
00402     }
00403     return 0;
00404 }
00405 
00432 int class_define_map(CLASS *oclass, 
00433                      ...) 
00434 {
00435     va_list arg;
00436     PROPERTYTYPE proptype;
00437     int count=0;
00438     PROPERTY *prop=NULL;
00439     va_start(arg,oclass);
00440     while ((proptype=va_arg(arg,PROPERTYTYPE))!=0)
00441     {
00442         if (proptype>_PT_LAST)
00443         {
00444             if (prop==NULL)
00445             {
00446                 errno = EINVAL;
00447                 output_error("class_map_define(): expected keyword missing after '%s'", class_get_property_typename(proptype));
00448                 goto Error;
00449             }
00450             else if (proptype==PT_KEYWORD && prop->ptype==PT_enumeration)
00451             {
00452                 char *keyword = va_arg(arg,char*);
00453                 long keyvalue = va_arg(arg,long);
00454                 if (!class_define_enumeration_member(oclass,prop->name,keyword,keyvalue))
00455                 {
00456                     errno = EINVAL;
00457                     output_error("class_map_define(): property keyword '%s' could not be defined as value %d", keyword,keyvalue);
00458                     goto Error;
00459                 }
00460             }
00461             else if (proptype==PT_KEYWORD && prop->ptype==PT_set)
00462             {
00463                 char *keyword = va_arg(arg,char*);
00464                 unsigned long keyvalue = va_arg(arg, int); 
00465                 if (!class_define_set_member(oclass,prop->name,keyword,keyvalue))
00466                 {
00467                     errno = EINVAL;
00468                     output_error("class_map_define(): property keyword '%s' could not be defined as value %d", keyword,keyvalue);
00469                     goto Error;
00470                 }
00471             }
00472             else if (proptype==PT_ACCESS)
00473             {
00474                 PROPERTYACCESS pa = va_arg(arg,PROPERTYACCESS); 
00475                 switch (pa) {
00476                 case PA_PUBLIC:
00477                 case PA_PROTECTED:
00478                 case PA_PRIVATE:
00479                 case PA_REFERENCE:
00480                     prop->access = pa;
00481                     break;
00482                 default:
00483                     errno = EINVAL;
00484                     output_error("class_map_define(): unrecognized property access code (value=%d is not valid)", pa);
00485                     goto Error;
00486                     break;
00487                 }
00488             }
00489             else if (proptype==PT_SIZE)
00490             {
00491                 prop->size = va_arg(arg,unsigned long);
00492                 if (prop->size<1)
00493                 {
00494                     errno = EINVAL;
00495                     output_error("class_map_define(): property size must be greater than 0", proptype);
00496                     goto Error;
00497                 }
00498             }
00499             else if (proptype==PT_FLAGS)
00500             {
00501                 prop->flags = va_arg(arg,unsigned int);
00502             }
00503             else
00504             {
00505                 char tcode[32];
00506                 char *ptypestr=class_get_property_typename(proptype);
00507                 sprintf(tcode,"%d",proptype);
00508                 if (strcmp(ptypestr,"##UNDEF##")==0)
00509                     ptypestr = tcode;
00510                 errno = EINVAL;
00511                 output_error("class_map_define(): unrecognized extended property (PROPERTYTYPE=%s)", ptypestr?ptypestr:tcode);
00512                 goto Error;
00513             }
00514         }
00515 
00516         else
00517         {
00518             DELEGATEDTYPE *delegation=(proptype==PT_delegated?va_arg(arg,DELEGATEDTYPE*):NULL);
00519             char *name = va_arg(arg,char*);
00520             PROPERTYADDR addr = va_arg(arg,PROPERTYADDR);
00521             char unitspec[1024];
00522             if (strlen(name)>=sizeof(prop->name))
00523             {
00524                 output_error("class_map_define(): property name '%s' is too big", prop->name);
00525                 errno = E2BIG;
00526                 goto Error;
00527             }
00528             prop = (PROPERTY*)malloc(sizeof(PROPERTY));
00529             if (prop==NULL)
00530             {
00531                 output_error("class_map_define(): memory allocation failed", prop->name);
00532                 errno = ENOMEM;
00533                 goto Error;
00534             }
00535             prop->ptype = proptype;
00536             prop->size = 0;
00537             prop->access = PA_PUBLIC;
00538             prop->otype = oclass->type;
00539             prop->flags = 0;
00540             prop->keywords = NULL;
00541             if (sscanf(name,"%[^[][%[A-Za-z0-9*/^]]",prop->name,unitspec)==2)
00542             {
00543                 prop->unit = unit_find(unitspec);
00544                 if (prop->unit==NULL)
00545                     output_warning("property %s unit '%s' is not recognized",prop->name,unitspec);
00546             }
00547             else
00548                 prop->unit = NULL;
00549             prop->addr = addr;
00550             prop->delegation = delegation;
00551             prop->next = NULL;
00552             if (first_property==NULL)
00553                 first_property = prop;
00554             else
00555                 last_property->next = prop;
00556             last_property = prop;
00557             
00558             /* link map to oclass if not yet done */
00559             if (oclass->pmap==NULL)
00560                 oclass->pmap = prop;
00561             count++;
00562 
00563             /* save enum property in case extended property come up */
00564             if (prop->ptype>_PT_LAST)
00565                 prop = NULL;
00566         }
00567     }
00568     va_end(arg);
00569     return count;
00570 Error:
00571     if (prop!=NULL)
00572         output_verbose("class_define_map() processed up to property %s", prop->name);
00573     return -count;
00574 }
00575 
00579 int class_define_enumeration_member(CLASS *oclass, 
00580                                     char *property_name, 
00581                                     char *member, 
00582                                     enumeration value) 
00583 {
00584     PROPERTY *prop = class_find_property(oclass,property_name);
00585     KEYWORD *key = (KEYWORD*)malloc(sizeof(KEYWORD));
00586     if (prop==NULL || key==NULL) return 0;
00587     key->next = prop->keywords;
00588     strncpy(key->name,member,sizeof(key->name));
00589     key->value = value;
00590     prop->keywords = key;
00591     return 1;
00592 }
00593 
00596 int class_define_set_member(CLASS *oclass, 
00597                             char *property_name, 
00598                             char *member, 
00599                             unsigned long value) 
00600 {
00601     PROPERTY *prop = class_find_property(oclass,property_name);
00602     KEYWORD *key = (KEYWORD*)malloc(sizeof(KEYWORD));
00603     if (prop==NULL || key==NULL) return 0;
00604     if (prop->keywords==NULL)
00605         prop->flags |= PF_CHARSET; /* enable single character keywords until a long keyword is defined */
00606     key->next = prop->keywords;
00607     strncpy(key->name,member,sizeof(key->name));
00608     key->name[sizeof(key->name)-1]='\0'; /* null terminate name in case is was too long for strncpy */
00609     if (strlen(key->name)>1 && (prop->flags&PF_CHARSET)) /* long keyword detected */
00610         prop->flags ^= PF_CHARSET; /* disable single character keywords */
00611     key->value = value;
00612     prop->keywords = key;
00613     return 1;
00614 }
00615 
00616 /* Define a class function.
00617  */
00618 FUNCTION *class_define_function(CLASS *oclass, FUNCTIONNAME functionname, FUNCTIONADDR call)
00619 {
00620     FUNCTION *func = (FUNCTION*)malloc(sizeof(FUNCTION));
00621     if (func==NULL)
00622     {
00623         errno = ENOMEM;
00624         return NULL;
00625     }
00626     func->addr = call;
00627     strcpy(func->name,functionname);
00628     func->next = NULL;
00629     func->otype = oclass->type;
00630     if (oclass->fmap==NULL)
00631         oclass->fmap = func;
00632     else
00633         oclass->fmap->next = func;
00634     return func;
00635 }
00636 
00637 /* Get the entry point of a class function
00638  */
00639 FUNCTIONADDR class_get_function(char *classname, char *functionname)
00640 {
00641     CLASS *oclass = class_get_class_from_classname(classname);
00642     FUNCTION *func;
00643     for (func=oclass->fmap; func!=NULL && func->otype==oclass->type; func=func->next)
00644     {
00645         if (strcmp(functionname,func->name)==0)
00646             return func->addr;
00647     }
00648     errno = ENOENT;
00649     return NULL;
00650 }
00651 
00655 int class_saveall(FILE *fp) 
00656 {
00657     unsigned count=0;
00658     count += fprintf(fp,"\n########################################################\n");
00659     count += fprintf(fp,"# classes\n");
00660     {   CLASS   *oclass;
00661         for (oclass=class_get_first_class(); oclass!=NULL; oclass=oclass->next)
00662         {
00663             PROPERTY *prop;
00664             FUNCTION *func;
00665             count += fprintf(fp,"class %s {\n",oclass->name,oclass->type);
00666             for (func=oclass->fmap; func!=NULL && func->otype==oclass->type; func=func->next)
00667                 count += fprintf(fp, "\tfunction %s();\n", func->name);
00668             for (prop=oclass->pmap; prop!=NULL && prop->otype==oclass->type; prop=prop->next)
00669             {
00670                 char *propname = class_get_property_typename(prop->ptype);
00671                 if (propname!=NULL)
00672                     count += fprintf(fp,"\t%s %s;\n", propname, prop->name);
00673             }
00674             count += fprintf(fp,"}\n");
00675         }
00676     }
00677     return count;
00678 }
00679 
00683 int class_saveall_xml(FILE *fp) 
00684 {
00685     unsigned count=0;
00686     count += fprintf(fp,"\t<classes>\n");
00687     {   CLASS   *oclass;
00688         for (oclass=class_get_first_class(); oclass!=NULL; oclass=oclass->next)
00689         {
00690             PROPERTY *prop;
00691             FUNCTION *func;
00692             count += fprintf(fp,"\t\t<class name=\"%s\">\n",oclass->name,oclass->type);
00693             for (func=oclass->fmap; func!=NULL && func->otype==oclass->type; func=func->next)
00694                 count += fprintf(fp, "\t\t<function>%s</function>\n", func->name);
00695             for (prop=oclass->pmap; prop!=NULL && prop->otype==oclass->type; prop=prop->next)
00696             {
00697                 char *propname = class_get_property_typename(prop->ptype);
00698                 if (propname!=NULL)
00699                     count += fprintf(fp,"\t\t\t<property type=\"%s\">%s</property>\n", propname, prop->name);
00700             }
00701             count += fprintf(fp,"\t\t</class>\n");
00702         }
00703     }
00704     count += fprintf(fp,"\t</classes>\n");
00705     return count;
00706 }
00707 
00710 void class_profiles(void)
00711 {
00712     CLASS *cl;
00713     int64 total=0;
00714     int count=0, i=0, hits;
00715     CLASS **index;
00716     output_profile("Model profiler results");
00717     output_profile("======================\n");
00718     output_profile("Class            Time (s) Time (%%) msec/obj");
00719     output_profile("---------------- -------- -------- --------");
00720     for (cl=first_class; cl!=NULL; cl=cl->next)
00721     {
00722         total+=cl->profiler.clocks;
00723         count++;
00724     }
00725     index = (CLASS**)malloc(sizeof(CLASS*)*count);
00726     for (cl=first_class; cl!=NULL; cl=cl->next)
00727         index[i++]=cl;
00728     hits=-1;
00729     while (hits!=0)
00730     {
00731         hits=0;
00732         for (i=0; i<count-1; i++)
00733         {
00734             if (index[i]->profiler.clocks<index[i+1]->profiler.clocks)
00735             {
00736                 CLASS *tmp = index[i];
00737                 index[i]=index[i+1];
00738                 index[i+1]=tmp;
00739                 hits++;
00740             }
00741         }
00742     }
00743     for (i=0; i<count; i++)
00744     {
00745         cl = index[i];
00746         if (cl->profiler.clocks>0)
00747         {
00748             double ts = (double)cl->profiler.clocks/CLOCKS_PER_SEC;
00749             double tp = (double)cl->profiler.clocks/total*100;
00750             double mt = ts/cl->profiler.numobjs*1000;
00751             output_profile("%-16.16s %7.3f %8.1f%% %8.1f", cl->name, ts,tp,mt);
00752         }
00753         else
00754             break;
00755     }
00756     free(index);
00757     output_profile("================ ======== ======== ========");
00758     output_profile("%-16.16s %7.3f %8.1f%% %8.1f\n", 
00759         "Total", (double)total/CLOCKS_PER_SEC,100.0,1000*(double)total/CLOCKS_PER_SEC/object_get_count());
00760 
00761 }
00762 
00770 DELEGATEDTYPE *class_register_type(CLASS *oclass, 
00771                                    char *type, 
00772                                    int (*from_string)(void*,char*), 
00773                                    int (*to_string)(void*,char*,int)) 
00774 {
00775     DELEGATEDTYPE *dt = (DELEGATEDTYPE*)malloc(sizeof(DELEGATEDTYPE));
00776     if (dt!=NULL)
00777     {
00778         dt->oclass = oclass;
00779         strncpy(dt->type,type,sizeof(dt->type));
00780         dt->from_string = from_string;
00781         dt->to_string = to_string;
00782     }
00783     else
00784         output_error("unable to register delegated type (memory allocation failed)");
00785     return dt;
00786 }
00787 
00788 /* this is not supported */
00789 int class_define_type(CLASS *oclass, DELEGATEDTYPE *delegation, ...)
00790 {
00791     output_error("delegated types not supported using class_define_type (use class_define_map instead)");
00792     return 0;
00793 }
00794 
00795 static int check = 0;  /* there must be a better way to do this, but this works. -MH */
00796 
00800 static int buffer_write(char *buffer, size_t len, char *format, ...){
00801     char temp[1025];
00802     unsigned int count = 0;
00803     va_list ptr;
00804 
00805     if(buffer == NULL)
00806         return 0;
00807     if(len < 1)
00808         return 0;
00809     if(check == 0)
00810         return 0;
00811     
00812     va_start(ptr,format);
00813     count = vsprintf(temp, format, ptr);
00814     va_end(ptr);
00815 
00816     if(count < len){
00817         strncpy(buffer, temp, count);
00818         return count;
00819     } else {
00820         check = 0;
00821         return 0;
00822     }
00823 }
00824 
00828 int class_get_xsd(CLASS *oclass, 
00829                   char *buffer, 
00830                   size_t len) 
00831 {
00832     size_t n=0;
00833     PROPERTY *prop;
00834     int i;
00835     extern KEYWORD oflags[];
00836     struct {
00837         char *name;
00838         char *type;
00839         KEYWORD *keys;
00840     } attribute[]={
00841         {"id", "int64",NULL},
00842         {"parent", "object",NULL},
00843         {"rank", "int32",NULL},
00844         {"clock", "datetime",NULL},
00845         {"latitude", "latitude",NULL},
00846         {"longitude", "longitude",NULL},
00847         {"in_svc", "datetime",NULL},
00848         {"out_svc", "datetime",NULL},
00849         {"flags", "set",oflags},
00850     };
00851     check = 1;
00852     n += buffer_write(buffer+n, len-n, "<xs:element name=\"%s\">\n", oclass->name);
00853     n += buffer_write(buffer+n, len-n, "\t<xs:complexType>\n");
00854     n += buffer_write(buffer+n, len-n, "\t\t<xs:all>\n");
00855     for (i=0; i < sizeof(attribute) / sizeof(attribute[0]); i++)
00856     {
00857         n += buffer_write(buffer+n, len-n, "\t\t\t<xs:element name=\"%s\">\n", attribute[i].name);
00858         n += buffer_write(buffer+n, len-n, "\t\t\t\t<xs:simpleType>\n");
00859         if (attribute[i].keys==NULL){
00860             n += buffer_write(buffer+n, len-n, "\t\t\t\t\t<xs:restriction base=\"xs:%s\"/>\n", attribute[i].type);
00861         }
00862         else
00863         {
00864             KEYWORD *key;
00865             n += buffer_write(buffer+n, len-n, "\t\t\t\t\t<xs:restriction base=\"xs:string\">\n");
00866             n += buffer_write(buffer+n, len-n, "\t\t\t\t\t\t<xs:pattern value=\"");
00867             for (key=attribute[i].keys; key!=NULL; key=key->next){
00868                 n += buffer_write(buffer+n, len-n, "%s%s", key==attribute[i].keys?"":"|", key->name);
00869             }
00870             n += buffer_write(buffer+n, len-n, "\"/>\n");
00871             n += buffer_write(buffer+n, len-n, "\t\t\t\t\t</xs:restriction>\n");
00872         }
00873         n += buffer_write(buffer+n, len-n, "\t\t\t\t</xs:simpleType>\n");
00874         n += buffer_write(buffer+n, len-n, "\t\t\t</xs:element>\n");
00875     }
00876     for (prop=oclass->pmap; prop!=NULL && prop->otype==oclass->type; prop=prop->next)
00877     {
00878         char *proptype=class_get_property_typename(prop->ptype);
00879         if (prop->unit!=NULL){
00880             n += buffer_write(buffer+n, len-n, "\t\t\t\t<xs:element name=\"%s\" type=\"xs:string\"/>\n", prop->name);
00881         } else {
00882             n += buffer_write(buffer+n, len-n, "\t\t\t<xs:element name=\"%s\">\n", prop->name);
00883             n += buffer_write(buffer+n, len-n, "\t\t\t\t<xs:simpleType>\n");
00884             n += buffer_write(buffer+n, len-n, "\t\t\t\t\t<xs:restriction base=\"xs:%s\">\n", proptype==NULL?"string":proptype);
00885             if (prop->keywords!=NULL)
00886             {
00887                 KEYWORD *key;
00888                 n += buffer_write(buffer+n, len-n, "\t\t\t\t\t<xs:pattern value=\"");
00889                 for (key=prop->keywords; key!=NULL; key=key->next){
00890                     n += buffer_write(buffer+n, len-n, "%s%s", key==prop->keywords?"":"|", key->name);
00891                 }
00892                 n += buffer_write(buffer+n, len-n, "\"/>\n"); 
00893             }
00894             n += buffer_write(buffer+n, len-n, "\t\t\t\t\t</xs:restriction>\n");
00895             n += buffer_write(buffer+n, len-n, "\t\t\t\t</xs:simpleType>\n");
00896             n += buffer_write(buffer+n, len-n, "\t\t\t</xs:element>\n");
00897         }
00898     }
00899     n += buffer_write(buffer+n, len-n, "\t\t</xs:all>\n");
00900     n += buffer_write(buffer+n, len-n, "\t</xs:complexType>\n");
00901     n += buffer_write(buffer+n, len-n, "</xs:element>\n");
00902     buffer[n] = 0;
00903     if(check == 0){
00904         printf("class_get_xsd() overflowed.\n");
00905         buffer[0] = 0;
00906         return 0;
00907     }
00908     return (int)n;
00909 }
00910 
00911 

GridLAB-DTM Version 1.0
An open-source project initiated by the US Department of Energy