blob: 08b5d280d9ed9b393e34e76551ec2f50dbb86a0d [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id: TandemPlatformUtils.cpp 568078 2007-08-21 11:43:25Z amassari $
*/
// ---------------------------------------------------------------------------
// Includes
// ---------------------------------------------------------------------------
// XXX #include <pthread.h>
// XXX #include <sys/atomic_op.h>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/RuntimeException.hpp>
#include <xercesc/util/Janitor.hpp>
#include <xercesc/util/PanicHandler.hpp>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <libgen.h>
#include <sys/timeb.h>
#include <string.h>
#include <xercesc/util/OutOfMemoryException.hpp>
#include <xercesc/util/XMLHolder.hpp>
#if defined (XML_USE_ICU_MESSAGELOADER)
#include <xercesc/util/MsgLoaders/ICU/ICUMsgLoader.hpp>
#elif defined (XML_USE_ICONV_MESSAGELOADER)
#include <xercesc/util/MsgLoaders/MsgCatalog/MsgCatalogLoader.hpp>
#else // use In-memory message loader
#include <xercesc/util/MsgLoaders/InMemory/InMemMsgLoader.hpp>
#endif
XERCES_CPP_NAMESPACE_BEGIN
// ---------------------------------------------------------------------------
// XMLPlatformUtils: Platform init method
// ---------------------------------------------------------------------------
void XMLPlatformUtils::platformInit()
{
}
//
// 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.
// In our case, we use the ICU based message loader mechanism.
//
XMLMsgLoader* XMLPlatformUtils::loadAMsgSet(const XMLCh* const msgDomain)
{
XMLMsgLoader* retVal;
try
{
#if defined (XML_USE_ICU_MESSAGELOADER)
retVal = new (fgMemoryManager) ICUMsgLoader(msgDomain);
#elif defined (XML_USE_ICONV_MESSAGELOADER)
retVal = new (fgMemoryManager) MsgCatalogLoader(msgDomain);
#else
retVal = new (fgMemoryManager) InMemMsgLoader(msgDomain);
#endif
}
catch(const OutOfMemoryException&)
{
throw;
}
catch(...)
{
panic(PanicHandler::Panic_CantLoadMsgDomain);
}
return retVal;
}
void XMLPlatformUtils::panic(const PanicHandler::PanicReasons reason)
{
fgUserPanicHandler? fgUserPanicHandler->panic(reason) : fgDefaultPanicHandler->panic(reason);
}
// ---------------------------------------------------------------------------
// XMLPlatformUtils: File Methods
// ---------------------------------------------------------------------------
unsigned int XMLPlatformUtils::curFilePos(FileHandle theFile
, MemoryManager* const manager)
{
// Get the current position
int curPos = ftell( (FILE*)theFile);
if (curPos == -1)
throw XMLPlatformUtilsException("XMLPlatformUtils::curFilePos - Could not get current pos");
return (unsigned int)curPos;
}
void XMLPlatformUtils::closeFile(FileHandle theFile
, MemoryManager* const manager)
{
if (fclose((FILE*)theFile))
throw XMLPlatformUtilsException("XMLPlatformUtils::closeFile - Could not close the file handle");
}
unsigned int XMLPlatformUtils::fileSize(FileHandle theFile
, MemoryManager* const manager)
{
// Get the current position
long int curPos = ftell((FILE*)theFile);
if (curPos == -1)
throw XMLPlatformUtilsException("XMLPlatformUtils::fileSize - Could not get current pos");
// Seek to the end and save that value for return
if (fseek( (FILE*)theFile, 0, SEEK_END) )
throw XMLPlatformUtilsException("XMLPlatformUtils::fileSize - Could not seek to end");
long int retVal = ftell( (FILE*)theFile);
if (retVal == -1)
throw XMLPlatformUtilsException("XMLPlatformUtils::fileSize - Could not get the file size");
// And put the pointer back
if (fseek( (FILE*)theFile, curPos, SEEK_SET) )
throw XMLPlatformUtilsException("XMLPlatformUtils::fileSize - Could not seek back to original pos");
return (unsigned int)retVal;
}
FileHandle XMLPlatformUtils::openFile(const unsigned short* const fileName
, MemoryManager* const manager)
{
const char* tmpFileName = XMLString::transcode(fileName, manager);
ArrayJanitor<char> tmpFileNameJan((char*)tmpFileName , manager);
FileHandle retVal = (FILE*)fopen( tmpFileName , "rb" );
if (retVal == NULL)
return 0;
return retVal;
}
unsigned int
XMLPlatformUtils::readFileBuffer( FileHandle theFile
, const unsigned int toRead
, XMLByte* const toFill
, MemoryManager* const manager)
{
size_t noOfItemsRead = fread( (void*) toFill, 1, toRead, (FILE*)theFile);
if(ferror((FILE*)theFile))
{
throw XMLPlatformUtilsException("XMLPlatformUtils::readFileBuffer - Read failed");
}
return (unsigned int)noOfItemsRead;
}
void XMLPlatformUtils::resetFile(FileHandle theFile
, MemoryManager* const manager)
{
// Seek to the start of the file
if (fseek((FILE*)theFile, 0, SEEK_SET) )
throw XMLPlatformUtilsException("XMLPlatformUtils::resetFile - Could not seek to beginning");
}
// ---------------------------------------------------------------------------
// XMLPlatformUtils: File system methods
// ---------------------------------------------------------------------------
XMLCh* XMLPlatformUtils::getFullPath(const XMLCh* const srcPath,
MemoryManager* const manager)
{
//
// 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, fgMemoryManager);
ArrayJanitor<char> newSrcJanitor(newSrc, fgMemoryManager);
// Use a local buffer that is big enough for the largest legal path
char* tmpPath = dirname((char*)newSrc);
if (!tmpPath)
{
throw XMLPlatformUtilsException("XMLPlatformUtils::resetFile - Could not get the base path name");
}
char* newXMLString = (char*) fgMemoryManager->allocate
(
(strlen(tmpPath) +1) * sizeof(char)
);//new char [strlen(tmpPath) +1];
ArrayJanitor<char> newJanitor(newXMLString, fgMemoryManager);
strcpy(newXMLString, tmpPath);
strcat(newXMLString , "/");
// Return a copy of the path, in Unicode format
return XMLString::transcode(newXMLString, manager);
}
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()
{
/***
* REVISIT:
*
* To be implemented later
***/
XMLCh curDir[]={ chPeriod, chForwardSlash, chNull};
return getFullPath(curDir);
}
inline bool XMLPlatformUtils::isAnySlash(XMLCh c)
{
return ( chBackSlash == c || chForwardSlash == c);
}
// ---------------------------------------------------------------------------
// XMLPlatformUtils: Timing Methods
// ---------------------------------------------------------------------------
unsigned long XMLPlatformUtils::getCurrentMillis()
{
timeb aTime;
ftime(&aTime);
return (unsigned long)(aTime.time*1000 + aTime.millitm);
}
#ifndef __TANDEM
// -----------------------------------------------------------------------
// Mutex methods
// -----------------------------------------------------------------------
typedef XMLHolder<pthread_mutex_t> MutexHolderType;
void XMLPlatformUtils::closeMutex(void* const mtxHandle)
{
if (mtxHandle != NULL)
{
MutexHolderType* const holder =
MutexHolderType::castTo(mtxHandle);
if (pthread_mutex_destroy(&holder->fInstance))
{
delete holder;
ThrowXMLwithMemMgr(XMLPlatformUtilsException,
XMLExcepts::Mutex_CouldNotDestroy, fgMemoryManager);
}
delete holder;
}
}
void XMLPlatformUtils::lockMutex(void* const mtxHandle)
{
if (mtxHandle != NULL)
{
if (pthread_mutex_lock(&MutexHolderType::castTo(mtxHandle)->fInstance))
{
panic(PanicHandler::Panic_MutexErr);
}
}
}
void* XMLPlatformUtils::makeMutex(MemoryManager* manager)
{
MutexHolderType* const holder = new (manager) MutexHolderType;
if (pthread_mutex_init(&holder->fInstance, NULL))
{
delete holder;
panic(PanicHandler::Panic_MutexErr);
}
return holder;
}
void XMLPlatformUtils::unlockMutex(void* const mtxHandle)
{
if (mtxHandle != NULL)
{
if (pthread_mutex_unlock(&MutexHolderType::castTo(mtxHandle)->fInstance))
{
panic(PanicHandler::Panic_MutexErr);
}
}
}
// -----------------------------------------------------------------------
// Miscellaneous synchronization methods
// -----------------------------------------------------------------------
void* XMLPlatformUtils::compareAndSwap ( void** toFill ,
const void* const newValue ,
const void* const toCompare)
{
boolean_t boolVar = compare_and_swap((atomic_p)toFill, (int *)&toCompare, (int)newValue );
return (void *)toCompare;
}
int XMLPlatformUtils::atomicIncrement(int &location)
{
int retVal = fetch_and_add( (atomic_p)&location, 1);
return retVal+1;
}
int XMLPlatformUtils::atomicDecrement(int &location)
{
int retVal = fetch_and_add( (atomic_p)&location, -1);
return retVal-1;
}
FileHandle XMLPlatformUtils::openStdInHandle(MemoryManager* const manager)
{
return (FileHandle)fdopen(dup(0), "rb");
}
#endif
void XMLPlatformUtils::platformTerm()
{
// We don't have any termination requirements at this time
}
#include <xercesc/util/LogicalPath.c>
XERCES_CPP_NAMESPACE_END