diff --git a/Projects/Win32/VC6/xerces-all/SAXCount/SAXCount.dsp b/Projects/Win32/VC6/xerces-all/SAXCount/SAXCount.dsp index dcb89e8f3a9ab6e6c6bd700380d5ae853ac39947..966cde32c36021c8bce4400c99aff5b4212fdd2f 100644 --- a/Projects/Win32/VC6/xerces-all/SAXCount/SAXCount.dsp +++ b/Projects/Win32/VC6/xerces-all/SAXCount/SAXCount.dsp @@ -67,7 +67,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /G6 /MDd /Za /W3 /Gm /GX /ZI /Od /I "..\..\..\..\..\src" /D "_DEBUG" /D "_CONSOLE" /D "WIN32" /D "_WINDOWS" /D "PLATFORM_WIN32" /FD /c +# ADD CPP /nologo /G6 /MDd /Za /W3 /Gm /GX /ZI /Od /I "..\..\..\..\..\src" /D "_DEBUG" /D "_CONSOLE" /D "WIN32" /D "_WINDOWS" /D "PLATFORM_WIN32" /FR /FD /c # SUBTRACT CPP /YX # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" diff --git a/Projects/Win32/VC6/xerces-all/XercesLib/XercesLib.dsp b/Projects/Win32/VC6/xerces-all/XercesLib/XercesLib.dsp index eb52a7d9b9723678f4e62c0f0923b302596278d2..35e47f8f797ae69877f7f3c70c396a7daa40c3e5 100644 --- a/Projects/Win32/VC6/xerces-all/XercesLib/XercesLib.dsp +++ b/Projects/Win32/VC6/xerces-all/XercesLib/XercesLib.dsp @@ -70,7 +70,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c -# ADD CPP /nologo /G6 /MDd /Za /W3 /Gm /GX /Zi /Od /I "..\..\src" /I "..\..\src\dom" /I "..\..\..\..\..\src" /D "PROJ_XMLPARSER" /D "PROJ_XMLUTIL" /D "PROJ_PARSERS" /D "PROJ_SAX4C" /D "PROJ_DOM" /D "PROJ_VALIDATORS" /D "XML_SINGLEDLL" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "XML_USE_WIN32_TRANSCODER" /D "XML_USE_WIN32_MSGLOADER" /D "XML_USE_NETACCESSOR_WINSOCK" /FD /c +# ADD CPP /nologo /G6 /MDd /Za /W3 /Gm /GX /Zi /Od /I "..\..\src" /I "..\..\src\dom" /I "..\..\..\..\..\src" /D "_CRTDBG_MAP_ALLOC" /D "PROJ_XMLPARSER" /D "PROJ_XMLUTIL" /D "PROJ_PARSERS" /D "PROJ_SAX4C" /D "PROJ_DOM" /D "PROJ_VALIDATORS" /D "XML_SINGLEDLL" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "XML_USE_WIN32_TRANSCODER" /D "XML_USE_WIN32_MSGLOADER" /D "XML_USE_NETACCESSOR_WINSOCK" /FR /FD /c # SUBTRACT CPP /YX # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 @@ -139,11 +139,6 @@ SOURCE=..\..\..\..\..\src\util\Transcoders\Win32\Win32TransService.cpp SOURCE=..\..\..\..\..\src\util\Transcoders\Win32\Win32TransService.hpp # End Source File -# Begin Source File - -SOURCE=..\..\..\..\..\src\util\Transcoders\Win32\Win32TransService2.cpp -# ADD CPP /Ze -# End Source File # End Group # Begin Group "NetAccessors" diff --git a/samples/DOMPrint/DOMPrint.cpp b/samples/DOMPrint/DOMPrint.cpp index eb0e597f30f4309f0951e0c994be4b9d419eea9b..c8f3b162ba9f7b039988ece8a2ad692589beb339 100644 --- a/samples/DOMPrint/DOMPrint.cpp +++ b/samples/DOMPrint/DOMPrint.cpp @@ -56,6 +56,12 @@ /* * $Log$ + * Revision 1.10 2000/05/09 00:22:27 andyh + * Memory Cleanup. XMLPlatformUtils::Terminate() deletes all lazily + * allocated memory; memory leak checking tools will no longer report + * that leaks exist. (DOM GetElementsByTagID temporarily removed + * as part of this.) + * * Revision 1.9 2000/04/25 20:27:44 aruna1 * DOM_XMLDecl type node introduced to get the information of the * XML Declaration in a document and store it part of the tree @@ -136,6 +142,7 @@ #include <parsers/DOMParser.hpp> #include <dom/DOM_Node.hpp> #include <dom/DOM_NamedNodeMap.hpp> +#include <dom/DomMemDebug.hpp> #include "DOMTreeErrorReporter.hpp" #include <string.h> #include <stdlib.h> @@ -206,6 +213,7 @@ int main(int argC, char* argV[]) if (argC < 2) { usage(); + XMLPlatformUtils::Terminate(); return 1; } @@ -213,6 +221,7 @@ int main(int argC, char* argV[]) if (!strcmp(argV[1], "-?")) { usage(); + XMLPlatformUtils::Terminate(); return 2; } @@ -251,6 +260,7 @@ int main(int argC, char* argV[]) else { usage(); + XMLPlatformUtils::Terminate(); return 1; } } @@ -262,22 +272,23 @@ int main(int argC, char* argV[]) if (parmInd + 1 != argC) { usage(); + XMLPlatformUtils::Terminate(); return 1; } xmlFile = argV[parmInd]; // - // Create our validator, then attach an error handler to the parser. + // Create our parser, then attach an error handler to the parser. // The parser will call back to methods of the ErrorHandler if it // discovers errors during the course of parsing the XML document. // - DOMParser parser; - parser.setDoValidation(doValidation); - parser.setDoNamespaces(doNamespaces); + DOMParser *parser = new DOMParser; + parser->setDoValidation(doValidation); + parser->setDoNamespaces(doNamespaces); ErrorHandler *errReporter = new DOMTreeErrorReporter(); - parser.setErrorHandler(errReporter); - parser.setExpandEntityReferences(doExpand); - parser.setToCreateXMLDeclTypeNode(doCreateXMLDecl); + parser->setErrorHandler(errReporter); + parser->setExpandEntityReferences(doExpand); + parser->setToCreateXMLDeclTypeNode(doCreateXMLDecl); // // Parse the XML file, catching any XML exceptions that might propogate // out of it. @@ -285,7 +296,7 @@ int main(int argC, char* argV[]) bool errorsOccured = false; try { - parser.parse(xmlFile); + parser->parse(xmlFile); } catch (const XMLException& e) @@ -298,19 +309,25 @@ int main(int argC, char* argV[]) // If the parse was successful, output the document data from the DOM tree if (!errorsOccured) { - DOM_Node doc = parser.getDocument(); + DOM_Node doc = parser->getDocument(); cout << doc << endl; } // - // Clean up the element counter object. The parser does not adopt handlers + // Clean up the error handler. The parser does not adopt handlers // since they could be many objects or one object installed for multiple // handlers. // delete errReporter; + // + // Delete the parser itself. Must be done prior to calling Terminate, below. + // + delete parser; + // And call the termination method XMLPlatformUtils::Terminate(); + // DomMemDebug().print(); // // The DOM document and its contents are reference counted, and need diff --git a/samples/SAXCount/SAXCount.cpp b/samples/SAXCount/SAXCount.cpp index ce2e360d3388536b1d37d5b702c3096f2b5891ed..105068ca65341d7c51e17af2835c19084896759e 100644 --- a/samples/SAXCount/SAXCount.cpp +++ b/samples/SAXCount/SAXCount.cpp @@ -1,85 +1,91 @@ /* - * The Apache Software License, Version 1.1 - * - * Copyright (c) 1999-2000 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Xerces" and "Apache Software Foundation" must - * not be used to endorse or promote products derived from this - * software without prior written permission. For written - * permission, please contact apache\@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * nor may "Apache" appear in their name, without prior written - * permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation, and was - * originally based on software copyright (c) 1999, International - * Business Machines, Inc., http://www.ibm.com . For more information - * on the Apache Software Foundation, please see - * <http://www.apache.org/>. - */ +* The Apache Software License, Version 1.1 +* +* Copyright (c) 1999-2000 The Apache Software Foundation. All rights +* reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* +* 3. The end-user documentation included with the redistribution, +* if any, must include the following acknowledgment: +* "This product includes software developed by the +* Apache Software Foundation (http://www.apache.org/)." +* Alternately, this acknowledgment may appear in the software itself, +* if and wherever such third-party acknowledgments normally appear. +* +* 4. The names "Xerces" and "Apache Software Foundation" must +* not be used to endorse or promote products derived from this +* software without prior written permission. For written +* permission, please contact apache\@apache.org. +* +* 5. Products derived from this software may not be called "Apache", +* nor may "Apache" appear in their name, without prior written +* permission of the Apache Software Foundation. +* +* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR +* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +* SUCH DAMAGE. +* ==================================================================== +* +* This software consists of voluntary contributions made by many +* individuals on behalf of the Apache Software Foundation, and was +* originally based on software copyright (c) 1999, International +* Business Machines, Inc., http://www.ibm.com . For more information +* on the Apache Software Foundation, please see +* <http://www.apache.org/>. +*/ /* - * $Log$ - * Revision 1.5 2000/03/03 01:29:31 roddey - * Added a scanReset()/parseReset() method to the scanner and - * parsers, to allow for reset after early exit from a progressive parse. - * Added calls to new Terminate() call to all of the samples. Improved - * documentation in SAX and DOM parsers. - * - * Revision 1.4 2000/03/02 19:53:47 roddey - * This checkin includes many changes done while waiting for the - * 1.1.0 code to be finished. I can't list them all here, but a list is - * available elsewhere. - * - * Revision 1.3 2000/02/11 02:39:10 abagchi - * Removed StrX::transcode - * - * Revision 1.2 2000/02/06 07:47:23 rahulj - * Year 2K copyright swat. - * - * Revision 1.1.1.1 1999/11/09 01:09:30 twl - * Initial checkin - * - * Revision 1.7 1999/11/08 20:43:40 rahul - * Swat for adding in Product name and CVS comment log variable. - * - */ +* $Log$ +* Revision 1.6 2000/05/09 00:22:29 andyh +* Memory Cleanup. XMLPlatformUtils::Terminate() deletes all lazily +* allocated memory; memory leak checking tools will no longer report +* that leaks exist. (DOM GetElementsByTagID temporarily removed +* as part of this.) +* +* Revision 1.5 2000/03/03 01:29:31 roddey +* Added a scanReset()/parseReset() method to the scanner and +* parsers, to allow for reset after early exit from a progressive parse. +* Added calls to new Terminate() call to all of the samples. Improved +* documentation in SAX and DOM parsers. +* +* Revision 1.4 2000/03/02 19:53:47 roddey +* This checkin includes many changes done while waiting for the +* 1.1.0 code to be finished. I can't list them all here, but a list is +* available elsewhere. +* +* Revision 1.3 2000/02/11 02:39:10 abagchi +* Removed StrX::transcode +* +* Revision 1.2 2000/02/06 07:47:23 rahulj +* Year 2K copyright swat. +* +* Revision 1.1.1.1 1999/11/09 01:09:30 twl +* Initial checkin +* +* Revision 1.7 1999/11/08 20:43:40 rahul +* Swat for adding in Product name and CVS comment log variable. +* +*/ // --------------------------------------------------------------------------- @@ -94,12 +100,12 @@ void usage() { cout << "\nUsage:\n" - << " SAXCount [-v -n] <XML file>\n\n" - << " -v Do a validating parse. Defaults to non-validating.\n" - << " -n Enable namespace processing. Defaults to off.\n\n" - << "This program prints the number of elements, attributes,\n" - << "white spaces and other non-white space characters in the " - << "input file.\n" << endl; + << " SAXCount [-v -n] <XML file>\n\n" + << " -v Do a validating parse. Defaults to non-validating.\n" + << " -n Enable namespace processing. Defaults to off.\n\n" + << "This program prints the number of elements, attributes,\n" + << "white spaces and other non-white space characters in the " + << "input file.\n" << endl; } @@ -111,58 +117,60 @@ int main(int argC, char* argV[]) // Initialize the XML4C2 system try { - XMLPlatformUtils::Initialize(); + XMLPlatformUtils::Initialize(); } - + catch (const XMLException& toCatch) { - cerr << "Error during initialization! Message:\n" - << StrX(toCatch.getMessage()) << endl; - return 1; + cerr << "Error during initialization! Message:\n" + << StrX(toCatch.getMessage()) << endl; + return 1; } - + // Check command line and extract arguments. if (argC < 2) { usage(); + XMLPlatformUtils::Terminate(); return 1; } - + const char* xmlFile; bool doValidation = false; bool doNamespaces = false; - + // See if non validating dom parser configuration is requested. if ((argC == 2) && !strcmp(argV[1], "-?")) { usage(); + XMLPlatformUtils::Terminate(); return 2; } - + int argInd; for (argInd = 1; argInd < argC; argInd++) { // Break out on first non-dash parameter if (argV[argInd][0] != '-') break; - + if (!strcmp(argV[argInd], "-v") - || !strcmp(argV[argInd], "-V")) + || !strcmp(argV[argInd], "-V")) { doValidation = true; } - else if (!strcmp(argV[argInd], "-n") - || !strcmp(argV[argInd], "-N")) + else if (!strcmp(argV[argInd], "-n") + || !strcmp(argV[argInd], "-N")) { doNamespaces = true; } - else + else { cerr << "Unknown option '" << argV[argInd] - << "', ignoring it\n" << endl; + << "', ignoring it\n" << endl; } } - + // // There should be only one and only one parameter left, and that // should be the file name. @@ -170,18 +178,20 @@ int main(int argC, char* argV[]) if (argInd != argC - 1) { usage(); + XMLPlatformUtils::Terminate(); return 1; } xmlFile = argV[argInd]; - + // // Create a SAX parser object. Then, according to what we were told on // the command line, set it to validate or not. // SAXParser parser; + parser.setDoValidation(doValidation); parser.setDoNamespaces(doNamespaces); - + // // Create our SAX handler object and install it on the parser, as the // document and error handler. @@ -189,8 +199,9 @@ int main(int argC, char* argV[]) SAXCountHandlers handler; parser.setDocumentHandler(&handler); parser.setErrorHandler(&handler); + - // + // // Get the starting time and kick off the parse of the indicated // file. Catch any exceptions that might propogate out of it. // @@ -202,28 +213,37 @@ int main(int argC, char* argV[]) const unsigned long endMillis = XMLPlatformUtils::getCurrentMillis(); duration = endMillis - startMillis; } - + catch (const XMLException& e) { cerr << "\nError during parsing: '" << xmlFile << "'\n" - << "Exception message is: \n" - << StrX(e.getMessage()) << "\n" << endl; + << "Exception message is: \n" + << StrX(e.getMessage()) << "\n" << endl; + XMLPlatformUtils::Terminate(); return -1; } + catch (...) + { + cerr << "\nUnexpected exception during parsing: '" << xmlFile << "'\n"; + XMLPlatformUtils::Terminate(); + return -1; + } + + // Print out the stats that we collected and time taken if (!handler.getSawErrors()) { cout << xmlFile << ": " << duration << " ms (" - << handler.getElementCount() << " elems, " - << handler.getAttrCount() << " attrs, " - << handler.getSpaceCount() << " spaces, " - << handler.getCharacterCount() << " chars)" << endl; + << handler.getElementCount() << " elems, " + << handler.getAttrCount() << " attrs, " + << handler.getSpaceCount() << " spaces, " + << handler.getCharacterCount() << " chars)" << endl; } - + // And call the termination method XMLPlatformUtils::Terminate(); - + return 0; } diff --git a/src/dom/DOMString.cpp b/src/dom/DOMString.cpp index 6ae2cf4f0bee9ef26412a2ecafe5e476b70ba4ca..fcbce52fe79775bb8b5c624a5971471237bb75e4 100644 --- a/src/dom/DOMString.cpp +++ b/src/dom/DOMString.cpp @@ -56,6 +56,12 @@ /* * $Log$ + * Revision 1.16 2000/05/09 00:22:29 andyh + * Memory Cleanup. XMLPlatformUtils::Terminate() deletes all lazily + * allocated memory; memory leak checking tools will no longer report + * that leaks exist. (DOM GetElementsByTagID temporarily removed + * as part of this.) + * * Revision 1.15 2000/03/28 19:43:13 roddey * Fixes for signed/unsigned warnings. New work for two way transcoding * stuff. @@ -142,6 +148,12 @@ #include <string.h> +//---------------------------------------------- +// +// Forward decls +// +//---------------------------------------------- +static void DOMStringTerminate(); //---------------------------------------------- // @@ -221,15 +233,18 @@ static const int allocGroupSize = 1024; // Number of string handles to allocat // as a chunk from the system's // memory allocator. +DOMStringHandle *DOMStringHandle::blockListPtr = 0; // Point to the head of the list + // of larger blocks in which DOMStringHandles + // are allocated. // // There is one global mutex that is used to synchronize access to the // allocator free list for DOMStringHandles. This function gets that // mutex, and will create it on the first attempt to get it. // +static XMLMutex* DOMStringHandleMutex = 0; // Mutex will be deleted by ~DOMStringHandle. XMLMutex& DOMStringHandle::getMutex() { - static XMLMutex* DOMStringHandleMutex = 0; if (!DOMStringHandleMutex) { XMLMutex* tmpMutex = new XMLMutex; @@ -239,6 +254,7 @@ XMLMutex& DOMStringHandle::getMutex() delete tmpMutex; } } + return *DOMStringHandleMutex; } @@ -260,12 +276,20 @@ void *DOMStringHandle::operator new(size_t sizeToAlloc) // Allocate a new batch of them, using the system's // operator new to get a chunk of memory. // - // Link all of these new StringHandles into our free list - // - DOMStringHandle *dsg = + DOMStringHandle *dsg = ::new DOMStringHandle[allocGroupSize]; - int i; - for (i=0; i<allocGroupSize-1; i++) { + + // Link the block itself into the list of blocks. The purpose of this is to + // let us locate and delete the blocks when shutting down. + // + *(DOMStringHandle **)dsg = blockListPtr; + blockListPtr = dsg; + + + // Link all of the new storage for StringHandles into the StringHandle free list + int i; // Start with index 1; index 0 is reserved for linking the + // larger allocation blocks together. + for (i=1; i<allocGroupSize-1; i++) { *(void **)&dsg[i] = freeListPtr; freeListPtr = &dsg[i]; } @@ -284,12 +308,34 @@ void *DOMStringHandle::operator new(size_t sizeToAlloc) // void DOMStringHandle::operator delete(void *pMem) { - XMLMutexLock lock(&getMutex()); // Lock the DOMStringHandle mutex for the - // duration of this function. - *(void **)pMem = freeListPtr; - freeListPtr = pMem; -}; + { + XMLMutexLock lock(&getMutex()); // Lock the DOMStringHandle mutex for the + // duration of this function. + *(void **)pMem = freeListPtr; + freeListPtr = pMem; + } + + // If ALL of the string handles are gone, delete the storage blocks used for the + // handles as well. This will generally only happen on PlatFormUtils::Terminate(), + // since any use of the DOM will cache some commonly used DOMStrings + // forever (until Terminate). + if (DOMString::gLiveStringHandleCount == 0) + { + DOMStringHandle *pThisBlock, *pNextBlock; + for (pThisBlock = blockListPtr; pThisBlock != 0; pThisBlock = pNextBlock) + { + pNextBlock = *(DOMStringHandle **)pThisBlock; + delete [] pThisBlock; + } + blockListPtr = 0; + freeListPtr = 0; + + DOMStringTerminate(); // Clean up everything else related to DOMString. + } + +}; + void DOMStringHandle::addRef() { @@ -303,8 +349,8 @@ void DOMStringHandle::removeRef() if (result==0) { fDSData->removeRef(); - delete this; XMLPlatformUtils::atomicDecrement(DOMString::gLiveStringHandleCount); + delete this; }; }; @@ -410,9 +456,9 @@ DOMString::DOMString(const XMLCh *data, unsigned int dataLength) // codepage to Unicode that is to be used when // a DOMString is constructed from a char *. // +static XMLLCPTranscoder* gDomConverter = 0; XMLLCPTranscoder* getDomConverter() { - static XMLLCPTranscoder* gDomConverter = 0; if (!gDomConverter) { XMLLCPTranscoder* transcoder = @@ -423,7 +469,7 @@ XMLLCPTranscoder* getDomConverter() if (XMLPlatformUtils::compareAndSwap((void **)&gDomConverter, transcoder, 0) != 0) - delete gDomConverter; + delete transcoder; } return gDomConverter; }; @@ -1127,3 +1173,18 @@ DOMString operator + (XMLCh lhs, const DOMString& rhs) +static void DOMStringTerminate() // Termination function cleans up all lazily created +{ // resources used by the DOMString implementation. + // Called when no DOMStrings remain in the app. (We + // know this from reference counting.) + + delete DOMStringHandleMutex; // Delete the synchronization mutex, + DOMStringHandleMutex = 0; + + delete gDomConverter; // Delete the local code page converter. + gDomConverter = 0; +}; + + + + diff --git a/src/dom/DOMStringImpl.hpp b/src/dom/DOMStringImpl.hpp index 5323a1112af9721f936388fd4cdb21407fa6a3ba..e351445c8f87426ee9734652cdde9e045996245b 100644 --- a/src/dom/DOMStringImpl.hpp +++ b/src/dom/DOMStringImpl.hpp @@ -59,6 +59,12 @@ /* * $Log$ + * Revision 1.8 2000/05/09 00:22:30 andyh + * Memory Cleanup. XMLPlatformUtils::Terminate() deletes all lazily + * allocated memory; memory leak checking tools will no longer report + * that leaks exist. (DOM GetElementsByTagID temporarily removed + * as part of this.) + * * Revision 1.7 2000/03/02 19:53:52 roddey * This checkin includes many changes done while waiting for the * 1.1.0 code to be finished. I can't list them all here, but a list is @@ -118,20 +124,29 @@ public: class DOMStringHandle { public: - unsigned int fLength; - int fRefCount; - DOMStringData *fDSData; + unsigned int fLength; // The logical length of the DOMString. + // This may be shorter than the buffer length. + int fRefCount; // The number of DOMString objects pointing to + // this string handle. + DOMStringData *fDSData; // Pointer to the string buffer. May be null. + + void *operator new( size_t sizeToAlloc); // StringHandles have custom, optimized + void operator delete( void *pvMem ); // memory allocation. + - void *operator new( size_t sizeToAlloc); - void operator delete( void *pvMem ); private: - static void *freeListPtr; + static void *freeListPtr; // Head of the linked list of unallocated String Handles + + static DOMStringHandle *blockListPtr; // Head of the linked list of memory blocks from which + // string handles are sub-allocated. + public: static DOMStringHandle *createNewStringHandle(unsigned int bufLength); DOMStringHandle *cloneStringHandle(); inline void addRef(); inline void removeRef(); ~DOMStringHandle() {}; + static void DOMStringCleanup(); private: inline DOMStringHandle() {}; static inline XMLMutex &getMutex(); diff --git a/src/dom/DOM_DOMImplementation.cpp b/src/dom/DOM_DOMImplementation.cpp index f81652911d0775bcd142f0e97911c9611a5e8ad1..66dedf27e28c3e0fb6b7be0bbb0b2d7e0a7f7200 100644 --- a/src/dom/DOM_DOMImplementation.cpp +++ b/src/dom/DOM_DOMImplementation.cpp @@ -56,6 +56,12 @@ /* * $Log$ + * Revision 1.9 2000/05/09 00:22:31 andyh + * Memory Cleanup. XMLPlatformUtils::Terminate() deletes all lazily + * allocated memory; memory leak checking tools will no longer report + * that leaks exist. (DOM GetElementsByTagID temporarily removed + * as part of this.) + * * Revision 1.8 2000/04/27 02:52:42 lehors * global reorganization similar to what I've done in Java, * nodes now are much smaller. @@ -115,7 +121,8 @@ #include "DocumentImpl.hpp" #include "DocumentTypeImpl.hpp" #include "DStringPool.hpp" -#include "util/PlatformUtils.hpp" +#include <util/XMLDeleterFor.hpp> +#include <util/PlatformUtils.hpp> // // Static constants. These are lazily initialized on first usage. @@ -174,7 +181,18 @@ DOM_DOMImplementation &DOM_DOMImplementation::getImplementation() { { DOM_DOMImplementation *t = new DOM_DOMImplementation; if (XMLPlatformUtils::compareAndSwap((void **)&gDomimp, t, 0) != 0) + { delete t; + } + else + { + + XMLPlatformUtils::registerLazyData + ( + new XMLDeleterFor<DOM_DOMImplementation>(gDomimp) + ); + } + } return *gDomimp; }; diff --git a/src/dom/DOM_Document.cpp b/src/dom/DOM_Document.cpp index bfcadcedb61d28d62d6a6233b6ac8b941b1e4beb..a391da1972ade439f758ceec1553990d0abb8e64 100644 --- a/src/dom/DOM_Document.cpp +++ b/src/dom/DOM_Document.cpp @@ -56,6 +56,12 @@ /* * $Log$ + * Revision 1.9 2000/05/09 00:22:31 andyh + * Memory Cleanup. XMLPlatformUtils::Terminate() deletes all lazily + * allocated memory; memory leak checking tools will no longer report + * that leaks exist. (DOM GetElementsByTagID temporarily removed + * as part of this.) + * * Revision 1.8 2000/04/25 20:29:33 aruna1 * DOM_XMLDecl type node introduced to get the information of the * XML Declaration in a document and store it part of the tree @@ -271,12 +277,6 @@ DOM_Element DOM_Document::getElementById(const DOMString &elementId) return DOM_Element(((DocumentImpl *)fImpl)->getElementById(elementId)); } -// Non-standard accessory function - -void DOM_Document::putIdentifier(const DOMString &elementId, const DOM_Element &ele) -{ - ((DocumentImpl*)fImpl)->putIdentifier(elementId,ele); -} DOM_XMLDecl DOM_Document::createXMLDecl(const DOMString& version, const DOMString& encoding, const DOMString& standalone) { diff --git a/src/dom/DStringPool.cpp b/src/dom/DStringPool.cpp index 0283616112b21a1448094b8598c8dcc980794ca7..833302ba558584109024dcadd5d3eae19f295300 100644 --- a/src/dom/DStringPool.cpp +++ b/src/dom/DStringPool.cpp @@ -56,6 +56,12 @@ /* * $Log$ + * Revision 1.4 2000/05/09 00:22:31 andyh + * Memory Cleanup. XMLPlatformUtils::Terminate() deletes all lazily + * allocated memory; memory leak checking tools will no longer report + * that leaks exist. (DOM GetElementsByTagID temporarily removed + * as part of this.) + * * Revision 1.3 2000/03/02 19:53:58 roddey * This checkin includes many changes done while waiting for the * 1.1.0 code to be finished. I can't list them all here, but a list is @@ -77,6 +83,7 @@ // #include "DStringPool.hpp" +#include <util/XMLDeleterFor.hpp> #include <util/XMLString.hpp> #include <util/PlatformUtils.hpp> @@ -190,6 +197,16 @@ const DOMString &DStringPool::getStaticString(const char *in, DOMString **loc) // pass them around by value. if (XMLPlatformUtils::compareAndSwap((void **)loc, t, 0) != 0) delete t; + else + { + // Register this string for deletion. Doing each string individually + // may be a little heavyweight, but will work for the time being + // for arranging the deletion of eveything on Termination of XML. + XMLPlatformUtils::registerLazyData + ( + new XMLDeleterFor<DOMString>(*loc) + ); + } } return **loc; } diff --git a/src/dom/DocumentImpl.cpp b/src/dom/DocumentImpl.cpp index 2d065d3c7dcb7fddf159cc90ae57266848363037..f0e5047c40d6670111cf1fb6d3d6ebbd74dfb7b5 100644 --- a/src/dom/DocumentImpl.cpp +++ b/src/dom/DocumentImpl.cpp @@ -88,29 +88,6 @@ #include "NodeIteratorImpl.hpp" #include "DOM_Document.hpp" -// --------------------------------------------------------------------------- -// StringPool::PoolElem: Constructors and Destructor -// --------------------------------------------------------------------------- -DocumentImpl::PoolElem::PoolElem( const DOMString string - , const DOM_Element &elem) : - fElem((DOM_Element&)elem) - , fString(string) -{ -} - -DocumentImpl::PoolElem::~PoolElem() -{ -} - -// --------------------------------------------------------------------------- -// DocumentImpl::PoolElem: Public methods -// --------------------------------------------------------------------------- -const XMLCh* DocumentImpl::PoolElem::getKey() const -{ - return fString.rawBuffer(); -} - - DocumentImpl::DocumentImpl() : ParentNode(this) @@ -118,7 +95,6 @@ DocumentImpl::DocumentImpl() docType=null; docElement=null; namePool = new DStringPool(257); - identifiers = new RefHashTableOf<PoolElem>(109); iterators = 0L; treeWalkers = 0L; }; @@ -137,7 +113,6 @@ DocumentImpl::DocumentImpl(const DOMString &fNamespaceURI, docElement=null; appendChild(createElementNS(fNamespaceURI, qualifiedName)); //root element namePool = new DStringPool(257); - identifiers = new RefHashTableOf<PoolElem>(109); iterators = 0L; treeWalkers = 0L; } @@ -178,9 +153,6 @@ DocumentImpl::~DocumentImpl() delete treeWalkers; } - if (identifiers != 0L) { - delete identifiers; - } delete namePool; // Do not delete docType and docElement pointers here. @@ -679,21 +651,9 @@ DeepNodeListImpl *DocumentImpl::getElementsByTagNameNS(const DOMString &fNamespa ElementImpl *DocumentImpl::getElementById(const DOMString &elementId) { - PoolElem *elem = identifiers->get(elementId.rawBuffer()); - if (elem) - { - return (ElementImpl*)elem->fElem.fImpl; - } - return null; } -// Non-standard accessory functions */ - -void DocumentImpl::putIdentifier(const DOMString &elementId, const DOM_Element &ele) -{ - identifiers->put(new PoolElem(elementId, ele)); -} //Return the index > 0 of ':' in the given qualified name qName="prefix:localName". //Return 0 if there is no ':', or -1 if qName is malformed such as ":abcd". diff --git a/src/dom/DocumentImpl.hpp b/src/dom/DocumentImpl.hpp index e9638ae1949bc098195987ee8f1c577139a6eff9..816a8dd60e77772cccdcc67bbbfd0be1ce90693a 100644 --- a/src/dom/DocumentImpl.hpp +++ b/src/dom/DocumentImpl.hpp @@ -108,17 +108,6 @@ private: // ----------------------------------------------------------------------- // Private data types // ----------------------------------------------------------------------- - class PoolElem - { - public : - PoolElem(const DOMString string, const DOM_Element &elem); - ~PoolElem(); - - const XMLCh* getKey() const; - - DOM_Element fElem; - DOMString fString; - }; void setDocumentType(DocumentTypeImpl *doctype); @@ -126,7 +115,6 @@ private: ElementImpl *docElement; DStringPool *namePool; - RefHashTableOf<PoolElem> *identifiers; NodeIterators *iterators; TreeWalkers *treeWalkers; friend class NodeIteratorImpl; @@ -183,9 +171,6 @@ public: const DOMString &localName); virtual ElementImpl *getElementById(const DOMString &elementId); - // Non-standard accessory functions - virtual void putIdentifier(const DOMString &elementId, const DOM_Element &ele); - //Return the index > 0 of ':' in the given qualified name qName="prefix:localName". //Return 0 if there is no ':', or -1 if qName is malformed such as ":abcd". static int indexofQualifiedName(const DOMString & qName); diff --git a/src/internal/XMLScanner.cpp b/src/internal/XMLScanner.cpp index 1a05c4e3d915acf88daeb8af9b82a296e9e49a97..2aeda5057bfee9db214233375e38d79a8d70edc0 100644 --- a/src/internal/XMLScanner.cpp +++ b/src/internal/XMLScanner.cpp @@ -56,6 +56,12 @@ /* * $Log$ + * Revision 1.17 2000/05/09 00:22:36 andyh + * Memory Cleanup. XMLPlatformUtils::Terminate() deletes all lazily + * allocated memory; memory leak checking tools will no longer report + * that leaks exist. (DOM GetElementsByTagID temporarily removed + * as part of this.) + * * Revision 1.16 2000/05/05 01:44:29 rahulj * Fixed defect in progressive parsing 'parseNext()' reported by Tim * Johnston <tim@gntsoftware.com>. Fix provided by Dean Roddey. @@ -291,10 +297,16 @@ void XMLScanner::scanDocument( const XMLCh* const systemId // it has to be fully qualified. If not, then assume we are just // mistaking a file for a URL. // + XMLURL tmpURL(systemId); - if (tmpURL.isRelative()) - ThrowXML(MalformedURLException, XMLExcepts::URL_NoProtocolPresent); - srcToUse = new URLInputSource(tmpURL); + if (tmpURL.isRelative()) { + srcToUse = new LocalFileInputSource(systemId); + } + else + { + srcToUse = new URLInputSource(tmpURL); + } + } catch(const MalformedURLException&) diff --git a/src/parsers/DOMParser.cpp b/src/parsers/DOMParser.cpp index d7eb072041d468232dcc26a3fca875854d24bcfa..6e907b77f8cfa6f819906609334042cead9f3de7 100644 --- a/src/parsers/DOMParser.cpp +++ b/src/parsers/DOMParser.cpp @@ -601,7 +601,7 @@ void DOMParser::startElement(const XMLElementDecl& elemDecl // Register identifiers if (oneAttrib->getType()==XMLAttDef::ID) { - fDocument.putIdentifier(oneAttrib->getValue(), elem); + // When we record ID attributes, here is the place to do it. } attr->setSpecified(oneAttrib->getSpecified()); } @@ -609,14 +609,14 @@ void DOMParser::startElement(const XMLElementDecl& elemDecl elem = fDocument.createElement(elemDecl.getFullName()); ElementImpl *elemImpl = (ElementImpl *) elem.fImpl; for (unsigned int index = 0; index < attrCount; ++index) { - const XMLAttr* oneAttrib = attrList.elementAt(index); - AttrImpl *attr = elemImpl->setAttribute(oneAttrib->getName(), oneAttrib->getValue()); - // Register identifiers - if (oneAttrib->getType()==XMLAttDef::ID) - { - fDocument.putIdentifier(oneAttrib->getValue(), elem); - } - attr->setSpecified(oneAttrib->getSpecified()); + const XMLAttr* oneAttrib = attrList.elementAt(index); + AttrImpl *attr = elemImpl->setAttribute(oneAttrib->getName(), oneAttrib->getValue()); + // Register identifiers + if (oneAttrib->getType()==XMLAttDef::ID) + { + // When we record ID attributes, here is the place to do it. + } + attr->setSpecified(oneAttrib->getSpecified()); } } @@ -850,7 +850,8 @@ void DOMParser::doctypeDecl dt = fDocument.getImplementation().createDocumentType(elemDecl.getFullName(), publicId, systemId); fDocumentType = (DocumentTypeImpl*)dt.fImpl; ((DocumentImpl*)fDocument.fImpl)->setDocumentType(fDocumentType); - populateDocumentType(); + + populateDocumentType(); // Add the entities and notations to this DocType. } diff --git a/src/util/PlatformUtils.cpp b/src/util/PlatformUtils.cpp index e4d7ada383bf31bc2b45c1ea5dfbfb32319881f9..d26c6c5d39a4b92c7c4153e541fce26fc3fdfee3 100644 --- a/src/util/PlatformUtils.cpp +++ b/src/util/PlatformUtils.cpp @@ -56,6 +56,12 @@ /* * $Log$ + * Revision 1.8 2000/05/09 00:22:40 andyh + * Memory Cleanup. XMLPlatformUtils::Terminate() deletes all lazily + * allocated memory; memory leak checking tools will no longer report + * that leaks exist. (DOM GetElementsByTagID temporarily removed + * as part of this.) + * * Revision 1.7 2000/03/24 19:50:29 roddey * Clear the 'initialized' flag when the termination call is made. Probably * not required technically, but... @@ -110,7 +116,7 @@ // the static data of the platform utilities class and here locally. // --------------------------------------------------------------------------- static XMLMutex* gSyncMutex = 0; -static RefVectorOf<XMLDeleter> gLazyData(512); +static RefVectorOf<XMLDeleter>* gLazyData; static bool gInitFlag = false; @@ -140,6 +146,9 @@ void XMLPlatformUtils::Initialize() // Create the local sync mutex gSyncMutex = new XMLMutex; + // Create the array for saving lazily allocated objects to be deleted at termination + gLazyData= new RefVectorOf<XMLDeleter>(512); + // // Call the platform init method, which is implemented in each of the // per-platform implementation cpp files. This one does the very low @@ -247,7 +256,7 @@ void XMLPlatformUtils::registerLazyData(XMLDeleter* const deleter) { // Just add a copy of this object to the vector. MUST be synchronized XMLMutexLock lock(gSyncMutex); - gLazyData.addElement(deleter); + gLazyData->addElement(deleter); } @@ -262,11 +271,11 @@ void XMLPlatformUtils::cleanupLazyData() // Also, note that we don't synchronize here because this is happening // during shutdown. // - while (gLazyData.size()) + while (gLazyData->size()) { try { - gLazyData.removeLastElement(); + gLazyData->removeLastElement(); } catch(...) @@ -274,4 +283,6 @@ void XMLPlatformUtils::cleanupLazyData() // We don't try to report errors here, just fall through } } + delete gLazyData; + gLazyData = 0; } diff --git a/src/util/Platforms/Win32/Win32PlatformUtils.cpp b/src/util/Platforms/Win32/Win32PlatformUtils.cpp index 6d9777db6d1fb8c395fb2d1644a9fd529e432828..d067fefcf4a9610f58271909977dcf9472eeb2f5 100644 --- a/src/util/Platforms/Win32/Win32PlatformUtils.cpp +++ b/src/util/Platforms/Win32/Win32PlatformUtils.cpp @@ -56,6 +56,12 @@ /* * $Log$ + * Revision 1.21 2000/05/09 00:22:41 andyh + * Memory Cleanup. XMLPlatformUtils::Terminate() deletes all lazily + * allocated memory; memory leak checking tools will no longer report + * that leaks exist. (DOM GetElementsByTagID temporarily removed + * as part of this.) + * * Revision 1.20 2000/04/18 23:26:01 andyh * Fix problem on NT with conflict between Korean Won Sign (0x20A9) * and backslash in file path names. @@ -156,6 +162,10 @@ #include <util/XMLUni.hpp> #include <windows.h> +#ifdef _DEBUG +#include <crtdbg.h> +#endif + // // These control which transcoding service is used by the Win32 version. // They allow this to be controlled from the build process by just defining @@ -803,6 +813,24 @@ XMLTransService* XMLPlatformUtils::makeTransService() // void XMLPlatformUtils::platformInit() { + +#if 1 && _DEBUG + // Enable this code for memeory leak testing + + // Send all reports to STDOUT + _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE ); + _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT ); + _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE ); + _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT ); + _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE ); + _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT ); + + int tmpDbgFlag; + tmpDbgFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); + tmpDbgFlag |= _CRTDBG_LEAK_CHECK_DF; + _CrtSetDbgFlag(tmpDbgFlag); +#endif + // Figure out if we are on NT and save that flag for later use OSVERSIONINFO OSVer; OSVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); diff --git a/src/util/Transcoders/Win32/Win32TransService.cpp b/src/util/Transcoders/Win32/Win32TransService.cpp index a3762c466335e555e29f1ea0de44e1035909e9cc..fecc3da41894810897bf7d09d193c3826f107261 100644 --- a/src/util/Transcoders/Win32/Win32TransService.cpp +++ b/src/util/Transcoders/Win32/Win32TransService.cpp @@ -56,6 +56,12 @@ /* * $Log$ + * Revision 1.13 2000/05/09 00:22:44 andyh + * Memory Cleanup. XMLPlatformUtils::Terminate() deletes all lazily + * allocated memory; memory leak checking tools will no longer report + * that leaks exist. (DOM GetElementsByTagID temporarily removed + * as part of this.) + * * Revision 1.12 2000/03/20 19:13:04 roddey * Fixed a compilation bug in one of the exception throwing calls. * @@ -111,14 +117,17 @@ // --------------------------------------------------------------------------- // Includes // --------------------------------------------------------------------------- +#include <util/PlatformUtils.hpp> #include <util/TranscodingException.hpp> #include <util/XMLException.hpp> #include <util/XMLString.hpp> #include <util/XMLUni.hpp> +#include <util/RefHashTableOf.hpp> #include "Win32TransService.hpp" #include <windows.h> + // --------------------------------------------------------------------------- // Local, const data // --------------------------------------------------------------------------- @@ -129,17 +138,365 @@ static const XMLCh gMyServiceId[] = + + + +// --------------------------------------------------------------------------- +// This is the simple CPMapEntry class. It just contains an encoding name +// and a code page for that encoding. +// --------------------------------------------------------------------------- +class CPMapEntry +{ +public : + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + CPMapEntry + ( + const XMLCh* const encodingName + , const unsigned int cpId + , const unsigned int ieId + ); + + CPMapEntry + ( + const char* const encodingName + , const unsigned int cpId + , const unsigned int ieId + ); + + ~CPMapEntry(); + + + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + const XMLCh* getEncodingName() const; + const XMLCh* getKey() const; + unsigned int getWinCP() const; + unsigned int getIEEncoding() const; + + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + CPMapEntry(); + CPMapEntry(const CPMapEntry&); + void operator=(const CPMapEntry&); + + + // ----------------------------------------------------------------------- + // Private data members + // + // fEncodingName + // This is the encoding name for the code page that this instance + // represents. + // + // fCPId + // This is the Windows specific code page for the encoding that this + // instance represents. + // + // fIEId + // This is the IE encoding id. Its not used at this time, but we + // go ahead and get it and store it just in case for later. + // ----------------------------------------------------------------------- + XMLCh* fEncodingName; + unsigned int fCPId; + unsigned int fIEId; +}; + +// --------------------------------------------------------------------------- +// CPMapEntry: Constructors and Destructor +// --------------------------------------------------------------------------- +CPMapEntry::CPMapEntry( const char* const encodingName + , const unsigned int cpId + , const unsigned int ieId) : + fEncodingName(0) + , fCPId(cpId) + , fIEId(ieId) +{ + // Transcode the name to Unicode and store that copy + const unsigned int srcLen = strlen(encodingName); + const unsigned int targetLen = ::mbstowcs(0, encodingName, srcLen); + fEncodingName = new XMLCh[targetLen + 1]; + ::mbstowcs(fEncodingName, encodingName, srcLen); + fEncodingName[targetLen] = 0; + + // + // Upper case it because we are using a hash table and need to be + // sure that we find all case combinations. + // + ::wcsupr(fEncodingName); +} + +CPMapEntry::CPMapEntry( const XMLCh* const encodingName + , const unsigned int cpId + , const unsigned int ieId) : + + fEncodingName(0) + , fCPId(cpId) + , fIEId(ieId) +{ + fEncodingName = XMLString::replicate(encodingName); + + // + // Upper case it because we are using a hash table and need to be + // sure that we find all case combinations. + // + ::wcsupr(fEncodingName); +} + +CPMapEntry::~CPMapEntry() +{ + delete [] fEncodingName; +} + + +// --------------------------------------------------------------------------- +// CPMapEntry: Getter methods +// --------------------------------------------------------------------------- +const XMLCh* CPMapEntry::getEncodingName() const +{ + return fEncodingName; +} + +const XMLCh* CPMapEntry::getKey() const +{ + return fEncodingName; +} + +unsigned int CPMapEntry::getWinCP() const +{ + return fCPId; +} + +unsigned int CPMapEntry::getIEEncoding() const +{ + return fIEId; +} + + + + + + +//--------------------------------------------------------------------------- +// +// class Win32TransService Implementation ... +// +//--------------------------------------------------------------------------- + + // --------------------------------------------------------------------------- // Win32TransService: Constructors and Destructor // --------------------------------------------------------------------------- Win32TransService::Win32TransService() { - // Call the init method to set up our code page map - initCPMap(); + fCPMap = new RefHashTableOf<CPMapEntry>(109); + + // + // Open up the registry key that contains the info we want. Note that, + // if this key does not exist, then we just return. It will just mean + // that we don't have any support except for intrinsic encodings supported + // by the parser itself (and the LCP support of course. + // + HKEY charsetKey; + if (::RegOpenKeyExA + ( + HKEY_CLASSES_ROOT + , "MIME\\Database\\Charset" + , 0 + , KEY_READ + , &charsetKey)) + { + return; + } + + // + // Read in the registry keys that hold the code page ids. Skip for now + // those entries which indicate that they are aliases for some other + // encodings. We'll come back and do a second round for those and look + // up the original name and get the code page id. + // + // Note that we have to use A versions here so that this will run on + // 98, and transcode the strings to Unicode. + // + const unsigned int nameBufSz = 1024; + char nameBuf[nameBufSz + 1]; + unsigned int subIndex = 0; + unsigned long theSize; + while (true) + { + // Get the name of the next key + theSize = nameBufSz; + if (::RegEnumKeyExA + ( + charsetKey + , subIndex + , nameBuf + , &theSize + , 0, 0, 0, 0) == ERROR_NO_MORE_ITEMS) + { + break; + } + + // Open this subkey + HKEY encodingKey; + if (::RegOpenKeyExA + ( + charsetKey + , nameBuf + , 0 + , KEY_READ + , &encodingKey)) + { + XMLPlatformUtils::panic(XMLPlatformUtils::Panic_NoTransService); + } + + // + // Lts see if its an alias. If so, then ignore it in this first + // loop. Else, we'll add a new entry for this one. + // + if (!isAlias(encodingKey)) + { + // + // Lets get the two values out of this key that we are + // interested in. There should be a code page entry and an + // IE entry. + // + unsigned long theType; + unsigned int CPId; + unsigned int IEId; + + theSize = sizeof(unsigned int); + if (::RegQueryValueExA + ( + encodingKey + , "Codepage" + , 0 + , &theType + , (unsigned char*)&CPId + , &theSize) != ERROR_SUCCESS) + { + XMLPlatformUtils::panic(XMLPlatformUtils::Panic_NoTransService); + } + + // + // If this is not a valid Id, and it might not be because its + // not loaded on this system, then don't take it. + // + if (::IsValidCodePage(CPId)) + { + theSize = sizeof(unsigned int); + if (::RegQueryValueExA + ( + encodingKey + , "InternetEncoding" + , 0 + , &theType + , (unsigned char*)&IEId + , &theSize) != ERROR_SUCCESS) + { + XMLPlatformUtils::panic(XMLPlatformUtils::Panic_NoTransService); + } + + CPMapEntry* newEntry = new CPMapEntry(nameBuf, CPId, IEId); + fCPMap->put(newEntry); + } + } + + // And now close the subkey handle and bump the subkey index + ::RegCloseKey(encodingKey); + subIndex++; + } + + // + // Now loop one more time and this time we do just the aliases. For + // each one we find, we look up that name in the map we've already + // built and add a new entry with this new name and the same id + // values we stored for the original. + // + subIndex = 0; + char aliasBuf[nameBufSz + 1]; + while (true) + { + // Get the name of the next key + theSize = nameBufSz; + if (::RegEnumKeyExA + ( + charsetKey + , subIndex + , nameBuf + , &theSize + , 0, 0, 0, 0) == ERROR_NO_MORE_ITEMS) + { + break; + } + + // Open this subkey + HKEY encodingKey; + if (::RegOpenKeyExA + ( + charsetKey + , nameBuf + , 0 + , KEY_READ + , &encodingKey)) + { + XMLPlatformUtils::panic(XMLPlatformUtils::Panic_NoTransService); + } + + // + // If its an alias, look up the name in the map. If we find it, + // then construct a new one with the new name and the aliased + // ids. + // + if (isAlias(encodingKey, aliasBuf, nameBufSz)) + { + const unsigned int srcLen = strlen(aliasBuf); + const unsigned int targetLen = ::mbstowcs(0, aliasBuf, srcLen); + XMLCh* uniAlias = new XMLCh[targetLen + 1]; + ::mbstowcs(uniAlias, aliasBuf, srcLen); + uniAlias[targetLen] = 0; + ::wcsupr(uniAlias); + + // Look up the alias name + CPMapEntry* aliasedEntry = fCPMap->get(uniAlias); + if (aliasedEntry) + { + // + // If the name is actually different, then take it. + // Otherwise, don't take it. They map aliases that are + // just different case. + // + if (::wcscmp(uniAlias, aliasedEntry->getEncodingName())) + { + CPMapEntry* newEntry = new CPMapEntry + ( + uniAlias + , aliasedEntry->getWinCP() + , aliasedEntry->getIEEncoding() + ); + fCPMap->put(newEntry); + } + } + delete [] uniAlias; + } + + // And now close the subkey handle and bump the subkey index + ::RegCloseKey(encodingKey); + subIndex++; + } + + // And close the main key handle + ::RegCloseKey(charsetKey); + } Win32TransService::~Win32TransService() { + delete fCPMap; } @@ -197,6 +554,74 @@ void Win32TransService::upperCase(XMLCh* const toUpperCase) const } +bool Win32TransService::isAlias(const HKEY encodingKey + , char* const aliasBuf + , const unsigned int nameBufSz ) +{ + unsigned long theType; + unsigned long theSize = nameBufSz; + return (::RegQueryValueExA + ( + encodingKey + , "AliasForCharset" + , 0 + , &theType + , (unsigned char*)aliasBuf + , &theSize + ) == ERROR_SUCCESS); +} + + +XMLTranscoder* +Win32TransService::makeNewXMLTranscoder(const XMLCh* const encodingName + , XMLTransService::Codes& resValue + , const unsigned int blockSize) +{ + const unsigned int upLen = 1024; + XMLCh upEncoding[upLen + 1]; + + // + // Get an upper cased copy of the encoding name, since we use a hash + // table and we store them all in upper case. + // + ::wcsncpy(upEncoding, encodingName, upLen); + upEncoding[upLen] = 0; + ::wcsupr(upEncoding); + + // Now to try to find this guy in the CP map + CPMapEntry* theEntry = fCPMap->get(upEncoding); + + // If not found, then return a null pointer + if (!theEntry) + { + resValue = XMLTransService::UnsupportedEncoding; + return 0; + } + + // We found it, so return a Win32 transcoder for this encoding + return new Win32Transcoder + ( + encodingName + , theEntry->getWinCP() + , theEntry->getIEEncoding() + , blockSize + ); +} + + + + + + + + +//--------------------------------------------------------------------------- +// +// class Win32Transcoder Implementation ... +// +//--------------------------------------------------------------------------- + + // --------------------------------------------------------------------------- // Win32Transcoder: Constructors and Destructor // --------------------------------------------------------------------------- @@ -419,6 +844,14 @@ bool Win32Transcoder::canTranscodeTo(const unsigned int toCheck) const } + + +//--------------------------------------------------------------------------- +// +// class Win32Transcoder Implementation ... +// +//--------------------------------------------------------------------------- + // --------------------------------------------------------------------------- // Win32LCPTranscoder: Constructors and Destructor // --------------------------------------------------------------------------- @@ -565,3 +998,9 @@ bool Win32LCPTranscoder::transcode( const XMLCh* const toTranscode toFill[maxBytes] = 0; return true; } + + + + + + diff --git a/src/util/Transcoders/Win32/Win32TransService.hpp b/src/util/Transcoders/Win32/Win32TransService.hpp index 9648b7e06c635a25290527aeee266473b2f7f10d..bab7adee644c9af5d7d55c3346e1eb118927e921 100644 --- a/src/util/Transcoders/Win32/Win32TransService.hpp +++ b/src/util/Transcoders/Win32/Win32TransService.hpp @@ -56,6 +56,12 @@ /* * $Log$ + * Revision 1.10 2000/05/09 00:22:45 andyh + * Memory Cleanup. XMLPlatformUtils::Terminate() deletes all lazily + * allocated memory; memory leak checking tools will no longer report + * that leaks exist. (DOM GetElementsByTagID temporarily removed + * as part of this.) + * * Revision 1.9 2000/03/18 00:00:04 roddey * Initial updates for two way transcoding support * @@ -98,7 +104,18 @@ #define WIN32TRANSSERVICE_HPP #include <util/TransService.hpp> +#include <util/RefHashTableOf.hpp> +#include <windows.h> + +class CPMapEntry; + + +//--------------------------------------------------------------------------- +// +// class Win32TransService +// +//--------------------------------------------------------------------------- class XMLUTIL_EXPORT Win32TransService : public XMLTransService { public : @@ -106,7 +123,7 @@ public : // Constructors and Destructor // ----------------------------------------------------------------------- Win32TransService(); - ~Win32TransService(); + virtual ~Win32TransService(); // ----------------------------------------------------------------------- @@ -155,15 +172,36 @@ private : Win32TransService(const Win32TransService&); void operator=(const Win32TransService&); + // This is a hash table of entries which map encoding names to their + // Windows specific code pages. The code page allows us to create + // transcoders for those encodings. The encoding names come from XML + // files. + // + // This map is shared unsynchronized among all threads of the process, + // which is cool since it will be read only once its initialized. - // ----------------------------------------------------------------------- - // Private helper methods, implemented in Win32TransService2.cpp! - // ----------------------------------------------------------------------- - void initCPMap(); + + + static bool isAlias(const HKEY encodingKey + , char* const aliasBuf = 0 + , const unsigned int nameBufSz = 0); + + + RefHashTableOf<CPMapEntry> *fCPMap; }; + + + + +//--------------------------------------------------------------------------- +// +// class Win32Transcoder +// +//--------------------------------------------------------------------------- + class XMLUTIL_EXPORT Win32Transcoder : public XMLTranscoder { public : @@ -231,6 +269,13 @@ private : + + +//--------------------------------------------------------------------------- +// +// class Win32LCPTranscoder +// +//--------------------------------------------------------------------------- class XMLUTIL_EXPORT Win32LCPTranscoder : public XMLLCPTranscoder { public : diff --git a/src/util/Transcoders/Win32/Win32TransService2.cpp b/src/util/Transcoders/Win32/Win32TransService2.cpp index 56b3ec4c6f7464c200ed1574f7b477d09e96800d..08debf47b07a377ac65f4cae3010af679d373555 100644 --- a/src/util/Transcoders/Win32/Win32TransService2.cpp +++ b/src/util/Transcoders/Win32/Win32TransService2.cpp @@ -56,6 +56,12 @@ /* * $Log$ + * Revision 1.3 2000/05/09 00:22:45 andyh + * Memory Cleanup. XMLPlatformUtils::Terminate() deletes all lazily + * allocated memory; memory leak checking tools will no longer report + * that leaks exist. (DOM GetElementsByTagID temporarily removed + * as part of this.) + * * Revision 1.2 2000/03/18 00:00:04 roddey * Initial updates for two way transcoding support * @@ -75,424 +81,3 @@ #include <windows.h> -// --------------------------------------------------------------------------- -// This is the simple CPMapEntry class. It just contains an encoding name -// and a code page for that encoding. -// --------------------------------------------------------------------------- -class CPMapEntry -{ -public : - // ----------------------------------------------------------------------- - // Constructors and Destructor - // ----------------------------------------------------------------------- - CPMapEntry - ( - const XMLCh* const encodingName - , const unsigned int cpId - , const unsigned int ieId - ); - - CPMapEntry - ( - const char* const encodingName - , const unsigned int cpId - , const unsigned int ieId - ); - - ~CPMapEntry(); - - - // ----------------------------------------------------------------------- - // Getter methods - // ----------------------------------------------------------------------- - const XMLCh* getEncodingName() const; - const XMLCh* getKey() const; - unsigned int getWinCP() const; - unsigned int getIEEncoding() const; - - -private : - // ----------------------------------------------------------------------- - // Unimplemented constructors and operators - // ----------------------------------------------------------------------- - CPMapEntry(); - CPMapEntry(const CPMapEntry&); - void operator=(const CPMapEntry&); - - - // ----------------------------------------------------------------------- - // Private data members - // - // fEncodingName - // This is the encoding name for the code page that this instance - // represents. - // - // fCPId - // This is the Windows specific code page for the encoding that this - // instance represents. - // - // fIEId - // This is the IE encoding id. Its not used at this time, but we - // go ahead and get it and store it just in case for later. - // ----------------------------------------------------------------------- - XMLCh* fEncodingName; - unsigned int fCPId; - unsigned int fIEId; -}; - - - -// --------------------------------------------------------------------------- -// Local data -// -// gCPMap -// This is hash table of entries which map encoding names to their -// Windows specific code pages. The code page allows us to create -// transcoders for those encodings. The encoding names come from XML -// files. -// -// This map is shared unsynchronized among all threads of the process, -// which is cool since it will be read only once its initialized. -// --------------------------------------------------------------------------- -RefHashTableOf<CPMapEntry> gCPMap(109); - - -// --------------------------------------------------------------------------- -// CPMapEntry: Constructors and Destructor -// --------------------------------------------------------------------------- -CPMapEntry::CPMapEntry( const char* const encodingName - , const unsigned int cpId - , const unsigned int ieId) : - fEncodingName(0) - , fCPId(cpId) - , fIEId(ieId) -{ - // Transcode the name to Unicode and store that copy - const unsigned int srcLen = strlen(encodingName); - const unsigned int targetLen = ::mbstowcs(0, encodingName, srcLen); - fEncodingName = new XMLCh[targetLen + 1]; - ::mbstowcs(fEncodingName, encodingName, srcLen); - fEncodingName[targetLen] = 0; - - // - // Upper case it because we are using a hash table and need to be - // sure that we find all case combinations. - // - ::wcsupr(fEncodingName); -} - -CPMapEntry::CPMapEntry( const XMLCh* const encodingName - , const unsigned int cpId - , const unsigned int ieId) : - - fEncodingName(0) - , fCPId(cpId) - , fIEId(ieId) -{ - fEncodingName = XMLString::replicate(encodingName); - - // - // Upper case it because we are using a hash table and need to be - // sure that we find all case combinations. - // - ::wcsupr(fEncodingName); -} - -CPMapEntry::~CPMapEntry() -{ - delete [] fEncodingName; -} - - -// --------------------------------------------------------------------------- -// CPMapEntry: Getter methods -// --------------------------------------------------------------------------- -const XMLCh* CPMapEntry::getEncodingName() const -{ - return fEncodingName; -} - -const XMLCh* CPMapEntry::getKey() const -{ - return fEncodingName; -} - -unsigned int CPMapEntry::getWinCP() const -{ - return fCPId; -} - -unsigned int CPMapEntry::getIEEncoding() const -{ - return fIEId; -} - - - -// --------------------------------------------------------------------------- -// Local methods -// --------------------------------------------------------------------------- -static bool isAlias(const HKEY encodingKey - , char* const aliasBuf = 0 - , const unsigned int nameBufSz = 0) -{ - unsigned long theType; - unsigned long theSize = nameBufSz; - return (::RegQueryValueExA - ( - encodingKey - , "AliasForCharset" - , 0 - , &theType - , (unsigned char*)aliasBuf - , &theSize - ) == ERROR_SUCCESS); -} - - -// --------------------------------------------------------------------------- -// Win32TransService: The protected virtual transcoding service API -// --------------------------------------------------------------------------- -XMLTranscoder* -Win32TransService::makeNewXMLTranscoder(const XMLCh* const encodingName - , XMLTransService::Codes& resValue - , const unsigned int blockSize) -{ - const unsigned int upLen = 1024; - XMLCh upEncoding[upLen + 1]; - - // - // Get an upper cased copy of the encoding name, since we use a hash - // table and we store them all in upper case. - // - ::wcsncpy(upEncoding, encodingName, upLen); - upEncoding[upLen] = 0; - ::wcsupr(upEncoding); - - // Now to try to find this guy in the CP map - CPMapEntry* theEntry = gCPMap.get(upEncoding); - - // If not found, then return a null pointer - if (!theEntry) - { - resValue = XMLTransService::UnsupportedEncoding; - return 0; - } - - // We found it, so return a Win32 transcoder for this encoding - return new Win32Transcoder - ( - encodingName - , theEntry->getWinCP() - , theEntry->getIEEncoding() - , blockSize - ); -} - - - -// --------------------------------------------------------------------------- -// Win32TransService: Private helper methods -// --------------------------------------------------------------------------- -void Win32TransService::initCPMap() -{ - // - // Open up the registry key that contains the info we want. Note that, - // if this key does not exist, then we just return. It will just mean - // that we don't have any support except for intrinsic encodings supported - // by the parser itself (and the LCP support of course. - // - HKEY charsetKey; - if (::RegOpenKeyExA - ( - HKEY_CLASSES_ROOT - , "MIME\\Database\\Charset" - , 0 - , KEY_READ - , &charsetKey)) - { - return; - } - - // - // Read in the registry keys that hold the code page ids. Skip for now - // those entries which indicate that they are aliases for some other - // encodings. We'll come back and do a second round for those and look - // up the original name and get the code page id. - // - // Note that we have to use A versions here so that this will run on - // 98, and transcode the strings to Unicode. - // - const unsigned int nameBufSz = 1024; - char nameBuf[nameBufSz + 1]; - unsigned int subIndex = 0; - unsigned long theSize; - while (true) - { - // Get the name of the next key - theSize = nameBufSz; - if (::RegEnumKeyExA - ( - charsetKey - , subIndex - , nameBuf - , &theSize - , 0, 0, 0, 0) == ERROR_NO_MORE_ITEMS) - { - break; - } - - // Open this subkey - HKEY encodingKey; - if (::RegOpenKeyExA - ( - charsetKey - , nameBuf - , 0 - , KEY_READ - , &encodingKey)) - { - XMLPlatformUtils::panic(XMLPlatformUtils::Panic_NoTransService); - } - - // - // Lts see if its an alias. If so, then ignore it in this first - // loop. Else, we'll add a new entry for this one. - // - if (!isAlias(encodingKey)) - { - // - // Lets get the two values out of this key that we are - // interested in. There should be a code page entry and an - // IE entry. - // - unsigned long theType; - unsigned int CPId; - unsigned int IEId; - - theSize = sizeof(unsigned int); - if (::RegQueryValueExA - ( - encodingKey - , "Codepage" - , 0 - , &theType - , (unsigned char*)&CPId - , &theSize) != ERROR_SUCCESS) - { - XMLPlatformUtils::panic(XMLPlatformUtils::Panic_NoTransService); - } - - // - // If this is not a valid Id, and it might not be because its - // not loaded on this system, then don't take it. - // - if (::IsValidCodePage(CPId)) - { - theSize = sizeof(unsigned int); - if (::RegQueryValueExA - ( - encodingKey - , "InternetEncoding" - , 0 - , &theType - , (unsigned char*)&IEId - , &theSize) != ERROR_SUCCESS) - { - XMLPlatformUtils::panic(XMLPlatformUtils::Panic_NoTransService); - } - - CPMapEntry* newEntry = new CPMapEntry(nameBuf, CPId, IEId); - gCPMap.put(newEntry); - } - } - - // And now close the subkey handle and bump the subkey index - ::RegCloseKey(encodingKey); - subIndex++; - } - - // - // Now loop one more time and this time we do just the aliases. For - // each one we find, we look up that name in the map we've already - // built and add a new entry with this new name and the same id - // values we stored for the original. - // - subIndex = 0; - char aliasBuf[nameBufSz + 1]; - while (true) - { - // Get the name of the next key - theSize = nameBufSz; - if (::RegEnumKeyExA - ( - charsetKey - , subIndex - , nameBuf - , &theSize - , 0, 0, 0, 0) == ERROR_NO_MORE_ITEMS) - { - break; - } - - // Open this subkey - HKEY encodingKey; - if (::RegOpenKeyExA - ( - charsetKey - , nameBuf - , 0 - , KEY_READ - , &encodingKey)) - { - XMLPlatformUtils::panic(XMLPlatformUtils::Panic_NoTransService); - } - - // - // If its an alias, look up the name in the map. If we find it, - // then construct a new one with the new name and the aliased - // ids. - // - if (isAlias(encodingKey, aliasBuf, nameBufSz)) - { - const unsigned int srcLen = strlen(aliasBuf); - const unsigned int targetLen = ::mbstowcs(0, aliasBuf, srcLen); - XMLCh* uniAlias = new XMLCh[targetLen + 1]; - ::mbstowcs(uniAlias, aliasBuf, srcLen); - uniAlias[targetLen] = 0; - ::wcsupr(uniAlias); - - // Look up the alias name - CPMapEntry* aliasedEntry = gCPMap.get(uniAlias); - if (aliasedEntry) - { - // - // If the name is actually different, then take it. - // Otherwise, don't take it. They map aliases that are - // just different case. - // - if (::wcscmp(uniAlias, aliasedEntry->getEncodingName())) - { - CPMapEntry* newEntry = new CPMapEntry - ( - uniAlias - , aliasedEntry->getWinCP() - , aliasedEntry->getIEEncoding() - ); - gCPMap.put(newEntry); - } - } - else - { - delete [] uniAlias; - } - } - - // And now close the subkey handle and bump the subkey index - ::RegCloseKey(encodingKey); - subIndex++; - } - - // And close the main key handle - ::RegCloseKey(charsetKey); -} diff --git a/src/util/XMLException.cpp b/src/util/XMLException.cpp index 21324e53cbe9e4be7ca26586ea0bf97e87ec666e..800c6a8add0cd05dcc0d59be2b3e0f49437fc3cc 100644 --- a/src/util/XMLException.cpp +++ b/src/util/XMLException.cpp @@ -56,6 +56,12 @@ /* * $Log$ + * Revision 1.5 2000/05/09 00:22:40 andyh + * Memory Cleanup. XMLPlatformUtils::Terminate() deletes all lazily + * allocated memory; memory leak checking tools will no longer report + * that leaks exist. (DOM GetElementsByTagID temporarily removed + * as part of this.) + * * Revision 1.4 2000/03/02 19:54:48 roddey * This checkin includes many changes done while waiting for the * 1.1.0 code to be finished. I can't list them all here, but a list is @@ -83,6 +89,7 @@ // --------------------------------------------------------------------------- #include <util/Mutexes.hpp> #include <util/PlatformUtils.hpp> +#include <util/XMLDeleterFor.hpp> #include <util/XMLException.hpp> #include <util/XMLMsgLoader.hpp> #include <util/XMLString.hpp> @@ -122,9 +129,18 @@ static XMLMutex& gMsgMutex() XMLMutex* tmpMutex = new XMLMutex; if (XMLPlatformUtils::compareAndSwap((void**)&msgMutex, tmpMutex, 0)) { - // Someone beat us to it, so let's clean up ours + // Some other thread beat us to it, so let's clean up ours. delete tmpMutex; } + else + { + // This is the real mutex. Register it for deletion at Termination. + XMLPlatformUtils::registerLazyData + ( + new XMLDeleterFor<XMLMutex>(msgMutex) + ); + } + } return *msgMutex; } @@ -151,8 +167,17 @@ static XMLMsgLoader& gGetMsgLoader() gLoader = XMLPlatformUtils::loadMsgSet(XMLUni::fgExceptDomain); if (!gLoader) XMLPlatformUtils::panic(XMLPlatformUtils::Panic_CantLoadMsgDomain); - } + // + // Register this XMLMsgLoader for deletion at Termination. + // + XMLPlatformUtils::registerLazyData + ( + new XMLDeleterFor<XMLMsgLoader>(gLoader) + ); + + } + // We got it, so return it return *gLoader; } diff --git a/tests/DOM/DOMMemTest/DOMMemTest.cpp b/tests/DOM/DOMMemTest/DOMMemTest.cpp index 3fffe143950a4766fc668a2a7141c52c2dd1ab0d..13dd5c4a4603707452f32b4cb48515dc14cbae56 100644 --- a/tests/DOM/DOMMemTest/DOMMemTest.cpp +++ b/tests/DOM/DOMMemTest/DOMMemTest.cpp @@ -66,6 +66,12 @@ /* * $Log$ + * Revision 1.22 2000/05/09 00:22:48 andyh + * Memory Cleanup. XMLPlatformUtils::Terminate() deletes all lazily + * allocated memory; memory leak checking tools will no longer report + * that leaks exist. (DOM GetElementsByTagID temporarily removed + * as part of this.) + * * Revision 1.21 2000/04/18 01:07:28 aruna1 * Rectified memory leak caused by doctype-getNodeName() * @@ -191,23 +197,15 @@ void tassert(bool c, char *file, int line) } - - -int main() +//--------------------------------------------------------------------------------------- +// +// DOMStringTests tests of class DOMString +// +//--------------------------------------------------------------------------------------- +void DOMStringTests() { DomMemDebug entryMemState, exitMemState; - - try { - XMLPlatformUtils::Initialize(); - } - catch (const XMLException& toCatch) { - char *pMessage = XMLString::transcode(toCatch.getMessage()); - fprintf(stderr, "Error during XMLPlatformUtils::Initialize(). \n" - " Message is: %s\n", pMessage); - delete [] pMessage; - return -1; - } - + // // Test 1. Basic operations on a simple string. // @@ -223,29 +221,28 @@ int main() TASSERT(foo.charAt(3) == 0); } TESTEPILOG - - - // - // Construct from XMLCh * - // - TESTPROLOG + + // + // Construct from XMLCh * + // + TESTPROLOG { // ToDo - this test will fail on EBCDIC machines. !! - + XMLCh a[] = {'H', 'e', 'l', 'l', 'o', 0}; DOMString x(a); DOMString y = "Hello"; TASSERT(x.equals(y)); - + DOMString z(a+2, 3); TASSERT(z.equals("llo")); } TESTEPILOG - - // - // Test 2. Empty strings shouldn't leave anything lying around - // - TESTPROLOG; + + // + // Test 2. Empty strings shouldn't leave anything lying around + // + TESTPROLOG; { DOMString a; DOMString b; @@ -253,18 +250,18 @@ int main() a = 0; TASSERT(a==0); TASSERT((a!=0) == false); - + DOMString c(0); TASSERT(c==0); TASSERT(c==a); } TESTEPILOG - - - // - // Test 3. Clones should be equal. - TESTPROLOG; - { + + + // + // Test 3. Clones should be equal. + TESTPROLOG; + { DOMString a = "hello"; DOMString b = a.clone(); TASSERT(a.equals(b)); @@ -275,12 +272,12 @@ int main() TASSERT(a.equals("")); } TESTEPILOG - - - // - // Test 4. Copy construction and assignemnt - // - TESTPROLOG; + + + // + // Test 4. Copy construction and assignemnt + // + TESTPROLOG; { DOMString a = "Test 04"; DOMString b(a); @@ -295,32 +292,32 @@ int main() // printf (" test04 should have 1 handle, 1 buffer here. "); } TESTEPILOG - - - // - // Test 5 AppendData, degenerate cases. - // - TESTPROLOG; + + + // + // Test 5 AppendData, degenerate cases. + // + TESTPROLOG; { DOMString a; DOMString b = "Test 05"; - + a.appendData(b); TASSERT(a.equals(b)); TASSERT(a!=b); TASSERT(a.equals("Test 05")); }; TESTEPILOG - - - // - // Test 6 Append data, degenerate case 2 - // - TESTPROLOG; + + + // + // Test 6 Append data, degenerate case 2 + // + TESTPROLOG; { DOMString a; DOMString b = "Test 06"; - + b.appendData(a); TASSERT(!a.equals(b)); TASSERT(a!=b); @@ -328,52 +325,52 @@ int main() TASSERT(a==0); } TESTEPILOG - - - // - // Test 7 Append Data, Common case, no extra space in original buffer. - // Also, operator +=, which is a convenience alias for appendData. - // - TESTPROLOG; + + + // + // Test 7 Append Data, Common case, no extra space in original buffer. + // Also, operator +=, which is a convenience alias for appendData. + // + TESTPROLOG; { DOMString a = "Test 07"; DOMString b = "append"; - + a.appendData(b); TASSERT(a.equals("Test 07append")); TASSERT(b.equals("append")); - + a.appendData((XMLCh)0x31); TASSERT(a.equals("Test 07append1")); - + XMLCh s[] = {0x32, 0x33, 0x00}; a.appendData(s); TASSERT(a.equals("Test 07append123")); - + a = "Test 07a "; a += b; TASSERT(a.equals("Test 07a append")); - + a += (XMLCh)0x31; TASSERT(a.equals("Test 07a append1")); - + a += s; TASSERT(a.equals("Test 07a append123")); - + } TESTEPILOG - - - // - // Test 8 Append Data, with plenty of extra space in buffer. - // - TESTPROLOG; + + + // + // Test 8 Append Data, with plenty of extra space in buffer. + // + TESTPROLOG; { DOMString a; - a.reserve(100); + a.reserve(100); DOMString b("Test 08"); DOMString c("append"); - + TASSERT(a != 0); // (The String object has an identity, even if no contents) TASSERT(a.length() == 0); a.appendData(b); @@ -386,26 +383,26 @@ int main() TASSERT(c.equals("append")); }; TESTEPILOG - - - - // - // Test 9 Append Data, with plenty of extra space in buffer, but with - // a clone, so that the original buffer can not be modified. - // - TESTPROLOG; + + + + // + // Test 9 Append Data, with plenty of extra space in buffer, but with + // a clone, so that the original buffer can not be modified. + // + TESTPROLOG; { DOMString a; - a.reserve(100); + a.reserve(100); DOMString b("Test 09"); DOMString c("append"); - + TASSERT(a.length() == 0); a.appendData(b); TASSERT(a.equals(b)); TASSERT(a.equals("Test 09")); TASSERT(a != b); - + DOMString d = a.clone(); TASSERT(a.equals("Test 09")); TASSERT(b.equals("Test 09")); @@ -413,7 +410,7 @@ int main() TASSERT(a != b); TASSERT(a != d); TASSERT(b != d); - + a.appendData(c); TASSERT(a.equals("Test 09append")); TASSERT(b.equals("Test 09")); @@ -421,8 +418,8 @@ int main() TASSERT(d.equals("Test 09")); }; TESTEPILOG; - - + + // // Test 10 DOMString Operator + // @@ -432,25 +429,25 @@ int main() DOMString b("DOMString "); XMLCh s[] = {0x58, 0x4d, 0x4c, 0x20, 0x00}; // Unicode "XML " XMLCh Z = 0x5A; // Unicode 'Z' - + a = b + b; TASSERT(a.equals("DOMString DOMString ")); - + a = b + s; TASSERT(a.equals("DOMString XML ")); - + a = s + b; TASSERT(a.equals("XML DOMString ")); - + a = b + Z; TASSERT(a.equals("DOMString Z")); - + a = Z + b; TASSERT(a.equals("ZDOMString ")); } TESTEPILOG; - - + + // // Test 11 DOMString::subStringData(unsigned int offset, unsigned int count) // @@ -458,33 +455,33 @@ int main() { DOMString srcString("This is the source string."); // 01234567890123456789012345 - + DOMString This = srcString.substringData(0,4); DOMString is = srcString.substringData(5,2); DOMString dot = srcString.substringData(25,1); DOMString offEnd = srcString.substringData(19, 1000); - + TASSERT(This.equals("This")); TASSERT(is .equals("is")); TASSERT(dot .equals(".")); TASSERT(offEnd.equals("string.")); - + EXCEPTION_TEST(srcString.substringData(-1, 10), DOM_DOMException::INDEX_SIZE_ERR); EXCEPTION_TEST(srcString.substringData(26, 1), DOM_DOMException::INDEX_SIZE_ERR); - + srcString.insertData(0, "x"); // Changing the source should not alter previously - // extracted substrings. - + // extracted substrings. + TASSERT(This.equals("This")); TASSERT(is .equals("is")); TASSERT(dot .equals(".")); TASSERT(offEnd.equals("string.")); TASSERT(srcString.equals("xThis is the source string.")); - + } TESTEPILOG; - - + + // // Test 12 DOMString::insertData(unsigned int offset, DOMString &src) // @@ -492,36 +489,97 @@ int main() { DOMString aString("This is a string."); // 01234567890123456 - + aString.insertData(17, " Added at end."); TASSERT(aString.equals("This is a string. Added at end.")); - + aString = "This is a string."; EXCEPTION_TEST(aString.insertData(18, "x"), DOM_DOMException::INDEX_SIZE_ERR); TASSERT(aString.equals("This is a string.")); - + aString = 0; aString.reserve(100); aString.appendData("This is a string."); aString.insertData(17, " Added at end."); TASSERT(aString.equals("This is a string. Added at end.")); - + aString.insertData(0, "So "); TASSERT(aString.equals("So This is a string. Added at end.")); - + aString.insertData(2, "x"); TASSERT(aString.equals("Sox This is a string. Added at end.")); - + EXCEPTION_TEST(aString.substringData(-1, 1), DOM_DOMException::INDEX_SIZE_ERR); + + + } + TESTEPILOG; + + // + // Minimal test of DOMString::transcode() + // + TESTPROLOG; + { + static char testStr[] = "This is our test string."; - } + DOMString DOMTestStr = testStr; + char *roundTripString = DOMTestStr.transcode(); + TASSERT(strcmp(testStr, roundTripString) == 0); + delete [] roundTripString; + + DOMString domstr2 = DOMString::transcode(testStr); + TASSERT(domstr2.equals(DOMTestStr)); + } TESTEPILOG; + // + // String bugs submitted by David Chung + // + TESTPROLOG; + { + DOMString greeting("hello"); + greeting.appendData(greeting); + TASSERT(greeting.equals("hellohello")); + + + // Test DOMString.insertData, when source string is the same as the destination. + // Implementation forces creation of a new buffer. + // + DOMString greeting2("Hello "); + // 0123456789012345678 + greeting2.deleteData(5, 14); // Leave unused space at end of buffer. + TASSERT(greeting2.equals("Hello")); + + greeting2.insertData(2, greeting2); + TASSERT(greeting2.equals("HeHellollo")); + + + // DOMString.insertData(). Original buffer has space, and is retained. + DOMString greeting3("Hello "); + // 0123456789012345678 + greeting3.deleteData(5, 14); // Leave unused space at end of buffer. + TASSERT(greeting3.equals("Hello")); + + greeting3.insertData(2, "ByeBye"); + TASSERT(greeting3.equals("HeByeByello")); + + } + TESTEPILOG; + +} +//--------------------------------------------------------------------------------------- +// +// DOMBasicTests Basic DOM Level 1 tests +// +//--------------------------------------------------------------------------------------- +void DOMBasicTests() +{ + DomMemDebug entryMemState, exitMemState; // // Test Doc01 Create a new empty document // @@ -946,57 +1004,18 @@ int main() TESTEPILOG; - // - // Minimal test of DOMString::transcode() - // - TESTPROLOG; - { - static char testStr[] = "This is our test string."; - - DOMString DOMTestStr = testStr; - char *roundTripString = DOMTestStr.transcode(); - TASSERT(strcmp(testStr, roundTripString) == 0); - delete [] roundTripString; - - DOMString domstr2 = DOMString::transcode(testStr); - TASSERT(domstr2.equals(DOMTestStr)); - } - TESTEPILOG; - - - // - // String bugs submitted by David Chung - // - TESTPROLOG; - { - DOMString greeting("hello"); - greeting.appendData(greeting); - TASSERT(greeting.equals("hellohello")); - - - // Test DOMString.insertData, when source string is the same as the destination. - // Implementation forces creation of a new buffer. - // - DOMString greeting2("Hello "); - // 0123456789012345678 - greeting2.deleteData(5, 14); // Leave unused space at end of buffer. - TASSERT(greeting2.equals("Hello")); - - greeting2.insertData(2, greeting2); - TASSERT(greeting2.equals("HeHellollo")); - +} - // DOMString.insertData(). Original buffer has space, and is retained. - DOMString greeting3("Hello "); - // 0123456789012345678 - greeting3.deleteData(5, 14); // Leave unused space at end of buffer. - TASSERT(greeting3.equals("Hello")); - greeting3.insertData(2, "ByeBye"); - TASSERT(greeting3.equals("HeByeByello")); +//--------------------------------------------------------------------------------------- +// +// DOMNSTests DOM Name Space tests +// +//--------------------------------------------------------------------------------------- +void DOMNSTests() +{ + DomMemDebug entryMemState, exitMemState; - } - TESTEPILOG; // @@ -1612,19 +1631,51 @@ int main() } TESTEPILOG; - + // + // + // + TESTPROLOG; { - } - + TESTEPILOG; + +} + + + +//--------------------------------------------------------------------------------------- +// +// main +// +//--------------------------------------------------------------------------------------- +int main() +{ + try { + XMLPlatformUtils::Initialize(); + } + catch (const XMLException& toCatch) { + char *pMessage = XMLString::transcode(toCatch.getMessage()); + fprintf(stderr, "Error during XMLPlatformUtils::Initialize(). \n" + " Message is: %s\n", pMessage); + delete [] pMessage; + return -1; + } + + + DOMStringTests(); + DOMBasicTests(); + DOMNSTests(); + // - // Print Final allocation stats for full test + // Print Final allocation stats for full set of tests // + XMLPlatformUtils::Terminate(); DomMemDebug().print(); - return 0; - }; - - + +}; + + +