source: icXML/icXML-devel/src/icxercesc/util/PlatformUtils.cpp @ 3555

Last change on this file since 3555 was 3555, checked in by cameron, 5 years ago

Updates to icXML 0.9

File size: 31.3 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*
19 * $Id: PlatformUtils.cpp 932877 2010-04-11 12:17:34Z borisk $
20 *
21 */
22
23
24// ---------------------------------------------------------------------------
25//  Includes
26// ---------------------------------------------------------------------------
27#if HAVE_CONFIG_H
28#       include <config.h>
29#endif
30
31#if HAVE_LIMITS_H
32#       include <limits.h>
33#endif
34#if HAVE_SYS_TIME_H
35#       include <sys/time.h>
36#endif
37#if HAVE_SYS_TIMEB_H
38#       include <sys/timeb.h>
39#endif
40#if HAVE_CPUID_H && !XERCES_HAVE_INTRIN_H
41#   include <cpuid.h>
42#endif
43
44#include <xercesc/util/Mutexes.hpp>
45#include <icxercesc/util/PlatformUtils.hpp>
46#include <xercesc/util/RefVectorOf.hpp>
47#include <icxercesc/util/XMLString.hpp>
48#include <xercesc/util/XMLUni.hpp>
49#include <icxercesc/internal/XMLReader.hpp>
50#include <xercesc/util/RuntimeException.hpp>
51#include <xercesc/util/OutOfMemoryException.hpp>
52#include <xercesc/util/DefaultPanicHandler.hpp>
53#include <xercesc/util/XMLInitializer.hpp>
54#include <icxercesc/internal/MemoryManagerImpl.hpp>
55
56#if XERCES_HAVE_INTRIN_H
57#   include <intrin.h>
58#endif
59
60#include <xercesc/util/XMLFileMgr.hpp>
61#if XERCES_USE_FILEMGR_POSIX
62#       include <xercesc/util/FileManagers/PosixFileMgr.hpp>
63#endif
64#if XERCES_USE_FILEMGR_WINDOWS
65#       include <xercesc/util/FileManagers/WindowsFileMgr.hpp>
66#endif
67
68#include <xercesc/util/XMLMutexMgr.hpp>
69#if XERCES_USE_MUTEXMGR_NOTHREAD
70#       include <xercesc/util/MutexManagers/NoThreadMutexMgr.hpp>
71#endif
72#if XERCES_USE_MUTEXMGR_POSIX
73#       include <xercesc/util/MutexManagers/PosixMutexMgr.hpp>
74#endif
75#if XERCES_USE_MUTEXMGR_WINDOWS
76#       include <xercesc/util/MutexManagers/WindowsMutexMgr.hpp>
77#endif
78
79#include <xercesc/util/XMLNetAccessor.hpp>
80#if XERCES_USE_NETACCESSOR_CURL
81#       include <xercesc/util/NetAccessors/Curl/CurlNetAccessor.hpp>
82#endif
83#if XERCES_USE_NETACCESSOR_SOCKET
84#       include <xercesc/util/NetAccessors/Socket/SocketNetAccessor.hpp>
85#endif
86#if XERCES_USE_NETACCESSOR_CFURL
87#       include <xercesc/util/NetAccessors/MacOSURLAccessCF/MacOSURLAccessCF.hpp>
88#endif
89#if XERCES_USE_NETACCESSOR_WINSOCK
90#       include <xercesc/util/NetAccessors/WinSock/WinSockNetAccessor.hpp>
91#endif
92
93
94#include <xercesc/util/XMLMsgLoader.hpp>
95#if XERCES_USE_MSGLOADER_ICU
96#       include <xercesc/util/MsgLoaders/ICU/ICUMsgLoader.hpp>
97#endif
98#if XERCES_USE_MSGLOADER_ICONV
99#       include <xercesc/util/MsgLoaders/MsgCatalog/MsgCatalogLoader.hpp>
100#endif
101#if XERCES_USE_MSGLOADER_INMEMORY
102#       include <xercesc/util/MsgLoaders/InMemory/InMemMsgLoader.hpp>
103#endif
104#if XERCES_USE_WIN32_MSGLOADER
105#       include <xercesc/util/MsgLoaders/Win32/Win32MsgLoader.hpp>
106#endif
107
108#include <icxercesc/util/TransService.hpp>
109#if XERCES_USE_TRANSCODER_ICU
110#       include <icxercesc/util/Transcoders/ICU/ICUTransService.hpp>
111#endif
112#if XERCES_USE_TRANSCODER_GNUICONV
113#       include <icxercesc/util/Transcoders/IconvGNU/IconvGNUTransService.hpp>
114#endif
115#if XERCES_USE_TRANSCODER_ICONV
116#       include <xercesc/util/Transcoders/Iconv/IconvTransService.hpp>
117#endif
118#if XERCES_USE_TRANSCODER_MACOSUNICODECONVERTER
119#       include <xercesc/util/Transcoders/MacOSUnicodeConverter/MacOSUnicodeConverter.hpp>
120#endif
121#if XERCES_USE_TRANSCODER_WINDOWS
122#       include <icxercesc/util/Transcoders/Win32/Win32TransService.hpp>
123#endif
124
125XERCES_CPP_NAMESPACE_BEGIN
126
127// ---------------------------------------------------------------------------
128//  Local data members
129//
130//  gSyncMutex
131//      This is a mutex that will be used to synchronize access to some of
132//      the static data of the platform utilities class and here locally.
133// ---------------------------------------------------------------------------
134static XMLMutex*                gSyncMutex = 0;
135static long                     gInitFlag = 0;
136
137
138// ---------------------------------------------------------------------------
139//  XMLPlatformUtils: Static Data Members
140// ---------------------------------------------------------------------------
141XMLNetAccessor*         XMLPlatformUtils::fgNetAccessor = 0;
142XMLTransService*        XMLPlatformUtils::fgTransService = 0;
143#ifdef OS390
144XMLTransService*        XMLPlatformUtils::fgTransService2 = 0;
145#endif
146PanicHandler*           XMLPlatformUtils::fgUserPanicHandler = 0;
147PanicHandler*           XMLPlatformUtils::fgDefaultPanicHandler = 0;
148MemoryManager*          XMLPlatformUtils::fgMemoryManager = 0;
149bool                    XMLPlatformUtils::fgMemMgrAdopted = true;
150
151XMLFileMgr*             XMLPlatformUtils::fgFileMgr = 0;
152XMLMutexMgr*            XMLPlatformUtils::fgMutexMgr = 0;
153
154XMLMutex*               XMLPlatformUtils::fgAtomicMutex = 0;
155
156bool                    XMLPlatformUtils::fgXMLChBigEndian = true;
157bool                    XMLPlatformUtils::fgSSE2ok = false;
158
159// ---------------------------------------------------------------------------
160//  XMLPlatformUtils: Init/term methods
161// ---------------------------------------------------------------------------
162void XMLPlatformUtils::Initialize(const char*          const locale
163                                , const char*          const nlsHome
164                                ,       PanicHandler*  const panicHandler
165                                ,       MemoryManager* const memoryManager)
166{
167    //
168    //  Effects of overflow:
169    //  . resouce re-allocations
170    //  . consequently resource leaks
171    //  . potentially terminate() may never get executed
172    //
173    //  We got to prevent overflow from happening.
174    //  no error or exception
175    //
176    if (gInitFlag == LONG_MAX)
177        return;
178
179    //
180    //  Make sure we haven't already been initialized. Note that this is not
181    //  thread safe and is not intended for that. Its more for those COM
182    //  like processes that cannot keep up with whether they have initialized
183    //  us yet or not.
184    //
185    gInitFlag++;
186
187    if (gInitFlag > 1)
188      return;
189
190    // Set pluggable memory manager
191    if (!fgMemoryManager)
192    {
193        if (memoryManager)
194        {
195            fgMemoryManager = memoryManager;
196            fgMemMgrAdopted = false;
197        }
198        else
199        {
200            fgMemoryManager = new MemoryManagerImpl();
201        }
202    }
203
204    /***
205     * Panic Handler:
206     *
207     ***/
208    if (!panicHandler)
209    {
210        fgDefaultPanicHandler = new DefaultPanicHandler();
211    }
212    else
213    {
214        fgUserPanicHandler = panicHandler;
215    }
216
217
218    // Determine our endianness (with regard to a XMLCh 16-bit word)
219    union {
220        XMLCh ch;
221        unsigned char ar[sizeof(XMLCh)];
222    } endianTest;
223    endianTest.ch = 1;
224    fgXMLChBigEndian = (endianTest.ar[sizeof(XMLCh)-1] == 1);
225
226    // Determine if we can use SSE2 functions
227#if defined(XERCES_HAVE_CPUID_INTRINSIC)
228    int CPUInfo[4]={0};
229    __cpuid(CPUInfo, 1);
230    if(CPUInfo[3] & (1UL << 26))
231        fgSSE2ok = true;
232    else
233        fgSSE2ok = false;
234#elif defined(XERCES_HAVE_GETCPUID)
235    unsigned int eax, ebx, ecx, edx;
236    if(!__get_cpuid (1, &eax, &ebx, &ecx, &edx) || (edx & (1UL << 26))==0)
237        fgSSE2ok = false;
238    else
239        fgSSE2ok = true;
240#elif defined(XERCES_HAVE_SSE2_INTRINSIC)
241    // if we cannot find out at runtime, assume the define has it right
242    fgSSE2ok = true;
243#else
244    fgSSE2ok = false;
245#endif
246
247    // Initialize the platform-specific mutex and file mgrs
248    fgMutexMgr          = makeMutexMgr(fgMemoryManager);
249    fgFileMgr           = makeFileMgr(fgMemoryManager);
250
251
252    // Create the local sync mutex
253    gSyncMutex = new XMLMutex(fgMemoryManager);
254
255    // Create the global "atomic operations" mutex.
256    fgAtomicMutex = new XMLMutex(fgMemoryManager);
257
258    //
259    //  Ask the per-platform code to make the desired transcoding service for
260    //  us to use. This call cannot throw any exceptions or do anything that
261    //  cause any transcoding to happen. It should create the service and
262    //  return it or zero if it cannot.
263    //
264    //  This one also cannot use any utility services. It can only create a
265    //  transcoding service object and return it.
266    //
267    //  If we cannot make one, then we call panic to end the process.
268    //
269    XMLInitializer::initializeTransService(); // TransService static data.
270
271    fgTransService = makeTransService();
272
273    if (!fgTransService)
274        panic(PanicHandler::Panic_NoTransService);
275
276    // Initialize the transcoder service
277    fgTransService->initTransService();
278
279    //
280    //  Try to create a default local code page transcoder. This is the one
281    //  that will be used internally by the XMLString class. If we cannot
282    //  create one, then call the panic method.
283    //
284    XMLLCPTranscoder* defXCode = XMLPlatformUtils::fgTransService->makeNewLCPTranscoder(fgMemoryManager);
285    if (!defXCode)
286        panic(PanicHandler::Panic_NoDefTranscoder);
287    XMLString::initString(defXCode, fgMemoryManager);
288
289    //
290    //  Now lets ask the per-platform code to give us an instance of the type
291    //  of network access implementation he wants to use. This can return
292    //  a zero pointer if this platform doesn't want to support this.
293    //
294    fgNetAccessor = makeNetAccessor();
295
296    /***
297     * Message Loader:
298     *
299     *     Locale setting
300     *     nlsHome setting
301     ***/
302    XMLMsgLoader::setLocale(locale);
303    XMLMsgLoader::setNLSHome(nlsHome);
304
305    // Initialize static data.
306    //
307    XMLInitializer::initializeStaticData();
308}
309
310void XMLPlatformUtils::Initialize(XMLSize_t initialDOMHeapAllocSize
311                                , XMLSize_t maxDOMHeapAllocSize
312                                , XMLSize_t maxDOMSubAllocationSize
313                                , const char*          const locale
314                                , const char*          const nlsHome
315                                ,       PanicHandler*  const panicHandler
316                                ,       MemoryManager* const memoryManager)
317{
318  Initialize (locale, nlsHome, panicHandler, memoryManager);
319
320  // Don't change the parameters unless it is the first time.
321  //
322  if (gInitFlag == 1)
323    XMLInitializer::initializeDOMHeap(initialDOMHeapAllocSize,
324                                      maxDOMHeapAllocSize,
325                                      maxDOMSubAllocationSize);
326}
327
328void XMLPlatformUtils::Terminate()
329{
330    //
331    // To prevent it from running underflow.
332    // otherwise we come to delete non-existing resources.
333    //
334    //  no error or exception
335    //
336    if (gInitFlag == 0)
337        return;
338
339    gInitFlag--;
340
341    if (gInitFlag > 0)
342        return;
343
344    // Terminate static data.
345    //
346    XMLInitializer::terminateStaticData();
347
348    // Delete any net accessor that got installed
349    delete fgNetAccessor;
350    fgNetAccessor = 0;
351
352    //
353    //  Call some other internal modules to give them a chance to clean up.
354    //  Do the string class last in case something tries to use it during
355    //  cleanup.
356    //
357    XMLString::termString();
358
359    // Clean up the the transcoding service
360    delete fgTransService;
361    fgTransService = 0;
362
363    XMLInitializer::terminateTransService(); // TransService static data.
364
365    // Clean up mutexes
366    delete gSyncMutex;          gSyncMutex = 0;
367    delete fgAtomicMutex;       fgAtomicMutex = 0;
368
369    // Clean up our mgrs
370    delete fgFileMgr;           fgFileMgr = 0;
371    delete fgMutexMgr;          fgMutexMgr = 0;
372
373    /***
374     *  de-allocate resource
375     *
376     *  refer to discussion in the Initialize()
377     ***/
378    XMLMsgLoader::setLocale(0);
379    XMLMsgLoader::setNLSHome(0);
380
381    delete fgDefaultPanicHandler;
382    fgDefaultPanicHandler = 0;
383    fgUserPanicHandler = 0;
384
385    // de-allocate default memory manager
386    if (fgMemMgrAdopted)
387        delete fgMemoryManager;
388    else
389        fgMemMgrAdopted = true;
390
391    // set memory manager to 0
392    fgMemoryManager = 0;
393
394    // And say we are no longer initialized
395    gInitFlag = 0;
396}
397
398
399
400
401// ---------------------------------------------------------------------------
402//  XMLPlatformUtils: The panic method
403// ---------------------------------------------------------------------------
404void XMLPlatformUtils::panic(const PanicHandler::PanicReasons reason)
405{
406    fgUserPanicHandler? fgUserPanicHandler->panic(reason) : fgDefaultPanicHandler->panic(reason);
407}
408
409
410
411// ---------------------------------------------------------------------------
412//  XMLPlatformUtils: Private Static Methods
413// ---------------------------------------------------------------------------
414
415XMLNetAccessor* XMLPlatformUtils::makeNetAccessor()
416{
417        XMLNetAccessor* na = 0;
418
419#if defined (XERCES_USE_NETACCESSOR_CURL)
420                na = new CurlNetAccessor();
421#elif defined (XERCES_USE_NETACCESSOR_SOCKET)
422                na = new SocketNetAccessor();
423#elif defined (XERCES_USE_NETACCESSOR_CFURL)
424                na = new MacOSURLAccessCF();
425#elif defined (XERCES_USE_NETACCESSOR_WINSOCK)
426                na = new WinSockNetAccessor();
427#endif
428
429        return na;
430}
431
432
433//
434//  This method is called by the platform independent part of this class
435//  when client code asks to have one of the supported message sets loaded.
436//
437
438XMLMsgLoader* XMLPlatformUtils::loadAMsgSet(const XMLCh* const msgDomain)
439{
440    XMLMsgLoader* ms=0;
441
442    try
443    {
444        #if defined (XERCES_USE_MSGLOADER_ICU)
445                ms = new ICUMsgLoader(msgDomain);
446        #elif defined (XERCES_USE_MSGLOADER_ICONV)
447                ms = new MsgCatalogLoader(msgDomain);
448    #elif defined (XERCES_USE_WIN32_MSGLOADER)
449                ms = new Win32MsgLoader(msgDomain);
450        #elif defined (XERCES_USE_MSGLOADER_INMEMORY)
451                ms = new InMemMsgLoader(msgDomain);
452        #else
453                #error No MsgLoader configured for platform! You must configure it.
454        #endif
455    }
456    catch(const OutOfMemoryException&)
457    {
458        throw;
459    }
460    catch(...)
461    {
462        panic(PanicHandler::Panic_CantLoadMsgDomain);
463    }
464
465    return ms;
466}
467
468
469//
470//  This method is called very early in the bootstrapping process. This guy
471//  must create a transcoding service and return it. It cannot use any string
472//  methods, any transcoding services, throw any exceptions, etc... It just
473//  makes a transcoding service and returns it, or returns zero on failure.
474//
475
476XMLTransService* XMLPlatformUtils::makeTransService()
477{
478        XMLTransService* tc = 0;
479
480        #if defined   (XERCES_USE_TRANSCODER_ICU)
481                tc = new ICUTransService(fgMemoryManager);
482        #elif defined (XERCES_USE_TRANSCODER_GNUICONV)
483                tc = new IconvGNUTransService(fgMemoryManager);
484        #elif defined (XERCES_USE_TRANSCODER_ICONV)
485                tc = new IconvTransService(fgMemoryManager);
486        #elif defined (XERCES_USE_TRANSCODER_MACOSUNICODECONVERTER)
487                tc = new MacOSUnicodeConverter(fgMemoryManager);
488        #elif defined (XERCES_USE_TRANSCODER_WINDOWS)
489                tc = new Win32TransService(fgMemoryManager);
490        #else
491                #error No Transcoder configured for platform! You must configure it.
492        #endif
493
494        return tc;
495}
496
497
498// ---------------------------------------------------------------------------
499//  XMLPlatformUtils: File Methods
500// ---------------------------------------------------------------------------
501XMLFileMgr*
502XMLPlatformUtils::makeFileMgr(MemoryManager* const memmgr)
503{
504        XMLFileMgr* mgr = NULL;
505
506        #if XERCES_USE_FILEMGR_POSIX
507                mgr = new (memmgr) PosixFileMgr;
508        #elif XERCES_USE_FILEMGR_WINDOWS
509                mgr = new (memmgr) WindowsFileMgr;
510        #else
511                #error No File Manager configured for platform! You must configure it.
512        #endif
513
514        return mgr;
515}
516
517
518FileHandle
519XMLPlatformUtils::openFile(const char* const fileName
520                           , MemoryManager* const memmgr)
521{
522    if (!fgFileMgr)
523                ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr);
524
525        return fgFileMgr->fileOpen(fileName, false, memmgr);
526}
527
528
529FileHandle
530XMLPlatformUtils::openFile(const XMLCh* const fileName, MemoryManager* const memmgr)
531{
532    if (!fgFileMgr)
533                ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr);
534
535        return fgFileMgr->fileOpen(fileName, false, memmgr);
536}
537
538
539FileHandle
540XMLPlatformUtils::openFileToWrite(const char* const fileName
541                                  , MemoryManager* const memmgr)
542{
543    if (!fgFileMgr)
544                ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr);
545
546        return fgFileMgr->fileOpen(fileName, true, memmgr);
547}
548
549
550FileHandle
551XMLPlatformUtils::openFileToWrite(const XMLCh* const fileName
552                                  , MemoryManager* const memmgr)
553{
554    if (!fgFileMgr)
555                ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr);
556
557        return fgFileMgr->fileOpen(fileName, true, memmgr);
558}
559
560
561FileHandle
562XMLPlatformUtils::openStdInHandle(MemoryManager* const memmgr)
563{
564    if (!fgFileMgr)
565                ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr);
566
567        return fgFileMgr->openStdIn(memmgr);
568}
569
570
571void
572XMLPlatformUtils::closeFile(FileHandle theFile
573                            , MemoryManager* const memmgr)
574{
575    if (!fgFileMgr)
576                ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr);
577
578        fgFileMgr->fileClose(theFile, memmgr);
579}
580
581void
582XMLPlatformUtils::resetFile(FileHandle theFile
583                            , MemoryManager* const memmgr)
584{
585    if (!fgFileMgr)
586                ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr);
587
588        fgFileMgr->fileReset(theFile, memmgr);
589}
590
591
592XMLFilePos
593XMLPlatformUtils::curFilePos(FileHandle theFile
594                             , MemoryManager* const memmgr)
595{
596    if (!fgFileMgr)
597                ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr);
598
599        return fgFileMgr->curPos(theFile, memmgr);
600}
601
602XMLFilePos
603XMLPlatformUtils::fileSize(FileHandle theFile
604                           , MemoryManager* const memmgr)
605{
606    if (!fgFileMgr)
607                ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr);
608
609        return fgFileMgr->fileSize(theFile, memmgr);
610}
611
612
613XMLSize_t
614XMLPlatformUtils::readFileBuffer(   FileHandle      theFile
615                                 ,  const XMLSize_t               toRead
616                                 ,        XMLByte* const  toFill
617                                 ,  MemoryManager* const  memmgr)
618{
619    if (!fgFileMgr)
620                ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr);
621
622    return fgFileMgr->fileRead(theFile, toRead, toFill, memmgr);
623}
624
625
626void
627XMLPlatformUtils::writeBufferToFile(   const   FileHandle   theFile
628                                    ,  XMLSize_t            toWrite
629                                    ,  const XMLByte* const toFlush
630                                    ,  MemoryManager* const memmgr)
631{
632    if (!fgFileMgr)
633                ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr);
634
635        fgFileMgr->fileWrite(theFile, toWrite, toFlush, memmgr);
636}
637
638
639// ---------------------------------------------------------------------------
640//  XMLPlatformUtils: File system methods
641// ---------------------------------------------------------------------------
642XMLCh* XMLPlatformUtils::getFullPath(const XMLCh* const srcPath,
643                                     MemoryManager* const memmgr)
644{
645    if (!fgFileMgr)
646                ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr);
647
648        return fgFileMgr->getFullPath(srcPath, memmgr);
649}
650
651
652XMLCh* XMLPlatformUtils::getCurrentDirectory(MemoryManager* const memmgr)
653{
654    if (!fgFileMgr)
655                ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr);
656
657    return fgFileMgr->getCurrentDirectory(memmgr);
658}
659
660
661bool XMLPlatformUtils::isRelative(const XMLCh* const toCheck
662                                  , MemoryManager* const memmgr)
663{
664    if (!fgFileMgr)
665                ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr);
666
667    return fgFileMgr->isRelative(toCheck, memmgr);
668}
669
670
671inline bool
672XMLPlatformUtils::isAnySlash(XMLCh c)
673{
674        // As far as we know, all supported Xerces
675        // platforms use at least a forward slash
676        // as a path delimiter. So we always check for
677        // that.
678        //
679        // If XERCES_PATH_DELIMITER_BACKSLASH evaluates to true,
680        // we also consider that as a slash.
681        //
682        // XERCES_PATH_DELIMITER_BACKSLASH may be set in config.h
683        // by configure, or elsewhere by platform-specific
684        // code.
685    return      (
686                        false
687                 || chForwardSlash == c
688        #if XERCES_PATH_DELIMITER_BACKSLASH
689                 || chBackSlash == c
690        #endif
691                );
692}
693
694
695// ---------------------------------------------------------------------------
696//  XMLPlatformUtils: Timing Methods
697// ---------------------------------------------------------------------------
698unsigned long XMLPlatformUtils::getCurrentMillis()
699{
700        unsigned long ms = 0;
701
702        // *** TODO: additional platform support?
703        #if HAVE_GETTIMEOFDAY
704                struct timeval aTime;
705                gettimeofday(&aTime, NULL);
706                ms = (unsigned long) (aTime.tv_sec * 1000 + aTime.tv_usec / 1000);
707        #elif HAVE_FTIME
708                timeb aTime;
709                ftime(&aTime);
710                ms = (unsigned long)(aTime.time*1000 + aTime.millitm);
711        #else
712                // Make this a warning instead?
713                #error No timing support is configured for this platform. You must configure it.
714        #endif
715
716        return ms;
717}
718
719
720// -----------------------------------------------------------------------
721//  Mutex methods
722// -----------------------------------------------------------------------
723XMLMutexMgr* XMLPlatformUtils::makeMutexMgr(MemoryManager* const memmgr)
724{
725        XMLMutexMgr* mgr = NULL;
726
727        #if XERCES_USE_MUTEXMGR_NOTHREAD
728                mgr = new (memmgr) NoThreadMutexMgr;
729        #elif XERCES_USE_MUTEXMGR_POSIX
730                mgr = new (memmgr) PosixMutexMgr;
731        #elif XERCES_USE_MUTEXMGR_WINDOWS
732                mgr = new (memmgr) WindowsMutexMgr;
733        #else
734                #error No Mutex Manager configured for platform! You must configure it.
735        #endif
736
737        return mgr;
738}
739
740
741XMLMutexHandle XMLPlatformUtils::makeMutex(MemoryManager* const memmgr)
742{
743    if (!fgMutexMgr)
744                XMLPlatformUtils::panic(PanicHandler::Panic_MutexErr);
745
746        return fgMutexMgr->create(memmgr);
747}
748
749
750void XMLPlatformUtils::closeMutex(XMLMutexHandle const mtx, MemoryManager* const memmgr)
751{
752    if (!fgMutexMgr)
753                XMLPlatformUtils::panic(PanicHandler::Panic_MutexErr);
754
755        fgMutexMgr->destroy(mtx, memmgr);
756}
757
758
759void XMLPlatformUtils::lockMutex(XMLMutexHandle const mtx)
760{
761    if (!fgMutexMgr)
762                XMLPlatformUtils::panic(PanicHandler::Panic_MutexErr);
763
764        fgMutexMgr->lock(mtx);
765}
766
767
768void XMLPlatformUtils::unlockMutex(XMLMutexHandle const mtx)
769{
770    if (!fgMutexMgr)
771                XMLPlatformUtils::panic(PanicHandler::Panic_MutexErr);
772
773        fgMutexMgr->unlock(mtx);
774}
775
776// ---------------------------------------------------------------------------
777//  XMLPlatformUtils: Msg support methods
778// ---------------------------------------------------------------------------
779XMLMsgLoader* XMLPlatformUtils::loadMsgSet(const XMLCh* const msgDomain)
780{
781    //
782    //  Ask the platform support to load up the correct type of message
783    //  loader for the indicated message set. We don't check here whether it
784    //  works or not. That's their decision.
785    //
786    return loadAMsgSet(msgDomain);
787}
788
789// ---------------------------------------------------------------------------
790//  XMLPlatformUtils: NEL Character Handling
791// ---------------------------------------------------------------------------
792void XMLPlatformUtils::recognizeNEL(bool state, MemoryManager* const manager) {
793
794    //Make sure initialize has been called
795    if (gInitFlag == 0) {
796        return;
797    }
798
799    if (state) {
800
801        if (!XMLChar1_0::isNELRecognized()) {
802            XMLChar1_0::enableNELWS();
803        }
804    }
805    else {
806
807        if (XMLChar1_0::isNELRecognized()) {
808            ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::NEL_RepeatedCalls, manager);
809        }
810    }
811}
812
813
814bool XMLPlatformUtils::isNELRecognized() {
815
816    return XMLChar1_0::isNELRecognized();
817}
818
819// ---------------------------------------------------------------------------
820//  XMLPlatformUtils: IANA Encoding checking setting
821// ---------------------------------------------------------------------------
822void XMLPlatformUtils::strictIANAEncoding(const bool state) {
823
824    //Make sure initialize has been called
825    if (gInitFlag == 0) {
826        return;
827    }
828
829    fgTransService->strictIANAEncoding(state);
830}
831
832
833bool XMLPlatformUtils::isStrictIANAEncoding() {
834
835    if (gInitFlag)
836        return fgTransService->isStrictIANAEncoding();
837
838    return false;
839}
840
841/***
842 *
843 *  Previously, each <OS>PlatformUtils.cpp has its onw copy of the
844 *  method weavePaths(), and almost of them implemented the same logic,
845 *  with few platform specific difference, and unfortunately that
846 *  implementation was wrong.
847 *
848 *  The only platform specific issue is slash character.
849 *  On all platforms other than Windows, chForwardSlash and chBackSlash
850 *  are considered slash, while on Windows, two additional characters,
851 *  chYenSign and chWonSign are slash as well.
852 *
853 *  The idea is to maintain a SINGLE copy of this method rather than
854 *  each <OS>PlatformUtils.cpp has its own copy, we introduce a new
855 *  method, XMLPlatformUtils::isAnySlash(), to replace the direct checking
856 *  code ( if ( c == chForwardSlash || c == chBackSlash).
857 *
858 *  With this approach, we might have a performance hit since isAnySlash()
859 *  is so frequently used in this implementation, so we intend to make it
860 *  inline. Then we face a complier issue.
861 *
862 *  There are two compilation units involved, one is PlatformUtils.cpp and
863 *  the other <OS>PlatformUtils.cpp. When PlatformUtils.cp get compiled,
864 *  the weavePath(), remove**Slash() have dependency upon isAnySlash() which
865 *  is in <OS>PlatformUtils.cpp (and what is worse, it is inlined), so we have
866 *  undefined/unresolved symbol: isAnySlash() on AIX/xlc_r, Solaris/cc and
867 *  Linux/gcc, while MSVC and HP/aCC are fine with this.
868 *
869 *  That means we can not place these new methods in PlatformUtils.cpp with
870 *  inlined XMLPlatformUtils::isAnySlash() in <OS>PlatformUtils.cpp.
871 *
872 *  The solution to this is <os>PlatformUtils.cpp will include this file so that
873 *  we have only one copy of these methods while get compiled in <os>PlatformUtils
874 *  inlined isAnySlash().
875 *
876 ***/
877XMLCh* XMLPlatformUtils::weavePaths(const XMLCh* const    basePath
878                                  , const XMLCh* const    relativePath
879                                  , MemoryManager* const  manager)
880
881{
882    // Create a buffer as large as both parts and empty it
883    XMLCh* tmpBuf = (XMLCh*) manager->allocate
884    (
885        (XMLString::stringLen(basePath)
886         + XMLString::stringLen(relativePath) + 2) * sizeof(XMLCh)
887    );//new XMLCh[XMLString::stringLen(basePath) + XMLString::stringLen(relativePath) + 2];
888    *tmpBuf = 0;
889
890    //
891    //  If we have no base path, then just take the relative path as is.
892    //
893    if ((!basePath) || (!*basePath))
894    {
895        XMLString::copyString(tmpBuf, relativePath);
896        return tmpBuf;
897    }
898
899    //
900    // Remove anything after the last slash
901    //
902    const XMLCh* basePtr = basePath + (XMLString::stringLen(basePath) - 1);
903    while ((basePtr >= basePath)  &&  ((isAnySlash(*basePtr) == false)))
904    {
905        basePtr--;
906    }
907
908    // There is no relevant base path, so just take the relative part
909    if (basePtr < basePath)
910    {
911        XMLString::copyString(tmpBuf, relativePath);
912        return tmpBuf;
913    }
914
915    //
916    // 1. concatenate the base and relative
917    // 2. remove all occurences of "/./"
918    // 3. remove all occurences of segment/../ where segment is not ../
919        //
920
921    XMLString::subString(tmpBuf, basePath, 0, (basePtr - basePath + 1), manager);
922    tmpBuf[basePtr - basePath + 1] = 0;
923    XMLString::catString(tmpBuf, relativePath);
924
925    removeDotSlash(tmpBuf, manager);
926
927    removeDotDotSlash(tmpBuf, manager);
928
929    return tmpBuf;
930
931}
932
933//
934// Remove all occurences of './' when it is part of '/./'
935//
936// Since it could be '.\' or other combination on windows ( eg, '.'+chYanSign)
937// we can't make use of patterMatch().
938//
939//
940void XMLPlatformUtils::removeDotSlash(XMLCh* const path
941                                      , MemoryManager* const manager)
942{
943    if ((!path) || (!*path))
944        return;
945
946    XMLCh* srcPtr = XMLString::replicate(path, manager);
947    XMLSize_t srcLen = XMLString::stringLen(srcPtr);
948    ArrayJanitor<XMLCh>   janName(srcPtr, manager);
949    XMLCh* tarPtr = path;
950
951    while (*srcPtr)
952    {
953        if ( 3 <= srcLen )
954        {
955            if ( (isAnySlash(*srcPtr))     &&
956                (chPeriod == *(srcPtr+1)) &&
957                (isAnySlash(*(srcPtr+2)))  )
958            {
959                // "\.\x" seen
960                // skip the first two, and start from the 3rd,
961                // since "\x" could be another "\."
962                srcPtr+=2;
963                srcLen-=2;
964            }
965            else
966            {
967                *tarPtr++ = *srcPtr++;  // eat the current char
968                srcLen--;
969            }
970        }
971        else if ( 1 == srcLen )
972        {
973            *tarPtr++ = *srcPtr++;
974        }
975        else if ( 2 == srcLen)
976        {
977            *tarPtr++ = *srcPtr++;
978            *tarPtr++ = *srcPtr++;
979        }
980
981    }
982
983    *tarPtr = 0;
984
985    return;
986}
987
988//
989// Remove all occurences of '/segment/../' when segment is not '..'
990//
991// Cases with extra /../ is left to the underlying file system.
992//
993void XMLPlatformUtils::removeDotDotSlash(XMLCh* const path
994                                         , MemoryManager* const manager)
995{
996    XMLSize_t pathLen = XMLString::stringLen(path);
997    XMLCh* tmp1 = (XMLCh*) manager->allocate
998    (
999        (pathLen+1) * sizeof(XMLCh)
1000    );//new XMLCh [pathLen+1];
1001    ArrayJanitor<XMLCh>   tmp1Name(tmp1, manager);
1002
1003    XMLCh* tmp2 = (XMLCh*) manager->allocate
1004    (
1005        (pathLen+1) * sizeof(XMLCh)
1006    );//new XMLCh [pathLen+1];
1007    ArrayJanitor<XMLCh>   tmp2Name(tmp2, manager);
1008
1009    // remove all "<segment>/../" where "<segment>" is a complete
1010    // path segment not equal to ".."
1011    int index = -1;
1012    int segIndex = -1;
1013    int offset = 1;
1014
1015    while ((index = searchSlashDotDotSlash(&(path[offset]))) != -1)
1016    {
1017        // Undo offset
1018        index += offset;
1019
1020        // Find start of <segment> within substring ending at found point.
1021        XMLString::subString(tmp1, path, 0, index-1, manager);
1022        segIndex = index - 1;
1023        while ((segIndex >= 0) && (!isAnySlash(tmp1[segIndex])))
1024        {
1025            segIndex--;
1026        }
1027
1028        // Ensure <segment> exists and != ".."
1029        if (segIndex >= 0                 &&
1030            (path[segIndex+1] != chPeriod ||
1031             path[segIndex+2] != chPeriod ||
1032             segIndex + 3 != index))
1033        {
1034
1035            XMLString::subString(tmp1, path, 0, segIndex, manager);
1036            XMLString::subString(tmp2, path, index+3, XMLString::stringLen(path), manager);
1037
1038            path[0] = 0;
1039            XMLString::catString(path, tmp1);
1040            XMLString::catString(path, tmp2);
1041
1042            offset = (segIndex == 0 ? 1 : segIndex);
1043        }
1044        else
1045        {
1046            offset += 4;
1047        }
1048
1049    }// while
1050
1051}
1052
1053int XMLPlatformUtils::searchSlashDotDotSlash(XMLCh* const srcPath)
1054{
1055    if ((!srcPath) || (!*srcPath))
1056        return -1;
1057
1058    XMLCh* srcPtr = srcPath;
1059    XMLSize_t srcLen = XMLString::stringLen(srcPath);
1060    int    retVal = -1;
1061
1062    while (*srcPtr)
1063    {
1064        if ( 4 <= srcLen )
1065        {
1066            if ( (isAnySlash(*srcPtr))     &&
1067                 (chPeriod == *(srcPtr+1)) &&
1068                 (chPeriod == *(srcPtr+2)) &&
1069                 (isAnySlash(*(srcPtr+3)))  )
1070            {
1071                retVal = (int)(srcPtr - srcPath);
1072                break;
1073            }
1074            else
1075            {
1076                srcPtr++;
1077                srcLen--;
1078            }
1079        }
1080        else
1081        {
1082            break;
1083        }
1084
1085    } // while
1086
1087    return retVal;
1088
1089}
1090
1091
1092XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.