12 // Precision in base 10
13 // for float is 6 significant figures
14 // for double is 16 significant figures
18 FileXML::FileXML(char left_delimiter, char right_delimiter)
20 tag.set_delimiters(left_delimiter, right_delimiter);
21 this->left_delimiter = left_delimiter;
22 this->right_delimiter = right_delimiter;
24 string = new char[available];
26 position = length = 0;
33 if(!share_string) delete [] string;
34 if(output_length) delete [] output;
39 printf("FileXML::dump:\n%s\n", string);
42 int FileXML::terminate_string()
51 length = strlen(string);
57 int FileXML::append_newline()
63 int FileXML::append_tag()
66 append_text(tag.string, tag.len);
71 int FileXML::append_text(char *text)
73 append_text(text, strlen(text));
77 int FileXML::serialize_and_append_text(char *text)
79 // We have to encode at least the '<' char
80 // We encode three things:
84 char leftb[] = "<";
85 char rightb[] = ">";
88 int len = strlen(text);
90 for (int i = 0; i < len; i++)
93 case '<': replacement = leftb; break;
94 case '>': replacement = rightb; break;
95 case '&': replacement = amp; break;
96 default: replacement = 0; break;
101 append_text(text + lastpos, i - lastpos);
102 append_text(replacement, strlen(replacement));
106 append_text(text + lastpos, len - lastpos);
110 int FileXML::append_text(char *text, long len)
112 while(position + len > available)
114 reallocate_string(available * 2);
117 for(int i = 0; i < len; i++, position++)
119 string[position] = text[i];
124 int FileXML::reallocate_string(long new_available)
128 char *new_string = new char[new_available];
129 for(int i = 0; i < position; i++) new_string[i] = string[i];
130 available = new_available;
137 char* FileXML::read_text()
139 long text_position = position;
142 // use < to mark end of text and start of tag
145 for(; position < length && string[position] != left_delimiter; position++)
150 // allocate enough space
151 if(output_length) delete [] output;
152 output_length = position - text_position;
153 output = new char[output_length + 1];
155 //printf("FileXML::read_text %d %c\n", text_position, string[text_position]);
156 for(i = 0; text_position < position; text_position++)
158 // filter out first newline
159 if((i > 0 && i < output_length - 1) || string[text_position] != '\n')
161 // check if we have to do deserializing
162 // but try to be most backward compatible possible
163 int character = string[text_position];
164 if (string[text_position] == '&')
166 if (text_position + 3 < length)
168 if (string[text_position + 1] == 'l' && string[text_position + 2] == 't' && string[text_position + 3] == ';')
173 if (string[text_position + 1] == 'g' && string[text_position + 2] == 't' && string[text_position + 3] == ';')
179 if (text_position + 4 < length)
181 if (string[text_position + 1] == 'a' && string[text_position + 2] == 'm' && string[text_position + 3] == 'p' && string[text_position + 4] == ';')
188 output[i] = character;
197 int FileXML::read_tag()
200 while(position < length && string[position] != left_delimiter)
205 if(position >= length) return 1;
206 //printf("FileXML::read_tag %s\n", &string[position]);
207 return tag.read_tag(string, position, length);
210 int FileXML::read_text_until(char *tag_end, char *output)
213 int out_position = 0;
214 int test_position1, test_position2;
217 while(!result && position < length)
219 while(position < length && string[position] != left_delimiter)
221 //printf("FileXML::read_text_until 1 %c\n", string[position]);
222 output[out_position++] = string[position++];
225 if(position < length && string[position] == left_delimiter)
229 result = 1; // assume end
231 for(test_position1 = 0, test_position2 = position + 1; // skip <
232 test_position2 < length &&
233 tag_end[test_position1] != 0 &&
235 test_position1++, test_position2++)
237 // null result when first wrong character is reached
238 //printf("FileXML::read_text_until 2 %c\n", string[test_position2]);
239 if(tag_end[test_position1] != string[test_position2]) result = 0;
242 // no end tag reached to copy <
245 output[out_position++] = string[position++];
249 output[out_position] = 0;
250 // if end tag is reached, position is left on the < of the end tag
255 int FileXML::write_to_file(char *filename)
258 strcpy(this->filename, filename);
259 if(out = fopen(filename, "wb"))
261 fprintf(out, "<?xml version=\"1.0\"?>\n");
262 // Position may have been rewound after storing so we use a strlen
263 if(!fwrite(string, strlen(string), 1, out) && strlen(string))
265 fprintf(stderr, "FileXML::write_to_file 1 \"%s\": %s\n",
277 fprintf(stderr, "FileXML::write_to_file 2 \"%s\": %s\n",
286 int FileXML::write_to_file(FILE *file)
288 strcpy(filename, "");
289 fprintf(file, "<?xml version=\"1.0\"?>\n");
290 // Position may have been rewound after storing
291 if(fwrite(string, strlen(string), 1, file) || !strlen(string))
297 fprintf(stderr, "FileXML::write_to_file \"%s\": %s\n",
305 int FileXML::read_from_file(char *filename, int ignore_error)
309 strcpy(this->filename, filename);
310 if(in = fopen(filename, "rb"))
312 fseek(in, 0, SEEK_END);
314 fseek(in, 0, SEEK_SET);
315 reallocate_string(length + 1);
316 fread(string, length, 1, in);
323 fprintf(stderr, "FileXML::read_from_file \"%s\" %s\n",
332 int FileXML::read_from_string(char *string)
334 strcpy(this->filename, "");
335 reallocate_string(strlen(string) + 1);
336 strcpy(this->string, string);
337 length = strlen(string);
342 int FileXML::set_shared_string(char *shared_string, long available)
344 strcpy(this->filename, "");
349 string = shared_string;
350 this->available = available;
359 // ================================ XML tag
364 total_properties = 0;
373 int XMLTag::set_delimiters(char left_delimiter, char right_delimiter)
375 this->left_delimiter = left_delimiter;
376 this->right_delimiter = right_delimiter;
380 int XMLTag::reset_tag() // clear all structures
383 for(int i = 0; i < total_properties; i++) delete [] tag_properties[i];
384 for(int i = 0; i < total_properties; i++) delete [] tag_property_values[i];
385 total_properties = 0;
389 int XMLTag::write_tag()
392 char *current_property, *current_value;
395 string[len] = left_delimiter;
399 for(i = 0; tag_title[i] != 0 && len < MAX_LENGTH; i++, len++) string[len] = tag_title[i];
402 for(i = 0; i < total_properties && len < MAX_LENGTH; i++)
404 string[len++] = ' '; // add a space before every property
406 current_property = tag_properties[i];
409 for(j = 0; current_property[j] != 0 && len < MAX_LENGTH; j++, len++)
411 string[len] = current_property[j];
414 if(len < MAX_LENGTH) string[len++] = '=';
416 current_value = tag_property_values[i];
419 if( len < MAX_LENGTH) string[len++] = '\"';
421 for(j = 0; current_value[j] != 0 && len < MAX_LENGTH; j++, len++)
423 string[len] = current_value[j];
425 if(len < MAX_LENGTH) string[len++] = '\"';
428 if(len < MAX_LENGTH) string[len++] = right_delimiter; // terminating bracket
432 int XMLTag::read_tag(char *input, long &position, long length)
435 int i, j, terminating_char;
437 // search for beginning of a tag
438 while(input[position] != left_delimiter && position < length) position++;
440 if(position >= length) return 1;
443 while(position < length &&
444 (input[position] == ' ' || // skip spaces
445 input[position] == '\n' || // also skip new lines
446 input[position] == left_delimiter)) // skip <
449 if(position >= length) return 1;
451 tag_start = position;
457 input[position] != '=' &&
458 input[position] != ' ' && // space ends title
459 input[position] != right_delimiter;
462 tag_title[i] = input[position];
466 if(position >= length) return 1;
468 if(input[position] == '=')
470 // no title but first property
472 position = tag_start; // rewind
477 i < MAX_PROPERTIES &&
479 input[position] != right_delimiter;
484 while(position < length &&
485 (input[position] == ' ' || // skip spaces
486 input[position] == '\n' || // also skip new lines
487 input[position] == left_delimiter)) // skip <
490 // read the property description
494 input[position] != right_delimiter &&
495 input[position] != ' ' &&
496 input[position] != '\n' && // also new line ends it
497 input[position] != '=';
500 string[j] = input[position];
505 // store the description in a property array
506 tag_properties[total_properties] = new char[strlen(string) + 1];
507 strcpy(tag_properties[total_properties], string);
509 // find the start of the value
510 while(position < length &&
511 (input[position] == ' ' || // skip spaces
512 input[position] == '\n' || // also skip new lines
513 input[position] == '=')) // skip =
516 // find the terminating char
517 if(position < length && input[position] == '\"')
519 terminating_char = '\"'; // use quotes to terminate
520 if(position < length) position++; // don't store the quote itself
522 else terminating_char = ' '; // use space to terminate
524 // read until the terminating char
528 input[position] != right_delimiter &&
529 input[position] != terminating_char;
532 string[j] = input[position];
536 // store the value in a property array
537 tag_property_values[total_properties] = new char[strlen(string) + 1];
538 strcpy(tag_property_values[total_properties], string);
540 // advance property if one was just loaded
541 if(tag_properties[total_properties][0] != 0) total_properties++;
543 // get the terminating char
544 if(position < length && input[position] != right_delimiter) position++;
548 if(position < length && input[position] == right_delimiter) position++;
550 if(total_properties || tag_title[0]) return 0; else return 1;
554 int XMLTag::title_is(char *title)
556 if(!strcasecmp(title, tag_title)) return 1;
560 char* XMLTag::get_title()
565 int XMLTag::get_title(char *value)
567 if(tag_title[0] != 0) strcpy(value, tag_title);
571 int XMLTag::test_property(char *property, char *value)
574 for(i = 0, result = 0; i < total_properties && !result; i++)
576 if(!strcasecmp(tag_properties[i], property) && !strcasecmp(value, tag_property_values[i]))
584 char* XMLTag::get_property(char *property, char *value)
587 for(i = 0, result = 0; i < total_properties && !result; i++)
589 if(!strcasecmp(tag_properties[i], property))
591 strcpy(value, tag_property_values[i]);
598 char* XMLTag::get_property_text(int number)
600 if(number < total_properties)
601 return tag_properties[number];
606 int XMLTag::get_property_int(int number)
608 if(number < total_properties)
609 return atol(tag_properties[number]);
614 float XMLTag::get_property_float(int number)
616 if(number < total_properties)
617 return atof(tag_properties[number]);
622 char* XMLTag::get_property(char *property)
625 for(i = 0, result = 0; i < total_properties && !result; i++)
627 if(!strcasecmp(tag_properties[i], property))
629 return tag_property_values[i];
636 int32_t XMLTag::get_property(char *property, int32_t default_)
639 get_property(property, temp_string);
640 if(temp_string[0] == 0)
643 return atol(temp_string);
646 int64_t XMLTag::get_property(char *property, int64_t default_)
650 get_property(property, temp_string);
651 if(temp_string[0] == 0)
655 sscanf(temp_string, "%lld", &result);
660 // int XMLTag::get_property(char *property, int default_)
662 // temp_string[0] = 0;
663 // get_property(property, temp_string);
664 // if(temp_string[0] == 0) return default_;
665 // else return atol(temp_string);
668 float XMLTag::get_property(char *property, float default_)
671 get_property(property, temp_string);
672 if(temp_string[0] == 0)
675 return atof(temp_string);
678 double XMLTag::get_property(char *property, double default_)
681 get_property(property, temp_string);
682 if(temp_string[0] == 0)
685 return atof(temp_string);
688 int XMLTag::set_title(char *text) // set the title field
690 strcpy(tag_title, text);
694 int XMLTag::set_property(char *text, int32_t value)
696 sprintf(temp_string, "%ld", value);
697 set_property(text, temp_string);
701 int XMLTag::set_property(char *text, int64_t value)
703 sprintf(temp_string, "%lld", value);
704 set_property(text, temp_string);
708 // int XMLTag::set_property(char *text, int value)
710 // sprintf(temp_string, "%d", value);
711 // set_property(text, temp_string);
715 int XMLTag::set_property(char *text, float value)
717 sprintf(temp_string, "%.6e", value);
718 set_property(text, temp_string);
722 int XMLTag::set_property(char *text, double value)
724 sprintf(temp_string, "%.16e", value);
725 set_property(text, temp_string);
729 int XMLTag::set_property(char *text, char *value)
731 tag_properties[total_properties] = new char[strlen(text) + 1];
732 strcpy(tag_properties[total_properties], text);
733 tag_property_values[total_properties] = new char[strlen(value) + 1];
734 strcpy(tag_property_values[total_properties], value);