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 @author Kris, John Reimer 00035 00036 *******************************************************************************/ 00037 00038 module mango.icu.ICU; 00039 00040 private import std.string; 00041 00042 /******************************************************************************* 00043 00044 *******************************************************************************/ 00045 00046 private static extern (C) uint strlen (char *s); 00047 private static extern (C) uint wcslen (wchar *s); 00048 00049 /******************************************************************************* 00050 00051 Some low-level routines to help bind the ICU C-API to D. 00052 00053 *******************************************************************************/ 00054 00055 protected class ICU 00056 { 00057 /*********************************************************************** 00058 00059 Use this for the primary argument-type to most ICU functions 00060 00061 ***********************************************************************/ 00062 00063 protected typedef void* Handle; 00064 00065 /*********************************************************************** 00066 00067 The library names to load within the target environment 00068 00069 ***********************************************************************/ 00070 00071 version(Win32) 00072 { 00073 protected static char[] icuuc = "icuuc30.dll"; 00074 protected static char[] icuin = "icuin30.dll"; 00075 } 00076 version(linux) 00077 { 00078 protected static char[] icuuc = "libicuuc.so.30"; 00079 protected static char[] icuin = "libicui18n.so.30"; 00080 } 00081 00082 /*********************************************************************** 00083 00084 The binary form of a version on ICU APIs is an array of 00085 four bytes 00086 00087 ***********************************************************************/ 00088 00089 public struct Version 00090 { 00091 ubyte[4] info; 00092 } 00093 00094 /*********************************************************************** 00095 00096 ICU error codes (the ones which are referenced) 00097 00098 ***********************************************************************/ 00099 00100 protected enum Error:int 00101 { 00102 OK, 00103 BufferOverflow=15 00104 } 00105 00106 /*********************************************************************** 00107 00108 ***********************************************************************/ 00109 00110 protected static final bool isError (Error e) 00111 { 00112 return e > 0; 00113 } 00114 00115 /*********************************************************************** 00116 00117 ***********************************************************************/ 00118 00119 protected static final void exception (char[] msg) 00120 { 00121 throw new ICUException (msg); 00122 } 00123 00124 /*********************************************************************** 00125 00126 ***********************************************************************/ 00127 00128 protected static final void testError (Error e, char[] msg) 00129 { 00130 if (e > 0) 00131 exception (msg); 00132 } 00133 00134 /*********************************************************************** 00135 00136 ***********************************************************************/ 00137 00138 protected static final char* toString (char[] string) 00139 { 00140 static char[] empty = ""; 00141 00142 if (! string.length) 00143 return ((cast(char*) string) ? empty : cast(char*) null); 00144 00145 if (* (&string[0] + string.length)) 00146 { 00147 // Need to make a copy 00148 char[] copy = new char [string.length + 1]; 00149 copy [0..string.length] = string; 00150 copy [string.length] = 0; 00151 string = copy; 00152 } 00153 return string; 00154 } 00155 00156 /*********************************************************************** 00157 00158 ***********************************************************************/ 00159 00160 protected static final wchar* toString (wchar[] string) 00161 { 00162 static wchar[] empty = ""; 00163 00164 if (! string.length) 00165 return ((cast(wchar*) string) ? empty : cast(wchar*) null); 00166 00167 if (* (&string[0] + string.length)) 00168 { 00169 // Need to make a copy 00170 wchar[] copy = new wchar [string.length + 1]; 00171 copy [0..string.length] = string; 00172 copy [string.length] = 0; 00173 string = copy; 00174 } 00175 return string; 00176 } 00177 00178 /*********************************************************************** 00179 00180 ***********************************************************************/ 00181 00182 protected static final uint length (char* s) 00183 { 00184 return strlen (s); 00185 } 00186 00187 /*********************************************************************** 00188 00189 ***********************************************************************/ 00190 00191 protected static final uint length (wchar* s) 00192 { 00193 return wcslen (s); 00194 } 00195 00196 /*********************************************************************** 00197 00198 ***********************************************************************/ 00199 00200 protected static final char[] toArray (char* s) 00201 { 00202 if (s) 00203 return s[0..strlen (s)]; 00204 return null; 00205 } 00206 00207 /*********************************************************************** 00208 00209 ***********************************************************************/ 00210 00211 protected static final wchar[] toArray (wchar* s) 00212 { 00213 if (s) 00214 return s[0..wcslen (s)]; 00215 return null; 00216 } 00217 } 00218 00219 00220 /******************************************************************************* 00221 00222 *******************************************************************************/ 00223 00224 class ICUException : Exception 00225 { 00226 /*********************************************************************** 00227 00228 Construct exception with the provided text string 00229 00230 ***********************************************************************/ 00231 00232 this (char[] msg) 00233 { 00234 super (msg); 00235 } 00236 } 00237 00238 00239 /******************************************************************************* 00240 00241 Function address loader for Win32 00242 00243 *******************************************************************************/ 00244 00245 version (Win32) 00246 { 00247 /*********************************************************************** 00248 00249 ***********************************************************************/ 00250 00251 class FunctionLoader 00252 { 00253 private import std.c.windows.windows; 00254 00255 /*************************************************************** 00256 00257 ***************************************************************/ 00258 00259 protected struct Bind 00260 { 00261 void** fnc; 00262 char[] name; 00263 } 00264 00265 /*************************************************************** 00266 00267 ***************************************************************/ 00268 00269 static final void* bind (char[] library, inout Bind[] targets) 00270 { 00271 static char[] vrsn = "_3_0\0"; 00272 00273 HANDLE lib = LoadLibraryA (ICU.toString(library)); 00274 00275 foreach (Bind b; targets) 00276 { 00277 char[] name = b.name ~ vrsn; 00278 *b.fnc = GetProcAddress (lib, name); 00279 if (*b.fnc) 00280 {}// printf ("bound '%.*s'\n", name); 00281 else 00282 throw new Exception ("required " ~ name ~ " in library " ~ library); 00283 } 00284 return lib; 00285 } 00286 00287 /*************************************************************** 00288 00289 ***************************************************************/ 00290 00291 static final void unbind (void* library) 00292 { 00293 version (CorrectedTeardown) 00294 FreeLibrary (cast(HANDLE) library); 00295 } 00296 } 00297 } 00298 00299 00300 /******************************************************************************* 00301 00302 2004-11-26: Added Linux shared library support -- John Reimer 00303 00304 *******************************************************************************/ 00305 00306 version (linux) 00307 { 00308 // from include/bits/dlfcn.h on Linux 00309 const int RTLD_LAZY = 0x00001; // Lazy function call binding 00310 const int RTLD_NOW = 0x00002; // Immediate function call binding 00311 const int RTLD_NOLOAD = 0x00004; // no object load 00312 const int RTLD_DEEPBIND = 0x00008; 00313 const int RTLD_GLOBAL = 0x00100; // make object available to whole program 00314 00315 extern(C) 00316 { 00317 void* dlopen(char* filename, int flag); 00318 char* dlerror(); 00319 void* dlsym(void* handle, char* symbol); 00320 int dlclose(void* handle); 00321 } 00322 00323 class FunctionLoader 00324 { 00325 /*************************************************************** 00326 00327 ***************************************************************/ 00328 00329 protected struct Bind 00330 { 00331 void** fnc; 00332 char[] name; 00333 } 00334 00335 /*************************************************************** 00336 00337 ***************************************************************/ 00338 00339 static final void* bind (char[] library, inout Bind[] targets) 00340 { 00341 static char[] vrsn = "_3_0\0"; 00342 static char[] errorInfo; 00343 // printf("the library is %s\n", ICU.toString(library)); 00344 void* lib = dlopen(ICU.toString(library), RTLD_NOW); 00345 00346 // clear the error buffer 00347 dlerror(); 00348 00349 foreach (Bind b; targets) 00350 { 00351 char[] name = b.name ~ vrsn; 00352 00353 *b.fnc = dlsym (lib, name); 00354 if (*b.fnc) 00355 {}// printf ("bound '%.*s'\n", name); 00356 else { 00357 // errorInfo = ICU.toArray(dlerror()); 00358 // printf("%s", dlerror()); 00359 throw new Exception ("required " ~ name ~ " in library " ~ library); 00360 } 00361 } 00362 return lib; 00363 } 00364 00365 /*************************************************************** 00366 00367 ***************************************************************/ 00368 00369 static final void unbind (void* library) 00370 { 00371 version (CorrectedTeardown) 00372 { 00373 if (! dlclose (library)) 00374 throw new Exception ("close library failed\n"); 00375 } 00376 } 00377 } 00378 }