libextractor

GNU libextractor
Log | Files | Refs | Submodules | README | LICENSE

intlemu.c (3128B)


      1 /*
      2  *  libintlemu - A Core Foundation libintl emulator
      3  *  Copyright Copyright (C) 2008  Heikki Lindholm <holin@iki.fi>
      4  *
      5  *  This program is free software; you can redistribute it and/or modify
      6  *  it under the terms of the GNU General Public License as published by
      7  *  the Free Software Foundation; either version 2 of the License, or
      8  *  (at your option) any later version.
      9  */
     10 
     11 #include <CoreFoundation/CoreFoundation.h>
     12 #include <stdlib.h>
     13 #include <pthread.h>
     14 
     15 static pthread_mutex_t intlemu_lock;
     16 static CFMutableDictionaryRef intlemu_dict;
     17 
     18 static void
     19 intlemu_cstring_release (CFAllocatorRef allocator, const void *value)
     20 {
     21   free ((void *) value);
     22 }
     23 
     24 
     25 void __attribute__ ((constructor))
     26 intlemu_init_ ()
     27 {
     28   CFDictionaryValueCallBacks cstring_value_callbacks = {
     29     0,   /* version */
     30     NULL,   /* retain callback */
     31     &intlemu_cstring_release,   /* release callback */
     32     NULL,   /* copy description */
     33     NULL   /* equal */
     34   };
     35   if (pthread_mutex_init (&intlemu_lock, NULL) != 0)
     36     abort ();
     37 
     38   intlemu_dict = CFDictionaryCreateMutable (
     39     kCFAllocatorDefault,
     40     0,
     41     &kCFCopyStringDictionaryKeyCallBacks,
     42     &cstring_value_callbacks);
     43   if (intlemu_dict == NULL)
     44     abort ();
     45 }
     46 
     47 
     48 void __attribute__ ((destructor))
     49 intlemu_fini_ ()
     50 {
     51   if (intlemu_dict)
     52     CFRelease (intlemu_dict);
     53 
     54   pthread_mutex_destroy (&intlemu_lock);
     55 }
     56 
     57 
     58 char *
     59 intlemu_bgettext (CFBundleRef bundle, const char *msgid)
     60 {
     61   CFStringRef key;
     62   const char *value;
     63   CFStringRef s;
     64   CFRange r;
     65   CFIndex len;
     66   CFIndex clen;
     67   char *buf;
     68 
     69   if (msgid == NULL)
     70     return NULL;
     71   if (bundle == NULL)
     72     return msgid;
     73 
     74   key = CFStringCreateWithBytes (
     75     kCFAllocatorDefault,
     76     (const UInt8 *) msgid,
     77     (CFIndex) strlen (msgid),
     78     kCFStringEncodingUTF8,
     79     false);
     80 
     81   if (pthread_mutex_lock (&intlemu_lock) != 0)
     82     abort ();
     83   value = (char *) CFDictionaryGetValue (intlemu_dict, key);
     84   if (pthread_mutex_unlock (&intlemu_lock) != 0)
     85     abort ();
     86   if (value != NULL)
     87   {
     88     CFRelease (key);
     89     return (char *) value;
     90   }
     91 
     92   /* no cached translaation, so, find one from the bundle */
     93   s = CFBundleCopyLocalizedString (
     94     bundle,
     95     key,
     96     NULL,
     97     NULL);
     98   if (s == key)
     99   {
    100     CFRelease (key);
    101     return (char *) msgid;
    102   }
    103   /* get the length in bytes */
    104   r.location = 0;
    105   r.length = CFStringGetLength (s);
    106   len = 0;
    107   clen = CFStringGetBytes (
    108     s,
    109     r,
    110     kCFStringEncodingUTF8,
    111     0,
    112     false,
    113     NULL,
    114     0,
    115     &len);
    116   buf = NULL;
    117   if (clen == r.length)
    118   {
    119     buf = malloc (len + 1);
    120   }
    121 
    122   if (buf == NULL)
    123   {
    124     CFRelease (s);
    125     CFRelease (key);
    126     return (char *) msgid;
    127   }
    128 
    129   clen = CFStringGetBytes (
    130     s,
    131     r,
    132     kCFStringEncodingUTF8,
    133     0,
    134     false,
    135     (UInt8 *) buf,
    136     len,
    137     &len);
    138   buf[len] = '\0';
    139   if (clen == r.length)
    140   {
    141     if (pthread_mutex_lock (&intlemu_lock) != 0)
    142       abort ();
    143     CFDictionaryAddValue (intlemu_dict, key, buf);
    144     if (pthread_mutex_unlock (&intlemu_lock) != 0)
    145       abort ();
    146     value = buf;
    147   }
    148   else
    149   {
    150     free (buf);
    151     value = msgid;
    152   }
    153 
    154   CFRelease (s);
    155 
    156   CFRelease (key);
    157 
    158   return (char *) value;
    159 }