13 // Precision in base 10
14 // for float is 6 significant figures
15 // for double is 16 significant figures
19 FileXML::FileXML(char left_delimiter, char right_delimiter)
21 tag.set_delimiters(left_delimiter, right_delimiter);
22 this->left_delimiter = left_delimiter;
23 this->right_delimiter = right_delimiter;
25 string = new char[available];
27 position = length = 0;
34 if(!share_string) delete [] string;
35 if(output_length) delete [] output;
40 printf("FileXML::dump:\n%s\n", string);
43 int FileXML::terminate_string()
52 length = strlen(string);
58 int FileXML::append_newline()
64 int FileXML::append_tag()
67 append_text(tag.string, tag.len);
72 int FileXML::append_text(char *text)
74 append_text(text, strlen(text));
78 int FileXML::append_text(char *text, long len)
80 while(position + len > available)
82 reallocate_string(available * 2);
85 for(int i = 0; i < len; i++, position++)
87 string[position] = text[i];
92 int FileXML::encode_text(char *text)
94 // We have to encode at least the '<' char
95 // We encode three things:
99 char leftb[] = "<";
100 char rightb[] = ">";
101 char amp[] = "&";
103 int len = strlen(text);
105 for (int i = 0; i < len; i++)
108 case '<': replacement = leftb; break;
109 case '>': replacement = rightb; break;
110 case '&': replacement = amp; break;
111 default: replacement = 0; break;
116 append_text(text + lastpos, i - lastpos);
117 append_text(replacement, strlen(replacement));
121 append_text(text + lastpos, len - lastpos);
127 int FileXML::reallocate_string(long new_available)
131 char *new_string = new char[new_available];
132 for(int i = 0; i < position; i++) new_string[i] = string[i];
133 available = new_available;
140 char* FileXML::read_text()
142 long text_position = position;
145 // use < to mark end of text and start of tag
148 for(; position < length && string[position] != left_delimiter; position++)
153 // allocate enough space
154 if(output_length) delete [] output;
155 output_length = position - text_position;
156 output = new char[output_length + 1];
158 //printf("FileXML::read_text %d %c\n", text_position, string[text_position]);
159 for(i = 0; text_position < position; text_position++)
161 // filter out first newline
162 if((i > 0 && i < output_length - 1) || string[text_position] != '\n')
164 // check if we have to decode special characters
165 // but try to be most backward compatible possible
166 int character = string[text_position];
167 if (string[text_position] == '&')
169 if (text_position + 3 < length)
171 if (string[text_position + 1] == 'l' && string[text_position + 2] == 't' && string[text_position + 3] == ';')
176 if (string[text_position + 1] == 'g' && string[text_position + 2] == 't' && string[text_position + 3] == ';')
182 if (text_position + 4 < length)
184 if (string[text_position + 1] == 'a' && string[text_position + 2] == 'm' && string[text_position + 3] == 'p' && string[text_position + 4] == ';')
191 output[i] = character;
200 int FileXML::read_tag()
203 while(position < length && string[position] != left_delimiter)
208 if(position >= length) return 1;
209 //printf("FileXML::read_tag %s\n", &string[position]);
210 return tag.read_tag(string, position, length);
213 int FileXML::read_text_until(char *tag_end, char *output, int max_len)
216 int out_position = 0;
217 int test_position1, test_position2;
220 while(!result && position < length && out_position < max_len - 1)
222 while(position < length && string[position] != left_delimiter)
224 //printf("FileXML::read_text_until 1 %c\n", string[position]);
225 output[out_position++] = string[position++];
228 if(position < length && string[position] == left_delimiter)
232 result = 1; // assume end
234 for(test_position1 = 0, test_position2 = position + 1; // skip <
235 test_position2 < length &&
236 tag_end[test_position1] != 0 &&
238 test_position1++, test_position2++)
240 // null result when first wrong character is reached
241 //printf("FileXML::read_text_until 2 %c\n", string[test_position2]);
242 if(tag_end[test_position1] != string[test_position2]) result = 0;
245 // no end tag reached to copy <
248 output[out_position++] = string[position++];
252 output[out_position] = 0;
253 // if end tag is reached, position is left on the < of the end tag
258 int FileXML::write_to_file(char *filename)
261 strcpy(this->filename, filename);
262 if(out = fopen(filename, "wb"))
264 fprintf(out, "<?xml version=\"1.0\"?>\n");
265 // Position may have been rewound after storing so we use a strlen
266 if(!fwrite(string, strlen(string), 1, out) && strlen(string))
268 fprintf(stderr, "FileXML::write_to_file 1 \"%s\": %s\n",
280 fprintf(stderr, "FileXML::write_to_file 2 \"%s\": %s\n",
289 int FileXML::write_to_file(FILE *file)
291 strcpy(filename, "");
292 fprintf(file, "<?xml version=\"1.0\"?>\n");
293 // Position may have been rewound after storing
294 if(fwrite(string, strlen(string), 1, file) || !strlen(string))
300 fprintf(stderr, "FileXML::write_to_file \"%s\": %s\n",
308 int FileXML::read_from_file(char *filename, int ignore_error)
312 strcpy(this->filename, filename);
313 if(in = fopen(filename, "rb"))
315 fseek(in, 0, SEEK_END);
316 int new_length = ftell(in);
317 fseek(in, 0, SEEK_SET);
318 reallocate_string(new_length + 1);
319 fread(string, new_length, 1, in);
320 string[new_length] = 0;
327 fprintf(stderr, "FileXML::read_from_file \"%s\" %s\n",
336 int FileXML::read_from_string(char *string)
338 strcpy(this->filename, "");
339 reallocate_string(strlen(string) + 1);
340 strcpy(this->string, string);
341 length = strlen(string);
346 int FileXML::set_shared_string(char *shared_string, long available)
348 strcpy(this->filename, "");
353 string = shared_string;
354 this->available = available;
363 // ================================ XML tag
368 total_properties = 0;
377 int XMLTag::set_delimiters(char left_delimiter, char right_delimiter)
379 this->left_delimiter = left_delimiter;
380 this->right_delimiter = right_delimiter;
384 int XMLTag::reset_tag() // clear all structures
387 for(int i = 0; i < total_properties; i++) delete [] tag_properties[i];
388 for(int i = 0; i < total_properties; i++) delete [] tag_property_values[i];
389 total_properties = 0;
393 int XMLTag::write_tag()
396 char *current_property, *current_value;
399 string[len] = left_delimiter;
403 for(i = 0; tag_title[i] != 0 && len < MAX_LENGTH; i++, len++) string[len] = tag_title[i];
406 for(i = 0; i < total_properties && len < MAX_LENGTH; i++)
408 string[len++] = ' '; // add a space before every property
410 current_property = tag_properties[i];
413 for(j = 0; current_property[j] != 0 && len < MAX_LENGTH; j++, len++)
415 string[len] = current_property[j];
418 if(len < MAX_LENGTH) string[len++] = '=';
420 current_value = tag_property_values[i];
423 if( len < MAX_LENGTH) string[len++] = '\"';
425 for(j = 0; current_value[j] != 0 && len < MAX_LENGTH; j++, len++)
427 string[len] = current_value[j];
429 if(len < MAX_LENGTH) string[len++] = '\"';
432 if(len < MAX_LENGTH) string[len++] = right_delimiter; // terminating bracket
436 int XMLTag::read_tag(char *input, long &position, long length)
439 int i, j, terminating_char;
441 // search for beginning of a tag
442 while(input[position] != left_delimiter && position < length) position++;
444 if(position >= length) return 1;
447 while(position < length &&
448 (input[position] == ' ' || // skip spaces
449 input[position] == '\n' || // also skip new lines
450 input[position] == left_delimiter)) // skip <
453 if(position >= length) return 1;
455 tag_start = position;
461 input[position] != '=' &&
462 input[position] != ' ' && // space ends title
463 input[position] != right_delimiter;
466 tag_title[i] = input[position];
470 if(position >= length) return 1;
472 if(input[position] == '=')
474 // no title but first property
476 position = tag_start; // rewind
481 i < MAX_PROPERTIES &&
483 input[position] != right_delimiter;
488 while(position < length &&
489 (input[position] == ' ' || // skip spaces
490 input[position] == '\n' || // also skip new lines
491 input[position] == left_delimiter)) // skip <
494 // read the property description
498 input[position] != right_delimiter &&
499 input[position] != ' ' &&
500 input[position] != '\n' && // also new line ends it
501 input[position] != '=';
504 string[j] = input[position];
509 // store the description in a property array
510 tag_properties[total_properties] = new char[strlen(string) + 1];
511 strcpy(tag_properties[total_properties], string);
513 // find the start of the value
514 while(position < length &&
515 (input[position] == ' ' || // skip spaces
516 input[position] == '\n' || // also skip new lines
517 input[position] == '=')) // skip =
520 // find the terminating char
521 if(position < length && input[position] == '\"')
523 terminating_char = '\"'; // use quotes to terminate
524 if(position < length) position++; // don't store the quote itself
527 terminating_char = ' '; // use space to terminate
529 // read until the terminating char
533 input[position] != right_delimiter &&
534 input[position] != '\n' &&
535 input[position] != terminating_char;
538 string[j] = input[position];
542 // store the value in a property array
543 tag_property_values[total_properties] = new char[strlen(string) + 1];
544 strcpy(tag_property_values[total_properties], string);
546 // advance property if one was just loaded
547 if(tag_properties[total_properties][0] != 0) total_properties++;
549 // get the terminating char
550 if(position < length && input[position] != right_delimiter) position++;
554 if(position < length && input[position] == right_delimiter) position++;
556 if(total_properties || tag_title[0])
563 int XMLTag::title_is(char *title)
565 if(!strcasecmp(title, tag_title)) return 1;
569 char* XMLTag::get_title()
574 int XMLTag::get_title(char *value)
576 if(tag_title[0] != 0) strcpy(value, tag_title);
580 int XMLTag::test_property(char *property, char *value)
583 for(i = 0, result = 0; i < total_properties && !result; i++)
585 if(!strcasecmp(tag_properties[i], property) && !strcasecmp(value, tag_property_values[i]))
593 char* XMLTag::get_property(char *property, char *value)
596 for(i = 0, result = 0; i < total_properties && !result; i++)
598 if(!strcasecmp(tag_properties[i], property))
600 //printf("XMLTag::get_property %s %s\n", tag_properties[i], tag_property_values[i]);
602 char *tv = tag_property_values[i];
603 while (j < strlen(tag_property_values[i])) {
604 if (!strncmp(tv + j,""",6)) {
608 value[k++] = tv[j++];
618 char* XMLTag::get_property_text(int number)
620 if(number < total_properties)
621 return tag_properties[number];
626 int XMLTag::get_property_int(int number)
628 if(number < total_properties)
629 return atol(tag_properties[number]);
634 float XMLTag::get_property_float(int number)
636 if(number < total_properties)
637 return atof(tag_properties[number]);
642 char* XMLTag::get_property(char *property)
645 for(i = 0, result = 0; i < total_properties && !result; i++)
647 if(!strcasecmp(tag_properties[i], property))
649 return tag_property_values[i];
656 int32_t XMLTag::get_property(char *property, int32_t default_)
659 get_property(property, temp_string);
660 if(temp_string[0] == 0)
663 return atol(temp_string);
666 int64_t XMLTag::get_property(char *property, int64_t default_)
670 get_property(property, temp_string);
671 if(temp_string[0] == 0)
675 sscanf(temp_string, "%lld", &result);
680 // int XMLTag::get_property(char *property, int default_)
682 // temp_string[0] = 0;
683 // get_property(property, temp_string);
684 // if(temp_string[0] == 0) return default_;
685 // else return atol(temp_string);
688 float XMLTag::get_property(char *property, float default_)
691 get_property(property, temp_string);
692 if(temp_string[0] == 0)
695 return atof(temp_string);
698 double XMLTag::get_property(char *property, double default_)
701 get_property(property, temp_string);
702 if(temp_string[0] == 0)
705 return atof(temp_string);
708 int XMLTag::set_title(char *text) // set the title field
710 strcpy(tag_title, text);
714 int XMLTag::set_property(char *text, int32_t value)
716 sprintf(temp_string, "%ld", value);
717 set_property(text, temp_string);
721 int XMLTag::set_property(char *text, int64_t value)
723 sprintf(temp_string, "%lld", value);
724 set_property(text, temp_string);
728 int XMLTag::set_property(char *text, float value)
730 if (value - (float)((int64_t)value) == 0)
731 sprintf(temp_string, "%lld", (int64_t)value);
733 sprintf(temp_string, "%.6e", value);
734 set_property(text, temp_string);
738 int XMLTag::set_property(char *text, double value)
740 if (value - (double)((int64_t)value) == 0)
741 sprintf(temp_string, "%lld", (int64_t)value);
743 sprintf(temp_string, "%.16e", value);
744 set_property(text, temp_string);
748 int XMLTag::set_property(char *text, char *value)
750 tag_properties[total_properties] = new char[strlen(text) + 1];
751 strcpy(tag_properties[total_properties], text);
755 for (int i = strlen(value)-1; i >= 0; i--)
759 // Allocate space, and replace quotes with "
760 tag_property_values[total_properties] = new char[strlen(value) + qcount*5 + 1];
762 for (int i = 0; i < strlen(value); i++) {
765 tag_property_values[total_properties][j] = 0;
766 strcat(tag_property_values[total_properties],""");
770 tag_property_values[total_properties][j++] = value[i];
773 tag_property_values[total_properties][j] = 0;