Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

filexml.C

Go to the documentation of this file.
00001 #include <ctype.h>
00002 #include <errno.h>
00003 #include <stdio.h>
00004 #include <stdlib.h>
00005 #include <string.h>
00006 
00007 #include "filexml.h"
00008 
00009 
00010 
00011 
00012 // Precision in base 10
00013 // for float is 6 significant figures
00014 // for double is 16 significant figures
00015 
00016 
00017 
00018 FileXML::FileXML(char left_delimiter, char right_delimiter)
00019 {
00020         tag.set_delimiters(left_delimiter, right_delimiter);
00021         this->left_delimiter = left_delimiter;
00022         this->right_delimiter = right_delimiter;
00023         available = 64;
00024         string = new char[available];
00025         string[0] = 0;
00026         position = length = 0;
00027         output_length = 0;
00028         share_string = 0;
00029 }
00030 
00031 FileXML::~FileXML()
00032 {
00033         if(!share_string) delete [] string;
00034         if(output_length) delete [] output;
00035 }
00036 
00037 void FileXML::dump()
00038 {
00039         printf("FileXML::dump:\n%s\n", string);
00040 }
00041 
00042 int FileXML::terminate_string()
00043 {
00044         append_text("", 1);
00045         return 0;
00046 }
00047 
00048 int FileXML::rewind()
00049 {
00050         terminate_string();
00051         length = strlen(string);
00052         position = 0;
00053         return 0;
00054 }
00055 
00056 
00057 int FileXML::append_newline()
00058 {
00059         append_text("\n", 1);
00060         return 0;
00061 }
00062 
00063 int FileXML::append_tag()
00064 {
00065         tag.write_tag();
00066         append_text(tag.string, tag.len);
00067         tag.reset_tag();
00068         return 0;
00069 }
00070 
00071 int FileXML::append_text(char *text)
00072 {
00073         append_text(text, strlen(text));
00074         return 0;
00075 }
00076 
00077 int FileXML::append_text(char *text, long len)
00078 {
00079         while(position + len > available)
00080         {
00081                 reallocate_string(available * 2);
00082         }
00083 
00084         for(int i = 0; i < len; i++, position++)
00085         {
00086                 string[position] = text[i];
00087         }
00088         return 0;
00089 }
00090 
00091 int FileXML::encode_text(char *text)
00092 {
00093 // We have to encode at least the '<' char
00094 // We encode three things:
00095 // '<' -> '&lt;' 
00096 // '>' -> '&gt;'
00097 // '&' -> '&amp;'
00098         char leftb[] = "&lt;";
00099         char rightb[] = "&gt;";
00100         char amp[] = "&amp;";
00101         char *replacement;
00102         int len = strlen(text);
00103         int lastpos = 0;
00104         for (int i = 0; i < len; i++) 
00105         {
00106                 switch (text[i]) {
00107                         case '<': replacement = leftb; break;
00108                         case '>': replacement = rightb; break;
00109                         case '&': replacement = amp; break;
00110                         default: replacement = 0; break;
00111                 }
00112                 if (replacement)
00113                 {
00114                         if (i - lastpos > 0)
00115                                 append_text(text + lastpos, i - lastpos);
00116                         append_text(replacement, strlen(replacement));
00117                         lastpos = i + 1;
00118                 }
00119         }
00120         append_text(text + lastpos, len - lastpos);
00121         return 0;
00122 }
00123 
00124 
00125 
00126 int FileXML::reallocate_string(long new_available)
00127 {
00128         if(!share_string)
00129         {
00130                 char *new_string = new char[new_available];
00131                 for(int i = 0; i < position; i++) new_string[i] = string[i];
00132                 available = new_available;
00133                 delete [] string;
00134                 string = new_string;
00135         }
00136         return 0;
00137 }
00138 
00139 char* FileXML::read_text()
00140 {
00141         long text_position = position;
00142         int i;
00143 
00144 // use < to mark end of text and start of tag
00145 
00146 // find end of text
00147         for(; position < length && string[position] != left_delimiter; position++)
00148         {
00149                 ;
00150         }
00151 
00152 // allocate enough space
00153         if(output_length) delete [] output;
00154         output_length = position - text_position;
00155         output = new char[output_length + 1];
00156 
00157 //printf("FileXML::read_text %d %c\n", text_position, string[text_position]);
00158         for(i = 0; text_position < position; text_position++)
00159         {
00160 // filter out first newline
00161                 if((i > 0 && i < output_length - 1) || string[text_position] != '\n') 
00162                 {
00163 // check if we have to decode special characters
00164 // but try to be most backward compatible possible
00165                         int character = string[text_position];
00166                         if (string[text_position] == '&')
00167                         {
00168                                 if (text_position + 3 < length)
00169                                 {
00170                                         if (string[text_position + 1] == 'l' && string[text_position + 2] == 't' && string[text_position + 3] == ';')
00171                                         {
00172                                                 character = '<';
00173                                                 text_position += 3;
00174                                         }               
00175                                         if (string[text_position + 1] == 'g' && string[text_position + 2] == 't' && string[text_position + 3] == ';')
00176                                         {
00177                                                 character = '>';
00178                                                 text_position += 3;
00179                                         }               
00180                                 }
00181                                 if (text_position + 4 < length)
00182                                 {
00183                                         if (string[text_position + 1] == 'a' && string[text_position + 2] == 'm' && string[text_position + 3] == 'p' && string[text_position + 4] == ';')
00184                                         {
00185                                                 character = '&';
00186                                                 text_position += 4;
00187                                         }               
00188                                 }
00189                         }
00190                         output[i] = character;
00191                         i++;
00192                 }
00193         }
00194         output[i] = 0;
00195 
00196         return output;
00197 }
00198 
00199 int FileXML::read_tag()
00200 {
00201 // scan to next tag
00202         while(position < length && string[position] != left_delimiter)
00203         {
00204                 position++;
00205         }
00206         tag.reset_tag();
00207         if(position >= length) return 1;
00208 //printf("FileXML::read_tag %s\n", &string[position]);
00209         return tag.read_tag(string, position, length);
00210 }
00211 
00212 int FileXML::read_text_until(char *tag_end, char *output, int max_len)
00213 {
00214 // read to next tag
00215         int out_position = 0;
00216         int test_position1, test_position2;
00217         int result = 0;
00218         
00219         while(!result && position < length && out_position < max_len - 1)
00220         {
00221                 while(position < length && string[position] != left_delimiter)
00222                 {
00223 //printf("FileXML::read_text_until 1 %c\n", string[position]);
00224                         output[out_position++] = string[position++];
00225                 }
00226                 
00227                 if(position < length && string[position] == left_delimiter)
00228                 {
00229 // tag reached
00230 // test for tag_end
00231                         result = 1;         // assume end
00232                         
00233                         for(test_position1 = 0, test_position2 = position + 1;   // skip < 
00234                                 test_position2 < length &&
00235                                 tag_end[test_position1] != 0 &&
00236                                 result; 
00237                                 test_position1++, test_position2++)
00238                         {
00239 // null result when first wrong character is reached
00240 //printf("FileXML::read_text_until 2 %c\n", string[test_position2]);
00241                                 if(tag_end[test_position1] != string[test_position2]) result = 0;
00242                         }
00243 
00244 // no end tag reached to copy <
00245                         if(!result)
00246                         {
00247                                 output[out_position++] = string[position++];
00248                         }
00249                 }
00250         }
00251         output[out_position] = 0;
00252 // if end tag is reached, position is left on the < of the end tag
00253         return 0;
00254 }
00255 
00256 
00257 int FileXML::write_to_file(char *filename)
00258 {
00259         FILE *out;
00260         strcpy(this->filename, filename);
00261         if(out = fopen(filename, "wb"))
00262         {
00263                 fprintf(out, "<?xml version=\"1.0\"?>\n");
00264 // Position may have been rewound after storing so we use a strlen
00265                 if(!fwrite(string, strlen(string), 1, out) && strlen(string))
00266                 {
00267                         fprintf(stderr, "FileXML::write_to_file 1 \"%s\": %s\n",
00268                                 filename,
00269                                 strerror(errno));
00270                         fclose(out);
00271                         return 1;
00272                 }
00273                 else
00274                 {
00275                 }
00276         }
00277         else
00278         {
00279                 fprintf(stderr, "FileXML::write_to_file 2 \"%s\": %s\n",
00280                         filename,
00281                         strerror(errno));
00282                 return 1;
00283         }
00284         fclose(out);
00285         return 0;
00286 }
00287 
00288 int FileXML::write_to_file(FILE *file)
00289 {
00290         strcpy(filename, "");
00291         fprintf(file, "<?xml version=\"1.0\"?>\n");
00292 // Position may have been rewound after storing
00293         if(fwrite(string, strlen(string), 1, file) || !strlen(string))
00294         {
00295                 return 0;
00296         }
00297         else
00298         {
00299                 fprintf(stderr, "FileXML::write_to_file \"%s\": %s\n",
00300                         filename,
00301                         strerror(errno));
00302                 return 1;
00303         }
00304         return 0;
00305 }
00306 
00307 int FileXML::read_from_file(char *filename, int ignore_error)
00308 {
00309         FILE *in;
00310         
00311         strcpy(this->filename, filename);
00312         if(in = fopen(filename, "rb"))
00313         {
00314                 fseek(in, 0, SEEK_END);
00315                 length = ftell(in);
00316                 fseek(in, 0, SEEK_SET);
00317                 reallocate_string(length + 1);
00318                 fread(string, length, 1, in);
00319                 string[length] = 0;
00320                 position = 0;
00321         }
00322         else
00323         {
00324                 if(!ignore_error) 
00325                         fprintf(stderr, "FileXML::read_from_file \"%s\" %s\n",
00326                                 filename,
00327                                 strerror(errno));
00328                 return 1;
00329         }
00330         fclose(in);
00331         return 0;
00332 }
00333 
00334 int FileXML::read_from_string(char *string)
00335 {
00336         strcpy(this->filename, "");
00337         reallocate_string(strlen(string) + 1);
00338         strcpy(this->string, string);
00339         length = strlen(string);
00340         position = 0;
00341         return 0;
00342 }
00343 
00344 int FileXML::set_shared_string(char *shared_string, long available)
00345 {
00346         strcpy(this->filename, "");
00347         if(!share_string)
00348         {
00349                 delete [] string;
00350                 share_string = 1;
00351                 string = shared_string;
00352                 this->available = available;
00353                 length = available;
00354                 position = 0;
00355         }
00356         return 0;
00357 }
00358 
00359 
00360 
00361 // ================================ XML tag
00362 
00363 
00364 XMLTag::XMLTag()
00365 {
00366         total_properties = 0;
00367         len = 0;
00368 }
00369 
00370 XMLTag::~XMLTag()
00371 {
00372         reset_tag();
00373 }
00374 
00375 int XMLTag::set_delimiters(char left_delimiter, char right_delimiter)
00376 {
00377         this->left_delimiter = left_delimiter;
00378         this->right_delimiter = right_delimiter;
00379         return 0;
00380 }
00381 
00382 int XMLTag::reset_tag()     // clear all structures
00383 {
00384         len = 0;
00385         for(int i = 0; i < total_properties; i++) delete [] tag_properties[i];
00386         for(int i = 0; i < total_properties; i++) delete [] tag_property_values[i];
00387         total_properties = 0;
00388         return 0;
00389 }
00390 
00391 int XMLTag::write_tag()
00392 {
00393         int i, j;
00394         char *current_property, *current_value;
00395 
00396 // opening bracket
00397         string[len] = left_delimiter;        
00398         len++;
00399         
00400 // title
00401         for(i = 0; tag_title[i] != 0 && len < MAX_LENGTH; i++, len++) string[len] = tag_title[i];
00402 
00403 // properties
00404         for(i = 0; i < total_properties && len < MAX_LENGTH; i++)
00405         {
00406                 string[len++] = ' ';         // add a space before every property
00407                 
00408                 current_property = tag_properties[i];
00409 
00410 // property title
00411                 for(j = 0; current_property[j] != 0 && len < MAX_LENGTH; j++, len++)
00412                 {
00413                         string[len] = current_property[j];
00414                 }
00415                 
00416                 if(len < MAX_LENGTH) string[len++] = '=';
00417                 
00418                 current_value = tag_property_values[i];
00419 
00420 // property value
00421                 if( len < MAX_LENGTH) string[len++] = '\"';
00422 // write the value
00423                 for(j = 0; current_value[j] != 0 && len < MAX_LENGTH; j++, len++)
00424                 {
00425                         string[len] = current_value[j];
00426                 }
00427                 if(len < MAX_LENGTH) string[len++] = '\"';
00428         }     // next property
00429         
00430         if(len < MAX_LENGTH) string[len++] = right_delimiter;   // terminating bracket
00431         return 0;
00432 }
00433 
00434 int XMLTag::read_tag(char *input, long &position, long length)
00435 {
00436         long tag_start;
00437         int i, j, terminating_char;
00438 
00439 // search for beginning of a tag
00440         while(input[position] != left_delimiter && position < length) position++;
00441         
00442         if(position >= length) return 1;
00443         
00444 // find the start
00445         while(position < length &&
00446                 (input[position] == ' ' ||         // skip spaces
00447                 input[position] == '\n' ||       // also skip new lines
00448                 input[position] == left_delimiter))           // skip <
00449                 position++;
00450 
00451         if(position >= length) return 1;
00452         
00453         tag_start = position;
00454         
00455 // read title
00456         for(i = 0; 
00457                 i < MAX_TITLE && 
00458                 position < length && 
00459                 input[position] != '=' && 
00460                 input[position] != ' ' &&       // space ends title
00461                 input[position] != right_delimiter;
00462                 position++, i++)
00463         {
00464                 tag_title[i] = input[position];
00465         }
00466         tag_title[i] = 0;
00467         
00468         if(position >= length) return 1;
00469         
00470         if(input[position] == '=')
00471         {
00472 // no title but first property
00473                 tag_title[0] = 0;
00474                 position = tag_start;       // rewind
00475         }
00476 
00477 // read properties
00478         for(i = 0;
00479                 i < MAX_PROPERTIES &&
00480                 position < length &&
00481                 input[position] != right_delimiter;
00482                 i++)
00483         {
00484 // read a tag
00485 // find the start
00486                 while(position < length &&
00487                         (input[position] == ' ' ||         // skip spaces
00488                         input[position] == '\n' ||         // also skip new lines
00489                         input[position] == left_delimiter))           // skip <
00490                         position++;
00491 
00492 // read the property description
00493                 for(j = 0; 
00494                         j < MAX_LENGTH &&
00495                         position < length &&
00496                         input[position] != right_delimiter &&
00497                         input[position] != ' ' &&
00498                         input[position] != '\n' &&      // also new line ends it
00499                         input[position] != '=';
00500                         j++, position++)
00501                 {
00502                         string[j] = input[position];
00503                 }
00504                 string[j] = 0;
00505 
00506 
00507 // store the description in a property array
00508                 tag_properties[total_properties] = new char[strlen(string) + 1];
00509                 strcpy(tag_properties[total_properties], string);
00510 
00511 // find the start of the value
00512                 while(position < length &&
00513                         (input[position] == ' ' ||         // skip spaces
00514                         input[position] == '\n' ||         // also skip new lines
00515                         input[position] == '='))           // skip =
00516                         position++;
00517 
00518 // find the terminating char
00519                 if(position < length && input[position] == '\"')
00520                 {
00521                         terminating_char = '\"';     // use quotes to terminate
00522                         if(position < length) position++;   // don't store the quote itself
00523                 }
00524                 else terminating_char = ' ';         // use space to terminate
00525 
00526 // read until the terminating char
00527                 for(j = 0;
00528                         j < MAX_LENGTH &&
00529                         position < length &&
00530                         input[position] != right_delimiter &&
00531                         input[position] != terminating_char;
00532                         j++, position++)
00533                 {
00534                         string[j] = input[position];
00535                 }
00536                 string[j] = 0;
00537 
00538 // store the value in a property array
00539                 tag_property_values[total_properties] = new char[strlen(string) + 1];
00540                 strcpy(tag_property_values[total_properties], string);
00541                 
00542 // advance property if one was just loaded
00543                 if(tag_properties[total_properties][0] != 0) total_properties++;
00544 
00545 // get the terminating char
00546                 if(position < length && input[position] != right_delimiter) position++;
00547         }
00548 
00549 // skip the >
00550         if(position < length && input[position] == right_delimiter) position++;
00551 
00552         if(total_properties || tag_title[0]) return 0; else return 1;
00553         return 0;
00554 }
00555 
00556 int XMLTag::title_is(char *title)
00557 {
00558         if(!strcasecmp(title, tag_title)) return 1;
00559         else return 0;
00560 }
00561 
00562 char* XMLTag::get_title()
00563 {
00564         return tag_title;
00565 }
00566 
00567 int XMLTag::get_title(char *value)
00568 {
00569         if(tag_title[0] != 0) strcpy(value, tag_title);
00570         return 0;
00571 }
00572 
00573 int XMLTag::test_property(char *property, char *value)
00574 {
00575         int i, result;
00576         for(i = 0, result = 0; i < total_properties && !result; i++)
00577         {
00578                 if(!strcasecmp(tag_properties[i], property) && !strcasecmp(value, tag_property_values[i]))
00579                 {
00580                         return 1;
00581                 }
00582         }
00583         return 0;
00584 }
00585 
00586 char* XMLTag::get_property(char *property, char *value)
00587 {
00588         int i, result;
00589         for(i = 0, result = 0; i < total_properties && !result; i++)
00590         {
00591                 if(!strcasecmp(tag_properties[i], property))
00592                 {
00593                         strcpy(value, tag_property_values[i]);
00594                         result = 1;
00595                 }
00596         }
00597         return value;
00598 }
00599 
00600 char* XMLTag::get_property_text(int number)
00601 {
00602         if(number < total_properties) 
00603                 return tag_properties[number];
00604         else
00605                 return "";
00606 }
00607 
00608 int XMLTag::get_property_int(int number)
00609 {
00610         if(number < total_properties) 
00611                 return atol(tag_properties[number]);
00612         else
00613                 return 0;
00614 }
00615 
00616 float XMLTag::get_property_float(int number)
00617 {
00618         if(number < total_properties) 
00619                 return atof(tag_properties[number]);
00620         else
00621                 return 0;
00622 }
00623 
00624 char* XMLTag::get_property(char *property)
00625 {
00626         int i, result;
00627         for(i = 0, result = 0; i < total_properties && !result; i++)
00628         {
00629                 if(!strcasecmp(tag_properties[i], property))
00630                 {
00631                         return tag_property_values[i];
00632                 }
00633         }
00634         return 0;
00635 }
00636 
00637 
00638 int32_t XMLTag::get_property(char *property, int32_t default_)
00639 {
00640         temp_string[0] = 0;
00641         get_property(property, temp_string);
00642         if(temp_string[0] == 0) 
00643                 return default_;
00644         else 
00645                 return atol(temp_string);
00646 }
00647 
00648 int64_t XMLTag::get_property(char *property, int64_t default_)
00649 {
00650         int64_t result;
00651         temp_string[0] = 0;
00652         get_property(property, temp_string);
00653         if(temp_string[0] == 0) 
00654                 result = default_;
00655         else 
00656         {
00657                 sscanf(temp_string, "%lld", &result);
00658         }
00659         return result;
00660 }
00661 // 
00662 // int XMLTag::get_property(char *property, int default_)
00663 // {
00664 //      temp_string[0] = 0;
00665 //      get_property(property, temp_string);
00666 //      if(temp_string[0] == 0) return default_;
00667 //      else return atol(temp_string);
00668 // }
00669 // 
00670 float XMLTag::get_property(char *property, float default_)
00671 {
00672         temp_string[0] = 0;
00673         get_property(property, temp_string);
00674         if(temp_string[0] == 0) 
00675                 return default_;
00676         else 
00677                 return atof(temp_string);
00678 }
00679 
00680 double XMLTag::get_property(char *property, double default_)
00681 {
00682         temp_string[0] = 0;
00683         get_property(property, temp_string);
00684         if(temp_string[0] == 0) 
00685                 return default_;
00686         else 
00687                 return atof(temp_string);
00688 }
00689 
00690 int XMLTag::set_title(char *text)       // set the title field
00691 {
00692         strcpy(tag_title, text);
00693         return 0;
00694 }
00695 
00696 int XMLTag::set_property(char *text, int32_t value)
00697 {
00698         sprintf(temp_string, "%ld", value);
00699         set_property(text, temp_string);
00700         return 0;
00701 }
00702 
00703 int XMLTag::set_property(char *text, int64_t value)
00704 {
00705         sprintf(temp_string, "%lld", value);
00706         set_property(text, temp_string);
00707         return 0;
00708 }
00709 
00710 // int XMLTag::set_property(char *text, int value)
00711 // {
00712 //      sprintf(temp_string, "%d", value);
00713 //      set_property(text, temp_string);
00714 //      return 0;
00715 // }
00716 
00717 int XMLTag::set_property(char *text, float value)
00718 {
00719         sprintf(temp_string, "%.6e", value);
00720         set_property(text, temp_string);
00721         return 0;
00722 }
00723 
00724 int XMLTag::set_property(char *text, double value)
00725 {
00726         sprintf(temp_string, "%.16e", value);
00727         set_property(text, temp_string);
00728         return 0;
00729 }
00730 
00731 int XMLTag::set_property(char *text, char *value)
00732 {
00733         tag_properties[total_properties] = new char[strlen(text) + 1];
00734         strcpy(tag_properties[total_properties], text);
00735         tag_property_values[total_properties] = new char[strlen(value) + 1];
00736         strcpy(tag_property_values[total_properties], value);
00737         total_properties++;
00738         return 0;
00739 }

Generated on Sun Jan 8 13:38:55 2006 for Cinelerra-svn by  doxygen 1.4.4