view com.ibm.icu/src/com/ibm/icu/mangoicu/ICU.d @ 120:536e43f63c81

Comprehensive update for Win32/Linux32 dmd-2.053/dmd-1.068+Tango-r5661 ===D2=== * added [Try]Immutable/Const/Shared templates to work with differenses in D1/D2 instead of version statements used these templates to work with strict type storage rules of dmd-2.053 * com.ibm.icu now also compilable with D2, but not tested yet * small fixes Snippet288 - shared data is in TLS ===Phobos=== * fixed critical bugs in Phobos implemention completely incorrect segfault prone fromStringz (Linux's port ruthless killer) terrible, incorrect StringBuffer realization (StyledText killer) * fixed small bugs as well Snippet72 - misprint in the snippet * implemented missed functionality for Phobos ByteArrayOutputStream implemented (image loading available) formatting correctly works for all DWT's cases As a result, folowing snippets now works with Phobos (Snippet### - what is fixed): Snippet24, 42, 111, 115, 130, 235, 276 - bad string formatting Snippet48, 282 - crash on image loading Snippet163, 189, 211, 213, 217, 218, 222 - crash on copy/cut in StyledText Snippet244 - hang-up ===Tango=== * few changes for the latest Tango trunc-r5661 * few small performance improvments ===General=== * implMissing-s for only one version changed to implMissingInTango/InPhobos * incorrect calls to Format in toString-s fixed * fixed loading \uXXXX characters in ResourceBundle * added good UTF-8 support for StyledText, TextLayout (Win32) and friends UTF functions revised and tested. It is now in java.nonstandard.*Utf modules StyledText and TextLayout (Win32) modules revised for UTF-8 support * removed small diferences in most identical files in *.swt.* folders *.swt.internal.image, *.swt.events and *.swt.custom are identical in Win32/Linux32 now 179 of 576 (~31%) files in *.swt.* folders are fully identical * Win32: snippets now have right subsystem, pretty icons and native system style controls * small fixes in snippets Snippet44 - it's not Snippet44 Snippet212 - functions work with different images and offsets arrays Win32: Snippet282 - crash on close if the button has an image Snippet293 - setGrayed is commented and others Win32: As a result, folowing snippets now works Snippet68 - color doesn't change Snippet163, 189, 211, 213, 217, 218, 222 - UTF-8 issues (see above) Snippet193 - no tabel headers
author Denis Shelomovskij <verylonglogin.reg@gmail.com>
date Sat, 09 Jul 2011 15:50:20 +0300
parents ebefa5c2eab4
children
line wrap: on
line source

/*******************************************************************************

        @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 com.ibm.icu.mangoicu.ICU;

import java.lang.util;
/*******************************************************************************

        Library version identifiers

*******************************************************************************/

version (ICU30)
        {
        private static const char[] ICULib = "30";
        private static const char[] ICUSig = "_3_0\0";
        }
version (ICU32)
        {
        private static const char[] ICULib = "32";
        private static const char[] ICUSig = "_3_2\0";
        }
version (ICU34)
        {
        private static const char[] ICULib = "34";
        private static const char[] ICUSig = "_3_4\0";
        }
version (ICU36)
        {
        private static const char[] ICULib = "36";
        private static const char[] ICUSig = "_3_6\0";
        }
else
        {
        private static const char[] ICULib = "38";
        private static const 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.

*******************************************************************************/

package static String genICUNative(String t, funcs...)() {
    static assert((t == "in" || t == "uc") && !(funcs.length & 1));
    String gsh = " ", sh = "";
    version(D_Version2) {
        gsh = " __gshared ";
        sh = "shared ";
    }
    String res = "private:
static"~gsh~"void* library;
static"~gsh~"extern(C) {\n";
    foreach(int i, name; funcs) static if(i & 1)
        res ~= funcs[i-1] ~ " " ~ name ~ ";\n";
    res ~= "}
static"~gsh~"FunctionLoader.Bind[] targets = [\n";
    foreach(int i, name; funcs) static if(i & 1)
        res ~= "{cast(void**) &" ~ name ~ ", `" ~ name ~ "`},\n";
    res ~= "];
"~sh~"static this() {
    library = FunctionLoader.bind(ICU.icu" ~ t ~ ", targets);
}
"~sh~"static ~this() {
    FunctionLoader.unbind(library);
}";
    return res;
}

protected class ICU
{
    
        /***********************************************************************

                The library names to load within the target environment

        ***********************************************************************/

        version (Win32)
                {
                package static char[] icuuc = "icuuc"~ICULib~".dll";
                package static char[] icuin = "icuin"~ICULib~".dll";
                }
        else
        version (linux)
                {
                package static char[] icuuc = "libicuuc.so."~ICULib;
                package static char[] icuin = "libicui18n.so."~ICULib;
                }
        else
        version (darwin)
                {
                package static char[] icuuc = "libicuuc.dylib."~ICULib;
                package 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)

        ***********************************************************************/

        package enum  UErrorCode:int
                        {
                        OK,
                        BufferOverflow=15
                        }

        /***********************************************************************

        ***********************************************************************/

        package static final bool isError (UErrorCode e)
        {
                return e > 0;
        }

        /***********************************************************************

        ***********************************************************************/

        package static final void exception (in char[] msg)
        {
                throw new ICUException (cast(String)msg);
        }

        /***********************************************************************

        ***********************************************************************/

        package static final void testError (UErrorCode e, in char[] msg)
        {
                if (e > 0)
                    exception (msg);
        }

        /***********************************************************************

        ***********************************************************************/

        package static final char* toString (in 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;
                   return copy.ptr;
                   }
                //return cast(char*)string.ptr;
        }

        /***********************************************************************

        ***********************************************************************/

        package static final wchar* toString (in 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;
                   return copy.ptr;
                   }
                //return cast(wchar*)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 (String msg)
        {
                super (msg);
        }
}

/*******************************************************************************

*******************************************************************************/

typedef void* UParseError;


/*******************************************************************************

        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);

        /***********************************************************************

        ***********************************************************************/

        package static class FunctionLoader
        {
                /***************************************************************

                ***************************************************************/

                protected struct Bind
                {
                        void**  fnc;
                        const String  name;
                }

                /***************************************************************

                ***************************************************************/

                static final void* bind (char[] library, ref Bind[] targets)
                {
                        HANDLE lib = LoadLibraryA (ICU.toString(library));

                        foreach (Bind b; targets)
                                {
                                auto name = b.name ~ ICUSig;
                                *b.fnc = GetProcAddress (lib, cast(char*)name.ptr);
                                if (*b.fnc)
                                   {}// printf ("bound '%.*s'\n", name);
                                else
                                   throw new Exception ( cast(String)("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;
                        const String  name;
                }

                /***************************************************************

                ***************************************************************/

                static final void* bind (char[] library, ref 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 = cast(char[])(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 (cast(String)("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;
                        const String  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, ref 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