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

Last change on this file since 3908 was 3908, checked in by nmedfort, 5 years ago

Removed SSE2 test.

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