00001 #include <ctype.h>
00002 #include <errno.h>
00003 #include <stdio.h>
00004 #include <stdlib.h>
00005 #include <string.h>
00006
00007 #include "bcsignals.h"
00008 #include "filexml.h"
00009 #include "mainerror.h"
00010
00011
00012
00013
00014
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
00094
00095
00096
00097
00098 char leftb[] = "<";
00099 char rightb[] = ">";
00100 char 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
00145
00146
00147 for(; position < length && string[position] != left_delimiter; position++)
00148 {
00149 ;
00150 }
00151
00152
00153 if(output_length) delete [] output;
00154 output_length = position - text_position;
00155 output = new char[output_length + 1];
00156
00157
00158 for(i = 0; text_position < position; text_position++)
00159 {
00160
00161 if((i > 0 && i < output_length - 1) || string[text_position] != '\n')
00162 {
00163
00164
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
00202 while(position < length && string[position] != left_delimiter)
00203 {
00204 position++;
00205 }
00206 tag.reset_tag();
00207 if(position >= length) return 1;
00208
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
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
00224 output[out_position++] = string[position++];
00225 }
00226
00227 if(position < length && string[position] == left_delimiter)
00228 {
00229
00230
00231 result = 1;
00232
00233 for(test_position1 = 0, test_position2 = position + 1;
00234 test_position2 < length &&
00235 tag_end[test_position1] != 0 &&
00236 result;
00237 test_position1++, test_position2++)
00238 {
00239
00240
00241 if(tag_end[test_position1] != string[test_position2]) result = 0;
00242 }
00243
00244
00245 if(!result)
00246 {
00247 output[out_position++] = string[position++];
00248 }
00249 }
00250 }
00251 output[out_position] = 0;
00252
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
00265 if(!fwrite(string, strlen(string), 1, out) && strlen(string))
00266 {
00267 eprintf("Error while writing to \"%s\": %m\n",
00268 filename);
00269 fclose(out);
00270 return 1;
00271 }
00272 else
00273 {
00274 }
00275 }
00276 else
00277 {
00278 eprintf("Error while opening \"%s\" for writing. \n%m\n", filename);
00279 return 1;
00280 }
00281 fclose(out);
00282 return 0;
00283 }
00284
00285 int FileXML::write_to_file(FILE *file)
00286 {
00287 strcpy(filename, "");
00288 fprintf(file, "<?xml version=\"1.0\"?>\n");
00289
00290 if(fwrite(string, strlen(string), 1, file) || !strlen(string))
00291 {
00292 return 0;
00293 }
00294 else
00295 {
00296 eprintf("Error while writing to \"%s\": %m\n",
00297 filename);
00298 return 1;
00299 }
00300 return 0;
00301 }
00302
00303 int FileXML::read_from_file(char *filename, int ignore_error)
00304 {
00305 FILE *in;
00306
00307 strcpy(this->filename, filename);
00308 if(in = fopen(filename, "rb"))
00309 {
00310 fseek(in, 0, SEEK_END);
00311 int new_length = ftell(in);
00312 fseek(in, 0, SEEK_SET);
00313 reallocate_string(new_length + 1);
00314 fread(string, new_length, 1, in);
00315 string[new_length] = 0;
00316 position = 0;
00317 length = new_length;
00318 }
00319 else
00320 {
00321 if(!ignore_error)
00322 eprintf("Error while opening \"%s\" for reading. \n%m\n", filename);
00323 return 1;
00324 }
00325 fclose(in);
00326 return 0;
00327 }
00328
00329 int FileXML::read_from_string(char *string)
00330 {
00331 strcpy(this->filename, "");
00332 reallocate_string(strlen(string) + 1);
00333 strcpy(this->string, string);
00334 length = strlen(string);
00335 position = 0;
00336 return 0;
00337 }
00338
00339 int FileXML::set_shared_string(char *shared_string, long available)
00340 {
00341 strcpy(this->filename, "");
00342 if(!share_string)
00343 {
00344 delete [] string;
00345 share_string = 1;
00346 string = shared_string;
00347 this->available = available;
00348 length = available;
00349 position = 0;
00350 }
00351 return 0;
00352 }
00353
00354
00355
00356
00357
00358
00359 XMLTag::XMLTag()
00360 {
00361 total_properties = 0;
00362 len = 0;
00363 }
00364
00365 XMLTag::~XMLTag()
00366 {
00367 reset_tag();
00368 }
00369
00370 int XMLTag::set_delimiters(char left_delimiter, char right_delimiter)
00371 {
00372 this->left_delimiter = left_delimiter;
00373 this->right_delimiter = right_delimiter;
00374 return 0;
00375 }
00376
00377 int XMLTag::reset_tag()
00378 {
00379 len = 0;
00380 for(int i = 0; i < total_properties; i++) delete [] tag_properties[i];
00381 for(int i = 0; i < total_properties; i++) delete [] tag_property_values[i];
00382 total_properties = 0;
00383 return 0;
00384 }
00385
00386 int XMLTag::write_tag()
00387 {
00388 int i, j;
00389 char *current_property, *current_value;
00390
00391
00392 string[len] = left_delimiter;
00393 len++;
00394
00395
00396 for(i = 0; tag_title[i] != 0 && len < MAX_LENGTH; i++, len++) string[len] = tag_title[i];
00397
00398
00399 for(i = 0; i < total_properties && len < MAX_LENGTH; i++)
00400 {
00401 string[len++] = ' ';
00402
00403 current_property = tag_properties[i];
00404
00405
00406 for(j = 0; current_property[j] != 0 && len < MAX_LENGTH; j++, len++)
00407 {
00408 string[len] = current_property[j];
00409 }
00410
00411 if(len < MAX_LENGTH) string[len++] = '=';
00412
00413 current_value = tag_property_values[i];
00414
00415
00416 if( len < MAX_LENGTH) string[len++] = '\"';
00417
00418 for(j = 0; current_value[j] != 0 && len < MAX_LENGTH; j++, len++)
00419 {
00420 string[len] = current_value[j];
00421 }
00422 if(len < MAX_LENGTH) string[len++] = '\"';
00423 }
00424
00425 if(len < MAX_LENGTH) string[len++] = right_delimiter;
00426 return 0;
00427 }
00428
00429 int XMLTag::read_tag(char *input, long &position, long length)
00430 {
00431 long tag_start;
00432 int i, j, terminating_char;
00433
00434
00435 while(input[position] != left_delimiter && position < length) position++;
00436
00437 if(position >= length) return 1;
00438
00439
00440 while(position < length &&
00441 (input[position] == ' ' ||
00442 input[position] == '\n' ||
00443 input[position] == left_delimiter))
00444 position++;
00445
00446 if(position >= length) return 1;
00447
00448 tag_start = position;
00449
00450
00451 for(i = 0;
00452 i < MAX_TITLE &&
00453 position < length &&
00454 input[position] != '=' &&
00455 input[position] != ' ' &&
00456 input[position] != right_delimiter;
00457 position++, i++)
00458 {
00459 tag_title[i] = input[position];
00460 }
00461 tag_title[i] = 0;
00462
00463 if(position >= length) return 1;
00464
00465 if(input[position] == '=')
00466 {
00467
00468 tag_title[0] = 0;
00469 position = tag_start;
00470 }
00471
00472
00473 for(i = 0;
00474 i < MAX_PROPERTIES &&
00475 position < length &&
00476 input[position] != right_delimiter;
00477 i++)
00478 {
00479
00480
00481 while(position < length &&
00482 (input[position] == ' ' ||
00483 input[position] == '\n' ||
00484 input[position] == left_delimiter))
00485 position++;
00486
00487
00488 for(j = 0;
00489 j < MAX_LENGTH &&
00490 position < length &&
00491 input[position] != right_delimiter &&
00492 input[position] != ' ' &&
00493 input[position] != '\n' &&
00494 input[position] != '=';
00495 j++, position++)
00496 {
00497 string[j] = input[position];
00498 }
00499 string[j] = 0;
00500
00501
00502
00503 tag_properties[total_properties] = new char[strlen(string) + 1];
00504 strcpy(tag_properties[total_properties], string);
00505
00506
00507 while(position < length &&
00508 (input[position] == ' ' ||
00509 input[position] == '\n' ||
00510 input[position] == '='))
00511 position++;
00512
00513
00514 if(position < length && input[position] == '\"')
00515 {
00516 terminating_char = '\"';
00517 if(position < length) position++;
00518 }
00519 else
00520 terminating_char = ' ';
00521
00522
00523 for(j = 0;
00524 j < MAX_LENGTH &&
00525 position < length &&
00526 input[position] != right_delimiter &&
00527 input[position] != '\n' &&
00528 input[position] != terminating_char;
00529 j++, position++)
00530 {
00531 string[j] = input[position];
00532 }
00533 string[j] = 0;
00534
00535
00536 tag_property_values[total_properties] = new char[strlen(string) + 1];
00537 strcpy(tag_property_values[total_properties], string);
00538
00539
00540 if(tag_properties[total_properties][0] != 0) total_properties++;
00541
00542
00543 if(position < length && input[position] != right_delimiter) position++;
00544 }
00545
00546
00547 if(position < length && input[position] == right_delimiter) position++;
00548
00549 if(total_properties || tag_title[0])
00550 return 0;
00551 else
00552 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
00594 int j = 0, k = 0;
00595 char *tv = tag_property_values[i];
00596 while (j < strlen(tag_property_values[i])) {
00597 if (!strncmp(tv + j,""",6)) {
00598 value[k++] = '\"';
00599 j += 6;
00600 } else {
00601 value[k++] = tv[j++];
00602 }
00603 }
00604 value[k] = 0;
00605 result = 1;
00606 }
00607 }
00608 return value;
00609 }
00610
00611 char* XMLTag::get_property_text(int number)
00612 {
00613 if(number < total_properties)
00614 return tag_properties[number];
00615 else
00616 return "";
00617 }
00618
00619 int XMLTag::get_property_int(int number)
00620 {
00621 if(number < total_properties)
00622 return atol(tag_properties[number]);
00623 else
00624 return 0;
00625 }
00626
00627 float XMLTag::get_property_float(int number)
00628 {
00629 if(number < total_properties)
00630 return atof(tag_properties[number]);
00631 else
00632 return 0;
00633 }
00634
00635 char* XMLTag::get_property(char *property)
00636 {
00637 int i, result;
00638 for(i = 0, result = 0; i < total_properties && !result; i++)
00639 {
00640 if(!strcasecmp(tag_properties[i], property))
00641 {
00642 return tag_property_values[i];
00643 }
00644 }
00645 return 0;
00646 }
00647
00648
00649 int32_t XMLTag::get_property(char *property, int32_t default_)
00650 {
00651 temp_string[0] = 0;
00652 get_property(property, temp_string);
00653 if(temp_string[0] == 0)
00654 return default_;
00655 else
00656 return atol(temp_string);
00657 }
00658
00659 int64_t XMLTag::get_property(char *property, int64_t default_)
00660 {
00661 int64_t result;
00662 temp_string[0] = 0;
00663 get_property(property, temp_string);
00664 if(temp_string[0] == 0)
00665 result = default_;
00666 else
00667 {
00668 sscanf(temp_string, "%lld", &result);
00669 }
00670 return result;
00671 }
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681 float XMLTag::get_property(char *property, float default_)
00682 {
00683 temp_string[0] = 0;
00684 get_property(property, temp_string);
00685 if(temp_string[0] == 0)
00686 return default_;
00687 else
00688 return atof(temp_string);
00689 }
00690
00691 double XMLTag::get_property(char *property, double default_)
00692 {
00693 temp_string[0] = 0;
00694 get_property(property, temp_string);
00695 if(temp_string[0] == 0)
00696 return default_;
00697 else
00698 return atof(temp_string);
00699 }
00700
00701 int XMLTag::set_title(char *text)
00702 {
00703 strcpy(tag_title, text);
00704 return 0;
00705 }
00706
00707 int XMLTag::set_property(char *text, int32_t value)
00708 {
00709 sprintf(temp_string, "%ld", value);
00710 set_property(text, temp_string);
00711 return 0;
00712 }
00713
00714 int XMLTag::set_property(char *text, int64_t value)
00715 {
00716 sprintf(temp_string, "%lld", value);
00717 set_property(text, temp_string);
00718 return 0;
00719 }
00720
00721 int XMLTag::set_property(char *text, float value)
00722 {
00723 if (value - (float)((int64_t)value) == 0)
00724 sprintf(temp_string, "%lld", (int64_t)value);
00725 else
00726 sprintf(temp_string, "%.6e", value);
00727 set_property(text, temp_string);
00728 return 0;
00729 }
00730
00731 int XMLTag::set_property(char *text, double value)
00732 {
00733 if (value - (double)((int64_t)value) == 0)
00734 sprintf(temp_string, "%lld", (int64_t)value);
00735 else
00736 sprintf(temp_string, "%.16e", value);
00737 set_property(text, temp_string);
00738 return 0;
00739 }
00740
00741 int XMLTag::set_property(char *text, char *value)
00742 {
00743 tag_properties[total_properties] = new char[strlen(text) + 1];
00744 strcpy(tag_properties[total_properties], text);
00745
00746
00747 int qcount = 0;
00748 for (int i = strlen(value)-1; i >= 0; i--)
00749 if (value[i] == '"')
00750 qcount++;
00751
00752
00753 tag_property_values[total_properties] = new char[strlen(value) + qcount*5 + 1];
00754 int j = 0;
00755 for (int i = 0; i < strlen(value); i++) {
00756 switch (value[i]){
00757 case '"':
00758 tag_property_values[total_properties][j] = 0;
00759 strcat(tag_property_values[total_properties],""");
00760 j += 6;
00761 break;
00762 default:
00763 tag_property_values[total_properties][j++] = value[i];
00764 }
00765 }
00766 tag_property_values[total_properties][j] = 0;
00767
00768 total_properties++;
00769 return 0;
00770 }