"Fossies" - the Fresh Open Source Software Archive

Member "xpdf-4.02/xpdf/UnicodeMap.cc" (25 Sep 2019, 6033 Bytes) of package /linux/misc/xpdf-4.02.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "UnicodeMap.cc" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 3.04_vs_4.00.

    1 //========================================================================
    2 //
    3 // UnicodeMap.cc
    4 //
    5 // Copyright 2001-2003 Glyph & Cog, LLC
    6 //
    7 //========================================================================
    8 
    9 #include <aconf.h>
   10 
   11 #ifdef USE_GCC_PRAGMAS
   12 #pragma implementation
   13 #endif
   14 
   15 #include <stdio.h>
   16 #include <string.h>
   17 #include "gmem.h"
   18 #include "gmempp.h"
   19 #include "gfile.h"
   20 #include "GString.h"
   21 #include "GList.h"
   22 #include "Error.h"
   23 #include "GlobalParams.h"
   24 #include "UnicodeMap.h"
   25 
   26 //------------------------------------------------------------------------
   27 
   28 #define maxExtCode 16
   29 
   30 struct UnicodeMapExt {
   31   Unicode u;            // Unicode char
   32   char code[maxExtCode];
   33   Guint nBytes;
   34 };
   35 
   36 //------------------------------------------------------------------------
   37 
   38 UnicodeMap *UnicodeMap::parse(GString *encodingNameA) {
   39   FILE *f;
   40   UnicodeMap *map;
   41   UnicodeMapRange *range;
   42   UnicodeMapExt *eMap;
   43   int size, eMapsSize;
   44   char buf[256];
   45   int line, nBytes, i, x;
   46   char *tok1, *tok2, *tok3;
   47 
   48   if (!(f = globalParams->getUnicodeMapFile(encodingNameA))) {
   49     error(errSyntaxError, -1,
   50       "Couldn't find unicodeMap file for the '{0:t}' encoding",
   51       encodingNameA);
   52     return NULL;
   53   }
   54 
   55   map = new UnicodeMap(encodingNameA->copy());
   56 
   57   size = 8;
   58   map->ranges = (UnicodeMapRange *)gmallocn(size, sizeof(UnicodeMapRange));
   59   eMapsSize = 0;
   60 
   61   line = 1;
   62   while (getLine(buf, sizeof(buf), f)) {
   63     if ((tok1 = strtok(buf, " \t\r\n")) &&
   64     (tok2 = strtok(NULL, " \t\r\n"))) {
   65       if (!(tok3 = strtok(NULL, " \t\r\n"))) {
   66     tok3 = tok2;
   67     tok2 = tok1;
   68       }
   69       nBytes = (int)strlen(tok3) / 2;
   70       if (nBytes <= 4) {
   71     if (map->len == size) {
   72       size *= 2;
   73       map->ranges = (UnicodeMapRange *)
   74         greallocn(map->ranges, size, sizeof(UnicodeMapRange));
   75     }
   76     range = &map->ranges[map->len];
   77     sscanf(tok1, "%x", &range->start);
   78     sscanf(tok2, "%x", &range->end);
   79     sscanf(tok3, "%x", &range->code);
   80     range->nBytes = nBytes;
   81     ++map->len;
   82       } else if (tok2 == tok1) {
   83     if (map->eMapsLen == eMapsSize) {
   84       eMapsSize += 16;
   85       map->eMaps = (UnicodeMapExt *)
   86         greallocn(map->eMaps, eMapsSize, sizeof(UnicodeMapExt));
   87     }
   88     eMap = &map->eMaps[map->eMapsLen];
   89     sscanf(tok1, "%x", &eMap->u);
   90     for (i = 0; i < nBytes; ++i) {
   91       sscanf(tok3 + i*2, "%2x", &x);
   92       eMap->code[i] = (char)x;
   93     }
   94     eMap->nBytes = nBytes;
   95     ++map->eMapsLen;
   96       } else {
   97     error(errSyntaxError, -1,
   98           "Bad line ({0:d}) in unicodeMap file for the '{1:t}' encoding",
   99           line, encodingNameA);
  100       }
  101     } else {
  102       error(errSyntaxError, -1,
  103         "Bad line ({0:d}) in unicodeMap file for the '{1:t}' encoding",
  104         line, encodingNameA);
  105     }
  106     ++line;
  107   }
  108 
  109   fclose(f);
  110 
  111   return map;
  112 }
  113 
  114 UnicodeMap::UnicodeMap(GString *encodingNameA) {
  115   encodingName = encodingNameA;
  116   unicodeOut = gFalse;
  117   kind = unicodeMapUser;
  118   ranges = NULL;
  119   len = 0;
  120   eMaps = NULL;
  121   eMapsLen = 0;
  122   refCnt = 1;
  123 }
  124 
  125 UnicodeMap::UnicodeMap(const char *encodingNameA, GBool unicodeOutA,
  126                UnicodeMapRange *rangesA, int lenA) {
  127   encodingName = new GString(encodingNameA);
  128   unicodeOut = unicodeOutA;
  129   kind = unicodeMapResident;
  130   ranges = rangesA;
  131   len = lenA;
  132   eMaps = NULL;
  133   eMapsLen = 0;
  134   refCnt = 1;
  135 }
  136 
  137 UnicodeMap::UnicodeMap(const char *encodingNameA, GBool unicodeOutA,
  138                UnicodeMapFunc funcA) {
  139   encodingName = new GString(encodingNameA);
  140   unicodeOut = unicodeOutA;
  141   kind = unicodeMapFunc;
  142   func = funcA;
  143   eMaps = NULL;
  144   eMapsLen = 0;
  145   refCnt = 1;
  146 }
  147 
  148 UnicodeMap::~UnicodeMap() {
  149   delete encodingName;
  150   if (kind == unicodeMapUser && ranges) {
  151     gfree(ranges);
  152   }
  153   if (eMaps) {
  154     gfree(eMaps);
  155   }
  156 }
  157 
  158 void UnicodeMap::incRefCnt() {
  159 #if MULTITHREADED
  160   gAtomicIncrement(&refCnt);
  161 #else
  162   ++refCnt;
  163 #endif
  164 }
  165 
  166 void UnicodeMap::decRefCnt() {
  167   GBool done;
  168 
  169 #if MULTITHREADED
  170   done = gAtomicDecrement(&refCnt) == 0;
  171 #else
  172   done = --refCnt == 0;
  173 #endif
  174   if (done) {
  175     delete this;
  176   }
  177 }
  178 
  179 GBool UnicodeMap::match(GString *encodingNameA) {
  180   return !encodingName->cmp(encodingNameA);
  181 }
  182 
  183 int UnicodeMap::mapUnicode(Unicode u, char *buf, int bufSize) {
  184   int a, b, m, n, i, j;
  185   Guint code;
  186 
  187   if (kind == unicodeMapFunc) {
  188     return (*func)(u, buf, bufSize);
  189   }
  190 
  191   a = 0;
  192   b = len;
  193   if (u >= ranges[a].start) {
  194     // invariant: ranges[a].start <= u < ranges[b].start
  195     while (b - a > 1) {
  196       m = (a + b) / 2;
  197       if (u >= ranges[m].start) {
  198     a = m;
  199       } else if (u < ranges[m].start) {
  200     b = m;
  201       }
  202     }
  203     if (u <= ranges[a].end) {
  204       n = ranges[a].nBytes;
  205       if (n > bufSize) {
  206     return 0;
  207       }
  208       code = ranges[a].code + (u - ranges[a].start);
  209       for (i = n - 1; i >= 0; --i) {
  210     buf[i] = (char)(code & 0xff);
  211     code >>= 8;
  212       }
  213       return n;
  214     }
  215   }
  216 
  217   for (i = 0; i < eMapsLen; ++i) {
  218     if (eMaps[i].u == u) {
  219       n = eMaps[i].nBytes;
  220       for (j = 0; j < n; ++j) {
  221     buf[j] = eMaps[i].code[j];
  222       }
  223       return n;
  224     }
  225   }
  226 
  227   return 0;
  228 }
  229 
  230 //------------------------------------------------------------------------
  231 
  232 UnicodeMapCache::UnicodeMapCache() {
  233   int i;
  234 
  235   for (i = 0; i < unicodeMapCacheSize; ++i) {
  236     cache[i] = NULL;
  237   }
  238 }
  239 
  240 UnicodeMapCache::~UnicodeMapCache() {
  241   int i;
  242 
  243   for (i = 0; i < unicodeMapCacheSize; ++i) {
  244     if (cache[i]) {
  245       cache[i]->decRefCnt();
  246     }
  247   }
  248 }
  249 
  250 UnicodeMap *UnicodeMapCache::getUnicodeMap(GString *encodingName) {
  251   UnicodeMap *map;
  252   int i, j;
  253 
  254   if (cache[0] && cache[0]->match(encodingName)) {
  255     cache[0]->incRefCnt();
  256     return cache[0];
  257   }
  258   for (i = 1; i < unicodeMapCacheSize; ++i) {
  259     if (cache[i] && cache[i]->match(encodingName)) {
  260       map = cache[i];
  261       for (j = i; j >= 1; --j) {
  262     cache[j] = cache[j - 1];
  263       }
  264       cache[0] = map;
  265       map->incRefCnt();
  266       return map;
  267     }
  268   }
  269   if ((map = UnicodeMap::parse(encodingName))) {
  270     if (cache[unicodeMapCacheSize - 1]) {
  271       cache[unicodeMapCacheSize - 1]->decRefCnt();
  272     }
  273     for (j = unicodeMapCacheSize - 1; j >= 1; --j) {
  274       cache[j] = cache[j - 1];
  275     }
  276     cache[0] = map;
  277     map->incRefCnt();
  278     return map;
  279   }
  280   return NULL;
  281 }