Mercurial > projects > dwt-addons
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/dwtxhelper/mangoicu/ICU.d Sun Jun 22 22:57:31 2008 +0200 @@ -0,0 +1,688 @@ +/******************************************************************************* + + @file ICU.d + + Copyright (c) 2004 Kris Bell + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for damages + of any kind arising from the use of this software. + + Permission is hereby granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and/or + redistribute it freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment within documentation of + said product would be appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any distribution + of the source. + + 4. Derivative works are permitted, but they must carry this notice + in full and credit the original source. + + + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + @version Initial version; October 2004 + Updated to ICU v3.2; March 2005 + + @author Kris + John Reimer + Anders F Bjorklund (Darwin patches) + + +*******************************************************************************/ + +module dwtx.dwthelper.mangoicu.ICU; + +/******************************************************************************* + + Library version identifiers + +*******************************************************************************/ + +version (ICU30) + { + private static const final char[] ICULib = "30"; + private static const final char[] ICUSig = "_3_0\0"; + } +version (ICU32) + { + private static const final char[] ICULib = "32"; + private static const final char[] ICUSig = "_3_2\0"; + } +version (ICU34) + { + private static const final char[] ICULib = "34"; + private static const final char[] ICUSig = "_3_4\0"; + } +version (ICU36) + { + private static const final char[] ICULib = "36"; + private static const final char[] ICUSig = "_3_6\0"; + } +else + { + private static const final char[] ICULib = "38"; + private static const final char[] ICUSig = "_3_8\0"; + } + +/******************************************************************************* + +*******************************************************************************/ + +private static extern (C) uint strlen (char *s); +private static extern (C) uint wcslen (wchar *s); + + +/******************************************************************************* + + Some low-level routines to help bind the ICU C-API to D. + +*******************************************************************************/ + +protected class ICU +{ + /*********************************************************************** + + The library names to load within the target environment + + ***********************************************************************/ + + version (Win32) + { + protected static char[] icuuc = "icuuc"~ICULib~".dll"; + protected static char[] icuin = "icuin"~ICULib~".dll"; + } + else + version (linux) + { + protected static char[] icuuc = "libicuuc.so."~ICULib; + protected static char[] icuin = "libicui18n.so."~ICULib; + } + else + version (darwin) + { + protected static char[] icuuc = "libicuuc.dylib."~ICULib; + protected static char[] icuin = "libicui18n.dylib."~ICULib; + } + else + { + static assert (false); + } + + /*********************************************************************** + + Use this for the primary argument-type to most ICU functions + + ***********************************************************************/ + + protected typedef void* Handle; + + /*********************************************************************** + + Parse-error filled in by several functions + + ***********************************************************************/ + + public struct ParseError + { + int line, + offset; + wchar[16] preContext, + postContext; + } + + /*********************************************************************** + + The binary form of a version on ICU APIs is an array of + four bytes + + ***********************************************************************/ + + public struct Version + { + ubyte[4] info; + } + + /*********************************************************************** + + ICU error codes (the ones which are referenced) + + ***********************************************************************/ + + protected enum Error:int + { + OK, + BufferOverflow=15 + } + + /*********************************************************************** + + ***********************************************************************/ + + protected static final bool isError (Error e) + { + return e > 0; + } + + /*********************************************************************** + + ***********************************************************************/ + + protected static final void exception (char[] msg) + { + throw new ICUException (msg); + } + + /*********************************************************************** + + ***********************************************************************/ + + protected static final void testError (Error e, char[] msg) + { + if (e > 0) + exception (msg); + } + + /*********************************************************************** + + ***********************************************************************/ + + protected static final char* toString (char[] string) + { + static char[] empty = ""; + + if (! string.length) + return (string.ptr) ? empty.ptr : null; + +// if (* (&string[0] + string.length)) + { + // Need to make a copy + char[] copy = new char [string.length + 1]; + copy [0..string.length] = string; + copy [string.length] = 0; + string = copy; + } + return string.ptr; + } + + /*********************************************************************** + + ***********************************************************************/ + + protected static final wchar* toString (wchar[] string) + { + static wchar[] empty = ""; + + if (! string.length) + return (string.ptr) ? empty.ptr : null; + +// if (* (&string[0] + string.length)) + { + // Need to make a copy + wchar[] copy = new wchar [string.length + 1]; + copy [0..string.length] = string; + copy [string.length] = 0; + string = copy; + } + return string.ptr; + } + + /*********************************************************************** + + ***********************************************************************/ + + protected static final uint length (char* s) + { + return strlen (s); + } + + /*********************************************************************** + + ***********************************************************************/ + + protected static final uint length (wchar* s) + { + return wcslen (s); + } + + /*********************************************************************** + + ***********************************************************************/ + + protected static final char[] toArray (char* s) + { + if (s) + return s[0..strlen (s)]; + return null; + } + + /*********************************************************************** + + ***********************************************************************/ + + protected static final wchar[] toArray (wchar* s) + { + if (s) + return s[0..wcslen (s)]; + return null; + } +} + + +/******************************************************************************* + +*******************************************************************************/ + +class ICUException : Exception +{ + /*********************************************************************** + + Construct exception with the provided text string + + ***********************************************************************/ + + this (char[] msg) + { + super (msg); + } +} + + +/******************************************************************************* + + Function address loader for Win32 + +*******************************************************************************/ + +version (Win32) +{ + typedef void* HANDLE; + extern (Windows) HANDLE LoadLibraryA (char*); + extern (Windows) HANDLE GetProcAddress (HANDLE, char*); + extern (Windows) void FreeLibrary (HANDLE); + + /*********************************************************************** + + ***********************************************************************/ + + class FunctionLoader + { + /*************************************************************** + + ***************************************************************/ + + protected struct Bind + { + void** fnc; + char[] name; + } + + /*************************************************************** + + ***************************************************************/ + + static final void* bind (char[] library, inout Bind[] targets) + { + HANDLE lib = LoadLibraryA (ICU.toString(library)); + + foreach (Bind b; targets) + { + char[] name = b.name ~ ICUSig; + *b.fnc = GetProcAddress (lib, name.ptr); + if (*b.fnc) + {}// printf ("bound '%.*s'\n", name); + else + throw new Exception ("required " ~ name ~ " in library " ~ library); + } + return lib; + } + + /*************************************************************** + + ***************************************************************/ + + static final void unbind (void* library) + { + version (CorrectedTeardown) + FreeLibrary (cast(HANDLE) library); + } + } +} + + +/******************************************************************************* + + 2004-11-26: Added Linux shared library support -- John Reimer + +*******************************************************************************/ + +else version (linux) +{ + //Tell build to link with dl library + version(build) { pragma(link, "dl"); } + + // from include/bits/dlfcn.h on Linux + const int RTLD_LAZY = 0x00001; // Lazy function call binding + const int RTLD_NOW = 0x00002; // Immediate function call binding + const int RTLD_NOLOAD = 0x00004; // no object load + const int RTLD_DEEPBIND = 0x00008; + const int RTLD_GLOBAL = 0x00100; // make object available to whole program + + extern(C) + { + void* dlopen(char* filename, int flag); + char* dlerror(); + void* dlsym(void* handle, char* symbol); + int dlclose(void* handle); + } + + class FunctionLoader + { + /*************************************************************** + + ***************************************************************/ + + protected struct Bind + { + void** fnc; + char[] name; + } + + /*************************************************************** + + ***************************************************************/ + + static final void* bind (char[] library, inout Bind[] targets) + { + static char[] errorInfo; + // printf("the library is %s\n", ICU.toString(library)); + void* lib = dlopen(ICU.toString(library), RTLD_NOW); + + // clear the error buffer + dlerror(); + + foreach (Bind b; targets) + { + char[] name = b.name ~ ICUSig; + + *b.fnc = dlsym (lib, name.ptr); + if (*b.fnc) + {}// printf ("bound '%.*s'\n", name); + else { + // errorInfo = ICU.toArray(dlerror()); + // printf("%s", dlerror()); + throw new Exception ("required " ~ name ~ " in library " ~ library); + } + } + return lib; + } + + /*************************************************************** + + ***************************************************************/ + + static final void unbind (void* library) + { + version (CorrectedTeardown) + { + if (! dlclose (library)) + throw new Exception ("close library failed\n"); + } + } + } +} + + +/******************************************************************************* + + 2004-12-20: Added Darwin shared library support -- afb + +*******************************************************************************/ + +else version (darwin) +{ + // #include <mach-o/loader.h> + + struct mach_header + { + uint magic; /* mach magic number identifier */ + uint cputype; /* cpu specifier */ + uint cpusubtype; /* machine specifier */ + uint filetype; /* type of file */ + uint ncmds; /* number of load commands */ + uint sizeofcmds; /* the size of all the load commands */ + uint flags; /* flags */ + } + + /* Constant for the magic field of the mach_header */ + const uint MH_MAGIC = 0xfeedface; // the mach magic number + const uint MH_CIGAM = 0xcefaedfe; // x86 variant + + // #include <mach-o/dyld.h> + + typedef void *NSObjectFileImage; + + typedef void *NSModule; + + typedef void *NSSymbol; + + enum // DYLD_BOOL: uint + { + FALSE, + TRUE + } + alias uint DYLD_BOOL; + + enum // NSObjectFileImageReturnCode: uint + { + NSObjectFileImageFailure, /* for this a message is printed on stderr */ + NSObjectFileImageSuccess, + NSObjectFileImageInappropriateFile, + NSObjectFileImageArch, + NSObjectFileImageFormat, /* for this a message is printed on stderr */ + NSObjectFileImageAccess + } + alias uint NSObjectFileImageReturnCode; + + enum // NSLinkEditErrors: uint + { + NSLinkEditFileAccessError, + NSLinkEditFileFormatError, + NSLinkEditMachResourceError, + NSLinkEditUnixResourceError, + NSLinkEditOtherError, + NSLinkEditWarningError, + NSLinkEditMultiplyDefinedError, + NSLinkEditUndefinedError + } + alias uint NSLinkEditErrors; + + extern(C) + { + NSObjectFileImageReturnCode NSCreateObjectFileImageFromFile(char *pathName, NSObjectFileImage* objectFileImage); + DYLD_BOOL NSDestroyObjectFileImage(NSObjectFileImage objectFileImage); + + mach_header * NSAddImage(char *image_name, uint options); + const uint NSADDIMAGE_OPTION_NONE = 0x0; + const uint NSADDIMAGE_OPTION_RETURN_ON_ERROR = 0x1; + const uint NSADDIMAGE_OPTION_WITH_SEARCHING = 0x2; + const uint NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED = 0x4; + const uint NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME = 0x8; + + NSModule NSLinkModule(NSObjectFileImage objectFileImage, char* moduleName, uint options); + const uint NSLINKMODULE_OPTION_NONE = 0x0; + const uint NSLINKMODULE_OPTION_BINDNOW = 0x01; + const uint NSLINKMODULE_OPTION_PRIVATE = 0x02; + const uint NSLINKMODULE_OPTION_RETURN_ON_ERROR = 0x04; + const uint NSLINKMODULE_OPTION_DONT_CALL_MOD_INIT_ROUTINES = 0x08; + const uint NSLINKMODULE_OPTION_TRAILING_PHYS_NAME = 0x10; + DYLD_BOOL NSUnLinkModule(NSModule module_, uint options); + + void NSLinkEditError(NSLinkEditErrors *c, int *errorNumber, char **fileName, char **errorString); + + DYLD_BOOL NSIsSymbolNameDefined(char *symbolName); + DYLD_BOOL NSIsSymbolNameDefinedInImage(mach_header *image, char *symbolName); + NSSymbol NSLookupAndBindSymbol(char *symbolName); + NSSymbol NSLookupSymbolInModule(NSModule module_, char* symbolName); + NSSymbol NSLookupSymbolInImage(mach_header *image, char *symbolName, uint options); + const uint NSLOOKUPSYMBOLINIMAGE_OPTION_BIND = 0x0; + const uint NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW = 0x1; + const uint NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY = 0x2; + const uint NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR = 0x4; + + void* NSAddressOfSymbol(NSSymbol symbol); + char* NSNameOfSymbol(NSSymbol symbol); + } + + + class FunctionLoader + { + /*************************************************************** + + ***************************************************************/ + + protected struct Bind + { + void** fnc; + char[] name; + } + + /*************************************************************** + + ***************************************************************/ + + private static NSModule open(char* filename) + { + NSModule mod = null; + NSObjectFileImage fileImage = null; + debug printf("Trying to load: %s\n", filename); + + NSObjectFileImageReturnCode returnCode = + NSCreateObjectFileImageFromFile(filename, &fileImage); + if(returnCode == NSObjectFileImageSuccess) + { + mod = NSLinkModule(fileImage,filename, + NSLINKMODULE_OPTION_RETURN_ON_ERROR | + NSLINKMODULE_OPTION_PRIVATE | + NSLINKMODULE_OPTION_BINDNOW); + NSDestroyObjectFileImage(fileImage); + } + else if(returnCode == NSObjectFileImageInappropriateFile) + { + NSDestroyObjectFileImage(fileImage); + /* Could be a dynamic library rather than a bundle */ + mod = cast(NSModule) NSAddImage(filename, + NSADDIMAGE_OPTION_RETURN_ON_ERROR); + } + else + { + debug printf("FileImage Failed: %d\n", returnCode); + } + return mod; + } + + private static void* symbol(NSModule mod, char* name) + { + NSSymbol symbol = null; + uint magic = (* cast(mach_header *) mod).magic; + + if ( (mod == cast(NSModule) -1) && NSIsSymbolNameDefined(name)) + /* Global context, use NSLookupAndBindSymbol */ + symbol = NSLookupAndBindSymbol(name); + else if ( ( magic == MH_MAGIC || magic == MH_CIGAM ) && + NSIsSymbolNameDefinedInImage(cast(mach_header *) mod, name)) + symbol = NSLookupSymbolInImage(cast(mach_header *) mod, name, + NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | + NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); + else + symbol = NSLookupSymbolInModule(mod, name); + + return NSAddressOfSymbol(symbol); + } + + static final void* bind (char[] library, inout Bind[] targets) + { + static char[] errorInfo; + + debug printf("the library is %s\n", ICU.toString(library)); + + void* lib = null; + static char[][] usual_suspects = [ "", "/usr/local/lib/", "/usr/lib/", + /* Fink */ "/sw/lib/", /* DarwinPorts */ "/opt/local/lib/" ]; + foreach (char[] prefix; usual_suspects) + { + lib = cast(void*) open(ICU.toString(prefix ~ library)); + if (lib != null) break; + } + if (lib == null) + { + throw new Exception ("could not open library " ~ library); + } + + // clear the error buffer + // error(); + + foreach (Bind b; targets) + { + // Note: all C functions have a underscore prefix in Mach-O symbols + char[] name = "_" ~ b.name ~ ICUSig; + + *b.fnc = symbol(cast(NSModule) lib, name.ptr); + if (*b.fnc != null) + { + debug printf ("bound '%.*s'\n", name); + } + else + { + // errorInfo = ICU.toArray(error()); + throw new Exception ("required " ~ name ~ " in library " ~ library); + } + } + return lib; + } + + /*************************************************************** + + ***************************************************************/ + + private static bool close(NSModule mod) + { + uint magic = (* cast(mach_header *) mod).magic; + if ( magic == MH_MAGIC || magic == MH_CIGAM ) + { + // Can not unlink dynamic libraries on Darwin + return true; + } + + return (NSUnLinkModule(mod, 0) == TRUE); + } + + static final void unbind (void* library) + { + version (CorrectedTeardown) + { + if (! close(cast(NSModule) library)) + throw new Exception ("close library failed\n"); + } + } + } +} + +/******************************************************************************* + + unknown platform + +*******************************************************************************/ + +else static assert(0); // need an implementation of FunctionLoader for this OS + +