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;
23 string = new char[available];
25 position = length = 0;
32 if(!share_string) delete [] string;
33 if(output_length) delete [] output;
38 printf("FileXML::dump:\n%s\n", string);
41 int FileXML::terminate_string()
50 length = strlen(string);
56 int FileXML::append_newline()
62 int FileXML::append_tag()
65 append_text(tag.string, tag.len);
70 int FileXML::append_text(char *text)
72 append_text(text, strlen(text));
76 int FileXML::append_text(char *text, long len)
78 while(position + len > available)
80 reallocate_string(available * 2);
83 for(int i = 0; i < len; i++, position++)
85 string[position] = text[i];
90 int FileXML::reallocate_string(long new_available)
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;
103 char* FileXML::read_text()
105 long text_position = position;
108 // use < to mark end of text and start of tag
111 for(; position < length && string[position] != left_delimiter; position++)
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++)
124 // filter out first newline
125 if((i > 0 && i < output_length - 1) || string[text_position] != '\n')
127 output[i] = string[text_position];
136 int FileXML::read_tag()
139 while(position < length && string[position] != left_delimiter)
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)
152 int out_position = 0;
153 int test_position1, test_position2;
156 while(!result && position < length)
158 while(position < length && string[position] != left_delimiter)
160 //printf("FileXML::read_text_until 1 %c\n", string[position]);
161 output[out_position++] = string[position++];
164 if(position < length && string[position] == left_delimiter)
168 result = 1; // assume end
170 for(test_position1 = 0, test_position2 = position + 1; // skip <
171 test_position2 < length &&
172 tag_end[test_position1] != 0 &&
174 test_position1++, test_position2++)
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;
181 // no end tag reached to copy <
184 output[out_position++] = string[position++];
188 output[out_position] = 0;
189 // if end tag is reached, position is left on the < of the end tag
194 int FileXML::write_to_file(char *filename)
197 strcpy(this->filename, filename);
198 if(out = fopen(filename, "wb"))
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))
204 perror("FileXML::write_to_file");
215 perror("FileXML::write_to_file");
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))
234 perror("FileXML::write_to_file");
240 int FileXML::read_from_file(char *filename, int ignore_error)
244 strcpy(this->filename, filename);
245 if(in = fopen(filename, "rb"))
247 fseek(in, 0, SEEK_END);
249 fseek(in, 0, SEEK_SET);
250 reallocate_string(length + 1);
251 fread(string, length, 1, in);
257 if(!ignore_error) perror("FileXML::read_from_file");
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);
274 int FileXML::set_shared_string(char *shared_string, long available)
276 strcpy(this->filename, "");
281 string = shared_string;
282 this->available = available;
291 // ================================ XML tag
296 total_properties = 0;
305 int XMLTag::set_delimiters(char left_delimiter, char right_delimiter)
307 this->left_delimiter = left_delimiter;
308 this->right_delimiter = right_delimiter;
312 int XMLTag::reset_tag() // clear all structures
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;
321 int XMLTag::write_tag()
324 char *current_property, *current_value;
328 string[len] = left_delimiter;
332 for(i = 0; tag_title[i] != 0 && len < MAX_LENGTH; i++, len++) string[len] = tag_title[i];
335 for(i = 0; i < total_properties && len < MAX_LENGTH; i++)
337 string[len++] = ' '; // add a space before every property
339 current_property = tag_properties[i];
342 for(j = 0; current_property[j] != 0 && len < MAX_LENGTH; j++, len++)
344 string[len] = current_property[j];
347 if(len < MAX_LENGTH) string[len++] = '=';
349 current_value = tag_property_values[i];
352 // search for spaces in value
353 for(j = 0, has_space = 0; current_value[j] != 0 && !has_space; j++)
355 if(current_value[j] == ' ') has_space = 1;
358 // add a quote if space
359 if(has_space && len < MAX_LENGTH) string[len++] = '\"';
361 for(j = 0; current_value[j] != 0 && len < MAX_LENGTH; j++, len++)
363 string[len] = current_value[j];
365 // add a quote if space
366 if(has_space && len < MAX_LENGTH) string[len++] = '\"';
369 if(len < MAX_LENGTH) string[len++] = right_delimiter; // terminating bracket
373 int XMLTag::read_tag(char *input, long &position, long length)
376 int i, j, terminating_char;
378 // search for beginning of a tag
379 while(input[position] != left_delimiter && position < length) position++;
381 if(position >= length) return 1;
384 while(position < length &&
385 (input[position] == ' ' || // skip spaces
386 input[position] == '\n' || // also skip new lines
387 input[position] == left_delimiter)) // skip <
390 if(position >= length) return 1;
392 tag_start = position;
398 input[position] != '=' &&
399 input[position] != ' ' && // space ends title
400 input[position] != right_delimiter;
403 tag_title[i] = input[position];
407 if(position >= length) return 1;
409 if(input[position] == '=')
411 // no title but first property
413 position = tag_start; // rewind
418 i < MAX_PROPERTIES &&
420 input[position] != right_delimiter;
425 while(position < length &&
426 (input[position] == ' ' || // skip spaces
427 input[position] == '\n' || // also skip new lines
428 input[position] == left_delimiter)) // skip <
431 // read the property description
435 input[position] != right_delimiter &&
436 input[position] != ' ' &&
437 input[position] != '\n' && // also new line ends it
438 input[position] != '=';
441 string[j] = input[position];
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 =
457 // find the terminating char
458 if(position < length && input[position] == '\"')
460 terminating_char = '\"'; // use quotes to terminate
461 if(position < length) position++; // don't store the quote itself
463 else terminating_char = ' '; // use space to terminate
465 // read until the terminating char
469 input[position] != right_delimiter &&
470 input[position] != terminating_char;
473 string[j] = input[position];
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);
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++;
489 if(position < length && input[position] == right_delimiter) position++;
491 if(total_properties || tag_title[0]) return 0; else return 1;
495 int XMLTag::title_is(char *title)
497 if(!strcasecmp(title, tag_title)) return 1;
501 char* XMLTag::get_title()
506 int XMLTag::get_title(char *value)
508 if(tag_title[0] != 0) strcpy(value, tag_title);
512 int XMLTag::test_property(char *property, char *value)
515 for(i = 0, result = 0; i < total_properties && !result; i++)
517 if(!strcasecmp(tag_properties[i], property) && !strcasecmp(value, tag_property_values[i]))
525 char* XMLTag::get_property(char *property, char *value)
528 for(i = 0, result = 0; i < total_properties && !result; i++)
530 if(!strcasecmp(tag_properties[i], property))
532 strcpy(value, tag_property_values[i]);
539 char* XMLTag::get_property_text(int number)
541 if(number < total_properties)
542 return tag_properties[number];
547 int XMLTag::get_property_int(int number)
549 if(number < total_properties)
550 return atol(tag_properties[number]);
555 float XMLTag::get_property_float(int number)
557 if(number < total_properties)
558 return atof(tag_properties[number]);
563 char* XMLTag::get_property(char *property)
566 for(i = 0, result = 0; i < total_properties && !result; i++)
568 if(!strcasecmp(tag_properties[i], property))
570 return tag_property_values[i];
577 int32_t XMLTag::get_property(char *property, int32_t default_)
580 get_property(property, temp_string);
581 if(temp_string[0] == 0)
584 return atol(temp_string);
587 int64_t XMLTag::get_property(char *property, int64_t default_)
591 get_property(property, temp_string);
592 if(temp_string[0] == 0)
596 sscanf(temp_string, "%lld", &result);
601 // int XMLTag::get_property(char *property, int default_)
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);
609 float XMLTag::get_property(char *property, float default_)
612 get_property(property, temp_string);
613 if(temp_string[0] == 0)
616 return atof(temp_string);
619 double XMLTag::get_property(char *property, double default_)
622 get_property(property, temp_string);
623 if(temp_string[0] == 0)
626 return atof(temp_string);
629 int XMLTag::set_title(char *text) // set the title field
631 strcpy(tag_title, text);
635 int XMLTag::set_property(char *text, int32_t value)
637 sprintf(temp_string, "%ld", value);
638 set_property(text, temp_string);
642 int XMLTag::set_property(char *text, int64_t value)
644 sprintf(temp_string, "%lld", value);
645 set_property(text, temp_string);
649 // int XMLTag::set_property(char *text, int value)
651 // sprintf(temp_string, "%d", value);
652 // set_property(text, temp_string);
656 int XMLTag::set_property(char *text, float value)
658 sprintf(temp_string, "%.6e", value);
659 set_property(text, temp_string);
663 int XMLTag::set_property(char *text, double value)
665 sprintf(temp_string, "%.16e", value);
666 set_property(text, temp_string);
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);