root/middleware-offline/trunk/_src/eidmw/pteid-poppler/poppler/CharCodeToUnicode.cc @ 226

Revision 226, 17.9 KB (checked in by vsilva, 8 years ago)

Improve PDF native Signature

Line 
1//========================================================================
2//
3// CharCodeToUnicode.cc
4//
5// Copyright 2001-2003 Glyph & Cog, LLC
6//
7//========================================================================
8
9//========================================================================
10//
11// Modified under the Poppler project - http://poppler.freedesktop.org
12//
13// All changes made under the Poppler project to this file are licensed
14// under GPL version 2 or later
15//
16// Copyright (C) 2006, 2008-2010, 2012 Albert Astals Cid <aacid@kde.org>
17// Copyright (C) 2007 Julien Rebetez <julienr@svn.gnome.org>
18// Copyright (C) 2007 Koji Otani <sho@bbr.jp>
19// Copyright (C) 2008 Michael Vrable <mvrable@cs.ucsd.edu>
20// Copyright (C) 2008 Vasile Gaburici <gaburici@cs.umd.edu>
21// Copyright (C) 2010 William Bader <williambader@hotmail.com>
22// Copyright (C) 2010 Jakub Wilk <ubanus@users.sf.net>
23// Copyright (C) 2012 Thomas Freitag <Thomas.Freitag@alfa.de>
24//
25// To see a description of the changes please see the Changelog file that
26// came with your tarball or type make ChangeLog if you are building from git
27//
28//========================================================================
29
30#include <config.h>
31
32#ifdef USE_GCC_PRAGMAS
33#pragma implementation
34#endif
35
36#include <stdio.h>
37#include <string.h>
38#include "goo/gmem.h"
39#include "goo/gfile.h"
40#include "goo/GooLikely.h"
41#include "goo/GooString.h"
42#include "Error.h"
43#include "GlobalParams.h"
44#include "PSTokenizer.h"
45#include "CharCodeToUnicode.h"
46
47//------------------------------------------------------------------------
48
49struct CharCodeToUnicodeString {
50  CharCode c;
51  Unicode *u;
52  int len;
53};
54
55//------------------------------------------------------------------------
56
57static int getCharFromString(void *data) {
58  char *p;
59  int c;
60
61  p = *(char **)data;
62  if (*p) {
63    c = *p++;
64    *(char **)data = p;
65  } else {
66    c = EOF;
67  }
68  return c;
69}
70
71static int getCharFromFile(void *data) {
72  return fgetc((FILE *)data);
73}
74
75//------------------------------------------------------------------------
76
77static int hexCharVals[256] = {
78  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x
79  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 1x
80  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 2x
81   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1, // 3x
82  -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 4x
83  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 5x
84  -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 6x
85  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 7x
86  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 8x
87  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 9x
88  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // Ax
89  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // Bx
90  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // Cx
91  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // Dx
92  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // Ex
93  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1  // Fx
94};
95
96// Parse a <len>-byte hex string <s> into *<val>.  Returns false on
97// error.
98static GBool parseHex(char *s, int len, Guint *val) {
99  int i, x;
100
101  *val = 0;
102  for (i = 0; i < len; ++i) {
103    x = hexCharVals[s[i] & 0xff];
104    if (x < 0) {
105      return gFalse;
106    }
107    *val = (*val << 4) + x;
108  }
109  return gTrue;
110}
111
112//------------------------------------------------------------------------
113
114CharCodeToUnicode *CharCodeToUnicode::makeIdentityMapping() {
115  CharCodeToUnicode *ctu = new CharCodeToUnicode();
116  ctu->isIdentity = gTrue;
117  ctu->mapLen = 1;
118  ctu->map = (Unicode *)gmallocn(ctu->mapLen, sizeof(Unicode));
119  return ctu;
120}
121
122CharCodeToUnicode *CharCodeToUnicode::parseCIDToUnicode(GooString *fileName,
123                                                        GooString *collection) {
124  FILE *f;
125  Unicode *mapA;
126  CharCode size, mapLenA;
127  char buf[64];
128  Unicode u;
129  CharCodeToUnicode *ctu;
130
131  if (!(f = openFile(fileName->getCString(), "r"))) {
132    error(errIO, -1, "Couldn't open cidToUnicode file '{0:t}'",
133          fileName);
134    return NULL;
135  }
136
137  size = 32768;
138  mapA = (Unicode *)gmallocn(size, sizeof(Unicode));
139  mapLenA = 0;
140
141  while (getLine(buf, sizeof(buf), f)) {
142    if (mapLenA == size) {
143      size *= 2;
144      mapA = (Unicode *)greallocn(mapA, size, sizeof(Unicode));
145    }
146    if (sscanf(buf, "%x", &u) == 1) {
147      mapA[mapLenA] = u;
148    } else {
149      error(errSyntaxWarning, -1, "Bad line ({0:d}) in cidToUnicode file '{1:t}'",
150            (int)(mapLenA + 1), fileName);
151      mapA[mapLenA] = 0;
152    }
153    ++mapLenA;
154  }
155  fclose(f);
156
157  ctu = new CharCodeToUnicode(collection->copy(), mapA, mapLenA, gTrue,
158                              NULL, 0, 0);
159  gfree(mapA);
160  return ctu;
161}
162
163CharCodeToUnicode *CharCodeToUnicode::parseUnicodeToUnicode(
164                                                    GooString *fileName) {
165  FILE *f;
166  Unicode *mapA;
167  CharCodeToUnicodeString *sMapA;
168  CharCode size, oldSize, len, sMapSizeA, sMapLenA;
169  char buf[256];
170  char *tok;
171  Unicode u0;
172  int uBufSize = 8;
173  Unicode *uBuf = (Unicode *)gmallocn(uBufSize, sizeof(Unicode));
174  CharCodeToUnicode *ctu;
175  int line, n, i;
176  char *tokptr;
177
178  if (!(f = openFile(fileName->getCString(), "r"))) {
179    gfree(uBuf);
180    error(errIO, -1, "Couldn't open unicodeToUnicode file '{0:t}'",
181          fileName);
182    return NULL;
183  }
184
185  size = 4096;
186  mapA = (Unicode *)gmallocn(size, sizeof(Unicode));
187  memset(mapA, 0, size * sizeof(Unicode));
188  len = 0;
189  sMapA = NULL;
190  sMapSizeA = sMapLenA = 0;
191
192  line = 0;
193  while (getLine(buf, sizeof(buf), f)) {
194    ++line;
195    if (!(tok = strtok_r(buf, " \t\r\n", &tokptr)) ||
196        !parseHex(tok, strlen(tok), &u0)) {
197      error(errSyntaxWarning, -1, "Bad line ({0:d}) in unicodeToUnicode file '{1:t}'",
198            line, fileName);
199      continue;
200    }
201    n = 0;
202    while ((tok = strtok_r(NULL, " \t\r\n", &tokptr))) {
203      if (n >= uBufSize)
204      {
205        uBufSize += 8;
206        uBuf = (Unicode *)greallocn(uBuf, uBufSize, sizeof(Unicode));
207      }
208      if (!parseHex(tok, strlen(tok), &uBuf[n])) {
209        error(errSyntaxWarning, -1, "Bad line ({0:d}) in unicodeToUnicode file '{1:t}'",
210              line, fileName);
211        break;
212      }
213      ++n;
214    }
215    if (n < 1) {
216      error(errSyntaxWarning, -1, "Bad line ({0:d}) in unicodeToUnicode file '{1:t}'",
217            line, fileName);
218      continue;
219    }
220    if (u0 >= size) {
221      oldSize = size;
222      while (u0 >= size) {
223        size *= 2;
224      }
225      mapA = (Unicode *)greallocn(mapA, size, sizeof(Unicode));
226      memset(mapA + oldSize, 0, (size - oldSize) * sizeof(Unicode));
227    }
228    if (n == 1) {
229      mapA[u0] = uBuf[0];
230    } else {
231      mapA[u0] = 0;
232      if (sMapLenA == sMapSizeA) {
233        sMapSizeA += 16;
234        sMapA = (CharCodeToUnicodeString *)
235                  greallocn(sMapA, sMapSizeA, sizeof(CharCodeToUnicodeString));
236      }
237      sMapA[sMapLenA].c = u0;
238      sMapA[sMapLenA].u = (Unicode*)gmallocn(n, sizeof(Unicode));
239      for (i = 0; i < n; ++i) {
240        sMapA[sMapLenA].u[i] = uBuf[i];
241      }
242      sMapA[sMapLenA].len = n;
243      ++sMapLenA;
244    }
245    if (u0 >= len) {
246      len = u0 + 1;
247    }
248  }
249  fclose(f);
250
251  ctu = new CharCodeToUnicode(fileName->copy(), mapA, len, gTrue,
252                              sMapA, sMapLenA, sMapSizeA);
253  gfree(mapA);
254  gfree(uBuf);
255  return ctu;
256}
257
258CharCodeToUnicode *CharCodeToUnicode::make8BitToUnicode(Unicode *toUnicode) {
259  return new CharCodeToUnicode(NULL, toUnicode, 256, gTrue, NULL, 0, 0);
260}
261
262CharCodeToUnicode *CharCodeToUnicode::parseCMap(GooString *buf, int nBits) {
263  CharCodeToUnicode *ctu;
264  char *p;
265
266  ctu = new CharCodeToUnicode(NULL);
267  p = buf->getCString();
268  ctu->parseCMap1(&getCharFromString, &p, nBits);
269  return ctu;
270}
271
272CharCodeToUnicode *CharCodeToUnicode::parseCMapFromFile(GooString *fileName,
273  int nBits) {
274  CharCodeToUnicode *ctu;
275  FILE *f;
276
277  ctu = new CharCodeToUnicode(NULL);
278  if ((f = globalParams->findToUnicodeFile(fileName))) {
279    ctu->parseCMap1(&getCharFromFile, f, nBits);
280    fclose(f);
281  } else {
282    error(errSyntaxError, -1, "Couldn't find ToUnicode CMap file for '{0:t}'",
283          fileName);
284  }
285  return ctu;
286}
287
288void CharCodeToUnicode::mergeCMap(GooString *buf, int nBits) {
289  char *p;
290
291  p = buf->getCString();
292  parseCMap1(&getCharFromString, &p, nBits);
293}
294
295void CharCodeToUnicode::parseCMap1(int (*getCharFunc)(void *), void *data,
296                                   int nBits) {
297  PSTokenizer *pst;
298  char tok1[256], tok2[256], tok3[256];
299  int n1, n2, n3;
300  CharCode i;
301  CharCode maxCode, code1, code2;
302  GooString *name;
303  FILE *f;
304
305  maxCode = (nBits == 8) ? 0xff : (nBits == 16) ? 0xffff : 0xffffffff;
306  pst = new PSTokenizer(getCharFunc, data);
307  pst->getToken(tok1, sizeof(tok1), &n1);
308  while (pst->getToken(tok2, sizeof(tok2), &n2)) {
309    if (!strcmp(tok2, "usecmap")) {
310      if (tok1[0] == '/') {
311        name = new GooString(tok1 + 1);
312        if ((f = globalParams->findToUnicodeFile(name))) {
313          parseCMap1(&getCharFromFile, f, nBits);
314          fclose(f);
315        } else {
316          error(errSyntaxError, -1, "Couldn't find ToUnicode CMap file for '{0:t}'",
317                name);
318        }
319        delete name;
320      }
321      pst->getToken(tok1, sizeof(tok1), &n1);
322    } else if (!strcmp(tok2, "beginbfchar")) {
323      while (pst->getToken(tok1, sizeof(tok1), &n1)) {
324        if (!strcmp(tok1, "endbfchar")) {
325          break;
326        }
327        if (!pst->getToken(tok2, sizeof(tok2), &n2) ||
328            !strcmp(tok2, "endbfchar")) {
329          error(errSyntaxWarning, -1, "Illegal entry in bfchar block in ToUnicode CMap");
330          break;
331        }
332        if (!(tok1[0] == '<' && tok1[n1 - 1] == '>' &&
333              tok2[0] == '<' && tok2[n2 - 1] == '>')) {
334          error(errSyntaxWarning, -1, "Illegal entry in bfchar block in ToUnicode CMap");
335          continue;
336        }
337        tok1[n1 - 1] = tok2[n2 - 1] = '\0';
338        if (!parseHex(tok1 + 1, n1 - 2, &code1)) {
339          error(errSyntaxWarning, -1, "Illegal entry in bfchar block in ToUnicode CMap");
340          continue;
341        }
342        if (code1 > maxCode) {
343          error(errSyntaxWarning, -1,
344                "Invalid entry in bfchar block in ToUnicode CMap");
345        }
346        addMapping(code1, tok2 + 1, n2 - 2, 0);
347      }
348      pst->getToken(tok1, sizeof(tok1), &n1);
349    } else if (!strcmp(tok2, "beginbfrange")) {
350      while (pst->getToken(tok1, sizeof(tok1), &n1)) {
351        if (!strcmp(tok1, "endbfrange")) {
352          break;
353        }
354        if (!pst->getToken(tok2, sizeof(tok2), &n2) ||
355            !strcmp(tok2, "endbfrange") ||
356            !pst->getToken(tok3, sizeof(tok3), &n3) ||
357            !strcmp(tok3, "endbfrange")) {
358          error(errSyntaxWarning, -1, "Illegal entry in bfrange block in ToUnicode CMap");
359          break;
360        }
361        if (!(tok1[0] == '<' && tok1[n1 - 1] == '>' &&
362              tok2[0] == '<' && tok2[n2 - 1] == '>')) {
363          error(errSyntaxWarning, -1, "Illegal entry in bfrange block in ToUnicode CMap");
364          continue;
365        }
366        tok1[n1 - 1] = tok2[n2 - 1] = '\0';
367        if (!parseHex(tok1 + 1, n1 - 2, &code1) ||
368            !parseHex(tok2 + 1, n2 - 2, &code2)) {
369          error(errSyntaxWarning, -1, "Illegal entry in bfrange block in ToUnicode CMap");
370          continue;
371        }
372        if (code1 > maxCode || code2 > maxCode) {
373          error(errSyntaxWarning, -1,
374                "Invalid entry in bfrange block in ToUnicode CMap");
375          if (code1 > maxCode) {
376            code1 = maxCode;
377          }
378          if (code2 > maxCode) {
379            code2 = maxCode;
380          }
381        }
382        if (!strcmp(tok3, "[")) {
383          i = 0;
384          while (pst->getToken(tok1, sizeof(tok1), &n1) &&
385                 code1 + i <= code2) {
386            if (!strcmp(tok1, "]")) {
387              break;
388            }
389            if (tok1[0] == '<' && tok1[n1 - 1] == '>') {
390              tok1[n1 - 1] = '\0';
391              addMapping(code1 + i, tok1 + 1, n1 - 2, 0);
392            } else {
393              error(errSyntaxWarning, -1, "Illegal entry in bfrange block in ToUnicode CMap");
394            }
395            ++i;
396          }
397        } else if (tok3[0] == '<' && tok3[n3 - 1] == '>') {
398          tok3[n3 - 1] = '\0';
399          for (i = 0; code1 <= code2; ++code1, ++i) {
400            addMapping(code1, tok3 + 1, n3 - 2, i);
401          }
402
403        } else {
404          error(errSyntaxWarning, -1, "Illegal entry in bfrange block in ToUnicode CMap");
405        }
406      }
407      pst->getToken(tok1, sizeof(tok1), &n1);
408    } else {
409      strcpy(tok1, tok2);
410    }
411  }
412  delete pst;
413}
414
415void CharCodeToUnicode::addMapping(CharCode code, char *uStr, int n,
416                                   int offset) {
417  CharCode oldLen, i;
418  Unicode u;
419  int j;
420
421  if (code > 0xffffff) {
422    // This is an arbitrary limit to avoid integer overflow issues.
423    // (I've seen CMaps with mappings for <ffffffff>.)
424    return;
425  }
426  if (code >= mapLen) {
427    oldLen = mapLen;
428    mapLen = mapLen ? 2 * mapLen : 256;
429    if (code >= mapLen) {
430      mapLen = (code + 256) & ~255;
431    }
432    if (unlikely(code >= mapLen)) {
433      error(errSyntaxWarning, -1, "Illegal code value in CharCodeToUnicode::addMapping");
434      return;
435    } else {
436      map = (Unicode *)greallocn(map, mapLen, sizeof(Unicode));
437      for (i = oldLen; i < mapLen; ++i) {
438        map[i] = 0;
439      }
440        }
441  }
442  if (n <= 4) {
443    if (!parseHex(uStr, n, &u)) {
444      error(errSyntaxWarning, -1, "Illegal entry in ToUnicode CMap");
445      return;
446    }
447    map[code] = u + offset;
448  } else {
449    if (sMapLen >= sMapSize) {
450      sMapSize = sMapSize + 16;
451      sMap = (CharCodeToUnicodeString *)
452               greallocn(sMap, sMapSize, sizeof(CharCodeToUnicodeString));
453    }
454    map[code] = 0;
455    sMap[sMapLen].c = code;
456    sMap[sMapLen].len = n / 4;
457    sMap[sMapLen].u = (Unicode*)gmallocn(sMap[sMapLen].len, sizeof(Unicode));
458    for (j = 0; j < sMap[sMapLen].len; ++j) {
459      if (!parseHex(uStr + j*4, 4, &sMap[sMapLen].u[j])) {
460        error(errSyntaxWarning, -1, "Illegal entry in ToUnicode CMap");
461        return;
462      }
463    }
464    sMap[sMapLen].u[sMap[sMapLen].len - 1] += offset;
465    ++sMapLen;
466  }
467}
468
469CharCodeToUnicode::CharCodeToUnicode() {
470  tag = NULL;
471  map = NULL;
472  mapLen = 0;
473  sMap = NULL;
474  sMapLen = sMapSize = 0;
475  refCnt = 1;
476  isIdentity = gFalse;
477#if MULTITHREADED
478  gInitMutex(&mutex);
479#endif
480}
481
482CharCodeToUnicode::CharCodeToUnicode(GooString *tagA) {
483  CharCode i;
484
485  tag = tagA;
486  mapLen = 256;
487  map = (Unicode *)gmallocn(mapLen, sizeof(Unicode));
488  for (i = 0; i < mapLen; ++i) {
489    map[i] = 0;
490  }
491  sMap = NULL;
492  sMapLen = sMapSize = 0;
493  refCnt = 1;
494  isIdentity = gFalse;
495#if MULTITHREADED
496  gInitMutex(&mutex);
497#endif
498}
499
500CharCodeToUnicode::CharCodeToUnicode(GooString *tagA, Unicode *mapA,
501                                     CharCode mapLenA, GBool copyMap,
502                                     CharCodeToUnicodeString *sMapA,
503                                     int sMapLenA, int sMapSizeA) {
504  tag = tagA;
505  mapLen = mapLenA;
506  if (copyMap) {
507    map = (Unicode *)gmallocn(mapLen, sizeof(Unicode));
508    memcpy(map, mapA, mapLen * sizeof(Unicode));
509  } else {
510    map = mapA;
511  }
512  sMap = sMapA;
513  sMapLen = sMapLenA;
514  sMapSize = sMapSizeA;
515  refCnt = 1;
516  isIdentity = gFalse;
517#if MULTITHREADED
518  gInitMutex(&mutex);
519#endif
520}
521
522CharCodeToUnicode::~CharCodeToUnicode() {
523  if (tag) {
524    delete tag;
525  }
526  gfree(map);
527  if (sMap) {
528    for (int i = 0; i < sMapLen; ++i) gfree(sMap[i].u);
529    gfree(sMap);
530  }
531#if MULTITHREADED
532  gDestroyMutex(&mutex);
533#endif
534}
535
536void CharCodeToUnicode::incRefCnt() {
537#if MULTITHREADED
538  gLockMutex(&mutex);
539#endif
540  ++refCnt;
541#if MULTITHREADED
542  gUnlockMutex(&mutex);
543#endif
544}
545
546void CharCodeToUnicode::decRefCnt() {
547  GBool done;
548
549#if MULTITHREADED
550  gLockMutex(&mutex);
551#endif
552  done = --refCnt == 0;
553#if MULTITHREADED
554  gUnlockMutex(&mutex);
555#endif
556  if (done) {
557    delete this;
558  }
559}
560
561GBool CharCodeToUnicode::match(GooString *tagA) {
562  return tag && !tag->cmp(tagA);
563}
564
565void CharCodeToUnicode::setMapping(CharCode c, Unicode *u, int len) {
566  int i, j;
567
568  if (!map || isIdentity) {
569    return;
570  }
571  if (len == 1) {
572    map[c] = u[0];
573  } else {
574    for (i = 0; i < sMapLen; ++i) {
575      if (sMap[i].c == c) {
576        gfree(sMap[i].u);
577        break;
578      }
579    }
580    if (i == sMapLen) {
581      if (sMapLen == sMapSize) {
582        sMapSize += 8;
583        sMap = (CharCodeToUnicodeString *)
584                 greallocn(sMap, sMapSize, sizeof(CharCodeToUnicodeString));
585      }
586      ++sMapLen;
587    }
588    map[c] = 0;
589    sMap[i].c = c;
590    sMap[i].len = len;
591    sMap[i].u = (Unicode*)gmallocn(len, sizeof(Unicode));
592    for (j = 0; j < len; ++j) {
593      sMap[i].u[j] = u[j];
594    }
595  }
596}
597
598int CharCodeToUnicode::mapToUnicode(CharCode c, Unicode **u) {
599  int i;
600
601  if (isIdentity) {
602    map[0] = (Unicode)c;
603    *u = map;
604    return 1;
605  }
606  if (c >= mapLen) {
607    return 0;
608  }
609  if (map[c]) {
610    *u = &map[c];
611    return 1;
612  }
613  for (i = sMapLen - 1; i >= 0; --i) { // in reverse so CMap takes precedence
614    if (sMap[i].c == c) {
615      *u = sMap[i].u;
616      return sMap[i].len;
617    }
618  }
619  return 0;
620}
621
622int CharCodeToUnicode::mapToCharCode(Unicode* u, CharCode *c, int usize) {
623  //look for charcode in map
624  if (usize == 1) {
625    if (isIdentity) {
626      *c = (CharCode) *u;
627      return 1;
628    }
629    for (CharCode i=0; i<mapLen; i++) {
630      if (map[i] == *u) {
631        *c = i;
632        return 1;
633      }
634    }
635    *c = 'x';
636  } else {
637    int i, j;
638    //for each entry in the sMap
639    for (i=0; i<sMapLen; i++) {
640      //if the entry's unicode length isn't the same are usize, the strings
641      // are obviously differents
642      if (sMap[i].len != usize) continue;
643      //compare the string char by char
644      for (j=0; j<sMap[i].len; j++) {
645        if (sMap[i].u[j] != u[j]) {
646          continue;
647        }
648      }
649
650      //we have the same strings
651      if (j==sMap[i].len) { 
652        *c = sMap[i].c;
653        return 1;
654      }
655    }
656  }
657  return 0;
658}
659
660//------------------------------------------------------------------------
661
662CharCodeToUnicodeCache::CharCodeToUnicodeCache(int sizeA) {
663  int i;
664
665  size = sizeA;
666  cache = (CharCodeToUnicode **)gmallocn(size, sizeof(CharCodeToUnicode *));
667  for (i = 0; i < size; ++i) {
668    cache[i] = NULL;
669  }
670}
671
672CharCodeToUnicodeCache::~CharCodeToUnicodeCache() {
673  int i;
674
675  for (i = 0; i < size; ++i) {
676    if (cache[i]) {
677      cache[i]->decRefCnt();
678    }
679  }
680  gfree(cache);
681}
682
683CharCodeToUnicode *CharCodeToUnicodeCache::getCharCodeToUnicode(GooString *tag) {
684  CharCodeToUnicode *ctu;
685  int i, j;
686
687  if (cache[0] && cache[0]->match(tag)) {
688    cache[0]->incRefCnt();
689    return cache[0];
690  }
691  for (i = 1; i < size; ++i) {
692    if (cache[i] && cache[i]->match(tag)) {
693      ctu = cache[i];
694      for (j = i; j >= 1; --j) {
695        cache[j] = cache[j - 1];
696      }
697      cache[0] = ctu;
698      ctu->incRefCnt();
699      return ctu;
700    }
701  }
702  return NULL;
703}
704
705void CharCodeToUnicodeCache::add(CharCodeToUnicode *ctu) {
706  int i;
707
708  if (cache[size - 1]) {
709    cache[size - 1]->decRefCnt();
710  }
711  for (i = size - 1; i >= 1; --i) {
712    cache[i] = cache[i - 1];
713  }
714  cache[0] = ctu;
715  ctu->incRefCnt();
716}
Note: See TracBrowser for help on using the browser.