00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 module mango.icu.ICU;
00044
00045 private import std.string;
00046
00047
00048
00049
00050
00051
00052
00053 version (ICU30)
00054 {
00055 private static const final char[] ICULib = "30";
00056 private static const final char[] ICUSig = "_3_0\0";
00057 }
00058 else
00059 {
00060 private static const final char[] ICULib = "32";
00061 private static const final char[] ICUSig = "_3_2\0";
00062 }
00063
00064
00065
00066
00067
00068 private static extern (C) uint strlen (char *s);
00069 private static extern (C) uint wcslen (wchar *s);
00070
00071
00072
00073
00074
00075
00076
00077
00078 protected class ICU
00079 {
00080
00081
00082
00083
00084
00085
00086 version(Win32)
00087 {
00088 protected static char[] icuuc = "icuuc"~ICULib~".dll";
00089 protected static char[] icuin = "icuin"~ICULib~".dll";
00090 }
00091 else
00092 version (linux)
00093 {
00094 protected static char[] icuuc = "libicuuc.so."~ICULib;
00095 protected static char[] icuin = "libicui18n.so."~ICULib;
00096 }
00097 else
00098 version (darwin)
00099 {
00100 protected static char[] icuuc = "libicuuc.dylib."~ICULib;
00101 protected static char[] icuin = "libicui18n.dylib."~ICULib;
00102 }
00103 else
00104 {
00105 static assert (false);
00106 }
00107
00108
00109
00110
00111
00112
00113
00114 protected typedef void* Handle;
00115
00116
00117
00118
00119
00120
00121
00122 public struct ParseError
00123 {
00124 int line,
00125 offset;
00126 wchar[16] preContext,
00127 postContext;
00128 }
00129
00130
00131
00132
00133
00134
00135
00136
00137 public struct Version
00138 {
00139 ubyte[4] info;
00140 }
00141
00142
00143
00144
00145
00146
00147
00148 protected enum Error:int
00149 {
00150 OK,
00151 BufferOverflow=15
00152 }
00153
00154
00155
00156
00157
00158 protected static final bool isError (Error e)
00159 {
00160 return e > 0;
00161 }
00162
00163
00164
00165
00166
00167 protected static final void exception (char[] msg)
00168 {
00169 throw new ICUException (msg);
00170 }
00171
00172
00173
00174
00175
00176 protected static final void testError (Error e, char[] msg)
00177 {
00178 if (e > 0)
00179 exception (msg);
00180 }
00181
00182
00183
00184
00185
00186 protected static final char* toString (char[] string)
00187 {
00188 static char[] empty = "";
00189
00190 if (! string.length)
00191 return (string.ptr) ? empty : cast(char*) null;
00192
00193
00194 {
00195
00196 char[] copy = new char [string.length + 1];
00197 copy [0..string.length] = string;
00198 copy [string.length] = 0;
00199 string = copy;
00200 }
00201 return string;
00202 }
00203
00204
00205
00206
00207
00208 protected static final wchar* toString (wchar[] string)
00209 {
00210 static wchar[] empty = "";
00211
00212 if (! string.length)
00213 return (string.ptr) ? empty : cast(wchar*) null;
00214
00215
00216 {
00217
00218 wchar[] copy = new wchar [string.length + 1];
00219 copy [0..string.length] = string;
00220 copy [string.length] = 0;
00221 string = copy;
00222 }
00223 return string;
00224 }
00225
00226
00227
00228
00229
00230 protected static final uint length (char* s)
00231 {
00232 return strlen (s);
00233 }
00234
00235
00236
00237
00238
00239 protected static final uint length (wchar* s)
00240 {
00241 return wcslen (s);
00242 }
00243
00244
00245
00246
00247
00248 protected static final char[] toArray (char* s)
00249 {
00250 if (s)
00251 return s[0..strlen (s)];
00252 return null;
00253 }
00254
00255
00256
00257
00258
00259 protected static final wchar[] toArray (wchar* s)
00260 {
00261 if (s)
00262 return s[0..wcslen (s)];
00263 return null;
00264 }
00265 }
00266
00267
00268
00269
00270
00271
00272 class ICUException : Exception
00273 {
00274
00275
00276
00277
00278
00279
00280 this (char[] msg)
00281 {
00282 super (msg);
00283 }
00284 }
00285
00286
00287
00288
00289
00290
00291
00292
00293 version (Win32)
00294 {
00295
00296
00297
00298
00299 class FunctionLoader
00300 {
00301 private import std.c.windows.windows;
00302
00303
00304
00305
00306
00307 protected struct Bind
00308 {
00309 void** fnc;
00310 char[] name;
00311 }
00312
00313
00314
00315
00316
00317 static final void* bind (char[] library, inout Bind[] targets)
00318 {
00319 HANDLE lib = LoadLibraryA (ICU.toString(library));
00320
00321 foreach (Bind b; targets)
00322 {
00323 char[] name = b.name ~ ICUSig;
00324 *b.fnc = GetProcAddress (lib, name);
00325 if (*b.fnc)
00326 {}
00327 else
00328 throw new Exception ("required " ~ name ~ " in library " ~ library);
00329 }
00330 return lib;
00331 }
00332
00333
00334
00335
00336
00337 static final void unbind (void* library)
00338 {
00339 version (CorrectedTeardown)
00340 FreeLibrary (cast(HANDLE) library);
00341 }
00342 }
00343 }
00344
00345
00346
00347
00348
00349
00350
00351
00352 else version (linux)
00353 {
00354
00355 const int RTLD_LAZY = 0x00001;
00356 const int RTLD_NOW = 0x00002;
00357 const int RTLD_NOLOAD = 0x00004;
00358 const int RTLD_DEEPBIND = 0x00008;
00359 const int RTLD_GLOBAL = 0x00100;
00360
00361 extern(C)
00362 {
00363 void* dlopen(char* filename, int flag);
00364 char* dlerror();
00365 void* dlsym(void* handle, char* symbol);
00366 int dlclose(void* handle);
00367 }
00368
00369 class FunctionLoader
00370 {
00371
00372
00373
00374
00375 protected struct Bind
00376 {
00377 void** fnc;
00378 char[] name;
00379 }
00380
00381
00382
00383
00384
00385 static final void* bind (char[] library, inout Bind[] targets)
00386 {
00387 static char[] errorInfo;
00388
00389 void* lib = dlopen(ICU.toString(library), RTLD_NOW);
00390
00391
00392 dlerror();
00393
00394 foreach (Bind b; targets)
00395 {
00396 char[] name = b.name ~ ICUSig;
00397
00398 *b.fnc = dlsym (lib, name);
00399 if (*b.fnc)
00400 {}
00401 else {
00402
00403
00404 throw new Exception ("required " ~ name ~ " in library " ~ library);
00405 }
00406 }
00407 return lib;
00408 }
00409
00410
00411
00412
00413
00414 static final void unbind (void* library)
00415 {
00416 version (CorrectedTeardown)
00417 {
00418 if (! dlclose (library))
00419 throw new Exception ("close library failed\n");
00420 }
00421 }
00422 }
00423 }
00424
00425
00426
00427
00428
00429
00430
00431
00432 else version (darwin)
00433 {
00434
00435
00436 struct mach_header
00437 {
00438 uint magic;
00439 uint cputype;
00440 uint cpusubtype;
00441 uint filetype;
00442 uint ncmds;
00443 uint sizeofcmds;
00444 uint flags;
00445 }
00446
00447
00448 const uint MH_MAGIC = 0xfeedface;
00449 const uint MH_CIGAM = 0xcefaedfe;
00450
00451
00452
00453 typedef void *NSObjectFileImage;
00454
00455 typedef void *NSModule;
00456
00457 typedef void *NSSymbol;
00458
00459 enum
00460 {
00461 FALSE,
00462 TRUE
00463 }
00464 alias uint DYLD_BOOL;
00465
00466 enum
00467 {
00468 NSObjectFileImageFailure,
00469 NSObjectFileImageSuccess,
00470 NSObjectFileImageInappropriateFile,
00471 NSObjectFileImageArch,
00472 NSObjectFileImageFormat,
00473 NSObjectFileImageAccess
00474 }
00475 alias uint NSObjectFileImageReturnCode;
00476
00477 enum
00478 {
00479 NSLinkEditFileAccessError,
00480 NSLinkEditFileFormatError,
00481 NSLinkEditMachResourceError,
00482 NSLinkEditUnixResourceError,
00483 NSLinkEditOtherError,
00484 NSLinkEditWarningError,
00485 NSLinkEditMultiplyDefinedError,
00486 NSLinkEditUndefinedError
00487 }
00488 alias uint NSLinkEditErrors;
00489
00490 extern(C)
00491 {
00492 NSObjectFileImageReturnCode NSCreateObjectFileImageFromFile(char *pathName, NSObjectFileImage* objectFileImage);
00493 DYLD_BOOL NSDestroyObjectFileImage(NSObjectFileImage objectFileImage);
00494
00495 mach_header * NSAddImage(char *image_name, uint options);
00496 const uint NSADDIMAGE_OPTION_NONE = 0x0;
00497 const uint NSADDIMAGE_OPTION_RETURN_ON_ERROR = 0x1;
00498 const uint NSADDIMAGE_OPTION_WITH_SEARCHING = 0x2;
00499 const uint NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED = 0x4;
00500 const uint NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME = 0x8;
00501
00502 NSModule NSLinkModule(NSObjectFileImage objectFileImage, char* moduleName, uint options);
00503 const uint NSLINKMODULE_OPTION_NONE = 0x0;
00504 const uint NSLINKMODULE_OPTION_BINDNOW = 0x01;
00505 const uint NSLINKMODULE_OPTION_PRIVATE = 0x02;
00506 const uint NSLINKMODULE_OPTION_RETURN_ON_ERROR = 0x04;
00507 const uint NSLINKMODULE_OPTION_DONT_CALL_MOD_INIT_ROUTINES = 0x08;
00508 const uint NSLINKMODULE_OPTION_TRAILING_PHYS_NAME = 0x10;
00509 DYLD_BOOL NSUnLinkModule(NSModule module_, uint options);
00510
00511 void NSLinkEditError(NSLinkEditErrors *c, int *errorNumber, char **fileName, char **errorString);
00512
00513 DYLD_BOOL NSIsSymbolNameDefined(char *symbolName);
00514 DYLD_BOOL NSIsSymbolNameDefinedInImage(mach_header *image, char *symbolName);
00515 NSSymbol NSLookupAndBindSymbol(char *symbolName);
00516 NSSymbol NSLookupSymbolInModule(NSModule module_, char* symbolName);
00517 NSSymbol NSLookupSymbolInImage(mach_header *image, char *symbolName, uint options);
00518 const uint NSLOOKUPSYMBOLINIMAGE_OPTION_BIND = 0x0;
00519 const uint NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW = 0x1;
00520 const uint NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY = 0x2;
00521 const uint NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR = 0x4;
00522
00523 void* NSAddressOfSymbol(NSSymbol symbol);
00524 char* NSNameOfSymbol(NSSymbol symbol);
00525 }
00526
00527
00528 class FunctionLoader
00529 {
00530
00531
00532
00533
00534 protected struct Bind
00535 {
00536 void** fnc;
00537 char[] name;
00538 }
00539
00540
00541
00542
00543
00544 private static NSModule open(char* filename)
00545 {
00546 NSModule mod = null;
00547 NSObjectFileImage fileImage = null;
00548 debug printf("Trying to load: %s\n", filename);
00549
00550 NSObjectFileImageReturnCode returnCode =
00551 NSCreateObjectFileImageFromFile(filename, &fileImage);
00552 if(returnCode == NSObjectFileImageSuccess)
00553 {
00554 mod = NSLinkModule(fileImage,filename,
00555 NSLINKMODULE_OPTION_RETURN_ON_ERROR |
00556 NSLINKMODULE_OPTION_PRIVATE |
00557 NSLINKMODULE_OPTION_BINDNOW);
00558 NSDestroyObjectFileImage(fileImage);
00559 }
00560 else if(returnCode == NSObjectFileImageInappropriateFile)
00561 {
00562 NSDestroyObjectFileImage(fileImage);
00563
00564 mod = cast(NSModule) NSAddImage(filename,
00565 NSADDIMAGE_OPTION_RETURN_ON_ERROR);
00566 }
00567 else
00568 {
00569 debug printf("Failed: %d\n", returnCode);
00570 }
00571 return mod;
00572 }
00573
00574 private static void* symbol(NSModule mod, char* name)
00575 {
00576 NSSymbol symbol = null;
00577 uint magic = (* cast(mach_header *) mod).magic;
00578
00579 if ( (mod == cast(NSModule) -1) && NSIsSymbolNameDefined(name))
00580
00581 symbol = NSLookupAndBindSymbol(name);
00582 else if ( ( magic == MH_MAGIC || magic == MH_CIGAM ) &&
00583 NSIsSymbolNameDefinedInImage(cast(mach_header *) mod, name))
00584 symbol = NSLookupSymbolInImage(cast(mach_header *) mod, name,
00585 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
00586 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
00587 else
00588 symbol = NSLookupSymbolInModule(mod, name);
00589
00590 return NSAddressOfSymbol(symbol);
00591 }
00592
00593 static final void* bind (char[] library, inout Bind[] targets)
00594 {
00595 static char[] errorInfo;
00596
00597 void* lib = cast(void*) open(ICU.toString(library));
00598
00599
00600
00601
00602 foreach (Bind b; targets)
00603 {
00604 char[] name = b.name ~ ICUSig;
00605
00606 *b.fnc = symbol (cast(NSModule) lib, name);
00607 if (*b.fnc)
00608 {}
00609 else {
00610
00611 throw new Exception ("required " ~ name ~ " in library " ~ library);
00612 }
00613 }
00614 return lib;
00615 }
00616
00617
00618
00619
00620
00621 private static bool close(NSModule mod)
00622 {
00623 uint magic = (* cast(mach_header *) mod).magic;
00624 if ( magic == MH_MAGIC || magic == MH_CIGAM )
00625 {
00626
00627 return true;
00628 }
00629
00630 return (NSUnLinkModule(mod, 0) == TRUE);
00631 }
00632
00633 static final void unbind (void* library)
00634 {
00635 version (CorrectedTeardown)
00636 {
00637 if (! close(cast(NSModule) library))
00638 throw new Exception ("close library failed\n");
00639 }
00640 }
00641 }
00642 }
00643
00644
00645
00646
00647
00648
00649
00650 else static assert(0);
00651