$NetBSD: patch-at,v 1.1 2005/12/31 00:56:42 joerg Exp $ --- /dev/null 2005-12-31 00:16:30.000000000 +0000 +++ util/Platforms/DragonFly/DragonFlyPlatformUtils.cpp @@ -0,0 +1,662 @@ +/* + * 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 + * . + */ + +/* + * + * + */ + + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- + +#if !defined(APP_NO_THREADS) +#include +#endif + +/* #ifndef __USE_UNIX98 + #error __USE_UNIX98 is not defined in your compile settings +#endif */ + +#include +#include +#include +#include +#include +#include +#include +#include /* for strcasecmp & strncasecmp */ +#include /* for win_t */ +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(XML_USE_ICU_TRANSCODER) + #include +#elif defined (XML_USE_GNU_TRANSCODER) + #include +#else + // Use native transcoder. Same as -DXML_USE_NATIVE_TRANSCODER + #include +#endif + + +#if defined(XML_USE_ICU_MESSAGELOADER) + #include +#elif defined(XML_USE_ICONV_MESSAGELOADER) + #include +#else + // Same as -DXML_USE_INMEM_MESSAGELOADER + #include +#endif + + +#if defined (XML_USE_NETACCESSOR_SOCKET) + #include +#endif + +XERCES_CPP_NAMESPACE_BEGIN + +// --------------------------------------------------------------------------- +// Local Methods +// --------------------------------------------------------------------------- + +static void WriteCharStr( FILE* stream, const char* const toWrite) +{ + if (fputs(toWrite, stream) == EOF) + { + ThrowXML(XMLPlatformUtilsException, + XMLExcepts::Strm_StdErrWriteFailure); + } +} + +static void WriteUStrStdErr( const XMLCh* const toWrite) +{ + char* tmpVal = XMLString::transcode(toWrite); + ArrayJanitor janText(tmpVal); + if (fputs(tmpVal, stderr) == EOF) + { + ThrowXML(XMLPlatformUtilsException, + XMLExcepts::Strm_StdErrWriteFailure); + } +} + +static void WriteUStrStdOut( const XMLCh* const toWrite) + { + char* tmpVal = XMLString::transcode(toWrite); + ArrayJanitor janText(tmpVal); + if (fputs(tmpVal, stdout) == EOF) + { + ThrowXML(XMLPlatformUtilsException, + XMLExcepts::Strm_StdOutWriteFailure); + } +} + +XMLNetAccessor* XMLPlatformUtils::makeNetAccessor() +{ +#if defined (XML_USE_NETACCESSOR_SOCKET) + return new SocketNetAccessor(); +#else + return 0; +#endif +} + +// --------------------------------------------------------------------------- +// XMLPlatformUtils: Private Static Methods +// --------------------------------------------------------------------------- + +// +// This method is called by the platform independent part of this class +// when client code asks to have one of the supported message sets loaded. +// + +XMLMsgLoader* XMLPlatformUtils::loadAMsgSet(const XMLCh* const msgDomain) +{ + XMLMsgLoader* retVal; + try + { +#if defined (XML_USE_ICU_MESSAGELOADER) + retVal = new ICUMsgLoader(msgDomain); +#elif defined (XML_USE_ICONV_MESSAGELOADER) + retVal = new MsgCatalogLoader(msgDomain); +#else + // same as -DXML_USE_INMEM_MESSAGELOADER + retVal = new InMemMsgLoader(msgDomain); +#endif + } + + catch(...) + { + panic(PanicHandler::Panic_CantLoadMsgDomain); + } + return retVal; +} + + +// +// This method is called very early in the bootstrapping process. This guy +// must create a transcoding service and return it. It cannot use any string +// methods, any transcoding services, throw any exceptions, etc... It just +// makes a transcoding service and returns it, or returns zero on failure. +// + +XMLTransService* XMLPlatformUtils::makeTransService() +{ +#if defined (XML_USE_ICU_TRANSCODER) + // Use ICU transcoding services. + // same as -DXML_USE_ICU_MESSAGELOADER + return new ICUTransService; +#elif defined (XML_USE_GNU_TRANSCODER) + return new IconvGNUTransService; +#else + // Use native transcoding services. + // same as -DXML_USE_INMEM_MESSAGELOADER + return new IconvTransService; + +#endif +} + +// --------------------------------------------------------------------------- +// XMLPlatformUtils: The panic method +// --------------------------------------------------------------------------- +void XMLPlatformUtils::panic(const PanicHandler::PanicReasons reason) +{ + fgUserPanicHandler? fgUserPanicHandler->panic(reason) : fgDefaultPanicHandler->panic(reason); +} + + +// --------------------------------------------------------------------------- +// XMLPlatformUtils: File Methods +// --------------------------------------------------------------------------- + +unsigned int XMLPlatformUtils::curFilePos(FileHandle theFile) +{ + if (theFile == NULL) + ThrowXML(XMLPlatformUtilsException, + XMLExcepts::CPtr_PointerIsZero); + int curPos = ftell( (FILE*)theFile); + if (curPos == -1) + ThrowXML(XMLPlatformUtilsException, + XMLExcepts::File_CouldNotGetSize); + + return (unsigned int)curPos; +} + +void XMLPlatformUtils::closeFile(FileHandle theFile) +{ + if (theFile == NULL) + ThrowXML(XMLPlatformUtilsException, + XMLExcepts::CPtr_PointerIsZero); + if (fclose((FILE*)theFile)) + ThrowXML(XMLPlatformUtilsException, + XMLExcepts::File_CouldNotCloseFile); +} + +unsigned int XMLPlatformUtils::fileSize(FileHandle theFile) +{ + if (theFile == NULL) + ThrowXML(XMLPlatformUtilsException, + XMLExcepts::CPtr_PointerIsZero); + // Get the current position + long int curPos = ftell((FILE*) theFile); + if (curPos == -1) + ThrowXML(XMLPlatformUtilsException, + XMLExcepts::File_CouldNotGetCurPos); + + // Seek to the end and save that value for return + if (fseek((FILE*) theFile, 0, SEEK_END)) + ThrowXML(XMLPlatformUtilsException, + XMLExcepts::File_CouldNotSeekToEnd); + + long int retVal = ftell((FILE*)theFile); + if (retVal == -1) + ThrowXML(XMLPlatformUtilsException, + XMLExcepts::File_CouldNotSeekToEnd); + + // And put the pointer back + + if (fseek( (FILE*)theFile, curPos, SEEK_SET) ) + ThrowXML(XMLPlatformUtilsException, + XMLExcepts::File_CouldNotSeekToPos); + + return (unsigned int)retVal; +} + +FileHandle XMLPlatformUtils::openFile(const XMLCh* const fileName) +{ + if (fileName == NULL) + ThrowXML(XMLPlatformUtilsException, + XMLExcepts::CPtr_PointerIsZero); + const char* tmpFileName = XMLString::transcode(fileName); + ArrayJanitor janText((char*)tmpFileName); + FileHandle retVal = (FILE*)fopen( tmpFileName , "r+" ); + + if (retVal == NULL) + return 0; + return retVal; +} + +FileHandle XMLPlatformUtils::openFile(const char* const fileName) +{ + if (fileName == NULL) + ThrowXML(XMLPlatformUtilsException, + XMLExcepts::CPtr_PointerIsZero); + FileHandle retVal = (FILE*)fopen( fileName , "r+" ); + + if (retVal == NULL) + return 0; + return retVal; +} + +FileHandle XMLPlatformUtils::openFileToWrite(const XMLCh* const fileName) +{ + if (fileName == NULL) + ThrowXML(XMLPlatformUtilsException, + XMLExcepts::CPtr_PointerIsZero); + const char* tmpFileName = XMLString::transcode(fileName); + ArrayJanitor janText((char*)tmpFileName); + + FileHandle retVal = (FILE*)fopen( tmpFileName, "r+" ); + if (retVal == NULL) + return 0; + return retVal; +} + +FileHandle XMLPlatformUtils::openFileToWrite(const char* const fileName) +{ + if (fileName == NULL) + ThrowXML(XMLPlatformUtilsException, + XMLExcepts::CPtr_PointerIsZero); + FileHandle retVal = (FILE*)fopen( fileName, "r+" ); + + if (retVal == NULL) + return 0; + return retVal; +} + +FileHandle XMLPlatformUtils::openStdInHandle() +{ + int nfd = dup(0); + if (nfd == -1) + ThrowXML(XMLPlatformUtilsException, + XMLExcepts::File_CouldNotDupHandle); + return (FileHandle)fdopen(dup(0), "r"); +} + + + +unsigned int +XMLPlatformUtils::readFileBuffer( FileHandle theFile + , const unsigned int toRead + , XMLByte* const toFill) +{ + if ( !theFile || !toFill ) + ThrowXML(XMLPlatformUtilsException, + XMLExcepts::CPtr_PointerIsZero); + if (toRead == 0) + return 0; + size_t noOfItemsRead = fread((void*) toFill, 1, toRead, (FILE*)theFile); + + if(ferror((FILE*)theFile)) + { + ThrowXML(XMLPlatformUtilsException, + XMLExcepts::File_CouldNotReadFromFile); + } + + return (unsigned int)noOfItemsRead; +} + +void XMLPlatformUtils::writeBufferToFile( FileHandle const theFile + , long toWrite + , const XMLByte* const toFlush ) +{ + if ( !theFile || !toFlush ) + ThrowXML(XMLPlatformUtilsException, + XMLExcepts::CPtr_PointerIsZero); + if ( toWrite <= 0 ) + return; + + const XMLByte* tmpFlush = (const XMLByte*) toFlush; + size_t bytesWritten = 0; + + while (true) + { + bytesWritten = fwrite(tmpFlush, sizeof(XMLByte), toWrite, (FILE*)theFile); + + if(ferror((FILE*)theFile)) + { +#if 0 + ThrowXML(XMLPlatformUtilsException, + XMLExcepts::File_CouldNotWriteToFile); +#else + ThrowXML(XMLPlatformUtilsException, + XMLExcepts::File_CouldNotReadFromFile); +#endif + } + + if (bytesWritten < (size_t) toWrite) //incomplete write + { + tmpFlush += bytesWritten; + toWrite -= bytesWritten; + bytesWritten = 0; + } + else + return; + } +} + +void XMLPlatformUtils::resetFile(FileHandle theFile) +{ + if (theFile == NULL) + ThrowXML(XMLPlatformUtilsException, + XMLExcepts::CPtr_PointerIsZero); + // Seek to the start of the file + if (fseek((FILE*)theFile, 0, SEEK_SET)) + ThrowXML(XMLPlatformUtilsException, + XMLExcepts::File_CouldNotResetFile); +} + + +// --------------------------------------------------------------------------- +// XMLPlatformUtils: Timing Methods +// --------------------------------------------------------------------------- + +unsigned long XMLPlatformUtils::getCurrentMillis() +{ + struct timeval t; + struct timezone tz; + + gettimeofday(&t, &tz); + return (unsigned long)(t.tv_sec*1000 + t.tv_usec); +} + +XMLCh* XMLPlatformUtils::getFullPath(const XMLCh* const srcPath, MemoryManager* const) +{ + + // + // NOTE: THe path provided has always already been opened successfully, + // so we know that its not some pathological freaky path. It comes in + // in native format, and goes out as Unicode always + // + char* newSrc = XMLString::transcode(srcPath); + ArrayJanitor janText(newSrc); + + // Use a local buffer that is big enough for the largest legal path + char *absPath = new char[1024]; + // get the absolute path + char* retPath = realpath(newSrc, absPath); + ArrayJanitor janText2(retPath); + + if (!retPath) + { + ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetBasePathName); + } + return XMLString::transcode(absPath); +} + +bool XMLPlatformUtils::isRelative(const XMLCh* const toCheck) +{ + // Check for pathological case of empty path + if (!toCheck[0]) + return false; + + // + // If it starts with a slash, then it cannot be relative. This covers + // both something like "\Test\File.xml" and an NT Lan type remote path + // that starts with a node like "\\MyNode\Test\File.xml". + // + if (toCheck[0] == XMLCh('/')) + return false; + + // Else assume its a relative path + return true; +} + +XMLCh* XMLPlatformUtils::getCurrentDirectory(MemoryManager* const) +{ + char dirBuf[PATH_MAX + 1]; + char *curDir = getcwd(&dirBuf[0], PATH_MAX + 1); + + if (!curDir) + { + ThrowXML(XMLPlatformUtilsException, + XMLExcepts::File_CouldNotGetBasePathName); + } + + return XMLString::transcode(curDir); +} + +inline bool XMLPlatformUtils::isAnySlash(XMLCh c) +{ + return ( chBackSlash == c || chForwardSlash == c); +} + + +// ----------------------------------------------------------------------- +// Mutex methods +// ----------------------------------------------------------------------- + +#if !defined(APP_NO_THREADS) + +// --------------------------------------------------------------------------- +// XMLPlatformUtils: Platform init method +// --------------------------------------------------------------------------- + +static XMLMutex atomicOpsMutex; + +void XMLPlatformUtils::platformInit() +{ + // + // The atomicOps mutex needs to be created early. + // Normally, mutexes are created on first use, but there is a + // circular dependency between compareAndExchange() and + // mutex creation that must be broken. + + if (atomicOpsMutex.fHandle == 0) + atomicOpsMutex.fHandle = XMLPlatformUtils::makeMutex(); +} + +void* XMLPlatformUtils::makeMutex() +{ + pthread_mutex_t* mutex = new pthread_mutex_t; + pthread_mutexattr_t* attr = new pthread_mutexattr_t; + pthread_mutexattr_init(attr); + pthread_mutexattr_settype(attr, PTHREAD_MUTEX_RECURSIVE); + if (pthread_mutex_init(mutex, attr)) + { + ThrowXML(XMLPlatformUtilsException, + XMLExcepts::Mutex_CouldNotCreate); + } + pthread_mutexattr_destroy(attr); + delete attr; + return (void*)(mutex); + +} + +void XMLPlatformUtils::closeMutex(void* const mtxHandle) +{ + if (mtxHandle != NULL) + { + if (pthread_mutex_destroy((pthread_mutex_t*) mtxHandle)) + { + ThrowXML(XMLPlatformUtilsException, + XMLExcepts::Mutex_CouldNotDestroy); + } + delete (pthread_mutex_t*)mtxHandle; + } +} + + +void XMLPlatformUtils::lockMutex(void* const mtxHandle) +{ + if (mtxHandle != NULL) + { + if (pthread_mutex_lock((pthread_mutex_t*) mtxHandle)) + { + ThrowXML(XMLPlatformUtilsException, + XMLExcepts::Mutex_CouldNotLock); + } + } +} + + +void XMLPlatformUtils::unlockMutex(void* const mtxHandle) +{ + if (mtxHandle != NULL) + { + if (pthread_mutex_unlock((pthread_mutex_t*) mtxHandle)) + { + ThrowXML(XMLPlatformUtilsException, + XMLExcepts::Mutex_CouldNotUnlock); + } + } +} + + +// ----------------------------------------------------------------------- +// Miscellaneous synchronization methods +// ----------------------------------------------------------------------- + +void* XMLPlatformUtils::compareAndSwap(void** toFill + , const void* const newValue + , const void* const toCompare) +{ + XMLMutexLock lockMutex(&atomicOpsMutex); + + void *retVal = *toFill; + if (*toFill == toCompare) + *toFill = (void *)newValue; + + return retVal; +} + +int XMLPlatformUtils::atomicIncrement(int &location) +{ + XMLMutexLock localLock(&atomicOpsMutex); + + return ++location; +} + +int XMLPlatformUtils::atomicDecrement(int &location) +{ + XMLMutexLock localLock(&atomicOpsMutex); + + return --location; +} + +#else // #if !defined (APP_NO_THREADS) + +void XMLPlatformUtils::platformInit() +{ +} + +void* XMLPlatformUtils::makeMutex() +{ + return 0; +} + +void XMLPlatformUtils::closeMutex(void* const mtxHandle) +{ +} + +void XMLPlatformUtils::lockMutex(void* const mtxHandle) +{ +} + +void XMLPlatformUtils::unlockMutex(void* const mtxHandle) +{ +} + +void* XMLPlatformUtils::compareAndSwap (void** toFill, + const void* const newValue, + const void* const toCompare) +{ + void *retVal = *toFill; + if (*toFill == toCompare) + *toFill = (void *)newValue; + return retVal; +} + +int XMLPlatformUtils::atomicIncrement(int &location) +{ + return ++location; +} + +int XMLPlatformUtils::atomicDecrement(int &location) +{ + return --location; +} + +#endif // APP_NO_THREADS + +void XMLPlatformUtils::platformTerm() +{ +#if !defined(APP_NO_THREADS) + // delete the mutex we created + closeMutex(atomicOpsMutex.fHandle); + atomicOpsMutex.fHandle = 0; +#endif +} + +#include + +XERCES_CPP_NAMESPACE_END