00001 /******************************************************************************* 00002 00003 @file UResourceBundle.d 00004 00005 Copyright (C) 2004 Kris Bell 00006 00007 This software is provided 'as-is', without any express or implied 00008 warranty. In no event will the authors be held liable for damages 00009 of any kind arising from the use of this software. 00010 00011 Permission is hereby granted to anyone to use this software for any 00012 purpose, including commercial applications, and to alter it and/or 00013 redistribute it freely, subject to the following restrictions: 00014 00015 1. The origin of this software must not be misrepresented; you must 00016 not claim that you wrote the original software. If you use this 00017 software in a product, an acknowledgment within documentation of 00018 said product would be appreciated but is not required. 00019 00020 2. Altered source versions must be plainly marked as such, and must 00021 not be misrepresented as being the original software. 00022 00023 3. This notice may not be removed or altered from any distribution 00024 of the source. 00025 00026 00027 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 00028 00029 00030 @version Initial version, November 2004 00031 @author Kris 00032 00033 Note that this package and documentation is built around the ICU 00034 project (http://oss.software.ibm.com/icu/). Below is the license 00035 statement as specified by that software: 00036 00037 00038 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 00039 00040 00041 ICU License - ICU 1.8.1 and later 00042 00043 COPYRIGHT AND PERMISSION NOTICE 00044 00045 Copyright (c) 1995-2003 International Business Machines Corporation and 00046 others. 00047 00048 All rights reserved. 00049 00050 Permission is hereby granted, free of charge, to any person obtaining a 00051 copy of this software and associated documentation files (the 00052 "Software"), to deal in the Software without restriction, including 00053 without limitation the rights to use, copy, modify, merge, publish, 00054 distribute, and/or sell copies of the Software, and to permit persons 00055 to whom the Software is furnished to do so, provided that the above 00056 copyright notice(s) and this permission notice appear in all copies of 00057 the Software and that both the above copyright notice(s) and this 00058 permission notice appear in supporting documentation. 00059 00060 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00061 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00062 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 00063 OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 00064 HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 00065 INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING 00066 FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 00067 NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 00068 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 00069 00070 Except as contained in this notice, the name of a copyright holder 00071 shall not be used in advertising or otherwise to promote the sale, use 00072 or other dealings in this Software without prior written authorization 00073 of the copyright holder. 00074 00075 ---------------------------------------------------------------------- 00076 00077 All trademarks and registered trademarks mentioned herein are the 00078 property of their respective owners. 00079 00080 *******************************************************************************/ 00081 00082 module mango.icu.UResourceBundle; 00083 00084 private import mango.icu.ICU, 00085 mango.icu.UString; 00086 00087 public import mango.icu.ULocale; 00088 00089 /******************************************************************************* 00090 00091 API representing a collection of resource information pertaining to 00092 a given locale. A resource bundle provides a way of accessing locale- 00093 specific information in a data file. You create a resource bundle that 00094 manages the resources for a given locale and then ask it for individual 00095 resources. 00096 00097 Resource bundles in ICU4C are currently defined using text files which 00098 conform to the following BNF definition. More on resource bundle concepts 00099 and syntax can be found in the Users Guide. 00100 00101 See <A HREF="http://oss.software.ibm.com/icu/apiref/ures_8h.html"> 00102 this page</A> for full details. 00103 00104 *******************************************************************************/ 00105 00106 class UResourceBundle : ICU 00107 { 00108 private Handle handle; 00109 00110 /*********************************************************************** 00111 00112 Internals opened up to the public 00113 00114 ***********************************************************************/ 00115 00116 // Numeric constants for types of resource items 00117 public enum ResType 00118 { 00119 None = -1, 00120 String = 0, 00121 Binary = 1, 00122 Table = 2, 00123 Alias = 3, 00124 Int = 7, 00125 Array = 8, 00126 IntVector = 14 00127 } 00128 00129 // The binary form of a version on ICU APIs is an array of 4 uint8_t 00130 public struct Version 00131 { 00132 ubyte[4] info; 00133 } 00134 00135 /*********************************************************************** 00136 00137 private constructor for internal use only 00138 00139 ***********************************************************************/ 00140 00141 private this (Handle handle) 00142 { 00143 this.handle = handle; 00144 } 00145 00146 /*********************************************************************** 00147 00148 Constructs a resource bundle for the locale-specific bundle 00149 in the specified path. 00150 00151 locale This is the locale this resource bundle is for. To 00152 get resources for the French locale, for example, you 00153 would create a ResourceBundle passing ULocale::FRENCH 00154 for the "locale" parameter, and all subsequent calls 00155 to that resource bundle will return resources that 00156 pertain to the French locale. If the caller passes a 00157 Locale.Default parameter, the default locale for the 00158 system (as returned by ULocale.getDefault()) will be 00159 used. Passing Locale.Root will cause the root-locale 00160 to be used. 00161 00162 path This is a full pathname in the platform-specific 00163 format for the directory containing the resource 00164 data files we want to load resources from. We use 00165 locale IDs to generate filenames, and the filenames 00166 have this string prepended to them before being passed 00167 to the C++ I/O functions. Therefore, this string must 00168 always end with a directory delimiter (whatever that 00169 is for the target OS) for this class to work correctly. 00170 A null value will open the default ICU data-files 00171 00172 ***********************************************************************/ 00173 00174 this (inout ULocale locale, char[] path = null) 00175 { 00176 Error e; 00177 00178 handle = ures_open (toString(path), toString(locale.name), e); 00179 testError (e, "failed to open resource bundle"); 00180 } 00181 00182 /*********************************************************************** 00183 00184 ***********************************************************************/ 00185 00186 ~this () 00187 { 00188 ures_close (handle); 00189 } 00190 00191 /*********************************************************************** 00192 00193 Returns the size of a resource. Size for scalar types is 00194 always 1, and for vector/table types is the number of child 00195 resources. 00196 00197 ***********************************************************************/ 00198 00199 uint getSize () 00200 { 00201 return ures_getSize (handle); 00202 } 00203 00204 /*********************************************************************** 00205 00206 Returns a signed integer from a resource. This integer is 00207 originally 28 bit and the sign gets propagated. 00208 00209 ***********************************************************************/ 00210 00211 int getInt () 00212 { 00213 Error e; 00214 00215 int x = ures_getInt (handle, e); 00216 testError (e, "failed to get resource integer"); 00217 return x; 00218 } 00219 00220 /*********************************************************************** 00221 00222 Returns a string from a string resource type 00223 00224 ***********************************************************************/ 00225 00226 UText getString () 00227 { 00228 Error e; 00229 uint len; 00230 00231 wchar* x = ures_getString (handle, len, e); 00232 testError (e, "failed to get resource string"); 00233 return new UText (x[0..len]); 00234 } 00235 00236 /*********************************************************************** 00237 00238 Returns the string in a given resource at the specified 00239 index 00240 00241 ***********************************************************************/ 00242 00243 UText getString (uint index) 00244 { 00245 Error e; 00246 uint len; 00247 00248 wchar* x = ures_getStringByIndex (handle, index, len, e); 00249 testError (e, "failed to get resource string"); 00250 return new UText (x[0..len]); 00251 } 00252 00253 /*********************************************************************** 00254 00255 Returns a string in a resource that has a given key. This 00256 procedure works only with table resources. 00257 00258 ***********************************************************************/ 00259 00260 UText getString (char[] key) 00261 { 00262 Error e; 00263 uint len; 00264 00265 wchar* x = ures_getStringByKey (handle, toString(key), len, e); 00266 testError (e, "failed to get resource string"); 00267 return new UText (x[0..len]); 00268 } 00269 00270 /*********************************************************************** 00271 00272 Returns the next string in a resource or NULL if there are 00273 no more resources to iterate over 00274 00275 ***********************************************************************/ 00276 00277 UText getNextString () 00278 { 00279 Error e; 00280 uint len; 00281 char* key; 00282 00283 wchar* x = ures_getNextString (handle, len, key, e); 00284 testError (e, "failed to get next resource string"); 00285 return new UText (x[0..len]); 00286 } 00287 00288 /*********************************************************************** 00289 00290 Returns a binary data from a resource. Can be used at most 00291 primitive resource types (binaries, strings, ints) 00292 00293 ***********************************************************************/ 00294 00295 void[] getBinary () 00296 { 00297 Error e; 00298 uint len; 00299 00300 void* x = ures_getBinary (handle, len, e); 00301 testError (e, "failed to get binary resource"); 00302 return x[0..len]; 00303 } 00304 00305 /*********************************************************************** 00306 00307 Returns an integer vector from a resource 00308 00309 ***********************************************************************/ 00310 00311 int[] getIntVector () 00312 { 00313 Error e; 00314 uint len; 00315 00316 int* x = ures_getIntVector (handle, len, e); 00317 testError (e, "failed to get vector resource"); 00318 return x[0..len]; 00319 } 00320 00321 /*********************************************************************** 00322 00323 Checks whether the resource has another element to 00324 iterate over 00325 00326 ***********************************************************************/ 00327 00328 bool hasNext () 00329 { 00330 return ures_hasNext (handle) != 0; 00331 } 00332 00333 /*********************************************************************** 00334 00335 Resets the internal context of a resource so that 00336 iteration starts from the first element 00337 00338 ***********************************************************************/ 00339 00340 void resetIterator () 00341 { 00342 ures_resetIterator (handle); 00343 } 00344 00345 /*********************************************************************** 00346 00347 Returns the next resource in a given resource or NULL if 00348 there are no more resources 00349 00350 ***********************************************************************/ 00351 00352 UResourceBundle getNextResource () 00353 { 00354 Error e; 00355 00356 return get (ures_getNextResource (handle, null, e), e); 00357 } 00358 00359 /*********************************************************************** 00360 00361 Returns a resource that has a given key. This procedure 00362 works only with table resources. 00363 00364 ***********************************************************************/ 00365 00366 UResourceBundle getResource (char[] key) 00367 { 00368 Error e; 00369 00370 return get (ures_getByKey (handle, toString(key), null, e), e); 00371 } 00372 00373 /*********************************************************************** 00374 00375 Returns the resource at the specified index 00376 00377 ***********************************************************************/ 00378 00379 UResourceBundle getResource (uint index) 00380 { 00381 Error e; 00382 00383 return get (ures_getByIndex (handle, index, null, e), e); 00384 } 00385 00386 /*********************************************************************** 00387 00388 Return the version number associated with this ResourceBundle 00389 as a UVersionInfo array 00390 00391 ***********************************************************************/ 00392 00393 void getVersion (inout Version info) 00394 { 00395 ures_getVersion (handle, info); 00396 } 00397 00398 /*********************************************************************** 00399 00400 Return the ULocale associated with this ResourceBundle 00401 00402 ***********************************************************************/ 00403 00404 void getLocale (inout ULocale locale) 00405 { 00406 Error e; 00407 00408 locale.name = toArray (ures_getLocale (handle, e)); 00409 testError (e, "failed to get resource locale"); 00410 } 00411 00412 /*********************************************************************** 00413 00414 Returns the key associated with this resource. Not all 00415 the resources have a key - only those that are members 00416 of a table. 00417 00418 ***********************************************************************/ 00419 00420 char[] getKey () 00421 { 00422 return toArray (ures_getKey (handle)); 00423 } 00424 00425 /*********************************************************************** 00426 00427 Returns the type of a resource. Available types are 00428 defined in enum UResType 00429 00430 ***********************************************************************/ 00431 00432 ResType getType () 00433 { 00434 return cast(ResType) ures_getType (handle); 00435 } 00436 00437 /*********************************************************************** 00438 00439 Worker function for constructing internal ResourceBundle 00440 instances. Returns null when the provided handle is null. 00441 00442 ***********************************************************************/ 00443 00444 private static final UResourceBundle get (Handle handle, inout Error e) 00445 { 00446 testError (e, "failed to create resource bundle"); 00447 if (handle) 00448 return new UResourceBundle (handle); 00449 return null; 00450 } 00451 00452 00453 /*********************************************************************** 00454 00455 Bind the ICU functions from a shared library. This is 00456 complicated by the issues regarding D and DLLs on the 00457 Windows platform 00458 00459 ***********************************************************************/ 00460 00461 version (Win32) 00462 { 00463 private static void* library; 00464 private static char[] libraryName = "icuuc30.dll"; 00465 00466 /*************************************************************** 00467 00468 ***************************************************************/ 00469 00470 private static extern (C) 00471 { 00472 Handle function (char*, char*, inout Error) ures_open; 00473 void function (Handle) ures_close; 00474 char* function (Handle, inout Error) ures_getLocale; 00475 void function (Handle, inout Version) ures_getVersion; 00476 uint function (Handle) ures_getSize; 00477 int function (Handle, inout Error) ures_getInt; 00478 wchar* function (Handle, inout uint, inout Error) ures_getString; 00479 wchar* function (Handle, uint, inout uint, inout Error) ures_getStringByIndex; 00480 wchar* function (Handle, char*, inout uint, inout Error) ures_getStringByKey; 00481 void* function (Handle, inout uint, inout Error) ures_getBinary; 00482 int* function (Handle, inout uint, inout Error) ures_getIntVector; 00483 byte function (Handle) ures_hasNext; 00484 void function (Handle) ures_resetIterator; 00485 wchar* function (Handle, inout uint, inout char*, inout Error) ures_getNextString; 00486 char* function (Handle) ures_getKey; 00487 int function (Handle) ures_getType; 00488 Handle function (Handle, Handle, inout Error) ures_getNextResource; 00489 Handle function (Handle, uint, Handle, inout Error) ures_getByIndex; 00490 Handle function (Handle, char*, Handle, inout Error) ures_getByKey; 00491 } 00492 00493 /*************************************************************** 00494 00495 ***************************************************************/ 00496 00497 static FunctionLoader.Bind[] targets = 00498 [ 00499 {cast(void**) &ures_open, "ures_open"}, 00500 {cast(void**) &ures_close, "ures_close"}, 00501 {cast(void**) &ures_getLocale, "ures_getLocale"}, 00502 {cast(void**) &ures_getVersion, "ures_getVersion"}, 00503 {cast(void**) &ures_getSize, "ures_getSize"}, 00504 {cast(void**) &ures_getInt, "ures_getInt"}, 00505 {cast(void**) &ures_getString, "ures_getString"}, 00506 {cast(void**) &ures_getStringByIndex, "ures_getStringByIndex"}, 00507 {cast(void**) &ures_getStringByKey, "ures_getStringByKey"}, 00508 {cast(void**) &ures_getBinary, "ures_getBinary"}, 00509 {cast(void**) &ures_hasNext, "ures_hasNext"}, 00510 {cast(void**) &ures_resetIterator, "ures_resetIterator"}, 00511 {cast(void**) &ures_getNextString, "ures_getNextString"}, 00512 {cast(void**) &ures_getKey, "ures_getKey"}, 00513 {cast(void**) &ures_getType, "ures_getType"}, 00514 {cast(void**) &ures_getNextResource, "ures_getNextResource"}, 00515 {cast(void**) &ures_getByIndex, "ures_getByIndex"}, 00516 {cast(void**) &ures_getByKey, "ures_getByKey"}, 00517 ]; 00518 00519 /*************************************************************** 00520 00521 ***************************************************************/ 00522 00523 static this () 00524 { 00525 library = FunctionLoader.bind (libraryName, targets); 00526 //test (); 00527 } 00528 00529 /*************************************************************** 00530 00531 ***************************************************************/ 00532 00533 static ~this () 00534 { 00535 FunctionLoader.unbind (library); 00536 } 00537 } 00538 00539 static void test() 00540 { 00541 UResourceBundle b = new UResourceBundle (ULocale.Default); 00542 UText t = b.getNextString(); 00543 UResourceBundle b1 = b.getNextResource (); 00544 } 00545 } 00546 00547