Changeset 7309 in vbox
- Timestamp:
- Mar 5, 2008 5:47:51 PM (17 years ago)
- Location:
- trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/settings.h
r6310 r7309 125 125 if (level > 5) 126 126 { 127 // if so, create a "Bar" key if it doesn't exist yet 127 // if so, create a "Bar" key if it doesn't exist yet 128 128 Key bar = (*it).createKey ("Bar"); 129 129 // set the "date" attribute … … 265 265 ////////////////////////////////////////////////////////////////////////////// 266 266 267 /** 267 /** 268 268 * Temporary holder for the formatted string. 269 269 * … … 276 276 public: 277 277 278 /** 278 /** 279 279 * Creates a formatted string using the format string and a set of 280 280 * printf-like arguments. … … 309 309 public: 310 310 311 Error (const char *aMsg = NULL) 311 Error (const char *aMsg = NULL) 312 312 : m (aMsg ? Str::New (aMsg) : NULL) {} 313 313 … … 440 440 int aBits, uint64_t aMin, uint64_t aMax); 441 441 442 /** 442 /** 443 443 * Generic template function to perform a conversion of an UTF-8 string to an 444 444 * arbitrary value of type @a T. … … 458 458 * 459 459 * @param aValue Value to convert. 460 * 460 * 461 461 * @return Result of conversion. 462 462 */ … … 492 492 template<> DECLEXPORT (RTTIMESPEC) FromString <RTTIMESPEC> (const char *aValue); 493 493 494 /** 494 /** 495 495 * Converts a string of hex digits to memory bytes. 496 * 496 * 497 497 * @param aValue String to convert. 498 498 * @param aLen Where to store the length of the returned memory 499 499 * block (may be NULL). 500 * 500 * 501 501 * @return Result of conversion (a block of @a aLen bytes). 502 502 */ … … 513 513 bool aSigned, int aBits); 514 514 515 /** 515 /** 516 516 * Generic template function to perform a conversion of an arbitrary value to 517 517 * an UTF-8 string. … … 569 569 ToString <RTTIMESPEC> (const RTTIMESPEC &aValue, unsigned int aExtra); 570 570 571 /** 571 /** 572 572 * Converts memory bytes to a null-terminated string of hex values. 573 * 573 * 574 574 * @param aData Pointer to the memory block. 575 575 * @param aLen Length of the memory block. 576 * 576 * 577 577 * @return Result of conversion. 578 578 */ … … 582 582 ////////////////////////////////////////////////////////////////////////////// 583 583 584 /** 584 /** 585 585 * The Key class represents a settings key. 586 586 * … … 647 647 }; 648 648 649 /** 649 /** 650 650 * Creates a new key object. If @a aBackend is @c NULL then a null key is 651 651 * created. … … 653 653 * Regular API users should never need to call this method with something 654 654 * other than NULL argument (which is the default). 655 * 655 * 656 656 * @param aBackend Key backend to use. 657 657 */ 658 658 Key (Backend *aBackend = NULL) : m (aBackend) {} 659 659 660 /** 660 /** 661 661 * Returns @c true if this key is null. 662 662 */ 663 663 bool isNull() const { return m.is_null(); } 664 664 665 /** 665 /** 666 666 * Makes this object a null key. 667 667 * … … 671 671 void setNull() { m = NULL; } 672 672 673 /** 673 /** 674 674 * Returns the name of this key. 675 675 * Returns NULL if this object a null (uninitialized) key. … … 677 677 const char *name() const { return m.is_null() ? NULL : m->name(); } 678 678 679 /** 679 /** 680 680 * Sets the name of this key. 681 * 681 * 682 682 * @param aName New key name. 683 683 */ 684 684 void setName (const char *aName) { if (!m.is_null()) m->setName (aName); } 685 685 686 /** 686 /** 687 687 * Returns the value of the attribute with the given name as an UTF-8 688 688 * string. Returns @c NULL if there is no attribute with the given name. … … 696 696 } 697 697 698 /** 698 /** 699 699 * Sets the value of the attribute with the given name from an UTF-8 700 700 * string. This method will do a copy of the supplied @a aValue string. 701 * 701 * 702 702 * @param aName Name of the attribute. NULL may be used to 703 703 * set the key value. … … 710 710 } 711 711 712 /** 712 /** 713 713 * Returns the value of the attribute with the given name as an object of 714 714 * type @a T. Throws ENoValue if there is no attribute with the given … … 718 718 * the attribute and then calls the FromString() template to convert this 719 719 * string to a value of the given type. 720 * 720 * 721 721 * @param aName Name of the attribute. NULL may be used to 722 722 * get the key value. … … 735 735 } 736 736 737 /** 737 /** 738 738 * Returns the value of the attribute with the given name as an object of 739 739 * type @a T. Returns the given default value if there is no attribute … … 743 743 * the attribute and then calls the FromString() template to convert this 744 744 * string to a value of the given type. 745 * 745 * 746 746 * @param aName Name of the attribute. NULL may be used to 747 747 * get the key value. … … 761 761 } 762 762 763 /** 763 /** 764 764 * Sets the value of the attribute with the given name from an object of 765 765 * type @a T. This method will do a copy of data represented by @a aValue … … 768 768 * This function converts the given value to a string using the ToString() 769 769 * template and then calls #setStringValue(). 770 * 770 * 771 771 * @param aName Name of the attribute. NULL may be used to 772 772 * set the key value. … … 790 790 } 791 791 792 /** 792 /** 793 793 * Sets the value of the attribute with the given name from an object of 794 794 * type @a T. If the value of the @a aValue object equals to the value of … … 798 798 * This function converts the given value to a string using the ToString() 799 799 * template and then calls #setStringValue(). 800 * 800 * 801 801 * @param aName Name of the attribute. NULL may be used to 802 802 * set the key value. … … 817 817 } 818 818 819 /** 819 /** 820 820 * Deletes the value of the attribute with the given name. 821 821 * Shortcut to <tt>setStringValue(aName, NULL)</tt>. … … 823 823 void zapValue (const char *aName) { setStringValue (aName, NULL); } 824 824 825 /** 825 /** 826 826 * Returns the key value. 827 827 * Shortcut to <tt>stringValue (NULL)</tt>. … … 829 829 const char *keyStringValue() const { return stringValue (NULL); } 830 830 831 /** 831 /** 832 832 * Sets the key value. 833 833 * Shortcut to <tt>setStringValue (NULL, aValue)</tt>. … … 835 835 void setKeyStringValue (const char *aValue) { setStringValue (NULL, aValue); } 836 836 837 /** 837 /** 838 838 * Returns the key value. 839 839 * Shortcut to <tt>value (NULL)</tt>. … … 842 842 T keyValue() const { return value <T> (NULL); } 843 843 844 /** 844 /** 845 845 * Returns the key value or the given default if the key value is NULL. 846 846 * Shortcut to <tt>value (NULL)</tt>. … … 849 849 T keyValueOr (const T &aDefault) const { return valueOr <T> (NULL, aDefault); } 850 850 851 /** 851 /** 852 852 * Sets the key value. 853 853 * Shortcut to <tt>setValue (NULL, aValue, aExtra)</tt>. … … 859 859 } 860 860 861 /** 861 /** 862 862 * Sets the key value. 863 863 * Shortcut to <tt>setValueOr (NULL, aValue, aDefault)</tt>. … … 870 870 } 871 871 872 /** 872 /** 873 873 * Deletes the key value. 874 874 * Shortcut to <tt>zapValue (NULL)</tt>. … … 876 876 void zapKeyValue () { zapValue (NULL); } 877 877 878 /** 878 /** 879 879 * Returns a list of all child keys named @a aName. 880 880 * 881 881 * If @a aname is @c NULL, returns a list of all child keys. 882 * 882 * 883 883 * @param aName Child key name to list. 884 884 */ 885 885 List keys (const char *aName = NULL) const 886 886 { 887 return m.is_null() ? List() : m->keys (aName); 887 return m.is_null() ? List() : m->keys (aName); 888 888 }; 889 889 890 /** 890 /** 891 891 * Returns the first child key with the given name. 892 892 * 893 893 * Throws ENoKey if no child key with the given name exists. 894 * 894 * 895 895 * @param aName Child key name. 896 896 */ … … 903 903 } 904 904 905 /** 905 /** 906 906 * Returns the first child key with the given name. 907 907 * 908 908 * As opposed to #key(), this method will not throw an exception if no 909 909 * child key with the given name exists, but return a null key instead. 910 * 910 * 911 911 * @param aName Child key name. 912 912 */ 913 913 Key findKey (const char *aName) const 914 914 { 915 return m.is_null() ? Key() : m->findKey (aName); 916 } 917 918 /** 915 return m.is_null() ? Key() : m->findKey (aName); 916 } 917 918 /** 919 919 * Creates a key with the given name as a child of this key and returns it 920 920 * to the caller. … … 922 922 * If one or more child keys with the given name already exist, no new key 923 923 * is created but the first matching child key is returned. 924 * 924 * 925 925 * @param aName Name of the child key to create. 926 926 */ … … 933 933 } 934 934 935 /** 935 /** 936 936 * Appends a key with the given name to the list of child keys of this key 937 937 * and returns the appended key to the caller. 938 * 938 * 939 939 * @param aName Name of the child key to create. 940 940 */ 941 941 Key appendKey (const char *aName) 942 942 { 943 return m.is_null() ? Key() : m->appendKey (aName); 944 } 945 946 /** 943 return m.is_null() ? Key() : m->appendKey (aName); 944 } 945 946 /** 947 947 * Deletes this key. 948 948 * … … 973 973 } 974 974 975 /** 975 /** 976 976 * Counterpart to operator==(). 977 977 */ … … 985 985 }; 986 986 987 /** 987 /** 988 988 * The Stream class is a base class for I/O streams. 989 989 */ … … 1016 1016 }; 1017 1017 1018 /** 1018 /** 1019 1019 * The Input class represents an input stream. 1020 1020 * … … 1029 1029 /** 1030 1030 * Reads from the stream to the supplied buffer. 1031 * 1031 * 1032 1032 * @param aBuf Buffer to store read data to. 1033 1033 * @param aLen Buffer length. 1034 * 1034 * 1035 1035 * @return Number of bytes read. 1036 1036 */ … … 1047 1047 /** 1048 1048 * Writes to the stream from the supplied buffer. 1049 * 1049 * 1050 1050 * @param aBuf Buffer to write data from. 1051 1051 * @param aLen Buffer length. 1052 * 1052 * 1053 1053 * @return Number of bytes written. 1054 1054 */ 1055 1055 virtual int write (const char *aBuf, int aLen) = 0; 1056 1056 1057 /** 1057 /** 1058 1058 * Truncates the stream from the current position and upto the end. 1059 1059 * The new file size will become exactly #pos() bytes. … … 1078 1078 public: 1079 1079 1080 /** 1080 /** 1081 1081 * Reads and parses the given input stream. 1082 1082 * … … 1094 1094 * given stream before reading. After the stream has been successfully 1095 1095 * parsed, the position will be set back to the beginning. 1096 * 1096 * 1097 1097 * @param aInput Input stream. 1098 1098 * @param aSchema Schema URI to use for input stream validation. … … 1106 1106 } 1107 1107 1108 /** 1108 /** 1109 1109 * Reads and parses the given input stream in a raw fashion. 1110 1110 * 1111 * Currently, the only difference from #read() is that this method doesn't 1112 * set the stream position to the beginnign before and after reading but 1113 * instead leaves it as is in both cases which can give unexpected 1114 * results. 1111 * This method doesn't set the stream position to the beginnign before and 1112 * after reading but instead leaves it as is in both cases. It's the 1113 * caller's responsibility to maintain the correct position. 1115 1114 * 1116 1115 * @see read() … … 1119 1118 int aFlags = 0) = 0; 1120 1119 1121 /** 1120 /** 1122 1121 * Writes the current settings tree to the given output stream. 1123 * 1122 * 1124 1123 * This method will set the read/write position to the beginning of the 1125 1124 * given stream before writing. After the settings have been successfully … … 1127 1126 * following the last byte written by this method anc ghd position will be 1128 1127 * set back to the beginning. 1129 * 1128 * 1130 1129 * @param aOutput Output stream. 1131 1130 */ … … 1138 1137 } 1139 1138 1140 /** 1139 /** 1141 1140 * Writes the current settings tree to the given output stream in a raw 1142 1141 * fashion. 1143 1142 * 1144 * Currently, the only difference from #write() is that this method1145 * doesn't set the stream position to the beginning before and after1146 * reading and doesn't thruncate the stream, but instead leaves it as is1147 * in both cases which can give unexpected results.1143 * This method doesn't set the stream position to the beginnign before and 1144 * after reading and doesn't truncate the stream, but instead leaves it as 1145 * is in both cases. It's the caller's responsibility to maintain the 1146 * correct position and perform truncation. 1148 1147 * 1149 1148 * @see write() … … 1151 1150 virtual void rawWrite (Output &aOutput) = 0; 1152 1151 1153 /** 1152 /** 1154 1153 * Deletes the current settings tree. 1155 1154 */ 1156 1155 virtual void reset() = 0; 1157 1156 1158 /** 1157 /** 1159 1158 * Returns the root settings key. 1160 1159 */ … … 1187 1186 * or ReadWrite, the file must exist. If @a aMode is Write, the file must 1188 1187 * not exist. Otherwise, an EIPRTFailure excetion will be thrown. 1189 * 1188 * 1190 1189 * @param aMode File mode. 1191 1190 * @param aFileName File name. … … 1223 1222 void setPos (uint64_t aPos); 1224 1223 1225 /** 1224 /** 1226 1225 * See Input::read(). If this method is called in wrong file mode, 1227 1226 * LogicError will be thrown. … … 1229 1228 int read (char *aBuf, int aLen); 1230 1229 1231 /** 1230 /** 1232 1231 * See Output::write(). If this method is called in wrong file mode, 1233 1232 * LogicError will be thrown. … … 1235 1234 int write (const char *aBuf, int aLen); 1236 1235 1237 /** 1236 /** 1238 1237 * See Output::truncate(). If this method is called in wrong file mode, 1239 1238 * LogicError will be thrown. … … 1251 1250 }; 1252 1251 1253 /** 1252 /** 1254 1253 * The MemoryBuf class represents a stream implementation that reads from the 1255 1254 * memory buffer. … … 1291 1290 enum 1292 1291 { 1293 /** 1292 /** 1294 1293 * Sbstitute default values for missing attributes that have defaults 1295 1294 * in the XML schema. Otherwise, stringValue() will return NULL for … … 1299 1298 }; 1300 1299 1301 /** 1300 /** 1302 1301 * The InputResolver class represents an input resolver, the service used to 1303 1302 * provide input streams for external entities given an URL and entity ID. … … 1310 1309 * Returns a newly allocated input stream for the given arguments. The 1311 1310 * caller will delete the returned object when no more necessary. 1312 * 1311 * 1313 1312 * @param aURI URI of the external entity. 1314 1313 * @param aID ID of the external entity (may be NULL). 1315 * 1314 * 1316 1315 * @return Input stream created using @c new or NULL to indicate 1317 1316 * a wrong URI/ID pair. … … 1324 1323 1325 1324 1326 /** 1325 /** 1327 1326 * The Error class represents errors that may happen when parsing or 1328 1327 * validating the XML document representing the settings tree. … … 1338 1337 ~XmlTreeBackend(); 1339 1338 1340 /** 1339 /** 1341 1340 * Sets an external entity resolver used to provide input streams for 1342 1341 * entities referred to by the XML document being parsed. … … 1345 1344 * until a different resolver is set using setInputResolver() or reset 1346 1345 * using resetInputResolver(). 1347 * 1346 * 1348 1347 * @param aResolver Resolver to use. 1349 1348 */ 1350 1349 void setInputResolver (InputResolver &aResolver); 1351 1350 1352 /** 1351 /** 1353 1352 * Resets the entity resolver to the default resolver. The default 1354 1353 * resolver provides support for 'file:' and 'http:' protocols. 1355 1354 */ 1356 1355 void resetInputResolver(); 1356 1357 /** 1358 * Sets up automatic settings tree conversion. 1359 * 1360 * Automatic settings tree conversion is useful for upgrading old settings 1361 * files to the new version transparently during execution of the #read() 1362 * method. 1363 * 1364 * Automatic conversion is performed after reading the document from the 1365 * stream but before validating it using the given XSLT template if the 1366 * version check fails. The version check consists of comparing the given 1367 * version string with the value of the given attribute of the root key. The 1368 * conversion is performed only when the version strings are not equal. 1369 * 1370 * Note that in order to make the conversion permanent, the resulting tree 1371 * needs to be exlicitly written back to the stream. 1372 * 1373 * The method will make copies of the supplied strings. 1374 * 1375 * Specifying a NULL value for all of the arguments will completely disable 1376 * automatic conversion. Specifying an invalid root key name or a 1377 * non-existent attribute name will disable automatic conversion too. By 1378 * default automatic conversion it is disabled. 1379 * 1380 * Specifying a NULL value only for some of the arguments will throw an 1381 * EInvalidArg exception. 1382 * 1383 * @param aRoot Name of the root key containing the version attribute. 1384 * @param aAttr Name of the attribute containing the version string. 1385 * @param aVersion Version string to compare with the attribute value. 1386 * @param aTemplate URI of the XSLT template that performs conversion. 1387 */ 1388 void setAutoConversion (const char *aRoot, const char *aAttr, 1389 const char *aVersion, const char *aTemplate); 1390 1391 /** 1392 * Disables automatic settings conversion previously enabled by 1393 * setAutoConversion(). By default automatic conversion it is disabled. 1394 */ 1395 void resetAutoConversion() 1396 { 1397 setAutoConversion (NULL, NULL, NULL, NULL); 1398 } 1357 1399 1358 1400 void rawRead (Input &aInput, const char *aSchema = NULL, int aFlags = 0); -
trunk/src/VBox/Main/Makefile.kmk
r6988 r7309 407 407 VBoxSettings_TEMPLATE = VBOXMAINDLL 408 408 VBoxSettings_NAME = $(basename $(notdir $(LIB_SETTINGS))) 409 VBoxSettings_SDKS = VBOX_LIBX ML2 VBOX_ZLIB409 VBoxSettings_SDKS = VBOX_LIBXSLT VBOX_LIBXML2 VBOX_ZLIB 410 410 VBoxSettings_DEFS = IN_VBOXSETTINGS_R3 411 411 VBoxSettings_INCS = \ -
trunk/src/VBox/Main/xml/Settings.cpp
r7027 r7309 30 30 31 31 #include <libxml/xmlschemas.h> 32 33 #include <libxslt/xsltInternals.h> 34 #include <libxslt/transform.h> 35 #include <libxslt/xsltutils.h> 32 36 33 37 #include <string.h> … … 804 808 std::auto_ptr <stdx::exception_trap_base> trappedErr; 805 809 810 struct AutoConv 811 { 812 AutoConv() : root (NULL), attr (NULL), version (NULL), xslt (NULL) {} 813 ~AutoConv() { uninit(); } 814 815 void uninit() 816 { 817 RTStrFree (xslt); xslt = NULL; 818 RTStrFree (version); version = NULL; 819 RTStrFree (attr); attr = NULL; 820 RTStrFree (root); root = NULL; 821 } 822 823 bool isNull() { return xslt == NULL; } 824 825 char *root; 826 char *attr; 827 char *version; 828 char *xslt; 829 } 830 autoConv; 831 806 832 /** 807 833 * This is to avoid throwing exceptions while in libxml2 code and … … 870 896 } 871 897 898 void XmlTreeBackend::setAutoConversion (const char *aRoot, const char *aAttr, 899 const char *aVersion, const char *aTemplate) 900 { 901 if (aRoot == NULL && aAttr == NULL && aVersion == NULL && aTemplate == NULL) 902 { 903 m->autoConv.uninit(); 904 return; 905 } 906 907 if (aRoot == NULL || aAttr == NULL || aVersion == NULL || aTemplate == NULL) 908 throw EInvalidArg (RT_SRC_POS); 909 910 m->autoConv.root = RTStrDup (aRoot); 911 m->autoConv.attr = RTStrDup (aAttr); 912 m->autoConv.version = RTStrDup (aVersion); 913 m->autoConv.xslt = RTStrDup (aTemplate); 914 } 915 872 916 void XmlTreeBackend::rawRead (Input &aInput, const char *aSchema /* = NULL */, 873 917 int aFlags /* = 0 */) … … 876 920 * libxml2 code. */ 877 921 m->trappedErr.reset(); 878 879 /* Set up an input stream for parsing the document. This will be deleted880 * when the stream is closed by the libxml2 API (e.g. when calling881 * xmlFreeParserCtxt()). */882 Data::InputCtxt *inputCtxt =883 new Data::InputCtxt (&aInput, m->trappedErr);884 922 885 923 /* Set up the external entity resolver. Note that we do it in a … … 899 937 900 938 /* parse the stream */ 939 /* NOTE: new InputCtxt instance will be deleted when the stream is closed by 940 * the libxml2 API (e.g. when calling xmlFreeParserCtxt()) */ 901 941 xmlDocPtr doc = xmlCtxtReadIO (m->ctxt, 902 942 ReadCallback, CloseCallback, 903 inputCtxt, aInput.uri(), NULL, 943 new Data::InputCtxt (&aInput, m->trappedErr), 944 aInput.uri(), NULL, 904 945 XML_PARSE_NOBLANKS); 905 946 if (doc == NULL) … … 916 957 } 917 958 959 /* perform automatic document transformation if necessary */ 960 if (!m->autoConv.isNull()) 961 { 962 Key root = Key (new XmlKeyBackend (xmlDocGetRootElement (doc))); 963 if (!strcmp (root.name(), m->autoConv.root)) 964 { 965 const char *ver = root.stringValue (m->autoConv.attr); 966 if (strcmp (ver, m->autoConv.version)) 967 { 968 /* version mismatch */ 969 970 xmlDocPtr xsltDoc = NULL; 971 xsltStylesheetPtr xslt = NULL; 972 xsltTransformContextPtr tranCtxt = NULL; 973 char *errorStr = NULL; 974 975 try 976 { 977 /* parse the XSLT */ 978 { 979 Input *xsltInput = 980 m->inputResolver->resolveEntity (m->autoConv.xslt, NULL); 981 /* NOTE: new InputCtxt instance will be deleted when the 982 * stream is closed by the libxml2 API */ 983 xsltDoc = xmlCtxtReadIO (m->ctxt, 984 ReadCallback, CloseCallback, 985 new Data::InputCtxt (xsltInput, m->trappedErr), 986 m->autoConv.xslt, NULL, 987 0); 988 delete xsltInput; 989 } 990 991 if (xsltDoc == NULL) 992 { 993 /* look if there was a forwared exception from the lower level */ 994 if (m->trappedErr.get() != NULL) 995 m->trappedErr->rethrow(); 996 997 throw XmlError (xmlCtxtGetLastError (m->ctxt)); 998 } 999 1000 xslt = xsltParseStylesheetDoc (xsltDoc); 1001 if (xslt == NULL) 1002 throw LogicError (RT_SRC_POS); 1003 1004 /* setup transformation error reporting */ 1005 tranCtxt = xsltNewTransformContext (xslt, xsltDoc); 1006 if (tranCtxt == NULL) 1007 throw LogicError (RT_SRC_POS); 1008 xsltSetTransformErrorFunc (tranCtxt, &errorStr, ValidityErrorCallback); 1009 1010 xmlDocPtr newDoc = xsltApplyStylesheetUser (xslt, doc, NULL, 1011 NULL, NULL, tranCtxt); 1012 if (newDoc == NULL) 1013 throw LogicError (RT_SRC_POS); 1014 1015 if (errorStr != NULL) 1016 { 1017 xmlFreeDoc (newDoc); 1018 throw Error (errorStr); 1019 /* errorStr is freed in catch(...) below */ 1020 } 1021 1022 /* replace the old document on success */ 1023 xmlFreeDoc (doc); 1024 doc = newDoc; 1025 1026 xsltFreeTransformContext (tranCtxt); 1027 1028 /* NOTE: xsltFreeStylesheet() also fress the document 1029 * passed to xsltParseStylesheetDoc(). */ 1030 xsltFreeStylesheet (xslt); 1031 } 1032 catch (...) 1033 { 1034 /* restore the previous entity resolver */ 1035 xmlSetExternalEntityLoader (oldEntityLoader); 1036 sThat = NULL; 1037 1038 RTStrFree (errorStr); 1039 1040 if (tranCtxt != NULL) 1041 xsltFreeTransformContext (tranCtxt); 1042 1043 /* NOTE: xsltFreeStylesheet() also fress the document 1044 * passed to xsltParseStylesheetDoc(). */ 1045 if (xslt != NULL) 1046 xsltFreeStylesheet (xslt); 1047 else if (xsltDoc != NULL) 1048 xmlFreeDoc (xsltDoc); 1049 1050 throw; 1051 } 1052 } 1053 } 1054 } 1055 1056 /* validate the document */ 918 1057 if (aSchema != NULL) 919 1058 { … … 923 1062 char *errorStr = NULL; 924 1063 925 /* validate the document */926 1064 try 927 1065 { … … 1161 1299 -- newMsgLen; 1162 1300 1163 if (str == NULL) 1164 { 1165 str = newMsg; 1166 newMsg [newMsgLen] = '\0'; 1167 } 1168 else 1169 { 1170 /* append to the existing string */ 1171 size_t strLen = strlen (str); 1172 char *newStr = (char *) RTMemRealloc (str, strLen + 2 + newMsgLen + 1); 1173 AssertReturnVoid (newStr != NULL); 1174 1175 memcpy (newStr + strLen, ".\n", 2); 1176 memcpy (newStr + strLen + 2, newMsg, newMsgLen); 1177 newStr [strLen + 2 + newMsgLen] = '\0'; 1178 str = newStr; 1179 RTStrFree (newMsg); 1301 /* anything left? */ 1302 if (newMsgLen > 0) 1303 { 1304 if (str == NULL) 1305 { 1306 str = newMsg; 1307 newMsg [newMsgLen] = '\0'; 1308 } 1309 else 1310 { 1311 /* append to the existing string */ 1312 size_t strLen = strlen (str); 1313 char *newStr = (char *) RTMemRealloc (str, strLen + 2 + newMsgLen + 1); 1314 AssertReturnVoid (newStr != NULL); 1315 1316 memcpy (newStr + strLen, ".\n", 2); 1317 memcpy (newStr + strLen + 2, newMsg, newMsgLen); 1318 newStr [strLen + 2 + newMsgLen] = '\0'; 1319 str = newStr; 1320 RTStrFree (newMsg); 1321 } 1180 1322 } 1181 1323 }
Note:
See TracChangeset
for help on using the changeset viewer.