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.hpp 568078 2007-08-21 11:43:25Z amassari $ |
---|
20 | */ |
---|
21 | |
---|
22 | |
---|
23 | #if !defined(PLATFORMUTILS_HPP) |
---|
24 | #define PLATFORMUTILS_HPP |
---|
25 | |
---|
26 | #include <xercesc/util/XMLException.hpp> |
---|
27 | #include <xercesc/util/PanicHandler.hpp> |
---|
28 | |
---|
29 | XERCES_CPP_NAMESPACE_BEGIN |
---|
30 | |
---|
31 | class XMLMsgLoader; |
---|
32 | class XMLNetAccessor; |
---|
33 | class XMLTransService; |
---|
34 | class MemoryManager; |
---|
35 | class XMLMutex; |
---|
36 | |
---|
37 | // |
---|
38 | // For internal use only |
---|
39 | // |
---|
40 | // This class provides a simple abstract API via which lazily evaluated |
---|
41 | // data can be cleaned up. |
---|
42 | // |
---|
43 | class XMLUTIL_EXPORT XMLDeleter |
---|
44 | { |
---|
45 | public : |
---|
46 | virtual ~XMLDeleter(); |
---|
47 | |
---|
48 | protected : |
---|
49 | XMLDeleter(); |
---|
50 | |
---|
51 | private : |
---|
52 | XMLDeleter(const XMLDeleter&); |
---|
53 | XMLDeleter& operator=(const XMLDeleter&); |
---|
54 | }; |
---|
55 | |
---|
56 | |
---|
57 | /** |
---|
58 | * Utilities that must be implemented in a platform-specific way. |
---|
59 | * |
---|
60 | * This class contains methods that must be implemented in a platform |
---|
61 | * specific manner. The actual implementations of these methods are |
---|
62 | * available in the per-platform files indide <code>src/util/Platforms |
---|
63 | * </code>. |
---|
64 | */ |
---|
65 | class XMLUTIL_EXPORT XMLPlatformUtils |
---|
66 | { |
---|
67 | public : |
---|
68 | |
---|
69 | /** @name Public Static Data */ |
---|
70 | //@{ |
---|
71 | |
---|
72 | /** The network accessor |
---|
73 | * |
---|
74 | * This is provided by the per-platform driver, so each platform can |
---|
75 | * choose what actual implementation it wants to use. The object must |
---|
76 | * be dynamically allocated. |
---|
77 | * |
---|
78 | * <i>Note that you may optionally, if your platform driver does not |
---|
79 | * install a network accessor, set it manually from your client code |
---|
80 | * after calling Initialize(). This works because this object is |
---|
81 | * not required during initialization, and only comes into play during |
---|
82 | * actual XML parsing.</i> |
---|
83 | */ |
---|
84 | static XMLNetAccessor* fgNetAccessor; |
---|
85 | |
---|
86 | /** The transcoding service. |
---|
87 | * |
---|
88 | * This is provided by the per platform driver, so each platform can |
---|
89 | * choose what implemenation it wants to use. When the platform |
---|
90 | * independent initialization code needs to get a transcoding service |
---|
91 | * object, it will call <code>makeTransService()</code> to ask the |
---|
92 | * per-platform code to create one. Only one transcoding service |
---|
93 | * object is reqeusted per-process, so it is shared and synchronized |
---|
94 | * among parser instances within that process. |
---|
95 | */ |
---|
96 | static XMLTransService* fgTransService; |
---|
97 | #ifdef OS390 |
---|
98 | static XMLTransService* fgTransService2; |
---|
99 | #endif |
---|
100 | |
---|
101 | /** The Panic Handler |
---|
102 | * |
---|
103 | * This is the application provided panic handler. |
---|
104 | */ |
---|
105 | static PanicHandler* fgUserPanicHandler; |
---|
106 | |
---|
107 | /** The Panic Handler |
---|
108 | * |
---|
109 | * This is the default panic handler. |
---|
110 | */ |
---|
111 | static PanicHandler* fgDefaultPanicHandler; |
---|
112 | |
---|
113 | /** The configurable memory manager |
---|
114 | * |
---|
115 | * This is the pluggable memory manager. If it is not provided by an |
---|
116 | * application, a default implementation is used. |
---|
117 | */ |
---|
118 | static MemoryManager* fgMemoryManager; |
---|
119 | |
---|
120 | /** The array-allocating memory manager |
---|
121 | * |
---|
122 | * This memory manager always allocates memory by calling the |
---|
123 | * global new[] operator. It may be used to allocate memory |
---|
124 | * where such memory needs to be deletable by calling delete []. |
---|
125 | * Since this allocator is always guaranteed to do the same thing |
---|
126 | * there is no reason, nor facility, to override it. |
---|
127 | */ |
---|
128 | static MemoryManager* fgArrayMemoryManager; |
---|
129 | |
---|
130 | static XMLMutex* fgAtomicMutex; |
---|
131 | |
---|
132 | //@} |
---|
133 | |
---|
134 | |
---|
135 | /** @name Initialization amd Panic methods */ |
---|
136 | //@{ |
---|
137 | |
---|
138 | /** Perform per-process parser initialization |
---|
139 | * |
---|
140 | * Initialization <b>must</b> be called first in any client code. |
---|
141 | * |
---|
142 | * The locale is set iff the Initialize() is invoked for the very first time, |
---|
143 | * to ensure that each and every message loaders, in the process space, share |
---|
144 | * the same locale. |
---|
145 | * |
---|
146 | * All subsequent invocations of Initialize(), with a different locale, have |
---|
147 | * no effect on the message loaders, either instantiated, or to be instantiated. |
---|
148 | * |
---|
149 | * To set to a different locale, client application needs to Terminate() (or |
---|
150 | * multiple Terminate() in the case where multiple Initialize() have been invoked |
---|
151 | * before), followed by Initialize(new_locale). |
---|
152 | * |
---|
153 | * The default locale is "en_US". |
---|
154 | * |
---|
155 | * nlsHome: user specified location where MsgLoader retrieves error message files. |
---|
156 | * the discussion above with regard to locale, applies to this nlsHome |
---|
157 | * as well. |
---|
158 | * |
---|
159 | * panicHandler: application's panic handler, application owns this handler. |
---|
160 | * Application shall make sure that the plugged panic handler persists |
---|
161 | * through the call to XMLPlatformUtils::terminate(). |
---|
162 | * |
---|
163 | * memoryManager: plugged-in memory manager which is owned by user |
---|
164 | * applications. Applications must make sure that the |
---|
165 | * plugged-in memory manager persist through the call to |
---|
166 | * XMLPlatformUtils::terminate() |
---|
167 | */ |
---|
168 | static void Initialize(const char* const locale = XMLUni::fgXercescDefaultLocale |
---|
169 | , const char* const nlsHome = 0 |
---|
170 | , PanicHandler* const panicHandler = 0 |
---|
171 | , MemoryManager* const memoryManager = 0 |
---|
172 | , bool toInitStatics = false); |
---|
173 | |
---|
174 | /** Perform per-process parser termination |
---|
175 | * |
---|
176 | * The termination call is currently optional, to aid those dynamically |
---|
177 | * loading the parser to clean up before exit, or to avoid spurious |
---|
178 | * reports from leak detectors. |
---|
179 | */ |
---|
180 | static void Terminate(); |
---|
181 | |
---|
182 | /** The panic mechanism. |
---|
183 | * |
---|
184 | * If, during initialization, we cannot even get far enough along |
---|
185 | * to get transcoding up or get message loading working, we call |
---|
186 | * this method.</p> |
---|
187 | * |
---|
188 | * Each platform can implement it however they want. This method will |
---|
189 | * delegate the panic handling to a user specified panic handler or |
---|
190 | * in the absence of it, the default panic handler. |
---|
191 | * |
---|
192 | * In case the default panic handler does not support a particular |
---|
193 | * platform, the platform specific panic hanlding shall be implemented |
---|
194 | * here </p>. |
---|
195 | * |
---|
196 | * @param reason The enumeration that defines the cause of the failure |
---|
197 | */ |
---|
198 | static void panic |
---|
199 | ( |
---|
200 | const PanicHandler::PanicReasons reason |
---|
201 | ); |
---|
202 | |
---|
203 | //@} |
---|
204 | |
---|
205 | /** @name File Methods */ |
---|
206 | //@{ |
---|
207 | |
---|
208 | /** Get the current file position |
---|
209 | * |
---|
210 | * This must be implemented by the per-platform driver, which should |
---|
211 | * use local file services to deterine the current position within |
---|
212 | * the passed file. |
---|
213 | * |
---|
214 | * Since the file API provided here only reads, if the host platform |
---|
215 | * supports separate read/write positions, only the read position is |
---|
216 | * of any interest, and hence should be the one returned. |
---|
217 | * |
---|
218 | * @param theFile The file handle |
---|
219 | * @param manager The MemoryManager to use to allocate objects |
---|
220 | */ |
---|
221 | static unsigned int curFilePos(FileHandle theFile |
---|
222 | , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); |
---|
223 | |
---|
224 | /** Closes the file handle |
---|
225 | * |
---|
226 | * This must be implemented by the per-platform driver, which should |
---|
227 | * use local file services to close the passed file handle, and to |
---|
228 | * destroy the passed file handle and any allocated data or system |
---|
229 | * resources it contains. |
---|
230 | * |
---|
231 | * @param theFile The file handle to close |
---|
232 | * @param manager The MemoryManager to use to allocate objects |
---|
233 | */ |
---|
234 | static void closeFile(FileHandle theFile |
---|
235 | , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); |
---|
236 | |
---|
237 | /** Returns the file size |
---|
238 | * |
---|
239 | * This must be implemented by the per-platform driver, which should |
---|
240 | * use local file services to determine the current size of the file |
---|
241 | * represented by the passed handle. |
---|
242 | * |
---|
243 | * @param theFile The file handle whose size you want |
---|
244 | * @param manager The MemoryManager to use to allocate objects |
---|
245 | * @return Returns the size of the file in bytes |
---|
246 | */ |
---|
247 | static unsigned int fileSize(FileHandle theFile |
---|
248 | , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); |
---|
249 | |
---|
250 | /** Opens the file |
---|
251 | * |
---|
252 | * This must be implemented by the per-platform driver, which should |
---|
253 | * use local file services to open passed file. If it fails, a |
---|
254 | * null handle pointer should be returned. |
---|
255 | * |
---|
256 | * @param fileName The string containing the name of the file |
---|
257 | * @param manager The MemoryManager to use to allocate objects |
---|
258 | * @return The file handle of the opened file |
---|
259 | */ |
---|
260 | static FileHandle openFile(const char* const fileName |
---|
261 | , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); |
---|
262 | |
---|
263 | /** Opens a named file |
---|
264 | * |
---|
265 | * This must be implemented by the per-platform driver, which should |
---|
266 | * use local file services to open the passed file. If it fails, a |
---|
267 | * null handle pointer should be returned. |
---|
268 | * |
---|
269 | * @param fileName The string containing the name of the file |
---|
270 | * @param manager The MemoryManager to use to allocate objects |
---|
271 | * @return The file handle of the opened file |
---|
272 | */ |
---|
273 | static FileHandle openFile(const XMLCh* const fileName |
---|
274 | , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); |
---|
275 | |
---|
276 | /** Open a named file to write |
---|
277 | * |
---|
278 | * This must be implemented by the per-platform driver, which should |
---|
279 | * use local file services to open passed file. If it fails, a |
---|
280 | * null handle pointer should be returned. |
---|
281 | * |
---|
282 | * @param fileName The string containing the name of the file |
---|
283 | * @param manager The MemoryManager to use to allocate objects |
---|
284 | * @return The file handle of the opened file |
---|
285 | */ |
---|
286 | static FileHandle openFileToWrite(const char* const fileName |
---|
287 | , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); |
---|
288 | |
---|
289 | /** Open a named file to write |
---|
290 | * |
---|
291 | * This must be implemented by the per-platform driver, which should |
---|
292 | * use local file services to open the passed file. If it fails, a |
---|
293 | * null handle pointer should be returned. |
---|
294 | * |
---|
295 | * @param fileName The string containing the name of the file |
---|
296 | * @param manager The MemoryManager to use to allocate objects |
---|
297 | * @return The file handle of the opened file |
---|
298 | */ |
---|
299 | static FileHandle openFileToWrite(const XMLCh* const fileName |
---|
300 | , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); |
---|
301 | |
---|
302 | /** Opens the standard input as a file |
---|
303 | * |
---|
304 | * This must be implemented by the per-platform driver, which should |
---|
305 | * use local file services to open a handle to the standard input. |
---|
306 | * It should be a copy of the standard input handle, since it will |
---|
307 | * be closed later! |
---|
308 | * |
---|
309 | * @param manager The MemoryManager to use to allocate objects |
---|
310 | * @return The file handle of the standard input stream |
---|
311 | */ |
---|
312 | static FileHandle openStdInHandle(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); |
---|
313 | |
---|
314 | /** Reads the file buffer |
---|
315 | * |
---|
316 | * This must be implemented by the per-platform driver, which should |
---|
317 | * use local file services to read up to 'toRead' bytes of data from |
---|
318 | * the passed file, and return those bytes in the 'toFill' buffer. It |
---|
319 | * is not an error not to read the requested number of bytes. When the |
---|
320 | * end of file is reached, zero should be returned. |
---|
321 | * |
---|
322 | * @param theFile The file handle to be read from. |
---|
323 | * @param toRead The maximum number of byte to read from the current |
---|
324 | * position |
---|
325 | * @param toFill The byte buffer to fill |
---|
326 | * @param manager The MemoryManager to use to allocate objects |
---|
327 | * |
---|
328 | * @return Returns the number of bytes read from the stream or file |
---|
329 | */ |
---|
330 | static unsigned int readFileBuffer |
---|
331 | ( |
---|
332 | FileHandle theFile |
---|
333 | , const unsigned int toRead |
---|
334 | , XMLByte* const toFill |
---|
335 | , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager |
---|
336 | ); |
---|
337 | |
---|
338 | /** Writes the buffer to the file |
---|
339 | * |
---|
340 | * This must be implemented by the per-platform driver, which should |
---|
341 | * use local file services to write up to 'toWrite' bytes of data to |
---|
342 | * the passed file. Unless exception raised by local file services, |
---|
343 | * 'toWrite' bytes of data is to be written to the passed file. |
---|
344 | * |
---|
345 | * @param theFile The file handle to be written to. |
---|
346 | * @param toWrite The maximum number of byte to write from the current |
---|
347 | * position |
---|
348 | * @param toFlush The byte buffer to flush |
---|
349 | * @param manager The MemoryManager to use to allocate objects |
---|
350 | * @return void |
---|
351 | */ |
---|
352 | static void writeBufferToFile |
---|
353 | ( |
---|
354 | FileHandle const theFile |
---|
355 | , long toWrite |
---|
356 | , const XMLByte* const toFlush |
---|
357 | , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager |
---|
358 | ); |
---|
359 | |
---|
360 | /** Resets the file handle |
---|
361 | * |
---|
362 | * This must be implemented by the per-platform driver which will use |
---|
363 | * local file services to reset the file position to the start of the |
---|
364 | * the file. |
---|
365 | * |
---|
366 | * @param theFile The file handle that you want to reset |
---|
367 | * @param manager The MemoryManager to use to allocate objects |
---|
368 | */ |
---|
369 | static void resetFile(FileHandle theFile |
---|
370 | , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); |
---|
371 | |
---|
372 | //@} |
---|
373 | |
---|
374 | |
---|
375 | /** @name File System Methods */ |
---|
376 | //@{ |
---|
377 | /** Gets the full path from a relative path |
---|
378 | * |
---|
379 | * This must be implemented by the per-platform driver. It should |
---|
380 | * complete a relative path using the 'current directory', or whatever |
---|
381 | * the local equivalent of a current directory is. If the passed |
---|
382 | * source path is actually fully qualified, then a straight copy of it |
---|
383 | * will be returned. |
---|
384 | * |
---|
385 | * @param srcPath The path of the file for which you want the full path |
---|
386 | * |
---|
387 | * @param manager Pointer to the memory manager to be used to |
---|
388 | * allocate objects. |
---|
389 | * |
---|
390 | * @return Returns the fully qualified path of the file name including |
---|
391 | * the file name. This is dyanmically allocated and must be |
---|
392 | * deleted by the caller when its no longer needed! The memory |
---|
393 | * returned will beallocated using the static memory manager, if |
---|
394 | * user do not supply a memory manager. Users then need to make |
---|
395 | * sure to use either the default or user specific memory manager |
---|
396 | * to deallocate the memory. |
---|
397 | */ |
---|
398 | static XMLCh* getFullPath |
---|
399 | ( |
---|
400 | const XMLCh* const srcPath |
---|
401 | , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager |
---|
402 | ); |
---|
403 | |
---|
404 | /** Gets the current working directory |
---|
405 | * |
---|
406 | * This must be implemented by the per-platform driver. It returns |
---|
407 | * the current working directory is. |
---|
408 | * @param manager The MemoryManager to use to allocate objects |
---|
409 | * @return Returns the current working directory. |
---|
410 | * This is dyanmically allocated and must be deleted |
---|
411 | * by the caller when its no longer needed! The memory returned |
---|
412 | * will be allocated using the static memory manager, if users |
---|
413 | * do not supply a memory manager. Users then need to make sure |
---|
414 | * to use either the default or user specific memory manager to |
---|
415 | * deallocate the memory. |
---|
416 | */ |
---|
417 | static XMLCh* getCurrentDirectory |
---|
418 | ( |
---|
419 | MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager |
---|
420 | ); |
---|
421 | |
---|
422 | /** Check if a charater is a slash |
---|
423 | * |
---|
424 | * This must be implemented by the per-platform driver. |
---|
425 | * |
---|
426 | * @param c the character to be examined |
---|
427 | * |
---|
428 | * @return true if the character examined is a slash |
---|
429 | * false otherwise |
---|
430 | */ |
---|
431 | static inline bool isAnySlash(XMLCh c); |
---|
432 | |
---|
433 | /** Remove occurences of the pair of dot slash |
---|
434 | * |
---|
435 | * To remove the sequence, dot slash if it is part of the sequence, |
---|
436 | * slash dot slash. |
---|
437 | * |
---|
438 | * @param srcPath The path for which you want to remove the dot slash sequence. |
---|
439 | * @param manager The MemoryManager to use to allocate objects |
---|
440 | * @return |
---|
441 | */ |
---|
442 | static void removeDotSlash(XMLCh* const srcPath |
---|
443 | , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); |
---|
444 | |
---|
445 | /** Remove occurences of the dot dot slash |
---|
446 | * |
---|
447 | * To remove the sequence, slash dot dot slash and its preceding path segment |
---|
448 | * if and only if the preceding path segment is not slash dot dot slash. |
---|
449 | * |
---|
450 | * @param srcPath The path for which you want to remove the slash dot |
---|
451 | * dot slash sequence and its preceding path segment. |
---|
452 | * @param manager The MemoryManager to use to allocate objects |
---|
453 | * @return |
---|
454 | */ |
---|
455 | static void removeDotDotSlash(XMLCh* const srcPath |
---|
456 | , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); |
---|
457 | |
---|
458 | /** Determines if a path is relative or absolute |
---|
459 | * |
---|
460 | * This must be implemented by the per-platform driver, which should |
---|
461 | * determine whether the passed path is relative or not. The concept |
---|
462 | * of relative and absolute might be... well relative on different |
---|
463 | * platforms. But, as long as the determination is made consistently |
---|
464 | * and in coordination with the weavePaths() method, it should work |
---|
465 | * for any platform. |
---|
466 | * |
---|
467 | * @param toCheck The file name which you want to check |
---|
468 | * @param manager The MemoryManager to use to allocate objects |
---|
469 | * @return Returns true if the filename appears to be relative |
---|
470 | */ |
---|
471 | static bool isRelative(const XMLCh* const toCheck |
---|
472 | , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager |
---|
473 | ); |
---|
474 | |
---|
475 | /** Utility to join two paths |
---|
476 | * |
---|
477 | * This must be implemented by the per-platform driver, and should |
---|
478 | * weave the relative path part together with the base part and return |
---|
479 | * a new path that represents this combination. |
---|
480 | * |
---|
481 | * If the relative part turns out to be fully qualified, it will be |
---|
482 | * returned as is. If it is not, then it will be woven onto the |
---|
483 | * passed base path, by removing one path component for each leading |
---|
484 | * "../" (or whatever is the equivalent in the local system) in the |
---|
485 | * relative path. |
---|
486 | * |
---|
487 | * @param basePath The string containing the base path |
---|
488 | * @param relativePath The string containing the relative path |
---|
489 | * @param manager The MemoryManager to use to allocate objects |
---|
490 | * @return Returns a string containing the 'woven' path. It should |
---|
491 | * be dynamically allocated and becomes the responsibility of the |
---|
492 | * caller to delete. |
---|
493 | */ |
---|
494 | static XMLCh* weavePaths |
---|
495 | ( |
---|
496 | const XMLCh* const basePath |
---|
497 | , const XMLCh* const relativePath |
---|
498 | , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager |
---|
499 | ); |
---|
500 | //@} |
---|
501 | |
---|
502 | /** @name Timing Methods */ |
---|
503 | //@{ |
---|
504 | |
---|
505 | /** Gets the system time in milliseconds |
---|
506 | * |
---|
507 | * This must be implemented by the per-platform driver, which should |
---|
508 | * use local services to return the current value of a running |
---|
509 | * millisecond timer. Note that the value returned is only as accurate |
---|
510 | * as the millisecond time of the underyling host system. |
---|
511 | * |
---|
512 | * @return Returns the system time as an unsigned long |
---|
513 | */ |
---|
514 | static unsigned long getCurrentMillis(); |
---|
515 | //@} |
---|
516 | |
---|
517 | /** @name Mutex Methods */ |
---|
518 | //@{ |
---|
519 | |
---|
520 | /** Closes a mutex handle |
---|
521 | * |
---|
522 | * Each per-platform driver must implement this. Only it knows what |
---|
523 | * the actual content of the passed mutex handle is. |
---|
524 | * |
---|
525 | * @param mtxHandle The mutex handle that you want to close |
---|
526 | */ |
---|
527 | static void closeMutex(void* const mtxHandle); |
---|
528 | |
---|
529 | /** Locks a mutex handle |
---|
530 | * |
---|
531 | * Each per-platform driver must implement this. Only it knows what |
---|
532 | * the actual content of the passed mutex handle is. |
---|
533 | * |
---|
534 | * @param mtxHandle The mutex handle that you want to lock |
---|
535 | */ |
---|
536 | static void lockMutex(void* const mtxHandle); |
---|
537 | |
---|
538 | /** Make a new mutex |
---|
539 | * |
---|
540 | * Each per-platform driver must implement this. Only it knows what |
---|
541 | * the actual content of the passed mutex handle is. The returned |
---|
542 | * handle pointer will be eventually passed to closeMutex() which is |
---|
543 | * also implemented by the platform driver. |
---|
544 | * |
---|
545 | * @param manager The MemoryManager to use to allocate objects |
---|
546 | */ |
---|
547 | static void* makeMutex(MemoryManager* manager = XMLPlatformUtils::fgMemoryManager); |
---|
548 | |
---|
549 | /** Unlocks a mutex |
---|
550 | * |
---|
551 | * Each per-platform driver must implement this. Only it knows what |
---|
552 | * the actual content of the passed mutex handle is. |
---|
553 | * |
---|
554 | * Note that, since the underlying system synchronization services |
---|
555 | * are used, Xerces cannot guarantee that lock/unlock operations are |
---|
556 | * correctly enforced on a per-thread basis or that incorrect nesting |
---|
557 | * of lock/unlock operations will be caught. |
---|
558 | * |
---|
559 | * @param mtxHandle The mutex handle that you want to unlock |
---|
560 | */ |
---|
561 | static void unlockMutex(void* const mtxHandle); |
---|
562 | |
---|
563 | //@} |
---|
564 | |
---|
565 | |
---|
566 | /** @name External Message Support */ |
---|
567 | //@{ |
---|
568 | |
---|
569 | /** Loads the message set from among the available domains |
---|
570 | * |
---|
571 | * The returned object must be dynamically allocated and the caller |
---|
572 | * becomes responsible for cleaning it up. |
---|
573 | * |
---|
574 | * @param msgDomain The message domain which you want to load |
---|
575 | */ |
---|
576 | static XMLMsgLoader* loadMsgSet(const XMLCh* const msgDomain); |
---|
577 | |
---|
578 | //@} |
---|
579 | |
---|
580 | /** @name Miscellaneous synchronization methods */ |
---|
581 | //@{ |
---|
582 | |
---|
583 | /** Conditionally updates or returns a single word variable atomically |
---|
584 | * |
---|
585 | * This must be implemented by the per-platform driver. The |
---|
586 | * compareAndSwap subroutine performs an atomic operation which |
---|
587 | * compares the contents of a single word variable with a stored old |
---|
588 | * value. If the values are equal, a new value is stored in the single |
---|
589 | * word variable and TRUE is returned; otherwise, the old value is set |
---|
590 | * to the current value of the single word variable and FALSE is |
---|
591 | * returned. |
---|
592 | * |
---|
593 | * The compareAndSwap subroutine is useful when a word value must be |
---|
594 | * updated only if it has not been changed since it was last read. |
---|
595 | * |
---|
596 | * Note: The word containing the single word variable must be aligned |
---|
597 | * on a full word boundary. |
---|
598 | * |
---|
599 | * @param toFill Specifies the address of the single word variable |
---|
600 | * @param newValue Specifies the new value to be conditionally assigned |
---|
601 | * to the single word variable. |
---|
602 | * @param toCompare Specifies the address of the old value to be checked |
---|
603 | * against (and conditionally updated with) the value of the single word |
---|
604 | * variable. |
---|
605 | * |
---|
606 | * @return Returns the new value assigned to the single word variable |
---|
607 | */ |
---|
608 | static void* compareAndSwap |
---|
609 | ( |
---|
610 | void** toFill |
---|
611 | , const void* const newValue |
---|
612 | , const void* const toCompare |
---|
613 | ); |
---|
614 | |
---|
615 | //@} |
---|
616 | |
---|
617 | |
---|
618 | /** @name Atomic Increment and Decrement */ |
---|
619 | //@{ |
---|
620 | |
---|
621 | /** Increments a single word variable atomically. |
---|
622 | * |
---|
623 | * This must be implemented by the per-platform driver. The |
---|
624 | * atomicIncrement subroutine increments one word in a single atomic |
---|
625 | * operation. This operation is useful when a counter variable is shared |
---|
626 | * between several threads or processes. When updating such a counter |
---|
627 | * variable, it is important to make sure that the fetch, update, and |
---|
628 | * store operations occur atomically (are not interruptible). |
---|
629 | * |
---|
630 | * @param location Specifies the address of the word variable to be |
---|
631 | * incremented. |
---|
632 | * |
---|
633 | * @return The function return value is positive if the result of the |
---|
634 | * operation was positive. Zero if the result of the operation was zero. |
---|
635 | * Negative if the result of the operation was negative. Except for the |
---|
636 | * zero case, the value returned may differ from the actual result of |
---|
637 | * the operation - only the sign and zero/nonzero state is guaranteed |
---|
638 | * to be correct. |
---|
639 | */ |
---|
640 | static int atomicIncrement(int& location); |
---|
641 | |
---|
642 | /** Decrements a single word variable atomically. |
---|
643 | * |
---|
644 | * This must be implemented by the per-platform driver. The |
---|
645 | * atomicDecrement subroutine increments one word in a single atomic |
---|
646 | * operation. This operation is useful when a counter variable is shared |
---|
647 | * between several threads or processes. When updating such a counter |
---|
648 | * variable, it is important to make sure that the fetch, update, and |
---|
649 | * store operations occur atomically (are not interruptible). |
---|
650 | * |
---|
651 | * @param location Specifies the address of the word variable to be |
---|
652 | * decremented. |
---|
653 | * |
---|
654 | * @return The function return value is positive if the result of the |
---|
655 | * operation was positive. Zero if the result of the operation was zero. |
---|
656 | * Negative if the result of the operation was negative. Except for the |
---|
657 | * zero case, the value returned may differ from the actual result of the |
---|
658 | * operation - only the sign and zero/nonzero state is guaranteed to be |
---|
659 | * correct. |
---|
660 | */ |
---|
661 | static int atomicDecrement(int& location); |
---|
662 | |
---|
663 | //@} |
---|
664 | |
---|
665 | /** @name NEL Character Handling */ |
---|
666 | //@{ |
---|
667 | /** |
---|
668 | * This function enables the recognition of NEL(0x85) char and LSEP (0x2028) as newline chars |
---|
669 | * which is disabled by default. |
---|
670 | * It is only called once per process. Once it is set, any subsequent calls |
---|
671 | * will result in exception being thrown. |
---|
672 | * |
---|
673 | * Note: 1. Turning this option on will make the parser non compliant to XML 1.0. |
---|
674 | * 2. This option has no effect to document conforming to XML 1.1 compliant, |
---|
675 | * which always recognize these two chars (0x85 and 0x2028) as newline characters. |
---|
676 | * |
---|
677 | */ |
---|
678 | static void recognizeNEL(bool state |
---|
679 | , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); |
---|
680 | |
---|
681 | /** |
---|
682 | * Return the value of fgNEL flag. |
---|
683 | */ |
---|
684 | static bool isNELRecognized(); |
---|
685 | //@} |
---|
686 | |
---|
687 | /** @name Strict IANA Encoding Checking */ |
---|
688 | //@{ |
---|
689 | /** |
---|
690 | * This function enables/disables strict IANA encoding names checking. |
---|
691 | * |
---|
692 | * The strict checking is disabled by default. |
---|
693 | * |
---|
694 | * @param state If true, a strict IANA encoding name check is performed, |
---|
695 | * otherwise, no checking. |
---|
696 | * |
---|
697 | */ |
---|
698 | static void strictIANAEncoding(const bool state); |
---|
699 | |
---|
700 | /** |
---|
701 | * Returns whether a strict IANA encoding name check is enabled or |
---|
702 | * disabled. |
---|
703 | */ |
---|
704 | static bool isStrictIANAEncoding(); |
---|
705 | //@} |
---|
706 | |
---|
707 | /** |
---|
708 | * Aligns the specified pointer per platform block allocation |
---|
709 | * requirements. |
---|
710 | * |
---|
711 | * The results of this function may be altered by defining |
---|
712 | * XML_PLATFORM_NEW_BLOCK_ALIGNMENT. |
---|
713 | */ |
---|
714 | static inline size_t alignPointerForNewBlockAllocation(size_t ptrSize); |
---|
715 | |
---|
716 | private : |
---|
717 | // ----------------------------------------------------------------------- |
---|
718 | // Unimplemented constructors and operators |
---|
719 | // ----------------------------------------------------------------------- |
---|
720 | XMLPlatformUtils(); |
---|
721 | |
---|
722 | /** @name Private static methods */ |
---|
723 | //@{ |
---|
724 | |
---|
725 | /** Loads a message set from the available domains |
---|
726 | * |
---|
727 | * @param msgDomain The message domain containing the message to be |
---|
728 | * loaded |
---|
729 | */ |
---|
730 | static XMLMsgLoader* loadAMsgSet(const XMLCh* const msgDomain); |
---|
731 | |
---|
732 | /** Creates a net accessor object. |
---|
733 | * |
---|
734 | * Each per-platform driver must implement this method. However, |
---|
735 | * having a Net Accessor is optional and this method can return a |
---|
736 | * null pointer if remote access via HTTP and FTP URLs is not required. |
---|
737 | * |
---|
738 | * @return An object derived from XMLNetAccessor. It must be dynamically |
---|
739 | * allocated, since it will be deleted later. |
---|
740 | */ |
---|
741 | static XMLNetAccessor* makeNetAccessor(); |
---|
742 | |
---|
743 | /** Creates a Transoding service |
---|
744 | * |
---|
745 | * Each per-platform driver must implement this method and return some |
---|
746 | * derivative of the XMLTransService class. This object serves as the |
---|
747 | * transcoder factory for this process. The object must be dynamically |
---|
748 | * allocated and the caller is responsible for cleaning it up. |
---|
749 | * |
---|
750 | * @return A dynamically allocated object of some class derived from |
---|
751 | * the XMLTransService class. |
---|
752 | */ |
---|
753 | static XMLTransService* makeTransService(); |
---|
754 | |
---|
755 | /** Does initialization for a particular platform |
---|
756 | * |
---|
757 | * Each per-platform driver must implement this to do any low level |
---|
758 | * system initialization required. It <b>cannot</b> use any XML |
---|
759 | * parser or utilities services! |
---|
760 | */ |
---|
761 | static void platformInit(); |
---|
762 | |
---|
763 | /** Does termination for a particular platform |
---|
764 | * |
---|
765 | * Each per-platform driver must implement this to do any low level |
---|
766 | * system resource cleanup required. It <b>cannot</b> use any XML |
---|
767 | * parser or utilities services! |
---|
768 | */ |
---|
769 | static void platformTerm(); |
---|
770 | |
---|
771 | /** Search for sequence, slash dot dot slash |
---|
772 | * |
---|
773 | * @param srcPath the path to search |
---|
774 | * |
---|
775 | * @return the position of the first occurence of slash dot dot slash |
---|
776 | * -1 if no such sequence is found |
---|
777 | */ |
---|
778 | static int searchSlashDotDotSlash(XMLCh* const srcPath); |
---|
779 | |
---|
780 | //@} |
---|
781 | |
---|
782 | /** @name Private static methods */ |
---|
783 | //@{ |
---|
784 | |
---|
785 | /** |
---|
786 | * Indicates whether the memory manager was supplied by the user |
---|
787 | * or not. Users own the memory manager, and if none is supplied, |
---|
788 | * Xerces uses a default one that it owns and is responsible for |
---|
789 | * deleting in Terminate(). |
---|
790 | */ |
---|
791 | static bool fgMemMgrAdopted; |
---|
792 | |
---|
793 | //@} |
---|
794 | }; |
---|
795 | |
---|
796 | |
---|
797 | MakeXMLException(XMLPlatformUtilsException, XMLUTIL_EXPORT) |
---|
798 | |
---|
799 | |
---|
800 | // --------------------------------------------------------------------------- |
---|
801 | // XMLPlatformUtils: alignPointerForNewBlockAllocation |
---|
802 | // --------------------------------------------------------------------------- |
---|
803 | // Calculate alignment required by platform for a new |
---|
804 | // block allocation. We use this in our custom allocators |
---|
805 | // to ensure that returned blocks are properly aligned. |
---|
806 | // Note that, although this will take a pointer and return the position |
---|
807 | // at which it should be placed for correct alignment, in our code |
---|
808 | // we normally use size_t parameters to discover what the alignment |
---|
809 | // of header blocks should be. Thus, if this is to be |
---|
810 | // used for the former purpose, to make compilers happy |
---|
811 | // some casting will be necessary - neilg. |
---|
812 | // |
---|
813 | // Note: XML_PLATFORM_NEW_BLOCK_ALIGNMENT may be specified on a |
---|
814 | // per-architecture basis to dictate the alignment requirements |
---|
815 | // of the architecture. In the absense of this specification, |
---|
816 | // this routine guesses at the correct alignment value. |
---|
817 | // |
---|
818 | // A XML_PLATFORM_NEW_BLOCK_ALIGNMENT value of zero is illegal. |
---|
819 | // If a platform requires absolutely no alignment, a value |
---|
820 | // of 1 should be specified ("align pointers on 1 byte boundaries"). |
---|
821 | // |
---|
822 | inline size_t |
---|
823 | XMLPlatformUtils::alignPointerForNewBlockAllocation(size_t ptrSize) |
---|
824 | { |
---|
825 | // Macro XML_PLATFORM_NEW_BLOCK_ALIGNMENT may be defined |
---|
826 | // as needed to dictate alignment requirements on a |
---|
827 | // per-architecture basis. In the absense of that we |
---|
828 | // take an educated guess. |
---|
829 | #ifdef XML_PLATFORM_NEW_BLOCK_ALIGNMENT |
---|
830 | size_t alignment = XML_PLATFORM_NEW_BLOCK_ALIGNMENT; |
---|
831 | #else |
---|
832 | size_t alignment = (sizeof(void*) >= sizeof(double)) ? sizeof(void*) : sizeof(double); |
---|
833 | #endif |
---|
834 | |
---|
835 | // Calculate current alignment of pointer |
---|
836 | size_t current = ptrSize % alignment; |
---|
837 | |
---|
838 | // Adjust pointer alignment as needed |
---|
839 | return (current == 0) |
---|
840 | ? ptrSize |
---|
841 | : (ptrSize + alignment - current); |
---|
842 | } |
---|
843 | |
---|
844 | |
---|
845 | |
---|
846 | // --------------------------------------------------------------------------- |
---|
847 | // XMLDeleter: Public Destructor |
---|
848 | // --------------------------------------------------------------------------- |
---|
849 | inline XMLDeleter::~XMLDeleter() |
---|
850 | { |
---|
851 | } |
---|
852 | |
---|
853 | // --------------------------------------------------------------------------- |
---|
854 | // XMLDeleter: Hidden constructors and operators |
---|
855 | // --------------------------------------------------------------------------- |
---|
856 | inline XMLDeleter::XMLDeleter() |
---|
857 | { |
---|
858 | } |
---|
859 | |
---|
860 | XERCES_CPP_NAMESPACE_END |
---|
861 | |
---|
862 | #endif |
---|