comparison dwtx/dwtxhelper/mangoicu/ICU.d @ 89:040da1cb0d76

Add a local copy of the mango ICU binding to work out the utf8 usability. Will hopefully go back into mango.
author Frank Benoit <benoit@tionex.de>
date Sun, 22 Jun 2008 22:57:31 +0200
parents
children 11e8159caf7a
comparison
equal deleted inserted replaced
88:cd18fa3b71f1 89:040da1cb0d76
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 dwtx.dwthelper.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 protected static char[] icuuc = "icuuc"~ICULib~".dll";
102 protected static char[] icuin = "icuin"~ICULib~".dll";
103 }
104 else
105 version (linux)
106 {
107 protected static char[] icuuc = "libicuuc.so."~ICULib;
108 protected static char[] icuin = "libicui18n.so."~ICULib;
109 }
110 else
111 version (darwin)
112 {
113 protected static char[] icuuc = "libicuuc.dylib."~ICULib;
114 protected 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 protected enum Error:int
162 {
163 OK,
164 BufferOverflow=15
165 }
166
167 /***********************************************************************
168
169 ***********************************************************************/
170
171 protected static final bool isError (Error e)
172 {
173 return e > 0;
174 }
175
176 /***********************************************************************
177
178 ***********************************************************************/
179
180 protected static final void exception (char[] msg)
181 {
182 throw new ICUException (msg);
183 }
184
185 /***********************************************************************
186
187 ***********************************************************************/
188
189 protected static final void testError (Error 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 Function address loader for Win32
303
304 *******************************************************************************/
305
306 version (Win32)
307 {
308 typedef void* HANDLE;
309 extern (Windows) HANDLE LoadLibraryA (char*);
310 extern (Windows) HANDLE GetProcAddress (HANDLE, char*);
311 extern (Windows) void FreeLibrary (HANDLE);
312
313 /***********************************************************************
314
315 ***********************************************************************/
316
317 class FunctionLoader
318 {
319 /***************************************************************
320
321 ***************************************************************/
322
323 protected struct Bind
324 {
325 void** fnc;
326 char[] name;
327 }
328
329 /***************************************************************
330
331 ***************************************************************/
332
333 static final void* bind (char[] library, inout Bind[] targets)
334 {
335 HANDLE lib = LoadLibraryA (ICU.toString(library));
336
337 foreach (Bind b; targets)
338 {
339 char[] name = b.name ~ ICUSig;
340 *b.fnc = GetProcAddress (lib, name.ptr);
341 if (*b.fnc)
342 {}// printf ("bound '%.*s'\n", name);
343 else
344 throw new Exception ("required " ~ name ~ " in library " ~ library);
345 }
346 return lib;
347 }
348
349 /***************************************************************
350
351 ***************************************************************/
352
353 static final void unbind (void* library)
354 {
355 version (CorrectedTeardown)
356 FreeLibrary (cast(HANDLE) library);
357 }
358 }
359 }
360
361
362 /*******************************************************************************
363
364 2004-11-26: Added Linux shared library support -- John Reimer
365
366 *******************************************************************************/
367
368 else version (linux)
369 {
370 //Tell build to link with dl library
371 version(build) { pragma(link, "dl"); }
372
373 // from include/bits/dlfcn.h on Linux
374 const int RTLD_LAZY = 0x00001; // Lazy function call binding
375 const int RTLD_NOW = 0x00002; // Immediate function call binding
376 const int RTLD_NOLOAD = 0x00004; // no object load
377 const int RTLD_DEEPBIND = 0x00008;
378 const int RTLD_GLOBAL = 0x00100; // make object available to whole program
379
380 extern(C)
381 {
382 void* dlopen(char* filename, int flag);
383 char* dlerror();
384 void* dlsym(void* handle, char* symbol);
385 int dlclose(void* handle);
386 }
387
388 class FunctionLoader
389 {
390 /***************************************************************
391
392 ***************************************************************/
393
394 protected struct Bind
395 {
396 void** fnc;
397 char[] name;
398 }
399
400 /***************************************************************
401
402 ***************************************************************/
403
404 static final void* bind (char[] library, inout Bind[] targets)
405 {
406 static char[] errorInfo;
407 // printf("the library is %s\n", ICU.toString(library));
408 void* lib = dlopen(ICU.toString(library), RTLD_NOW);
409
410 // clear the error buffer
411 dlerror();
412
413 foreach (Bind b; targets)
414 {
415 char[] name = b.name ~ ICUSig;
416
417 *b.fnc = dlsym (lib, name.ptr);
418 if (*b.fnc)
419 {}// printf ("bound '%.*s'\n", name);
420 else {
421 // errorInfo = ICU.toArray(dlerror());
422 // printf("%s", dlerror());
423 throw new Exception ("required " ~ name ~ " in library " ~ library);
424 }
425 }
426 return lib;
427 }
428
429 /***************************************************************
430
431 ***************************************************************/
432
433 static final void unbind (void* library)
434 {
435 version (CorrectedTeardown)
436 {
437 if (! dlclose (library))
438 throw new Exception ("close library failed\n");
439 }
440 }
441 }
442 }
443
444
445 /*******************************************************************************
446
447 2004-12-20: Added Darwin shared library support -- afb
448
449 *******************************************************************************/
450
451 else version (darwin)
452 {
453 // #include <mach-o/loader.h>
454
455 struct mach_header
456 {
457 uint magic; /* mach magic number identifier */
458 uint cputype; /* cpu specifier */
459 uint cpusubtype; /* machine specifier */
460 uint filetype; /* type of file */
461 uint ncmds; /* number of load commands */
462 uint sizeofcmds; /* the size of all the load commands */
463 uint flags; /* flags */
464 }
465
466 /* Constant for the magic field of the mach_header */
467 const uint MH_MAGIC = 0xfeedface; // the mach magic number
468 const uint MH_CIGAM = 0xcefaedfe; // x86 variant
469
470 // #include <mach-o/dyld.h>
471
472 typedef void *NSObjectFileImage;
473
474 typedef void *NSModule;
475
476 typedef void *NSSymbol;
477
478 enum // DYLD_BOOL: uint
479 {
480 FALSE,
481 TRUE
482 }
483 alias uint DYLD_BOOL;
484
485 enum // NSObjectFileImageReturnCode: uint
486 {
487 NSObjectFileImageFailure, /* for this a message is printed on stderr */
488 NSObjectFileImageSuccess,
489 NSObjectFileImageInappropriateFile,
490 NSObjectFileImageArch,
491 NSObjectFileImageFormat, /* for this a message is printed on stderr */
492 NSObjectFileImageAccess
493 }
494 alias uint NSObjectFileImageReturnCode;
495
496 enum // NSLinkEditErrors: uint
497 {
498 NSLinkEditFileAccessError,
499 NSLinkEditFileFormatError,
500 NSLinkEditMachResourceError,
501 NSLinkEditUnixResourceError,
502 NSLinkEditOtherError,
503 NSLinkEditWarningError,
504 NSLinkEditMultiplyDefinedError,
505 NSLinkEditUndefinedError
506 }
507 alias uint NSLinkEditErrors;
508
509 extern(C)
510 {
511 NSObjectFileImageReturnCode NSCreateObjectFileImageFromFile(char *pathName, NSObjectFileImage* objectFileImage);
512 DYLD_BOOL NSDestroyObjectFileImage(NSObjectFileImage objectFileImage);
513
514 mach_header * NSAddImage(char *image_name, uint options);
515 const uint NSADDIMAGE_OPTION_NONE = 0x0;
516 const uint NSADDIMAGE_OPTION_RETURN_ON_ERROR = 0x1;
517 const uint NSADDIMAGE_OPTION_WITH_SEARCHING = 0x2;
518 const uint NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED = 0x4;
519 const uint NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME = 0x8;
520
521 NSModule NSLinkModule(NSObjectFileImage objectFileImage, char* moduleName, uint options);
522 const uint NSLINKMODULE_OPTION_NONE = 0x0;
523 const uint NSLINKMODULE_OPTION_BINDNOW = 0x01;
524 const uint NSLINKMODULE_OPTION_PRIVATE = 0x02;
525 const uint NSLINKMODULE_OPTION_RETURN_ON_ERROR = 0x04;
526 const uint NSLINKMODULE_OPTION_DONT_CALL_MOD_INIT_ROUTINES = 0x08;
527 const uint NSLINKMODULE_OPTION_TRAILING_PHYS_NAME = 0x10;
528 DYLD_BOOL NSUnLinkModule(NSModule module_, uint options);
529
530 void NSLinkEditError(NSLinkEditErrors *c, int *errorNumber, char **fileName, char **errorString);
531
532 DYLD_BOOL NSIsSymbolNameDefined(char *symbolName);
533 DYLD_BOOL NSIsSymbolNameDefinedInImage(mach_header *image, char *symbolName);
534 NSSymbol NSLookupAndBindSymbol(char *symbolName);
535 NSSymbol NSLookupSymbolInModule(NSModule module_, char* symbolName);
536 NSSymbol NSLookupSymbolInImage(mach_header *image, char *symbolName, uint options);
537 const uint NSLOOKUPSYMBOLINIMAGE_OPTION_BIND = 0x0;
538 const uint NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW = 0x1;
539 const uint NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY = 0x2;
540 const uint NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR = 0x4;
541
542 void* NSAddressOfSymbol(NSSymbol symbol);
543 char* NSNameOfSymbol(NSSymbol symbol);
544 }
545
546
547 class FunctionLoader
548 {
549 /***************************************************************
550
551 ***************************************************************/
552
553 protected struct Bind
554 {
555 void** fnc;
556 char[] name;
557 }
558
559 /***************************************************************
560
561 ***************************************************************/
562
563 private static NSModule open(char* filename)
564 {
565 NSModule mod = null;
566 NSObjectFileImage fileImage = null;
567 debug printf("Trying to load: %s\n", filename);
568
569 NSObjectFileImageReturnCode returnCode =
570 NSCreateObjectFileImageFromFile(filename, &fileImage);
571 if(returnCode == NSObjectFileImageSuccess)
572 {
573 mod = NSLinkModule(fileImage,filename,
574 NSLINKMODULE_OPTION_RETURN_ON_ERROR |
575 NSLINKMODULE_OPTION_PRIVATE |
576 NSLINKMODULE_OPTION_BINDNOW);
577 NSDestroyObjectFileImage(fileImage);
578 }
579 else if(returnCode == NSObjectFileImageInappropriateFile)
580 {
581 NSDestroyObjectFileImage(fileImage);
582 /* Could be a dynamic library rather than a bundle */
583 mod = cast(NSModule) NSAddImage(filename,
584 NSADDIMAGE_OPTION_RETURN_ON_ERROR);
585 }
586 else
587 {
588 debug printf("FileImage Failed: %d\n", returnCode);
589 }
590 return mod;
591 }
592
593 private static void* symbol(NSModule mod, char* name)
594 {
595 NSSymbol symbol = null;
596 uint magic = (* cast(mach_header *) mod).magic;
597
598 if ( (mod == cast(NSModule) -1) && NSIsSymbolNameDefined(name))
599 /* Global context, use NSLookupAndBindSymbol */
600 symbol = NSLookupAndBindSymbol(name);
601 else if ( ( magic == MH_MAGIC || magic == MH_CIGAM ) &&
602 NSIsSymbolNameDefinedInImage(cast(mach_header *) mod, name))
603 symbol = NSLookupSymbolInImage(cast(mach_header *) mod, name,
604 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
605 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
606 else
607 symbol = NSLookupSymbolInModule(mod, name);
608
609 return NSAddressOfSymbol(symbol);
610 }
611
612 static final void* bind (char[] library, inout Bind[] targets)
613 {
614 static char[] errorInfo;
615
616 debug printf("the library is %s\n", ICU.toString(library));
617
618 void* lib = null;
619 static char[][] usual_suspects = [ "", "/usr/local/lib/", "/usr/lib/",
620 /* Fink */ "/sw/lib/", /* DarwinPorts */ "/opt/local/lib/" ];
621 foreach (char[] prefix; usual_suspects)
622 {
623 lib = cast(void*) open(ICU.toString(prefix ~ library));
624 if (lib != null) break;
625 }
626 if (lib == null)
627 {
628 throw new Exception ("could not open library " ~ library);
629 }
630
631 // clear the error buffer
632 // error();
633
634 foreach (Bind b; targets)
635 {
636 // Note: all C functions have a underscore prefix in Mach-O symbols
637 char[] name = "_" ~ b.name ~ ICUSig;
638
639 *b.fnc = symbol(cast(NSModule) lib, name.ptr);
640 if (*b.fnc != null)
641 {
642 debug printf ("bound '%.*s'\n", name);
643 }
644 else
645 {
646 // errorInfo = ICU.toArray(error());
647 throw new Exception ("required " ~ name ~ " in library " ~ library);
648 }
649 }
650 return lib;
651 }
652
653 /***************************************************************
654
655 ***************************************************************/
656
657 private static bool close(NSModule mod)
658 {
659 uint magic = (* cast(mach_header *) mod).magic;
660 if ( magic == MH_MAGIC || magic == MH_CIGAM )
661 {
662 // Can not unlink dynamic libraries on Darwin
663 return true;
664 }
665
666 return (NSUnLinkModule(mod, 0) == TRUE);
667 }
668
669 static final void unbind (void* library)
670 {
671 version (CorrectedTeardown)
672 {
673 if (! close(cast(NSModule) library))
674 throw new Exception ("close library failed\n");
675 }
676 }
677 }
678 }
679
680 /*******************************************************************************
681
682 unknown platform
683
684 *******************************************************************************/
685
686 else static assert(0); // need an implementation of FunctionLoader for this OS
687
688