Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

ICU.d

Go to the documentation of this file.
00001 /*******************************************************************************
00002 
00003         @file ICU.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         4. Derivative works are permitted, but they must carry this notice
00027            in full and credit the original source.
00028 
00029 
00030                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00031 
00032 
00033         @version        Initial version; October 2004   
00034                         Updated to ICU v3.2; March 2005
00035 
00036         @author         Kris 
00037                         John Reimer
00038                         Anders F Bjorklund (Darwin patches)
00039 
00040 
00041 *******************************************************************************/
00042 
00043 module mango.icu.ICU;
00044 
00045 private import std.string;
00046 
00047 /*******************************************************************************
00048 
00049         Library version identifiers
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         Some low-level routines to help bind the ICU C-API to D.
00075 
00076 *******************************************************************************/
00077 
00078 protected class ICU
00079 {
00080         /***********************************************************************
00081 
00082                 The library names to load within the target environment
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                 Use this for the primary argument-type to most ICU functions
00111 
00112         ***********************************************************************/
00113 
00114         protected typedef void* Handle;
00115 
00116         /***********************************************************************
00117         
00118                 Parse-error filled in by several functions
00119 
00120         ***********************************************************************/
00121 
00122         public struct   ParseError 
00123                         {
00124                         int             line,
00125                                         offset;
00126                         wchar[16]       preContext,
00127                                         postContext;
00128                         }
00129 
00130         /***********************************************************************
00131 
00132                 The binary form of a version on ICU APIs is an array of 
00133                 four bytes        
00134 
00135         ***********************************************************************/
00136 
00137         public struct   Version
00138                         {
00139                         ubyte[4] info;
00140                         }
00141 
00142         /***********************************************************************
00143         
00144                 ICU error codes (the ones which are referenced)
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 //                if (* (&string[0] + string.length))
00194                    {
00195                    // Need to make a copy
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 //                if (* (&string[0] + string.length))
00216                    {
00217                    // Need to make a copy
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                 Construct exception with the provided text string
00277 
00278         ***********************************************************************/
00279 
00280         this (char[] msg)
00281         {
00282                 super (msg);
00283         }
00284 }
00285 
00286 
00287 /*******************************************************************************
00288         
00289         Function address loader for Win32
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                                    {}// printf ("bound '%.*s'\n", name);
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         2004-11-26:  Added Linux shared library support -- John Reimer
00349 
00350 *******************************************************************************/
00351 
00352 else version (linux)
00353 {
00354         // from include/bits/dlfcn.h on Linux
00355         const int RTLD_LAZY     = 0x00001;      // Lazy function call binding
00356         const int RTLD_NOW      = 0x00002;      // Immediate function call binding
00357         const int RTLD_NOLOAD   = 0x00004;      // no object load
00358         const int RTLD_DEEPBIND = 0x00008;
00359         const int RTLD_GLOBAL   = 0x00100;      // make object available to whole program    
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                         // printf("the library is %s\n", ICU.toString(library));
00389                         void* lib = dlopen(ICU.toString(library), RTLD_NOW);
00390                         
00391                         // clear the error buffer
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                                    {}// printf ("bound '%.*s'\n", name);
00401                                 else {
00402                                         // errorInfo = ICU.toArray(dlerror());
00403                                         // printf("%s", dlerror());
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         2004-12-20:  Added Darwin shared library support -- afb
00429 
00430 *******************************************************************************/
00431 
00432 else version (darwin)
00433 {
00434         // #include <mach-o/loader.h>
00435 
00436         struct mach_header
00437         {
00438             uint    magic;      /* mach magic number identifier */
00439             uint    cputype;    /* cpu specifier */
00440             uint    cpusubtype; /* machine specifier */
00441             uint    filetype;   /* type of file */
00442             uint    ncmds;      /* number of load commands */
00443             uint    sizeofcmds; /* the size of all the load commands */
00444             uint    flags;      /* flags */
00445         }
00446         
00447         /* Constant for the magic field of the mach_header */
00448         const uint MH_MAGIC = 0xfeedface;   // the mach magic number
00449         const uint MH_CIGAM = 0xcefaedfe;   // x86 variant
00450 
00451         // #include <mach-o/dyld.h>
00452         
00453         typedef void *NSObjectFileImage;
00454         
00455         typedef void *NSModule;
00456         
00457         typedef void *NSSymbol;
00458 
00459         enum // DYLD_BOOL: uint
00460         {
00461             FALSE,
00462             TRUE
00463         }
00464         alias uint DYLD_BOOL;
00465 
00466         enum // NSObjectFileImageReturnCode: uint
00467         {
00468             NSObjectFileImageFailure, /* for this a message is printed on stderr */
00469             NSObjectFileImageSuccess,
00470             NSObjectFileImageInappropriateFile,
00471             NSObjectFileImageArch,
00472             NSObjectFileImageFormat, /* for this a message is printed on stderr */
00473             NSObjectFileImageAccess
00474         }
00475         alias uint NSObjectFileImageReturnCode;
00476         
00477         enum // NSLinkEditErrors: uint
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                                 /* Could be dynamic library rather than a bundle */
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                                 /* Global context, use NSLookupAndBindSymbol */
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                         // printf("the library is %s\n", ICU.toString(library));
00597                         void* lib = cast(void*) open(ICU.toString(library));
00598                         
00599                         // clear the error buffer
00600                         // error();
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                                    {}// printf ("bound '%.*s'\n", name);
00609                                 else {
00610                                         // errorInfo = ICU.toArray(error());
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                                 // Can not unlink dynamic libraries on Darwin
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         unknown platform
00647 
00648 *******************************************************************************/
00649 
00650 else static assert(0); // need an implementation of FunctionLoader for this OS
00651 

Generated on Sat Apr 9 20:11:27 2005 for Mango by doxygen 1.3.6