r121: This commit was manufactured by cvs2svn to create tag
[cinelerra_cv/mob.git] / hvirtual / cinelerra / filexml.C
blobadc261da178df203236763324b8cfcac8872d0ca
1 #include <ctype.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
6 #include "filexml.h"
11 // Precision in base 10
12 // for float is 6 significant figures
13 // for double is 16 significant figures
17 FileXML::FileXML(char left_delimiter, char right_delimiter)
19         tag.set_delimiters(left_delimiter, right_delimiter);
20         this->left_delimiter = left_delimiter;
21         this->right_delimiter = right_delimiter;
22         available = 64;
23         string = new char[available];
24         string[0] = 0;
25         position = length = 0;
26         output_length = 0;
27         share_string = 0;
30 FileXML::~FileXML()
32         if(!share_string) delete [] string;
33         if(output_length) delete [] output;
36 void FileXML::dump()
38         printf("FileXML::dump:\n%s\n", string);
41 int FileXML::terminate_string()
43         append_text("", 1);
44         return 0;
47 int FileXML::rewind()
49         terminate_string();
50         length = strlen(string);
51         position = 0;
52         return 0;
56 int FileXML::append_newline()
58         append_text("\n", 1);
59         return 0;
62 int FileXML::append_tag()
64         tag.write_tag();
65         append_text(tag.string, tag.len);
66         tag.reset_tag();
67         return 0;
70 int FileXML::append_text(char *text)
72         append_text(text, strlen(text));
73         return 0;
76 int FileXML::append_text(char *text, long len)
78         while(position + len > available)
79         {
80                 reallocate_string(available * 2);
81         }
83         for(int i = 0; i < len; i++, position++)
84         {
85                 string[position] = text[i];
86         }
87         return 0;
90 int FileXML::reallocate_string(long new_available)
92         if(!share_string)
93         {
94                 char *new_string = new char[new_available];
95                 for(int i = 0; i < position; i++) new_string[i] = string[i];
96                 available = new_available;
97                 delete [] string;
98                 string = new_string;
99         }
100         return 0;
103 char* FileXML::read_text()
105         long text_position = position;
106         int i;
108 // use < to mark end of text and start of tag
110 // find end of text
111         for(; position < length && string[position] != left_delimiter; position++)
112         {
113                 ;
114         }
116 // allocate enough space
117         if(output_length) delete [] output;
118         output_length = position - text_position;
119         output = new char[output_length + 1];
121 //printf("FileXML::read_text %d %c\n", text_position, string[text_position]);
122         for(i = 0; text_position < position; text_position++)
123         {
124 // filter out first newline
125                 if((i > 0 && i < output_length - 1) || string[text_position] != '\n') 
126                 {
127                         output[i] = string[text_position];
128                         i++;
129                 }
130         }
131         output[i] = 0;
133         return output;
136 int FileXML::read_tag()
138 // scan to next tag
139         while(position < length && string[position] != left_delimiter)
140         {
141                 position++;
142         }
143         tag.reset_tag();
144         if(position >= length) return 1;
145 //printf("FileXML::read_tag %s\n", &string[position]);
146         return tag.read_tag(string, position, length);
149 int FileXML::read_text_until(char *tag_end, char *output)
151 // read to next tag
152         int out_position = 0;
153         int test_position1, test_position2;
154         int result = 0;
155         
156         while(!result && position < length)
157         {
158                 while(position < length && string[position] != left_delimiter)
159                 {
160 //printf("FileXML::read_text_until 1 %c\n", string[position]);
161                         output[out_position++] = string[position++];
162                 }
163                 
164                 if(position < length && string[position] == left_delimiter)
165                 {
166 // tag reached
167 // test for tag_end
168                         result = 1;         // assume end
169                         
170                         for(test_position1 = 0, test_position2 = position + 1;   // skip < 
171                                 test_position2 < length &&
172                                 tag_end[test_position1] != 0 &&
173                                 result; 
174                                 test_position1++, test_position2++)
175                         {
176 // null result when first wrong character is reached
177 //printf("FileXML::read_text_until 2 %c\n", string[test_position2]);
178                                 if(tag_end[test_position1] != string[test_position2]) result = 0;
179                         }
181 // no end tag reached to copy <
182                         if(!result)
183                         {
184                                 output[out_position++] = string[position++];
185                         }
186                 }
187         }
188         output[out_position] = 0;
189 // if end tag is reached, position is left on the < of the end tag
190         return 0;
194 int FileXML::write_to_file(char *filename)
196         FILE *out;
197         strcpy(this->filename, filename);
198         if(out = fopen(filename, "wb"))
199         {
200                 fprintf(out, "<?xml version=\"1.0\"?>\n");
201 // Position may have been rewound after storing so we use a strlen
202                 if(!fwrite(string, strlen(string), 1, out))
203                 {
204                         perror("FileXML::write_to_file");
205                         fclose(out);
206                         return 1;
207                 }
208                 else
209                 {
210 //                      fputc(0, out);
211                 }
212         }
213         else
214         {
215                 perror("FileXML::write_to_file");
216                 return 1;
217         }
218         fclose(out);
219         return 0;
222 int FileXML::write_to_file(FILE *file)
224         strcpy(this->filename, "");
225         fprintf(file, "<?xml version=\"1.0\"?>\n");
226 // Position may have been rewound after storing
227         if(fwrite(string, strlen(string), 1, file))
228         {
229 //              fputc(0, file);
230                 return 0;
231         }
232         else
233         {
234                 perror("FileXML::write_to_file");
235                 return 1;
236         }
237         return 0;
240 int FileXML::read_from_file(char *filename, int ignore_error)
242         FILE *in;
243         
244         strcpy(this->filename, filename);
245         if(in = fopen(filename, "rb"))
246         {
247                 fseek(in, 0, SEEK_END);
248                 length = ftell(in);
249                 fseek(in, 0, SEEK_SET);
250                 reallocate_string(length + 1);
251                 fread(string, length, 1, in);
252                 string[length] = 0;
253                 position = 0;
254         }
255         else
256         {
257                 if(!ignore_error) perror("FileXML::read_from_file");
258                 return 1;
259         }
260         fclose(in);
261         return 0;
264 int FileXML::read_from_string(char *string)
266         strcpy(this->filename, "");
267         reallocate_string(strlen(string) + 1);
268         strcpy(this->string, string);
269         length = strlen(string);
270         position = 0;
271         return 0;
274 int FileXML::set_shared_string(char *shared_string, long available)
276         strcpy(this->filename, "");
277         if(!share_string)
278         {
279                 delete [] string;
280                 share_string = 1;
281                 string = shared_string;
282                 this->available = available;
283                 length = available;
284                 position = 0;
285         }
286         return 0;
291 // ================================ XML tag
294 XMLTag::XMLTag()
296         total_properties = 0;
297         len = 0;
300 XMLTag::~XMLTag()
302         reset_tag();
305 int XMLTag::set_delimiters(char left_delimiter, char right_delimiter)
307         this->left_delimiter = left_delimiter;
308         this->right_delimiter = right_delimiter;
309         return 0;
312 int XMLTag::reset_tag()     // clear all structures
314         len = 0;
315         for(int i = 0; i < total_properties; i++) delete [] tag_properties[i];
316         for(int i = 0; i < total_properties; i++) delete [] tag_property_values[i];
317         total_properties = 0;
318         return 0;
321 int XMLTag::write_tag()
323         int i, j;
324         char *current_property, *current_value;
325         int has_space;
327 // opening bracket
328         string[len] = left_delimiter;        
329         len++;
330         
331 // title
332         for(i = 0; tag_title[i] != 0 && len < MAX_LENGTH; i++, len++) string[len] = tag_title[i];
334 // properties
335         for(i = 0; i < total_properties && len < MAX_LENGTH; i++)
336         {
337                 string[len++] = ' ';         // add a space before every property
338                 
339                 current_property = tag_properties[i];
341 // property title
342                 for(j = 0; current_property[j] != 0 && len < MAX_LENGTH; j++, len++)
343                 {
344                         string[len] = current_property[j];
345                 }
346                 
347                 if(len < MAX_LENGTH) string[len++] = '=';
348                 
349                 current_value = tag_property_values[i];
351 // property value
352 // search for spaces in value
353                 for(j = 0, has_space = 0; current_value[j] != 0 && !has_space; j++)
354                 {
355                         if(current_value[j] == ' ') has_space = 1;
356                 }
358 // add a quote if space
359                 if(has_space && len < MAX_LENGTH) string[len++] = '\"';
360 // write the value
361                 for(j = 0; current_value[j] != 0 && len < MAX_LENGTH; j++, len++)
362                 {
363                         string[len] = current_value[j];
364                 }
365 // add a quote if space
366                 if(has_space && len < MAX_LENGTH) string[len++] = '\"';
367         }     // next property
368         
369         if(len < MAX_LENGTH) string[len++] = right_delimiter;   // terminating bracket
370         return 0;
373 int XMLTag::read_tag(char *input, long &position, long length)
375         long tag_start;
376         int i, j, terminating_char;
378 // search for beginning of a tag
379         while(input[position] != left_delimiter && position < length) position++;
380         
381         if(position >= length) return 1;
382         
383 // find the start
384         while(position < length &&
385                 (input[position] == ' ' ||         // skip spaces
386                 input[position] == '\n' ||       // also skip new lines
387                 input[position] == left_delimiter))           // skip <
388                 position++;
390         if(position >= length) return 1;
391         
392         tag_start = position;
393         
394 // read title
395         for(i = 0; 
396                 i < MAX_TITLE && 
397                 position < length && 
398                 input[position] != '=' && 
399                 input[position] != ' ' &&       // space ends title
400                 input[position] != right_delimiter;
401                 position++, i++)
402         {
403                 tag_title[i] = input[position];
404         }
405         tag_title[i] = 0;
406         
407         if(position >= length) return 1;
408         
409         if(input[position] == '=')
410         {
411 // no title but first property
412                 tag_title[0] = 0;
413                 position = tag_start;       // rewind
414         }
416 // read properties
417         for(i = 0;
418                 i < MAX_PROPERTIES &&
419                 position < length &&
420                 input[position] != right_delimiter;
421                 i++)
422         {
423 // read a tag
424 // find the start
425                 while(position < length &&
426                         (input[position] == ' ' ||         // skip spaces
427                         input[position] == '\n' ||         // also skip new lines
428                         input[position] == left_delimiter))           // skip <
429                         position++;
431 // read the property description
432                 for(j = 0; 
433                         j < MAX_LENGTH &&
434                         position < length &&
435                         input[position] != right_delimiter &&
436                         input[position] != ' ' &&
437                         input[position] != '\n' &&      // also new line ends it
438                         input[position] != '=';
439                         j++, position++)
440                 {
441                         string[j] = input[position];
442                 }
443                 string[j] = 0;
446 // store the description in a property array
447                 tag_properties[total_properties] = new char[strlen(string) + 1];
448                 strcpy(tag_properties[total_properties], string);
450 // find the start of the value
451                 while(position < length &&
452                         (input[position] == ' ' ||         // skip spaces
453                         input[position] == '\n' ||         // also skip new lines
454                         input[position] == '='))           // skip =
455                         position++;
457 // find the terminating char
458                 if(position < length && input[position] == '\"')
459                 {
460                         terminating_char = '\"';     // use quotes to terminate
461                         if(position < length) position++;   // don't store the quote itself
462                 }
463                 else terminating_char = ' ';         // use space to terminate
465 // read until the terminating char
466                 for(j = 0;
467                         j < MAX_LENGTH &&
468                         position < length &&
469                         input[position] != right_delimiter &&
470                         input[position] != terminating_char;
471                         j++, position++)
472                 {
473                         string[j] = input[position];
474                 }
475                 string[j] = 0;
477 // store the value in a property array
478                 tag_property_values[total_properties] = new char[strlen(string) + 1];
479                 strcpy(tag_property_values[total_properties], string);
480                 
481 // advance property if one was just loaded
482                 if(tag_properties[total_properties][0] != 0) total_properties++;
484 // get the terminating char
485                 if(position < length && input[position] != right_delimiter) position++;
486         }
488 // skip the >
489         if(position < length && input[position] == right_delimiter) position++;
491         if(total_properties || tag_title[0]) return 0; else return 1;
492         return 0;
495 int XMLTag::title_is(char *title)
497         if(!strcasecmp(title, tag_title)) return 1;
498         else return 0;
501 char* XMLTag::get_title()
503         return tag_title;
506 int XMLTag::get_title(char *value)
508         if(tag_title[0] != 0) strcpy(value, tag_title);
509         return 0;
512 int XMLTag::test_property(char *property, char *value)
514         int i, result;
515         for(i = 0, result = 0; i < total_properties && !result; i++)
516         {
517                 if(!strcasecmp(tag_properties[i], property) && !strcasecmp(value, tag_property_values[i]))
518                 {
519                         return 1;
520                 }
521         }
522         return 0;
525 char* XMLTag::get_property(char *property, char *value)
527         int i, result;
528         for(i = 0, result = 0; i < total_properties && !result; i++)
529         {
530                 if(!strcasecmp(tag_properties[i], property))
531                 {
532                         strcpy(value, tag_property_values[i]);
533                         result = 1;
534                 }
535         }
536         return value;
539 char* XMLTag::get_property_text(int number)
541         if(number < total_properties) 
542                 return tag_properties[number];
543         else
544                 return "";
547 int XMLTag::get_property_int(int number)
549         if(number < total_properties) 
550                 return atol(tag_properties[number]);
551         else
552                 return 0;
555 float XMLTag::get_property_float(int number)
557         if(number < total_properties) 
558                 return atof(tag_properties[number]);
559         else
560                 return 0;
563 char* XMLTag::get_property(char *property)
565         int i, result;
566         for(i = 0, result = 0; i < total_properties && !result; i++)
567         {
568                 if(!strcasecmp(tag_properties[i], property))
569                 {
570                         return tag_property_values[i];
571                 }
572         }
573         return 0;
577 int32_t XMLTag::get_property(char *property, int32_t default_)
579         temp_string[0] = 0;
580         get_property(property, temp_string);
581         if(temp_string[0] == 0) 
582                 return default_;
583         else 
584                 return atol(temp_string);
587 int64_t XMLTag::get_property(char *property, int64_t default_)
589         int64_t result;
590         temp_string[0] = 0;
591         get_property(property, temp_string);
592         if(temp_string[0] == 0) 
593                 result = default_;
594         else 
595         {
596                 sscanf(temp_string, "%lld", &result);
597         }
598         return result;
600 // 
601 // int XMLTag::get_property(char *property, int default_)
602 // {
603 //      temp_string[0] = 0;
604 //      get_property(property, temp_string);
605 //      if(temp_string[0] == 0) return default_;
606 //      else return atol(temp_string);
607 // }
608 // 
609 float XMLTag::get_property(char *property, float default_)
611         temp_string[0] = 0;
612         get_property(property, temp_string);
613         if(temp_string[0] == 0) 
614                 return default_;
615         else 
616                 return atof(temp_string);
619 double XMLTag::get_property(char *property, double default_)
621         temp_string[0] = 0;
622         get_property(property, temp_string);
623         if(temp_string[0] == 0) 
624                 return default_;
625         else 
626                 return atof(temp_string);
629 int XMLTag::set_title(char *text)       // set the title field
631         strcpy(tag_title, text);
632         return 0;
635 int XMLTag::set_property(char *text, int32_t value)
637         sprintf(temp_string, "%ld", value);
638         set_property(text, temp_string);
639         return 0;
642 int XMLTag::set_property(char *text, int64_t value)
644         sprintf(temp_string, "%lld", value);
645         set_property(text, temp_string);
646         return 0;
649 // int XMLTag::set_property(char *text, int value)
650 // {
651 //      sprintf(temp_string, "%d", value);
652 //      set_property(text, temp_string);
653 //      return 0;
654 // }
656 int XMLTag::set_property(char *text, float value)
658         sprintf(temp_string, "%.6e", value);
659         set_property(text, temp_string);
660         return 0;
663 int XMLTag::set_property(char *text, double value)
665         sprintf(temp_string, "%.16e", value);
666         set_property(text, temp_string);
667         return 0;
670 int XMLTag::set_property(char *text, char *value)
672         tag_properties[total_properties] = new char[strlen(text) + 1];
673         strcpy(tag_properties[total_properties], text);
674         tag_property_values[total_properties] = new char[strlen(value) + 1];
675         strcpy(tag_property_values[total_properties], value);
676         total_properties++;
677         return 0;