VPR-6.0

libvpr/read_xml_util.c

Go to the documentation of this file.
00001 #include <assert.h>
00002 #include <stdio.h>
00003 #include <stdlib.h>
00004 #include <string.h>
00005 #include "util.h"
00006 #include "ezxml.h"
00007 #include "read_xml_util.h"
00008 
00009 /** Finds child element with given name and returns it. Errors out if
00010  * more than one instance exists. */
00011 ezxml_t
00012 FindElement(INP ezxml_t Parent, INP const char *Name, INP boolean Required)
00013 {
00014     ezxml_t Cur;
00015 
00016         /* Find the first node of correct name */
00017         Cur = ezxml_child(Parent, Name);
00018 
00019         /* Error out if node isn't found but they required it */
00020         if(Required)
00021         {
00022             if(NULL == Cur)
00023                 {
00024                     printf(ERRTAG
00025                             "[LINE %d] Element '%s' not found within element '%s'.\n", Parent->line,
00026                                                         Name, Parent->name);
00027                     exit(1);
00028                 }
00029         }
00030 
00031         /* Look at next tag with same name and error out if exists */
00032         if(Cur != NULL && Cur->next)
00033         {
00034             printf(ERRTAG "[LINE %d] Element '%s' found twice within element '%s'.\n", Parent->line,
00035                     Name, Parent->name);
00036             exit(1);
00037         }
00038     return Cur;
00039 }
00040 /** Finds child element with given name and returns it. */
00041 ezxml_t
00042 FindFirstElement(INP ezxml_t Parent, INP const char *Name, INP boolean Required)
00043 {
00044     ezxml_t Cur;
00045 
00046         /* Find the first node of correct name */
00047         Cur = ezxml_child(Parent, Name);
00048 
00049         /* Error out if node isn't found but they required it */
00050         if(Required)
00051         {
00052             if(NULL == Cur)
00053                 {
00054                     printf(ERRTAG
00055                                                 "[LINE %d] Element '%s' not found within element '%s'.\n", Parent->line,
00056                             Name, Parent->name);
00057                     exit(1);
00058                 }
00059         }
00060 
00061     return Cur;
00062 }
00063 
00064 
00065 /** Checks the node is an element with name equal to one given */
00066 void
00067 CheckElement(INP ezxml_t Node, INP const char *Name)
00068 {
00069         assert(Node != NULL && Name != NULL);
00070     if(0 != strcmp(Node->name, Name))
00071         {
00072             printf(ERRTAG
00073                                 "[LINE %d] Element '%s' within element '%s' does match expected "
00074                                 "element type of '%s'\n", Node->line, Node->name, Node->parent->name,
00075                     Name);
00076             exit(1);
00077         }
00078 }
00079 
00080 /** Checks that the node has no remaining child nodes or property nodes,
00081  * then unlinks the node from the tree which updates pointers and
00082  * frees the memory 
00083  */
00084 void
00085 FreeNode(INOUTP ezxml_t Node)
00086 {
00087     ezxml_t Cur;
00088     char *Txt;
00089 
00090 
00091         /* Shouldn't have unprocessed properties */
00092         if(Node->attr[0])
00093         {
00094                         printf(ERRTAG "[LINE %d] Node '%s' has invalid property %s=\"%s\".\n", Node->line,
00095                     Node->name, Node->attr[0], Node->attr[1]);
00096             exit(1);
00097         }
00098 
00099         /* Shouldn't have non-whitespace text */
00100         Txt = Node->txt;
00101     while(*Txt)
00102         {
00103             if(!IsWhitespace(*Txt))
00104                 {
00105                     printf(ERRTAG
00106                                                 "[LINE %d] Node '%s' has unexpected text '%s' within it.\n", Node->line,
00107                             Node->name, Node->txt);
00108                     exit(1);
00109                 }
00110             ++Txt;
00111         }
00112 
00113         /* We shouldn't have child items left */
00114         Cur = Node->child;
00115     if(Cur)
00116         {
00117                         printf(ERRTAG "[LINE %d] Node '%s' has invalid child node '%s'.\n", Node->line,
00118                     Node->name, Cur->name);
00119             exit(1);
00120         }
00121 
00122         /* Now actually unlink and free the node */
00123         ezxml_remove(Node);
00124 }
00125 
00126 /** Returns TRUE if character is whatspace between tokens */
00127 boolean
00128 IsWhitespace(char c)
00129 {
00130     switch (c)
00131         {
00132         case ' ':
00133         case '\t':
00134         case '\r':
00135         case '\n':
00136             return TRUE;
00137         default:
00138             return FALSE;
00139         }
00140 }
00141 
00142 const char *
00143 FindProperty(INP ezxml_t Parent, INP const char *Name, INP boolean Required)
00144 {
00145     const char *Res;
00146 
00147     Res = ezxml_attr(Parent, Name);
00148     if(Required)
00149         {
00150             if(NULL == Res)
00151                 {
00152                     printf(ERRTAG
00153                                                 "[Line %d] Required property '%s' not found for element '%s'.\n", Parent->line,
00154                             Name, Parent->name);
00155                     exit(1);
00156                 }
00157         }
00158     return Res;
00159 }
00160 
00161 
00162 
00163 /** Count tokens and length in all the Text children nodes of current node. */ 
00164 extern void
00165 CountTokensInString(INP const char *Str, OUTP int *Num, OUTP int *Len)
00166 {
00167     boolean InToken;
00168     *Num = 0;
00169     *Len = 0;
00170     InToken = FALSE;
00171     while(*Str)
00172         {
00173             if(IsWhitespace(*Str))
00174                 {
00175                     InToken = FALSE;
00176                 }
00177             
00178             else
00179                 
00180                 {
00181                     if(!InToken)
00182                         {
00183                             ++(*Num);
00184                         }
00185                     ++(*Len);
00186                     InToken = TRUE;
00187                 }
00188             ++Str;              /* Advance pointer */
00189         }
00190 }
00191 
00192 /** Returns a token list of the text nodes of a given node. This
00193  * unlinks all the text nodes from the document */ 
00194 extern char **
00195 GetNodeTokens(INP ezxml_t Node)
00196 {
00197         int Count, Len;
00198         char *Cur, *Dst;
00199         boolean InToken;
00200         char **Tokens;
00201 
00202     
00203         /* Count the tokens and find length of token data */ 
00204         CountTokensInString(Node->txt, &Count, &Len);
00205     
00206         /* Error out if no tokens found */ 
00207         if(Count < 1)
00208         {
00209             return NULL;
00210         }
00211     Len = (sizeof(char) * Len) + /* Length of actual data */ 
00212         (sizeof(char) * Count); /* Null terminators */
00213     
00214         /* Alloc the pointer list and data list. Count the final 
00215          * empty string we will use as list terminator */ 
00216         Tokens = (char **)my_malloc(sizeof(char *) * (Count + 1));
00217     Dst = (char *)my_malloc(sizeof(char) * Len);
00218     Count = 0;
00219     
00220         /* Copy data to tokens */ 
00221         Cur = Node->txt;
00222     InToken = FALSE;
00223     while(*Cur)
00224         {
00225             if(IsWhitespace(*Cur))
00226                 {
00227                     if(InToken)
00228                         {
00229                             *Dst = '\0';
00230                             ++Dst;
00231                         }
00232                     InToken = FALSE;
00233                 }
00234             
00235             else
00236                 {
00237                     if(!InToken)
00238                         {
00239                             Tokens[Count] = Dst;
00240                             ++Count;
00241                         }
00242                     *Dst = *Cur;
00243                     ++Dst;
00244                     InToken = TRUE;
00245                 }
00246             ++Cur;
00247         }
00248     if(InToken)
00249         {                       /* Null term final token */
00250             *Dst = '\0';
00251             ++Dst;
00252         }
00253     ezxml_set_txt(Node, "");
00254     Tokens[Count] = NULL;       /* End of tokens marker is a NULL */
00255     
00256         /* Return the list */ 
00257         return Tokens;
00258 }
00259 
00260 
00261 /** Returns a token list of the text nodes of a given node. This
00262  * does not unlink the text nodes from the document */ 
00263 extern char **
00264 LookaheadNodeTokens(INP ezxml_t Node)
00265 {
00266         int Count, Len;
00267         char *Cur, *Dst;
00268         boolean InToken;
00269         char **Tokens;
00270 
00271     
00272         /* Count the tokens and find length of token data */ 
00273         CountTokensInString(Node->txt, &Count, &Len);
00274     
00275         /* Error out if no tokens found */ 
00276         if(Count < 1)
00277         {
00278             return NULL;
00279         }
00280     Len = (sizeof(char) * Len) + /* Length of actual data */ 
00281         (sizeof(char) * Count); /* Null terminators */
00282     
00283         /* Alloc the pointer list and data list. Count the final 
00284          * empty string we will use as list terminator */ 
00285         Tokens = (char **)my_malloc(sizeof(char *) * (Count + 1));
00286     Dst = (char *)my_malloc(sizeof(char) * Len);
00287     Count = 0;
00288     
00289         /* Copy data to tokens */ 
00290         Cur = Node->txt;
00291     InToken = FALSE;
00292     while(*Cur)
00293         {
00294             if(IsWhitespace(*Cur))
00295                 {
00296                     if(InToken)
00297                         {
00298                             *Dst = '\0';
00299                             ++Dst;
00300                         }
00301                     InToken = FALSE;
00302                 }
00303             
00304             else
00305                 {
00306                     if(!InToken)
00307                         {
00308                             Tokens[Count] = Dst;
00309                             ++Count;
00310                         }
00311                     *Dst = *Cur;
00312                     ++Dst;
00313                     InToken = TRUE;
00314                 }
00315             ++Cur;
00316         }
00317     if(InToken)
00318         {                       /* Null term final token */
00319             *Dst = '\0';
00320             ++Dst;
00321         }
00322     Tokens[Count] = NULL;       /* End of tokens marker is a NULL */
00323     
00324         /* Return the list */ 
00325         return Tokens;
00326 }
00327 
00328 /** Find integer attribute matching Name in XML tag Parent and return it if exists.  
00329 Removes attribute from Parent */
00330 extern int GetIntProperty(INP ezxml_t Parent,
00331                                  INP const char *Name,
00332                                  INP boolean Required,
00333                                  INP int default_value)
00334 {
00335         const char * Prop;
00336         int property_value;
00337 
00338         property_value = default_value;
00339         Prop = FindProperty(Parent, Name, Required);
00340     if(Prop)
00341         {
00342             property_value = my_atoi(Prop);
00343             ezxml_set_attr(Parent, Name, NULL);
00344         }
00345         return property_value;
00346 }
00347 
00348 /** Find floating-point attribute matching Name in XML tag Parent and return it if exists.  
00349 Removes attribute from Parent */
00350 extern float GetFloatProperty(INP ezxml_t Parent,
00351                                  INP const char *Name,
00352                                  INP boolean Required,
00353                                  INP float default_value)
00354 {
00355         
00356         const char * Prop;
00357         float property_value;
00358 
00359         property_value = default_value;
00360         Prop = FindProperty(Parent, Name, Required);
00361     if(Prop)
00362         {
00363             property_value = atof(Prop);
00364             ezxml_set_attr(Parent, Name, NULL);
00365         }
00366         return property_value;
00367 }
00368 
00369 /** Find boolean attribute matching Name in XML tag Parent and return it if exists.  
00370 Removes attribute from Parent */
00371 extern boolean GetBooleanProperty(INP ezxml_t Parent,
00372                                  INP const char *Name,
00373                                  INP boolean Required,
00374                                  INP boolean default_value)
00375 {
00376         
00377         const char * Prop;
00378         boolean property_value;
00379 
00380         property_value = default_value;
00381         Prop = FindProperty(Parent, Name, Required);
00382     if(Prop)
00383         {
00384             if((strcmp(Prop, "false") == 0) ||
00385                         (strcmp(Prop, "FALSE") == 0) ||
00386                         (strcmp(Prop, "False") == 0)) {
00387                         property_value = FALSE;
00388                 } else if ((strcmp(Prop, "true") == 0) ||
00389                         (strcmp(Prop, "TRUE") == 0) ||
00390                         (strcmp(Prop, "True") == 0)) {
00391                         property_value = TRUE;
00392                 } else {
00393                         printf(ERRTAG "[LINE %d] Unknown value %s for boolean attribute %s in %s", Parent->line,
00394                                 Prop, Name, Parent->name);
00395                         exit(1);
00396                 }
00397             ezxml_set_attr(Parent, Name, NULL);
00398         }
00399         return property_value;
00400 }
00401 
00402 
00403 /** Counts number of child elements in a container element. 
00404  * Name is the name of the child element. 
00405  * Errors if no occurances found. */ 
00406 extern int
00407 CountChildren(INP ezxml_t Node, INP const char *Name, INP int min_count)
00408 {
00409     ezxml_t Cur, sibling;
00410     int Count;
00411 
00412     Count = 0;
00413     Cur = Node->child;
00414         sibling = NULL;
00415 
00416         if(Cur)
00417         {
00418                 sibling = Cur->sibling;
00419         }
00420             
00421     while(Cur)
00422         {
00423                 if(strcmp(Cur->name, Name) == 0)
00424                 {
00425                     ++Count;
00426                 }
00427             Cur = Cur->next;
00428             if(Cur == NULL)
00429                 {
00430                     Cur = sibling;
00431                         if(Cur != NULL)
00432                         {
00433                                 sibling = Cur->sibling;
00434                         }
00435                 }
00436         }   
00437         /* Error if no occurances found */ 
00438         if(Count < min_count)
00439         {
00440                 printf(ERRTAG "[Line %d] Expected node '%s' to have %d "
00441                     "child elements, but none found.\n", Node->line, Node->name, min_count);
00442             exit(1);
00443         }
00444     return Count;
00445 }
00446 
00447