comparison java/src/java/mangoicu/ICU.d @ 16:dbfb303e8fb0

first complete successful compile (win-only)
author Frank Benoit <benoit@tionex.de>
date Wed, 18 Mar 2009 08:56:47 +0100
parents
children 9b96950f2c3c
comparison
equal deleted inserted replaced
15:c4b1a29263fc 16:dbfb303e8fb0
1 /*******************************************************************************
2
3 @file ICU.d
4
5 Copyright (c) 2004 Kris Bell
6
7 This software is provided 'as-is', without any express or implied
8 warranty. In no event will the authors be held liable for damages
9 of any kind arising from the use of this software.
10
11 Permission is hereby granted to anyone to use this software for any
12 purpose, including commercial applications, and to alter it and/or
13 redistribute it freely, subject to the following restrictions:
14
15 1. The origin of this software must not be misrepresented; you must
16 not claim that you wrote the original software. If you use this
17 software in a product, an acknowledgment within documentation of
18 said product would be appreciated but is not required.
19
20 2. Altered source versions must be plainly marked as such, and must
21 not be misrepresented as being the original software.
22
23 3. This notice may not be removed or altered from any distribution
24 of the source.
25
26 4. Derivative works are permitted, but they must carry this notice
27 in full and credit the original source.
28
29
30 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
31
32
33 @version Initial version; October 2004
34 Updated to ICU v3.2; March 2005
35
36 @author Kris
37 John Reimer
38 Anders F Bjorklund (Darwin patches)
39
40
41 *******************************************************************************/
42
43 module java.mangoicu.ICU;
44
45 /*******************************************************************************
46
47 Library version identifiers
48
49 *******************************************************************************/
50
51 version (ICU30)
52 {
53 private static const final char[] ICULib = "30";
54 private static const final char[] ICUSig = "_3_0\0";
55 }
56 version (ICU32)
57 {
58 private static const final char[] ICULib = "32";
59 private static const final char[] ICUSig = "_3_2\0";
60 }
61 version (ICU34)
62 {
63 private static const final char[] ICULib = "34";
64 private static const final char[] ICUSig = "_3_4\0";
65 }
66 version (ICU36)
67 {
68 private static const final char[] ICULib = "36";
69 private static const final char[] ICUSig = "_3_6\0";
70 }
71 else
72 {
73 private static const final char[] ICULib = "38";
74 private static const final char[] ICUSig = "_3_8\0";
75 }
76
77 /*******************************************************************************
78
79 *******************************************************************************/
80
81 private static extern (C) uint strlen (char *s);
82 private static extern (C) uint wcslen (wchar *s);
83
84
85 /*******************************************************************************
86
87 Some low-level routines to help bind the ICU C-API to D.
88
89 *******************************************************************************/
90
91 protected class ICU
92 {
93 /***********************************************************************
94
95 The library names to load within the target environment
96
97 ***********************************************************************/
98
99 version (Win32)
100 {
101 package static char[] icuuc = "icuuc"~ICULib~".dll";
102 package static char[] icuin = "icuin"~ICULib~".dll";
103 }
104 else
105 version (linux)
106 {
107 package static char[] icuuc = "libicuuc.so."~ICULib;
108 package static char[] icuin = "libicui18n.so."~ICULib;
109 }
110 else
111 version (darwin)
112 {
113 package static char[] icuuc = "libicuuc.dylib."~ICULib;
114 package static char[] icuin = "libicui18n.dylib."~ICULib;
115 }
116 else
117 {
118 static assert (false);
119 }
120
121 /***********************************************************************
122
123 Use this for the primary argument-type to most ICU functions
124
125 ***********************************************************************/
126
127 protected typedef void* Handle;
128
129 /***********************************************************************
130
131 Parse-error filled in by several functions
132
133 ***********************************************************************/
134
135 public struct ParseError
136 {
137 int line,
138 offset;
139 wchar[16] preContext,
140 postContext;
141 }
142
143 /***********************************************************************
144
145 The binary form of a version on ICU APIs is an array of
146 four bytes
147
148 ***********************************************************************/
149
150 public struct Version
151 {
152 ubyte[4] info;
153 }
154
155 /***********************************************************************
156
157 ICU error codes (the ones which are referenced)
158
159 ***********************************************************************/
160
161 package enum UErrorCode:int
162 {
163 OK,
164 BufferOverflow=15
165 }
166
167 /***********************************************************************
168
169 ***********************************************************************/
170
171 package static final bool isError (UErrorCode e)
172 {
173 return e > 0;
174 }
175
176 /***********************************************************************
177
178 ***********************************************************************/
179
180 package static final void exception (char[] msg)
181 {
182 throw new ICUException (msg);
183 }
184
185 /***********************************************************************
186
187 ***********************************************************************/
188
189 package static final void testError (UErrorCode e, char[] msg)
190 {
191 if (e > 0)
192 exception (msg);
193 }
194
195 /***********************************************************************
196
197 ***********************************************************************/
198
199 protected static final char* toString (char[] string)
200 {
201 static char[] empty = "";
202
203 if (! string.length)
204 return (string.ptr) ? empty.ptr : null;
205
206 // if (* (&string[0] + string.length))
207 {
208 // Need to make a copy
209 char[] copy = new char [string.length + 1];
210 copy [0..string.length] = string;
211 copy [string.length] = 0;
212 string = copy;
213 }
214 return string.ptr;
215 }
216
217 /***********************************************************************
218
219 ***********************************************************************/
220
221 protected static final wchar* toString (wchar[] string)
222 {
223 static wchar[] empty = "";
224
225 if (! string.length)
226 return (string.ptr) ? empty.ptr : null;
227
228 // if (* (&string[0] + string.length))
229 {
230 // Need to make a copy
231 wchar[] copy = new wchar [string.length + 1];
232 copy [0..string.length] = string;
233 copy [string.length] = 0;
234 string = copy;
235 }
236 return string.ptr;
237 }
238
239 /***********************************************************************
240
241 ***********************************************************************/
242
243 protected static final uint length (char* s)
244 {
245 return strlen (s);
246 }
247
248 /***********************************************************************
249
250 ***********************************************************************/
251
252 protected static final uint length (wchar* s)
253 {
254 return wcslen (s);
255 }
256
257 /***********************************************************************
258
259 ***********************************************************************/
260
261 protected static final char[] toArray (char* s)
262 {
263 if (s)
264 return s[0..strlen (s)];
265 return null;
266 }
267
268 /***********************************************************************
269
270 ***********************************************************************/
271
272 protected static final wchar[] toArray (wchar* s)
273 {
274 if (s)
275 return s[0..wcslen (s)];
276 return null;
277 }
278 }
279
280
281 /*******************************************************************************
282
283 *******************************************************************************/
284
285 class ICUException : Exception
286 {
287 /***********************************************************************
288
289 Construct exception with the provided text string
290
291 ***********************************************************************/
292
293 this (char[] msg)
294 {
295 super (msg);
296 }
297 }
298
299 /*******************************************************************************
300
301 *******************************************************************************/
302
303 typedef void* UParseError;
304
305
306 /*******************************************************************************
307
308 Function address loader for Win32
309
310 *******************************************************************************/
311
312 version (Win32)
313 {
314 typedef void* HANDLE;
315 extern (Windows) HANDLE LoadLibraryA (char*);
316 extern (Windows) HANDLE GetProcAddress (HANDLE, char*);
317 extern (Windows) void FreeLibrary (HANDLE);
318
319 /***********************************************************************
320
321 ***********************************************************************/
322
323 package static class FunctionLoader
324 {
325 /***************************************************************
326
327 ***************************************************************/
328
329 protected struct Bind
330 {
331 void** fnc;
332 char[] name;
333 }
334
335 /***************************************************************
336
337 ***************************************************************/
338
339 static final void* bind (char[] library, inout Bind[] targets)
340 {
341 HANDLE lib = LoadLibraryA (ICU.toString(library));
342
343 foreach (Bind b; targets)
344 {
345 char[] name = b.name ~ ICUSig;
346 *b.fnc = GetProcAddress (lib, name.ptr);
347 if (*b.fnc)
348 {}// printf ("bound '%.*s'\n", name);
349 else
350 throw new Exception ("required " ~ name ~ " in library " ~ library);
351 }
352 return lib;
353 }
354
355 /***************************************************************
356
357 ***************************************************************/
358
359 static final void unbind (void* library)
360 {
361 version (CorrectedTeardown)
362 FreeLibrary (cast(HANDLE) library);
363 }
364 }
365 }
366
367
368 /*******************************************************************************
369
370 2004-11-26: Added Linux shared library support -- John Reimer
371
372 *******************************************************************************/
373
374 else version (linux)
375 {
376 //Tell build to link with dl library
377 version(build) { pragma(link, "dl"); }
378
379 // from include/bits/dlfcn.h on Linux
380 const int RTLD_LAZY = 0x00001; // Lazy function call binding
381 const int RTLD_NOW = 0x00002; // Immediate function call binding
382 const int RTLD_NOLOAD = 0x00004; // no object load
383 const int RTLD_DEEPBIND = 0x00008;
384 const int RTLD_GLOBAL = 0x00100; // make object available to whole program
385
386 extern(C)
387 {
388 void* dlopen(char* filename, int flag);
389 char* dlerror();
390 void* dlsym(void* handle, char* symbol);
391 int dlclose(void* handle);
392 }
393
394 class FunctionLoader
395 {
396 /***************************************************************
397
398 ***************************************************************/
399
400 protected struct Bind
401 {
402 void** fnc;
403 char[] name;
404 }
405
406 /***************************************************************
407
408 ***************************************************************/
409
410 static final void* bind (char[] library, inout Bind[] targets)
411 {
412 static char[] errorInfo;
413 // printf("the library is %s\n", ICU.toString(library));
414 void* lib = dlopen(ICU.toString(library), RTLD_NOW);
415
416 // clear the error buffer
417 dlerror();
418
419 foreach (Bind b; targets)
420 {
421 char[] name = b.name ~ ICUSig;
422
423 *b.fnc = dlsym (lib, name.ptr);
424 if (*b.fnc)
425 {}// printf ("bound '%.*s'\n", name);
426 else {
427 // errorInfo = ICU.toArray(dlerror());
428 // printf("%s", dlerror());
429 throw new Exception ("required " ~ name ~ " in library " ~ library);
430 }
431 }
432 return lib;
433 }
434
435 /***************************************************************
436
437 ***************************************************************/
438
439 static final void unbind (void* library)
440 {
441 version (CorrectedTeardown)
442 {
443 if (! dlclose (library))
444 throw new Exception ("close library failed\n");
445 }
446 }
447 }
448 }
449
450
451 /*******************************************************************************
452
453 2004-12-20: Added Darwin shared library support -- afb
454
455 *******************************************************************************/
456
457 else version (darwin)
458 {
459 // #include <mach-o/loader.h>
460
461 struct mach_header
462 {
463 uint magic; /* mach magic number identifier */
464 uint cputype; /* cpu specifier */
465 uint cpusubtype; /* machine specifier */
466 uint filetype; /* type of file */
467 uint ncmds; /* number of load commands */
468 uint sizeofcmds; /* the size of all the load commands */
469 uint flags; /* flags */
470 }
471
472 /* Constant for the magic field of the mach_header */
473 const uint MH_MAGIC = 0xfeedface; // the mach magic number
474 const uint MH_CIGAM = 0xcefaedfe; // x86 variant
475
476 // #include <mach-o/dyld.h>
477
478 typedef void *NSObjectFileImage;
479
480 typedef void *NSModule;
481
482 typedef void *NSSymbol;
483
484 enum // DYLD_BOOL: uint
485 {
486 FALSE,
487 TRUE
488 }
489 alias uint DYLD_BOOL;
490
491 enum // NSObjectFileImageReturnCode: uint
492 {
493 NSObjectFileImageFailure, /* for this a message is printed on stderr */
494 NSObjectFileImageSuccess,
495 NSObjectFileImageInappropriateFile,
496 NSObjectFileImageArch,
497 NSObjectFileImageFormat, /* for this a message is printed on stderr */
498 NSObjectFileImageAccess
499 }
500 alias uint NSObjectFileImageReturnCode;
501
502 enum // NSLinkEditErrors: uint
503 {
504 NSLinkEditFileAccessError,
505 NSLinkEditFileFormatError,
506 NSLinkEditMachResourceError,
507 NSLinkEditUnixResourceError,
508 NSLinkEditOtherError,
509 NSLinkEditWarningError,
510 NSLinkEditMultiplyDefinedError,
511 NSLinkEditUndefinedError
512 }
513 alias uint NSLinkEditErrors;
514
515 extern(C)
516 {
517 NSObjectFileImageReturnCode NSCreateObjectFileImageFromFile(char *pathName, NSObjectFileImage* objectFileImage);
518 DYLD_BOOL NSDestroyObjectFileImage(NSObjectFileImage objectFileImage);
519
520 mach_header * NSAddImage(char *image_name, uint options);
521 const uint NSADDIMAGE_OPTION_NONE = 0x0;
522 const uint NSADDIMAGE_OPTION_RETURN_ON_ERROR = 0x1;
523 const uint NSADDIMAGE_OPTION_WITH_SEARCHING = 0x2;
524 const uint NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED = 0x4;
525 const uint NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME = 0x8;
526
527 NSModule NSLinkModule(NSObjectFileImage objectFileImage, char* moduleName, uint options);
528 const uint NSLINKMODULE_OPTION_NONE = 0x0;
529 const uint NSLINKMODULE_OPTION_BINDNOW = 0x01;
530 const uint NSLINKMODULE_OPTION_PRIVATE = 0x02;
531 const uint NSLINKMODULE_OPTION_RETURN_ON_ERROR = 0x04;
532 const uint NSLINKMODULE_OPTION_DONT_CALL_MOD_INIT_ROUTINES = 0x08;
533 const uint NSLINKMODULE_OPTION_TRAILING_PHYS_NAME = 0x10;
534 DYLD_BOOL NSUnLinkModule(NSModule module_, uint options);
535
536 void NSLinkEditError(NSLinkEditErrors *c, int *errorNumber, char **fileName, char **errorString);
537
538 DYLD_BOOL NSIsSymbolNameDefined(char *symbolName);
539 DYLD_BOOL NSIsSymbolNameDefinedInImage(mach_header *image, char *symbolName);
540 NSSymbol NSLookupAndBindSymbol(char *symbolName);
541 NSSymbol NSLookupSymbolInModule(NSModule module_, char* symbolName);
542 NSSymbol NSLookupSymbolInImage(mach_header *image, char *symbolName, uint options);
543 const uint NSLOOKUPSYMBOLINIMAGE_OPTION_BIND = 0x0;
544 const uint NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW = 0x1;
545 const uint NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY = 0x2;
546 const uint NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR = 0x4;
547
548 void* NSAddressOfSymbol(NSSymbol symbol);
549 char* NSNameOfSymbol(NSSymbol symbol);
550 }
551
552
553 class FunctionLoader
554 {
555 /***************************************************************
556
557 ***************************************************************/
558
559 protected struct Bind
560 {
561 void** fnc;
562 char[] name;
563 }
564
565 /***************************************************************
566
567 ***************************************************************/
568
569 private static NSModule open(char* filename)
570 {
571 NSModule mod = null;
572 NSObjectFileImage fileImage = null;
573 debug printf("Trying to load: %s\n", filename);
574
575 NSObjectFileImageReturnCode returnCode =
576 NSCreateObjectFileImageFromFile(filename, &fileImage);
577 if(returnCode == NSObjectFileImageSuccess)
578 {
579 mod = NSLinkModule(fileImage,filename,
580 NSLINKMODULE_OPTION_RETURN_ON_ERROR |
581 NSLINKMODULE_OPTION_PRIVATE |
582 NSLINKMODULE_OPTION_BINDNOW);
583 NSDestroyObjectFileImage(fileImage);
584 }
585 else if(returnCode == NSObjectFileImageInappropriateFile)
586 {
587 NSDestroyObjectFileImage(fileImage);
588 /* Could be a dynamic library rather than a bundle */
589 mod = cast(NSModule) NSAddImage(filename,
590 NSADDIMAGE_OPTION_RETURN_ON_ERROR);
591 }
592 else
593 {
594 debug printf("FileImage Failed: %d\n", returnCode);
595 }
596 return mod;
597 }
598
599 private static void* symbol(NSModule mod, char* name)
600 {
601 NSSymbol symbol = null;
602 uint magic = (* cast(mach_header *) mod).magic;
603
604 if ( (mod == cast(NSModule) -1) && NSIsSymbolNameDefined(name))
605 /* Global context, use NSLookupAndBindSymbol */
606 symbol = NSLookupAndBindSymbol(name);
607 else if ( ( magic == MH_MAGIC || magic == MH_CIGAM ) &&
608 NSIsSymbolNameDefinedInImage(cast(mach_header *) mod, name))
609 symbol = NSLookupSymbolInImage(cast(mach_header *) mod, name,
610 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
611 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
612 else
613 symbol = NSLookupSymbolInModule(mod, name);
614
615 return NSAddressOfSymbol(symbol);
616 }
617
618 static final void* bind (char[] library, inout Bind[] targets)
619 {
620 static char[] errorInfo;
621
622 debug printf("the library is %s\n", ICU.toString(library));
623
624 void* lib = null;
625 static char[][] usual_suspects = [ "", "/usr/local/lib/", "/usr/lib/",
626 /* Fink */ "/sw/lib/", /* DarwinPorts */ "/opt/local/lib/" ];
627 foreach (char[] prefix; usual_suspects)
628 {
629 lib = cast(void*) open(ICU.toString(prefix ~ library));
630 if (lib != null) break;
631 }
632 if (lib == null)
633 {
634 throw new Exception ("could not open library " ~ library);
635 }
636
637 // clear the error buffer
638 // error();
639
640 foreach (Bind b; targets)
641 {
642 // Note: all C functions have a underscore prefix in Mach-O symbols
643 char[] name = "_" ~ b.name ~ ICUSig;
644
645 *b.fnc = symbol(cast(NSModule) lib, name.ptr);
646 if (*b.fnc != null)
647 {
648 debug printf ("bound '%.*s'\n", name);
649 }
650 else
651 {
652 // errorInfo = ICU.toArray(error());
653 throw new Exception ("required " ~ name ~ " in library " ~ library);
654 }
655 }
656 return lib;
657 }
658
659 /***************************************************************
660
661 ***************************************************************/
662
663 private static bool close(NSModule mod)
664 {
665 uint magic = (* cast(mach_header *) mod).magic;
666 if ( magic == MH_MAGIC || magic == MH_CIGAM )
667 {
668 // Can not unlink dynamic libraries on Darwin
669 return true;
670 }
671
672 return (NSUnLinkModule(mod, 0) == TRUE);
673 }
674
675 static final void unbind (void* library)
676 {
677 version (CorrectedTeardown)
678 {
679 if (! close(cast(NSModule) library))
680 throw new Exception ("close library failed\n");
681 }
682 }
683 }
684 }
685
686 /*******************************************************************************
687
688 unknown platform
689
690 *******************************************************************************/
691
692 else static assert(0); // need an implementation of FunctionLoader for this OS
693
694