Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(399)

Side by Side Diff: icu46/source/common/udata.cpp

Issue 5516007: Check in the pristine copy of ICU 4.6... (Closed) Base URL: svn://chrome-svn/chrome/trunk/deps/third_party/
Patch Set: Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « icu46/source/common/ucol_swp.cpp ('k') | icu46/source/common/udatamem.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 /*
2 ******************************************************************************
3 *
4 * Copyright (C) 1999-2010, International Business Machines
5 * Corporation and others. All Rights Reserved.
6 *
7 ******************************************************************************
8 * file name: udata.cpp
9 * encoding: US-ASCII
10 * tab size: 8 (not used)
11 * indentation:4
12 *
13 * created on: 1999oct25
14 * created by: Markus W. Scherer
15 */
16
17 #include "unicode/utypes.h" /* U_LINUX */
18
19 #ifdef U_LINUX
20 /* if gcc
21 #define ATTRIBUTE_WEAK __attribute__ ((weak))
22 might have to #include some other header
23 */
24 #endif
25
26 #include "unicode/putil.h"
27 #include "unicode/udata.h"
28 #include "unicode/uversion.h"
29 #include "charstr.h"
30 #include "cmemory.h"
31 #include "cstring.h"
32 #include "putilimp.h"
33 #include "ucln_cmn.h"
34 #include "ucmndata.h"
35 #include "udatamem.h"
36 #include "uhash.h"
37 #include "umapfile.h"
38 #include "umutex.h"
39
40 /***********************************************************************
41 *
42 * Notes on the organization of the ICU data implementation
43 *
44 * All of the public API is defined in udata.h
45 *
46 * The implementation is split into several files...
47 *
48 * - udata.c (this file) contains higher level code that knows about
49 * the search paths for locating data, caching opened data, e tc.
50 *
51 * - umapfile.c contains the low level platform-specific code for actual ly loading
52 * (memory mapping, file reading, whatever) data into memory.
53 *
54 * - ucmndata.c deals with the tables of contents of ICU data items with in
55 * an ICU common format data file. The implementation includ es
56 * an abstract interface and support for multiple TOC formats .
57 * All knowledge of any specific TOC format is encapsulated h ere.
58 *
59 * - udatamem.c has code for managing UDataMemory structs. These are lit tle
60 * descriptor objects for blocks of memory holding ICU data o f
61 * various types.
62 */
63
64 /* configuration ---------------------------------------------------------- */
65
66 /* If you are excruciatingly bored turn this on .. */
67 /* #define UDATA_DEBUG 1 */
68
69 #if defined(UDATA_DEBUG)
70 # include <stdio.h>
71 #endif
72
73 #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
74
75 U_NAMESPACE_USE
76
77 /***********************************************************************
78 *
79 * static (Global) data
80 *
81 ************************************************************************/
82
83 /*
84 * Pointers to the common ICU data.
85 *
86 * We store multiple pointers to ICU data packages and iterate through them
87 * when looking for a data item.
88 *
89 * It is possible to combine this with dependency inversion:
90 * One or more data package libraries may export
91 * functions that each return a pointer to their piece of the ICU data,
92 * and this file would import them as weak functions, without a
93 * strong linker dependency from the common library on the data library.
94 *
95 * Then we can have applications depend on only that part of ICU's data
96 * that they really need, reducing the size of binaries that take advantage
97 * of this.
98 */
99 static UDataMemory *gCommonICUDataArray[10] = { NULL };
100
101 static UBool gHaveTriedToLoadCommonData = FALSE; /* See extendICUData(). */
102
103 static UHashtable *gCommonDataCache = NULL; /* Global hash table of opened ICU data files. */
104
105 static UDataFileAccess gDataFileAccess = UDATA_DEFAULT_ACCESS;
106
107 static UBool U_CALLCONV
108 udata_cleanup(void)
109 {
110 int32_t i;
111
112 if (gCommonDataCache) { /* Delete the cache of user data mapping s. */
113 uhash_close(gCommonDataCache); /* Table owns the contents, and will d elete them. */
114 gCommonDataCache = NULL; /* Cleanup is not thread safe. */
115 }
116
117 for (i = 0; i < LENGTHOF(gCommonICUDataArray) && gCommonICUDataArray[i] != N ULL; ++i) {
118 udata_close(gCommonICUDataArray[i]);
119 gCommonICUDataArray[i] = NULL;
120 }
121 gHaveTriedToLoadCommonData = FALSE;
122
123 return TRUE; /* Everything was cleaned up */
124 }
125
126
127
128
129 /*
130 * setCommonICUData. Set a UDataMemory to be the global ICU Data
131 */
132 static UBool
133 setCommonICUData(UDataMemory *pData, /* The new common data. Belongs to ca ller, we copy it. */
134 UBool warn, /* If true, set USING_DEFAULT warning if ICUData was */
135 /* changed by another thread before we got to it. */
136 UErrorCode *pErr)
137 {
138 UDataMemory *newCommonData = UDataMemory_createNewInstance(pErr);
139 int32_t i;
140 UBool didUpdate = FALSE;
141 if (U_FAILURE(*pErr)) {
142 return FALSE;
143 }
144
145 /* For the assignment, other threads must cleanly see either the old */
146 /* or the new, not some partially initialized new. The old can not be */
147 /* deleted - someone may still have a pointer to it lying around in */
148 /* their locals. */
149 UDatamemory_assign(newCommonData, pData);
150 umtx_lock(NULL);
151 for (i = 0; i < LENGTHOF(gCommonICUDataArray); ++i) {
152 if (gCommonICUDataArray[i] == NULL) {
153 gCommonICUDataArray[i] = newCommonData;
154 ucln_common_registerCleanup(UCLN_COMMON_UDATA, udata_cleanup);
155 didUpdate = TRUE;
156 break;
157 } else if (gCommonICUDataArray[i]->pHeader == pData->pHeader) {
158 /* The same data pointer is already in the array. */
159 break;
160 }
161 }
162 umtx_unlock(NULL);
163
164 if (i == LENGTHOF(gCommonICUDataArray) && warn) {
165 *pErr = U_USING_DEFAULT_WARNING;
166 }
167 if (!didUpdate) {
168 uprv_free(newCommonData);
169 }
170 return didUpdate;
171 }
172
173 static UBool
174 setCommonICUDataPointer(const void *pData, UBool /*warn*/, UErrorCode *pErrorCod e) {
175 UDataMemory tData;
176 UDataMemory_init(&tData);
177 tData.pHeader = (const DataHeader *)pData;
178 udata_checkCommonData(&tData, pErrorCode);
179 return setCommonICUData(&tData, FALSE, pErrorCode);
180 }
181
182 static const char *
183 findBasename(const char *path) {
184 const char *basename=uprv_strrchr(path, U_FILE_SEP_CHAR);
185 if(basename==NULL) {
186 return path;
187 } else {
188 return basename+1;
189 }
190 }
191
192 #ifdef UDATA_DEBUG
193 static const char *
194 packageNameFromPath(const char *path)
195 {
196 if((path == NULL) || (*path == 0)) {
197 return U_ICUDATA_NAME;
198 }
199
200 path = findBasename(path);
201
202 if((path == NULL) || (*path == 0)) {
203 return U_ICUDATA_NAME;
204 }
205
206 return path;
207 }
208 #endif
209
210 /*----------------------------------------------------------------------*
211 * *
212 * Cache for common data *
213 * Functions for looking up or adding entries to a cache of *
214 * data that has been previously opened. Avoids a potentially *
215 * expensive operation of re-opening the data for subsequent *
216 * uses. *
217 * *
218 * Data remains cached for the duration of the process. *
219 * *
220 *----------------------------------------------------------------------*/
221
222 typedef struct DataCacheElement {
223 char *name;
224 UDataMemory *item;
225 } DataCacheElement;
226
227
228
229 /*
230 * Deleter function for DataCacheElements.
231 * udata cleanup function closes the hash table; hash table in turn call s back to
232 * here for each entry.
233 */
234 static void U_CALLCONV DataCacheElement_deleter(void *pDCEl) {
235 DataCacheElement *p = (DataCacheElement *)pDCEl;
236 udata_close(p->item); /* unmaps storage */
237 uprv_free(p->name); /* delete the hash key string. */
238 uprv_free(pDCEl); /* delete 'this' */
239 }
240
241 /* udata_getCacheHashTable()
242 * Get the hash table used to store the data cache entries.
243 * Lazy create it if it doesn't yet exist.
244 */
245 static UHashtable *udata_getHashTable() {
246 UErrorCode err = U_ZERO_ERROR;
247 UBool cacheIsInitialized;
248 UHashtable *tHT = NULL;
249
250 UMTX_CHECK(NULL, (gCommonDataCache != NULL), cacheIsInitialized);
251
252 if (cacheIsInitialized) {
253 return gCommonDataCache;
254 }
255
256 tHT = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &err);
257 /* Check for null pointer. */
258 if (tHT == NULL) {
259 return NULL; /* TODO: Handle this error better. */
260 }
261 uhash_setValueDeleter(tHT, DataCacheElement_deleter);
262
263 umtx_lock(NULL);
264 if (gCommonDataCache == NULL) {
265 gCommonDataCache = tHT;
266 tHT = NULL;
267 ucln_common_registerCleanup(UCLN_COMMON_UDATA, udata_cleanup);
268 }
269 umtx_unlock(NULL);
270 if (tHT != NULL) {
271 uhash_close(tHT);
272 }
273
274 if (U_FAILURE(err)) {
275 return NULL; /* TODO: handle this error better. */
276 }
277 return gCommonDataCache;
278 }
279
280
281
282 static UDataMemory *udata_findCachedData(const char *path)
283 {
284 UHashtable *htable;
285 UDataMemory *retVal = NULL;
286 DataCacheElement *el;
287 const char *baseName;
288
289 baseName = findBasename(path); /* Cache remembers only the base name, not the full path. */
290 htable = udata_getHashTable();
291 umtx_lock(NULL);
292 el = (DataCacheElement *)uhash_get(htable, baseName);
293 umtx_unlock(NULL);
294 if (el != NULL) {
295 retVal = el->item;
296 }
297 #ifdef UDATA_DEBUG
298 fprintf(stderr, "Cache: [%s] -> %p\n", baseName, retVal);
299 #endif
300 return retVal;
301 }
302
303
304 static UDataMemory *udata_cacheDataItem(const char *path, UDataMemory *item, UEr rorCode *pErr) {
305 DataCacheElement *newElement;
306 const char *baseName;
307 int32_t nameLen;
308 UHashtable *htable;
309 DataCacheElement *oldValue = NULL;
310 UErrorCode subErr = U_ZERO_ERROR;
311
312 if (U_FAILURE(*pErr)) {
313 return NULL;
314 }
315
316 /* Create a new DataCacheElement - the thingy we store in the hash table -
317 * and copy the supplied path and UDataMemoryItems into it.
318 */
319 newElement = (DataCacheElement *)uprv_malloc(sizeof(DataCacheElement));
320 if (newElement == NULL) {
321 *pErr = U_MEMORY_ALLOCATION_ERROR;
322 return NULL;
323 }
324 newElement->item = UDataMemory_createNewInstance(pErr);
325 if (U_FAILURE(*pErr)) {
326 uprv_free(newElement);
327 return NULL;
328 }
329 UDatamemory_assign(newElement->item, item);
330
331 baseName = findBasename(path);
332 nameLen = (int32_t)uprv_strlen(baseName);
333 newElement->name = (char *)uprv_malloc(nameLen+1);
334 if (newElement->name == NULL) {
335 *pErr = U_MEMORY_ALLOCATION_ERROR;
336 uprv_free(newElement->item);
337 uprv_free(newElement);
338 return NULL;
339 }
340 uprv_strcpy(newElement->name, baseName);
341
342 /* Stick the new DataCacheElement into the hash table.
343 */
344 htable = udata_getHashTable();
345 umtx_lock(NULL);
346 oldValue = (DataCacheElement *)uhash_get(htable, path);
347 if (oldValue != NULL) {
348 subErr = U_USING_DEFAULT_WARNING;
349 }
350 else {
351 uhash_put(
352 htable,
353 newElement->name, /* Key */
354 newElement, /* Value */
355 &subErr);
356 }
357 umtx_unlock(NULL);
358
359 #ifdef UDATA_DEBUG
360 fprintf(stderr, "Cache: [%s] <<< %p : %s. vFunc=%p\n", newElement->name,
361 newElement->item, u_errorName(subErr), newElement->item->vFuncs);
362 #endif
363
364 if (subErr == U_USING_DEFAULT_WARNING || U_FAILURE(subErr)) {
365 *pErr = subErr; /* copy sub err unto fillin ONLY if something happens. * /
366 uprv_free(newElement->name);
367 uprv_free(newElement->item);
368 uprv_free(newElement);
369 return oldValue ? oldValue->item : NULL;
370 }
371
372 return newElement->item;
373 }
374
375 /*----------------------------------------------------------------------*======= =======
376 * *
377 * Path management. Could be shared with other tools/etc if need be *
378 * later on. *
379 * *
380 *----------------------------------------------------------------------*/
381
382 #define U_DATA_PATHITER_BUFSIZ 128 /* Size of local buffer for paths */
383 /* Overflow causes malloc of larger buf */
384
385 U_NAMESPACE_BEGIN
386
387 class UDataPathIterator
388 {
389 public:
390 UDataPathIterator(const char *path, const char *pkg,
391 const char *item, const char *suffix, UBool doCheckLastFou r,
392 UErrorCode *pErrorCode);
393 const char *next(UErrorCode *pErrorCode);
394
395 private:
396 const char *path; /* working path (u_icudata_Di r) */
397 const char *nextPath; /* path following this one */
398 const char *basename; /* item's basename (icudt22e_ mt.res)*/
399 const char *suffix; /* item suffix (can be null) */
400
401 uint32_t basenameLen; /* length of basename */
402
403 CharString itemPath; /* path passed in with item n ame */
404 CharString pathBuffer; /* output path for this it'io n */
405 CharString packageStub; /* example: "/icudt28b". Wil l ignore that leaf in set paths. */
406
407 UBool checkLastFour; /* if TRUE then allow paths s uch as '/foo/myapp.dat'
408 * to match, checks last 4 ch ars of suffix with
409 * last 4 of path, then previ ous chars. */
410 };
411
412 /**
413 * @param iter The iterator to be initialized. Its current state does not matte r.
414 * @param path The full pathname to be iterated over. If NULL, defaults to U_I CUDATA_NAME
415 * @param pkg Package which is being searched for, ex "icudt28l". Will ignore leave directories such as /icudt28l
416 * @param item Item to be searched for. Can include full path, such as /a/b/fo o.dat
417 * @param suffix Optional item suffix, if not-null (ex. ".dat") then 'path' can contain 'item' explicitly.
418 * Ex: 'stuff.dat' would be found in '/a/foo:/tmp/stuff.dat:/bar /baz' as item #2.
419 * '/blarg/stuff.dat' would also be found.
420 */
421 UDataPathIterator::UDataPathIterator(const char *inPath, const char *pkg,
422 const char *item, const char *inSuffix, UBo ol doCheckLastFour,
423 UErrorCode *pErrorCode)
424 {
425 #ifdef UDATA_DEBUG
426 fprintf(stderr, "SUFFIX1=%s PATH=%s\n", inSuffix, inPath);
427 #endif
428 /** Path **/
429 if(inPath == NULL) {
430 path = u_getDataDirectory();
431 } else {
432 path = inPath;
433 }
434
435 /** Package **/
436 if(pkg != NULL) {
437 packageStub.append(U_FILE_SEP_CHAR, *pErrorCode).append(pkg, *pErrorCode);
438 #ifdef UDATA_DEBUG
439 fprintf(stderr, "STUB=%s [%d]\n", packageStub.data(), packageStub.length() );
440 #endif
441 }
442
443 /** Item **/
444 basename = findBasename(item);
445 basenameLen = (int32_t)uprv_strlen(basename);
446
447 /** Item path **/
448 if(basename == item) {
449 nextPath = path;
450 } else {
451 itemPath.append(item, (int32_t)(basename-item), *pErrorCode);
452 nextPath = itemPath.data();
453 }
454 #ifdef UDATA_DEBUG
455 fprintf(stderr, "SUFFIX=%s [%p]\n", inSuffix, inSuffix);
456 #endif
457
458 /** Suffix **/
459 if(inSuffix != NULL) {
460 suffix = inSuffix;
461 } else {
462 suffix = "";
463 }
464
465 checkLastFour = doCheckLastFour;
466
467 /* pathBuffer will hold the output path strings returned by this iterator */
468
469 #ifdef UDATA_DEBUG
470 fprintf(stderr, "%p: init %s -> [path=%s], [base=%s], [suff=%s], [itempath=% s], [nextpath=%s], [checklast4=%s]\n",
471 iter,
472 item,
473 path,
474 basename,
475 suffix,
476 itemPath.data(),
477 nextPath,
478 checkLastFour?"TRUE":"false");
479 #endif
480 }
481
482 /**
483 * Get the next path on the list.
484 *
485 * @param iter The Iter to be used
486 * @param len If set, pointer to the length of the returned path, for convenien ce.
487 * @return Pointer to the next path segment, or NULL if there are no more.
488 */
489 const char *UDataPathIterator::next(UErrorCode *pErrorCode)
490 {
491 if(U_FAILURE(*pErrorCode)) {
492 return NULL;
493 }
494
495 const char *currentPath = NULL;
496 int32_t pathLen = 0;
497 const char *pathBasename;
498
499 do
500 {
501 if( nextPath == NULL ) {
502 break;
503 }
504 currentPath = nextPath;
505
506 if(nextPath == itemPath.data()) { /* we were processing item's path. */
507 nextPath = path; /* start with regular path next tm. */
508 pathLen = (int32_t)uprv_strlen(currentPath);
509 } else {
510 /* fix up next for next time */
511 nextPath = uprv_strchr(currentPath, U_PATH_SEP_CHAR);
512 if(nextPath == NULL) {
513 /* segment: entire path */
514 pathLen = (int32_t)uprv_strlen(currentPath);
515 } else {
516 /* segment: until next segment */
517 pathLen = (int32_t)(nextPath - currentPath);
518 /* skip divider */
519 nextPath ++;
520 }
521 }
522
523 if(pathLen == 0) {
524 continue;
525 }
526
527 #ifdef UDATA_DEBUG
528 fprintf(stderr, "rest of path (IDD) = %s\n", currentPath);
529 fprintf(stderr, " ");
530 {
531 uint32_t qqq;
532 for(qqq=0;qqq<pathLen;qqq++)
533 {
534 fprintf(stderr, " ");
535 }
536
537 fprintf(stderr, "^\n");
538 }
539 #endif
540 pathBuffer.clear().append(currentPath, pathLen, *pErrorCode);
541
542 /* check for .dat files */
543 pathBasename = findBasename(pathBuffer.data());
544
545 if(checkLastFour == TRUE &&
546 (pathLen>=4) &&
547 uprv_strncmp(pathBuffer.data() +(pathLen-4), suffix, 4)==0 && /* suff ix matches */
548 uprv_strncmp(findBasename(pathBuffer.data()), basename, basenameLen)= =0 && /* base matches */
549 uprv_strlen(pathBasename)==(basenameLen+4)) { /* base+suffix = full l en */
550
551 #ifdef UDATA_DEBUG
552 fprintf(stderr, "Have %s file on the path: %s\n", suffix, pathBuffer .data());
553 #endif
554 /* do nothing */
555 }
556 else
557 { /* regular dir path */
558 if(pathBuffer[pathLen-1] != U_FILE_SEP_CHAR) {
559 if((pathLen>=4) &&
560 uprv_strncmp(pathBuffer.data()+(pathLen-4), ".dat", 4) == 0)
561 {
562 #ifdef UDATA_DEBUG
563 fprintf(stderr, "skipping non-directory .dat file %s\n", pat hBuffer.data());
564 #endif
565 continue;
566 }
567
568 /* Check if it is a directory with the same name as our package */
569 if(!packageStub.isEmpty() &&
570 (pathLen > packageStub.length()) &&
571 !uprv_strcmp(pathBuffer.data() + pathLen - packageStub.length (), packageStub.data())) {
572 #ifdef UDATA_DEBUG
573 fprintf(stderr, "Found stub %s (will add package %s of len %d) \n", packageStub.data(), basename, basenameLen);
574 #endif
575 pathBuffer.truncate(pathLen - packageStub.length());
576 }
577 pathBuffer.append(U_FILE_SEP_CHAR, *pErrorCode);
578 }
579
580 /* + basename */
581 pathBuffer.append(packageStub.data()+1, packageStub.length()-1, *pEr rorCode);
582
583 if(*suffix) /* tack on suffix */
584 {
585 pathBuffer.append(suffix, *pErrorCode);
586 }
587 }
588
589 #ifdef UDATA_DEBUG
590 fprintf(stderr, " --> %s\n", pathBuffer.data());
591 #endif
592
593 return pathBuffer.data();
594
595 } while(path);
596
597 /* fell way off the end */
598 return NULL;
599 }
600
601 U_NAMESPACE_END
602
603 /* ============================================================================= =====*/
604
605
606 /*----------------------------------------------------------------------*
607 * *
608 * Add a static reference to the common data library *
609 * Unless overridden by an explicit udata_setCommonData, this will be *
610 * our common data. *
611 * *
612 *----------------------------------------------------------------------*/
613 extern "C" const DataHeader U_DATA_API U_ICUDATA_ENTRY_POINT;
614
615 /*
616 * This would be a good place for weak-linkage declarations of
617 * partial-data-library access functions where each returns a pointer
618 * to its data package, if it is linked in.
619 */
620 /*
621 extern const void *uprv_getICUData_collation(void) ATTRIBUTE_WEAK;
622 extern const void *uprv_getICUData_conversion(void) ATTRIBUTE_WEAK;
623 */
624
625 /*----------------------------------------------------------------------*
626 * *
627 * openCommonData Attempt to open a common format (.dat) file *
628 * Map it into memory (if it's not there already) *
629 * and return a UDataMemory object for it. *
630 * *
631 * If the requested data is already open and cached *
632 * just return the cached UDataMem object. *
633 * *
634 *----------------------------------------------------------------------*/
635 static UDataMemory *
636 openCommonData(const char *path, /* Path from OpenChoice? */
637 int32_t commonDataIndex, /* ICU Data (index >= 0) if path == N ULL */
638 UErrorCode *pErrorCode)
639 {
640 UDataMemory tData;
641 const char *pathBuffer;
642 const char *inBasename;
643
644 if (U_FAILURE(*pErrorCode)) {
645 return NULL;
646 }
647
648 UDataMemory_init(&tData);
649
650 /* ??????? TODO revisit this */
651 if (commonDataIndex >= 0) {
652 /* "mini-cache" for common ICU data */
653 if(commonDataIndex >= LENGTHOF(gCommonICUDataArray)) {
654 return NULL;
655 }
656 if(gCommonICUDataArray[commonDataIndex] == NULL) {
657 int32_t i;
658 for(i = 0; i < commonDataIndex; ++i) {
659 if(gCommonICUDataArray[i]->pHeader == &U_ICUDATA_ENTRY_POINT) {
660 /* The linked-in data is already in the list. */
661 return NULL;
662 }
663 }
664
665 /* Add the linked-in data to the list. */
666 /*
667 * This is where we would check and call weakly linked partial-data- library
668 * access functions.
669 */
670 /*
671 if (uprv_getICUData_collation) {
672 setCommonICUDataPointer(uprv_getICUData_collation(), FALSE, pErr orCode);
673 }
674 if (uprv_getICUData_conversion) {
675 setCommonICUDataPointer(uprv_getICUData_conversion(), FALSE, pEr rorCode);
676 }
677 */
678 setCommonICUDataPointer(&U_ICUDATA_ENTRY_POINT, FALSE, pErrorCode);
679 }
680 return gCommonICUDataArray[commonDataIndex];
681 }
682
683
684 /* request is NOT for ICU Data. */
685
686 /* Find the base name portion of the supplied path. */
687 /* inBasename will be left pointing somewhere within the original path str ing. */
688 inBasename = findBasename(path);
689 #ifdef UDATA_DEBUG
690 fprintf(stderr, "inBasename = %s\n", inBasename);
691 #endif
692
693 if(*inBasename==0) {
694 /* no basename. This will happen if the original path was a director y name, */
695 /* like "a/b/c/". (Fallback to separate files will still work.) */
696 #ifdef UDATA_DEBUG
697 fprintf(stderr, "ocd: no basename in %s, bailing.\n", path);
698 #endif
699 *pErrorCode=U_FILE_ACCESS_ERROR;
700 return NULL;
701 }
702
703 /* Is the requested common data file already open and cached? */
704 /* Note that the cache is keyed by the base name only. The rest of the pat h, */
705 /* if any, is not considered. */
706 {
707 UDataMemory *dataToReturn = udata_findCachedData(inBasename);
708 if (dataToReturn != NULL) {
709 return dataToReturn;
710 }
711 }
712
713 /* Requested item is not in the cache.
714 * Hunt it down, trying all the path locations
715 */
716
717 UDataPathIterator iter(u_getDataDirectory(), inBasename, path, ".dat", TRUE, pErrorCode);
718
719 while((UDataMemory_isLoaded(&tData)==FALSE) && (pathBuffer = iter.next(pErro rCode)) != NULL)
720 {
721 #ifdef UDATA_DEBUG
722 fprintf(stderr, "ocd: trying path %s - ", pathBuffer);
723 #endif
724 uprv_mapFile(&tData, pathBuffer);
725 #ifdef UDATA_DEBUG
726 fprintf(stderr, "%s\n", UDataMemory_isLoaded(&tData)?"LOADED":"not loade d");
727 #endif
728 }
729
730 #if defined(OS390_STUBDATA) && defined(OS390BATCH)
731 if (!UDataMemory_isLoaded(&tData)) {
732 char ourPathBuffer[1024];
733 /* One more chance, for extendCommonData() */
734 uprv_strncpy(ourPathBuffer, path, 1019);
735 ourPathBuffer[1019]=0;
736 uprv_strcat(ourPathBuffer, ".dat");
737 uprv_mapFile(&tData, ourPathBuffer);
738 }
739 #endif
740
741 if (!UDataMemory_isLoaded(&tData)) {
742 /* no common data */
743 *pErrorCode=U_FILE_ACCESS_ERROR;
744 return NULL;
745 }
746
747 /* we have mapped a file, check its header */
748 udata_checkCommonData(&tData, pErrorCode);
749
750
751 /* Cache the UDataMemory struct for this .dat file,
752 * so we won't need to hunt it down and map it again next time
753 * something is needed from it. */
754 return udata_cacheDataItem(inBasename, &tData, pErrorCode);
755 }
756
757
758 /*----------------------------------------------------------------------*
759 * *
760 * extendICUData If the full set of ICU data was not loaded at *
761 * program startup, load it now. This function will *
762 * be called when the lookup of an ICU data item in *
763 * the common ICU data fails. *
764 * *
765 * return true if new data is loaded, false otherwise.*
766 * *
767 *----------------------------------------------------------------------*/
768 static UBool extendICUData(UErrorCode *pErr)
769 {
770 UDataMemory *pData;
771 UDataMemory copyPData;
772 UBool didUpdate = FALSE;
773
774 /*
775 * There is a chance for a race condition here.
776 * Normally, ICU data is loaded from a DLL or via mmap() and
777 * setCommonICUData() will detect if the same address is set twice.
778 * If ICU is built with data loading via fread() then the address will
779 * be different each time the common data is loaded and we may add
780 * multiple copies of the data.
781 * In this case, use a mutex to prevent the race.
782 * Use a specific mutex to avoid nested locks of the global mutex.
783 */
784 #if MAP_IMPLEMENTATION==MAP_STDIO
785 static UMTX extendICUDataMutex = NULL;
786 umtx_lock(&extendICUDataMutex);
787 #endif
788 if(!gHaveTriedToLoadCommonData) {
789 gHaveTriedToLoadCommonData = TRUE;
790
791 /* See if we can explicitly open a .dat file for the ICUData. */
792 pData = openCommonData(
793 U_ICUDATA_NAME, /* "icudt20l" , for example. */
794 -1, /* Pretend we're not opening ICUD ata */
795 pErr);
796
797 /* How about if there is no pData, eh... */
798
799 UDataMemory_init(&copyPData);
800 if(pData != NULL) {
801 UDatamemory_assign(&copyPData, pData);
802 copyPData.map = 0; /* The mapping for this data is owned by the hash table */
803 copyPData.mapAddr = 0; /* which will unmap it when ICU is s hut down. */
804 /* CommonICUData is also unmapped when ICU is shut down.*/
805 /* To avoid unmapping the data twice, zero out the map */
806 /* fields in the UDataMemory that we 're assigning */
807 /* to CommonICUData. */
808
809 didUpdate =
810 setCommonICUData(&copyPData,/* The new common data. */
811 FALSE, /* No warnings if write didn't happen */
812 pErr); /* setCommonICUData honors errors; NO P if error set */
813 }
814 }
815 #if MAP_IMPLEMENTATION==MAP_STDIO
816 umtx_unlock(&extendICUDataMutex);
817 #endif
818 return didUpdate; /* Return true if ICUData pointer was update d. */
819 /* (Could potentialy have been done by ano ther thread racing */
820 /* us through here, but that's fine, we st ill return true */
821 /* so that current thread will also examin e extended data. */
822 }
823
824 /*----------------------------------------------------------------------*
825 * *
826 * udata_setCommonData *
827 * *
828 *----------------------------------------------------------------------*/
829 U_CAPI void U_EXPORT2
830 udata_setCommonData(const void *data, UErrorCode *pErrorCode) {
831 UDataMemory dataMemory;
832
833 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
834 return;
835 }
836
837 if(data==NULL) {
838 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
839 return;
840 }
841
842 /* set the data pointer and test for validity */
843 UDataMemory_init(&dataMemory);
844 UDataMemory_setData(&dataMemory, data);
845 udata_checkCommonData(&dataMemory, pErrorCode);
846 if (U_FAILURE(*pErrorCode)) {return;}
847
848 /* we have good data */
849 /* Set it up as the ICU Common Data. */
850 setCommonICUData(&dataMemory, TRUE, pErrorCode);
851 }
852
853 /*---------------------------------------------------------------------------
854 *
855 * udata_setAppData
856 *
857 *---------------------------------------------------------------------------- * /
858 U_CAPI void U_EXPORT2
859 udata_setAppData(const char *path, const void *data, UErrorCode *err)
860 {
861 UDataMemory udm;
862
863 if(err==NULL || U_FAILURE(*err)) {
864 return;
865 }
866 if(data==NULL) {
867 *err=U_ILLEGAL_ARGUMENT_ERROR;
868 return;
869 }
870
871 UDataMemory_init(&udm);
872 UDataMemory_setData(&udm, data);
873 udata_checkCommonData(&udm, err);
874 udata_cacheDataItem(path, &udm, err);
875 }
876
877 /*----------------------------------------------------------------------------*
878 * *
879 * checkDataItem Given a freshly located/loaded data item, either *
880 * an entry in a common file or a separately loaded file, *
881 * sanity check its header, and see if the data is *
882 * acceptable to the app. *
883 * If the data is good, create and return a UDataMemory *
884 * object that can be returned to the application. *
885 * Return NULL on any sort of failure. *
886 * *
887 *----------------------------------------------------------------------------*/
888 static UDataMemory *
889 checkDataItem
890 (
891 const DataHeader *pHeader, /* The data item to be checked. */
892 UDataMemoryIsAcceptable *isAcceptable, /* App's call-back function */
893 void *context, /* pass-thru param for above. */
894 const char *type, /* pass-thru param for above. */
895 const char *name, /* pass-thru param for above. */
896 UErrorCode *nonFatalErr, /* Error code if this data was not a cceptable */
897 /* but openChoice should continue with */
898 /* trying to get data from fallbac k path. */
899 UErrorCode *fatalErr /* Bad error, caller should return i mmediately */
900 )
901 {
902 UDataMemory *rDataMem = NULL; /* the new UDataMemory, to be return ed. */
903
904 if (U_FAILURE(*fatalErr)) {
905 return NULL;
906 }
907
908 if(pHeader->dataHeader.magic1==0xda &&
909 pHeader->dataHeader.magic2==0x27 &&
910 (isAcceptable==NULL || isAcceptable(context, type, name, &pHeader->info) )
911 ) {
912 rDataMem=UDataMemory_createNewInstance(fatalErr);
913 if (U_FAILURE(*fatalErr)) {
914 return NULL;
915 }
916 rDataMem->pHeader = pHeader;
917 } else {
918 /* the data is not acceptable, look further */
919 /* If we eventually find something good, this errorcode will be */
920 /* cleared out. */
921 *nonFatalErr=U_INVALID_FORMAT_ERROR;
922 }
923 return rDataMem;
924 }
925
926 /**
927 * @return 0 if not loaded, 1 if loaded or err
928 */
929 static UDataMemory *doLoadFromIndividualFiles(const char *pkgName,
930 const char *dataPath, const char *tocEntryPathSuffix,
931 /* following arguments are the same as doOpenChoice itself */
932 const char *path, const char *type, const char *name,
933 UDataMemoryIsAcceptable *isAcceptable, void *context,
934 UErrorCode *subErrorCode,
935 UErrorCode *pErrorCode)
936 {
937 const char *pathBuffer;
938 UDataMemory dataMemory;
939 UDataMemory *pEntryData;
940
941 /* look in ind. files: package\nam.typ ========================= */
942 /* init path iterator for individual files */
943 UDataPathIterator iter(dataPath, pkgName, path, tocEntryPathSuffix, FALSE, p ErrorCode);
944
945 while((pathBuffer = iter.next(pErrorCode)))
946 {
947 #ifdef UDATA_DEBUG
948 fprintf(stderr, "UDATA: trying individual file %s\n", pathBuffer);
949 #endif
950 if(uprv_mapFile(&dataMemory, pathBuffer))
951 {
952 pEntryData = checkDataItem(dataMemory.pHeader, isAcceptable, context , type, name, subErrorCode, pErrorCode);
953 if (pEntryData != NULL) {
954 /* Data is good.
955 * Hand off ownership of the backing memory to the user's UDataM emory.
956 * and return it. */
957 pEntryData->mapAddr = dataMemory.mapAddr;
958 pEntryData->map = dataMemory.map;
959
960 #ifdef UDATA_DEBUG
961 fprintf(stderr, "** Mapped file: %s\n", pathBuffer);
962 #endif
963 return pEntryData;
964 }
965
966 /* the data is not acceptable, or some error occured. Either way, u nmap the memory */
967 udata_close(&dataMemory);
968
969 /* If we had a nasty error, bail out completely. */
970 if (U_FAILURE(*pErrorCode)) {
971 return NULL;
972 }
973
974 /* Otherwise remember that we found data but didn't like it for some reason */
975 *subErrorCode=U_INVALID_FORMAT_ERROR;
976 }
977 #ifdef UDATA_DEBUG
978 fprintf(stderr, "%s\n", UDataMemory_isLoaded(&dataMemory)?"LOADED":"not loaded");
979 #endif
980 }
981 return NULL;
982 }
983
984 /**
985 * @return 0 if not loaded, 1 if loaded or err
986 */
987 static UDataMemory *doLoadFromCommonData(UBool isICUData, const char * /*pkgName */,
988 const char * /*dataPath*/, const char * /*tocEntryPathSuffix*/, const ch ar *tocEntryName,
989 /* following arguments are the same as doOpenChoice itself */
990 const char *path, const char *type, const char *name,
991 UDataMemoryIsAcceptable *isAcceptable, void *context,
992 UErrorCode *subErrorCode,
993 UErrorCode *pErrorCode)
994 {
995 UDataMemory *pEntryData;
996 const DataHeader *pHeader;
997 UDataMemory *pCommonData;
998 int32_t commonDataIndex;
999 /* try to get common data. The loop is for platforms such as the 390 that d o
1000 * not initially load the full set of ICU data. If the lookup of an ICU da ta item
1001 * fails, the full (but slower to load) set is loaded, the and the loop rep eats,
1002 * trying the lookup again. Once the full set of ICU data is loaded, the l oop wont
1003 * repeat because the full set will be checked the first time through.
1004 *
1005 * The loop also handles the fallback to a .dat file if the application lin ked
1006 * to the stub data library rather than a real library.
1007 */
1008 for (commonDataIndex = isICUData ? 0 : -1;;) {
1009 pCommonData=openCommonData(path, commonDataIndex, subErrorCode); /** sea rch for pkg **/
1010
1011 if(U_SUCCESS(*subErrorCode) && pCommonData!=NULL) {
1012 int32_t length;
1013
1014 /* look up the data piece in the common data */
1015 pHeader=pCommonData->vFuncs->Lookup(pCommonData, tocEntryName, &leng th, subErrorCode);
1016 #ifdef UDATA_DEBUG
1017 fprintf(stderr, "%s: pHeader=%p - %s\n", tocEntryName, pHeader, u_er rorName(*subErrorCode));
1018 #endif
1019
1020 if(pHeader!=NULL) {
1021 pEntryData = checkDataItem(pHeader, isAcceptable, context, type, name, subErrorCode, pErrorCode);
1022 #ifdef UDATA_DEBUG
1023 fprintf(stderr, "pEntryData=%p\n", pEntryData);
1024 #endif
1025 if (U_FAILURE(*pErrorCode)) {
1026 return NULL;
1027 }
1028 if (pEntryData != NULL) {
1029 pEntryData->length = length;
1030 return pEntryData;
1031 }
1032 }
1033 }
1034 /* Data wasn't found. If we were looking for an ICUData item and there is
1035 * more data available, load it and try again,
1036 * otherwise break out of this loop. */
1037 if (!isICUData) {
1038 return NULL;
1039 } else if (pCommonData != NULL) {
1040 ++commonDataIndex; /* try the next data package */
1041 } else if (extendICUData(subErrorCode)) {
1042 /* try this data package slot again: it changed from NULL to non-NUL L */
1043 } else {
1044 return NULL;
1045 }
1046 }
1047 }
1048
1049 /*
1050 * A note on the ownership of Mapped Memory
1051 *
1052 * For common format files, ownership resides with the UDataMemory object
1053 * that lives in the cache of opened common data. These UDataMemorys are pri vate
1054 * to the udata implementation, and are never seen directly by users.
1055 *
1056 * The UDataMemory objects returned to users will have the address of some de sired
1057 * data within the mapped region, but they wont have the mapping info itself, and thus
1058 * won't cause anything to be removed from memory when they are closed.
1059 *
1060 * For individual data files, the UDataMemory returned to the user holds the
1061 * information necessary to unmap the data on close. If the user independently
1062 * opens the same data file twice, two completely independent mappings will be made.
1063 * (There is no cache of opened data items from individual files, only a cache of
1064 * opened Common Data files, that is, files containing a collection of data it ems.)
1065 *
1066 * For common data passed in from the user via udata_setAppData() or
1067 * udata_setCommonData(), ownership remains with the user.
1068 *
1069 * UDataMemory objects themselves, as opposed to the memory they describe,
1070 * can be anywhere - heap, stack/local or global.
1071 * They have a flag to indicate when they're heap allocated and thus
1072 * must be deleted when closed.
1073 */
1074
1075
1076 /*----------------------------------------------------------------------------*
1077 * *
1078 * main data loading functions *
1079 * *
1080 *----------------------------------------------------------------------------*/
1081 static UDataMemory *
1082 doOpenChoice(const char *path, const char *type, const char *name,
1083 UDataMemoryIsAcceptable *isAcceptable, void *context,
1084 UErrorCode *pErrorCode)
1085 {
1086 UDataMemory *retVal = NULL;
1087
1088 const char *dataPath;
1089
1090 int32_t tocEntrySuffixIndex;
1091 const char *tocEntryPathSuffix;
1092 UErrorCode subErrorCode=U_ZERO_ERROR;
1093 const char *treeChar;
1094
1095 UBool isICUData = FALSE;
1096
1097
1098 /* Is this path ICU data? */
1099 if(path == NULL ||
1100 !strcmp(path, U_ICUDATA_ALIAS) || /* "ICUDATA" */
1101 !uprv_strncmp(path, U_ICUDATA_NAME U_TREE_SEPARATOR_STRING, /* "icudt26e- " */
1102 uprv_strlen(U_ICUDATA_NAME U_TREE_SEPARATOR_STRING)) ||
1103 !uprv_strncmp(path, U_ICUDATA_ALIAS U_TREE_SEPARATOR_STRING, /* "ICUDATA- " */
1104 uprv_strlen(U_ICUDATA_ALIAS U_TREE_SEPARATOR_STRING))) {
1105 isICUData = TRUE;
1106 }
1107
1108 #if (U_FILE_SEP_CHAR != U_FILE_ALT_SEP_CHAR) /* Windows: try "foo\bar" and "fo o/bar" */
1109 /* remap from alternate path char to the main one */
1110 CharString altSepPath;
1111 if(path) {
1112 if(uprv_strchr(path,U_FILE_ALT_SEP_CHAR) != NULL) {
1113 altSepPath.append(path, *pErrorCode);
1114 char *p;
1115 while((p=uprv_strchr(altSepPath.data(), U_FILE_ALT_SEP_CHAR))) {
1116 *p = U_FILE_SEP_CHAR;
1117 }
1118 #if defined (UDATA_DEBUG)
1119 fprintf(stderr, "Changed path from [%s] to [%s]\n", path, altSepPath .s);
1120 #endif
1121 path = altSepPath.data();
1122 }
1123 }
1124 #endif
1125
1126 CharString tocEntryName; /* entry name in tree format. ex: 'icudt28b/coll/a r.res' */
1127 CharString tocEntryPath; /* entry name in path format. ex: 'icudt28b\\coll\ \ar.res' */
1128
1129 CharString pkgName;
1130 CharString treeName;
1131
1132 /* ======= Set up strings */
1133 if(path==NULL) {
1134 pkgName.append(U_ICUDATA_NAME, *pErrorCode);
1135 } else {
1136 const char *pkg;
1137 const char *first;
1138 pkg = uprv_strrchr(path, U_FILE_SEP_CHAR);
1139 first = uprv_strchr(path, U_FILE_SEP_CHAR);
1140 if(uprv_pathIsAbsolute(path) || (pkg != first)) { /* more than one slash in the path- not a tree name */
1141 /* see if this is an /absolute/path/to/package path */
1142 if(pkg) {
1143 pkgName.append(pkg+1, *pErrorCode);
1144 } else {
1145 pkgName.append(path, *pErrorCode);
1146 }
1147 } else {
1148 treeChar = uprv_strchr(path, U_TREE_SEPARATOR);
1149 if(treeChar) {
1150 treeName.append(treeChar+1, *pErrorCode); /* following '-' */
1151 if(isICUData) {
1152 pkgName.append(U_ICUDATA_NAME, *pErrorCode);
1153 } else {
1154 pkgName.append(path, (int32_t)(treeChar-path), *pErrorCode);
1155 if (first == NULL) {
1156 /*
1157 This user data has no path, but there is a tree name.
1158 Look up the correct path from the data cache later.
1159 */
1160 path = pkgName.data();
1161 }
1162 }
1163 } else {
1164 if(isICUData) {
1165 pkgName.append(U_ICUDATA_NAME, *pErrorCode);
1166 } else {
1167 pkgName.append(path, *pErrorCode);
1168 }
1169 }
1170 }
1171 }
1172
1173 #ifdef UDATA_DEBUG
1174 fprintf(stderr, " P=%s T=%s\n", pkgName.data(), treeName.data());
1175 #endif
1176
1177 /* setting up the entry name and file name
1178 * Make up a full name by appending the type to the supplied
1179 * name, assuming that a type was supplied.
1180 */
1181
1182 /* prepend the package */
1183 tocEntryName.append(pkgName, *pErrorCode);
1184 tocEntryPath.append(pkgName, *pErrorCode);
1185 tocEntrySuffixIndex = tocEntryName.length();
1186
1187 if(!treeName.isEmpty()) {
1188 tocEntryName.append(U_TREE_ENTRY_SEP_CHAR, *pErrorCode).append(treeName, *pErrorCode);
1189 tocEntryPath.append(U_FILE_SEP_CHAR, *pErrorCode).append(treeName, *pErr orCode);
1190 }
1191
1192 tocEntryName.append(U_TREE_ENTRY_SEP_CHAR, *pErrorCode).append(name, *pError Code);
1193 tocEntryPath.append(U_FILE_SEP_CHAR, *pErrorCode).append(name, *pErrorCode);
1194 if(type!=NULL && *type!=0) {
1195 tocEntryName.append(".", *pErrorCode).append(type, *pErrorCode);
1196 tocEntryPath.append(".", *pErrorCode).append(type, *pErrorCode);
1197 }
1198 tocEntryPathSuffix = tocEntryPath.data()+tocEntrySuffixIndex; /* suffix star ts here */
1199
1200 #ifdef UDATA_DEBUG
1201 fprintf(stderr, " tocEntryName = %s\n", tocEntryName.data());
1202 fprintf(stderr, " tocEntryPath = %s\n", tocEntryName.data());
1203 #endif
1204
1205 if(path == NULL) {
1206 path = COMMON_DATA_NAME; /* "icudt26e" */
1207 }
1208
1209 /************************ Begin loop looking for ind. files ***************/
1210 #ifdef UDATA_DEBUG
1211 fprintf(stderr, "IND: inBasename = %s, pkg=%s\n", "(n/a)", packageNameFromPa th(path));
1212 #endif
1213
1214 /* End of dealing with a null basename */
1215 dataPath = u_getDataDirectory();
1216
1217 /**** COMMON PACKAGE - only if packages are first. */
1218 if(gDataFileAccess == UDATA_PACKAGES_FIRST) {
1219 #ifdef UDATA_DEBUG
1220 fprintf(stderr, "Trying packages (UDATA_PACKAGES_FIRST)\n");
1221 #endif
1222 /* #2 */
1223 retVal = doLoadFromCommonData(isICUData,
1224 pkgName.data(), dataPath, tocEntryPathSuffix, tocEnt ryName.data(),
1225 path, type, name, isAcceptable, context, &subErrorCo de, pErrorCode);
1226 if((retVal != NULL) || U_FAILURE(*pErrorCode)) {
1227 return retVal;
1228 }
1229 }
1230
1231 /**** INDIVIDUAL FILES */
1232 if((gDataFileAccess==UDATA_PACKAGES_FIRST) ||
1233 (gDataFileAccess==UDATA_FILES_FIRST)) {
1234 #ifdef UDATA_DEBUG
1235 fprintf(stderr, "Trying individual files\n");
1236 #endif
1237 /* Check to make sure that there is a dataPath to iterate over */
1238 if ((dataPath && *dataPath) || !isICUData) {
1239 retVal = doLoadFromIndividualFiles(pkgName.data(), dataPath, tocEntr yPathSuffix,
1240 path, type, name, isAcceptable, context, &subErrorCo de, pErrorCode);
1241 if((retVal != NULL) || U_FAILURE(*pErrorCode)) {
1242 return retVal;
1243 }
1244 }
1245 }
1246
1247 /**** COMMON PACKAGE */
1248 if((gDataFileAccess==UDATA_ONLY_PACKAGES) ||
1249 (gDataFileAccess==UDATA_FILES_FIRST)) {
1250 #ifdef UDATA_DEBUG
1251 fprintf(stderr, "Trying packages (UDATA_ONLY_PACKAGES || UDATA_FILES_FIR ST)\n");
1252 #endif
1253 retVal = doLoadFromCommonData(isICUData,
1254 pkgName.data(), dataPath, tocEntryPathSuffix, tocEnt ryName.data(),
1255 path, type, name, isAcceptable, context, &subErrorCo de, pErrorCode);
1256 if((retVal != NULL) || U_FAILURE(*pErrorCode)) {
1257 return retVal;
1258 }
1259 }
1260
1261 /* Load from DLL. If we haven't attempted package load, we also haven't had any chance to
1262 try a DLL (static or setCommonData/etc) load.
1263 If we ever have a "UDATA_ONLY_FILES", add it to the or list here. */
1264 if(gDataFileAccess==UDATA_NO_FILES) {
1265 #ifdef UDATA_DEBUG
1266 fprintf(stderr, "Trying common data (UDATA_NO_FILES)\n");
1267 #endif
1268 retVal = doLoadFromCommonData(isICUData,
1269 pkgName.data(), "", tocEntryPathSuffix, tocEntryName .data(),
1270 path, type, name, isAcceptable, context, &subErrorCo de, pErrorCode);
1271 if((retVal != NULL) || U_FAILURE(*pErrorCode)) {
1272 return retVal;
1273 }
1274 }
1275
1276 /* data not found */
1277 if(U_SUCCESS(*pErrorCode)) {
1278 if(U_SUCCESS(subErrorCode)) {
1279 /* file not found */
1280 *pErrorCode=U_FILE_ACCESS_ERROR;
1281 } else {
1282 /* entry point not found or rejected */
1283 *pErrorCode=subErrorCode;
1284 }
1285 }
1286 return retVal;
1287 }
1288
1289
1290
1291 /* API ---------------------------------------------------------------------- */
1292
1293 U_CAPI UDataMemory * U_EXPORT2
1294 udata_open(const char *path, const char *type, const char *name,
1295 UErrorCode *pErrorCode) {
1296 #ifdef UDATA_DEBUG
1297 fprintf(stderr, "udata_open(): Opening: %s : %s . %s\n", (path?path:"NULL"), n ame, type);
1298 fflush(stderr);
1299 #endif
1300
1301 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
1302 return NULL;
1303 } else if(name==NULL || *name==0) {
1304 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
1305 return NULL;
1306 } else {
1307 return doOpenChoice(path, type, name, NULL, NULL, pErrorCode);
1308 }
1309 }
1310
1311
1312
1313 U_CAPI UDataMemory * U_EXPORT2
1314 udata_openChoice(const char *path, const char *type, const char *name,
1315 UDataMemoryIsAcceptable *isAcceptable, void *context,
1316 UErrorCode *pErrorCode) {
1317 #ifdef UDATA_DEBUG
1318 fprintf(stderr, "udata_openChoice(): Opening: %s : %s . %s\n", (path?path:"NUL L"), name, type);
1319 #endif
1320
1321 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
1322 return NULL;
1323 } else if(name==NULL || *name==0 || isAcceptable==NULL) {
1324 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
1325 return NULL;
1326 } else {
1327 return doOpenChoice(path, type, name, isAcceptable, context, pErrorCode) ;
1328 }
1329 }
1330
1331
1332
1333 U_CAPI void U_EXPORT2
1334 udata_getInfo(UDataMemory *pData, UDataInfo *pInfo) {
1335 if(pInfo!=NULL) {
1336 if(pData!=NULL && pData->pHeader!=NULL) {
1337 const UDataInfo *info=&pData->pHeader->info;
1338 uint16_t dataInfoSize=udata_getInfoSize(info);
1339 if(pInfo->size>dataInfoSize) {
1340 pInfo->size=dataInfoSize;
1341 }
1342 uprv_memcpy((uint16_t *)pInfo+1, (const uint16_t *)info+1, pInfo->si ze-2);
1343 if(info->isBigEndian!=U_IS_BIG_ENDIAN) {
1344 /* opposite endianness */
1345 uint16_t x=info->reservedWord;
1346 pInfo->reservedWord=(uint16_t)((x<<8)|(x>>8));
1347 }
1348 } else {
1349 pInfo->size=0;
1350 }
1351 }
1352 }
1353
1354
1355 U_CAPI void U_EXPORT2 udata_setFileAccess(UDataFileAccess access, UErrorCode * / *status*/)
1356 {
1357 gDataFileAccess = access;
1358 }
OLDNEW
« no previous file with comments | « icu46/source/common/ucol_swp.cpp ('k') | icu46/source/common/udatamem.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698