GooString.cc 6.15 KB
Newer Older
Kristian Høgsberg's avatar
Kristian Høgsberg committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
//========================================================================
//
// GooString.cc
//
// Simple variable-length string type.
//
// Copyright 1996-2003 Glyph & Cog, LLC
//
//========================================================================

#include <config.h>

#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif

#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <ctype.h>
Albert Astals Cid's avatar
Albert Astals Cid committed
21
#include <assert.h>
Kristian Høgsberg's avatar
Kristian Høgsberg committed
22 23 24
#include "gtypes.h"
#include "GooString.h"

Albert Astals Cid's avatar
Albert Astals Cid committed
25
int inline GooString::roundedSize(int len) {
Kristian Høgsberg's avatar
Kristian Høgsberg committed
26
  int delta;
Albert Astals Cid's avatar
Albert Astals Cid committed
27 28
  if (len <= STR_STATIC_SIZE-1)
      return STR_STATIC_SIZE;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
29 30 31 32
  delta = len < 256 ? 7 : 255;
  return ((len + 1) + delta) & ~delta;
}

Albert Astals Cid's avatar
Albert Astals Cid committed
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
// Make sure that the buffer is big enough to contain <newLength> characters
// plus terminating 0.
// We assume that if this is being called from the constructor, <s> was set
// to NULL and <length> was set to 0 to indicate unused string before calling us.
void inline GooString::resize(int newLength) {
  char *s1 = s;

  if (!s || (roundedSize(length) != roundedSize(newLength))) {
    // requires re-allocating data for string
    if (newLength < STR_STATIC_SIZE)
        s1 = sStatic;
    else
        s1 = new char[roundedSize(newLength)];

    // we had to re-allocate the memory, so copy the content of previous
    // buffer into a new buffer
    if (s) {
      if (newLength < length) {
        memcpy(s1, s, newLength);
      } else {
        memcpy(s1, s, length);
      }
55
    }
Albert Astals Cid's avatar
Albert Astals Cid committed
56 57
    if (s != sStatic)
      delete[] s;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
58
  }
Albert Astals Cid's avatar
Albert Astals Cid committed
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96

  s = s1;
  length = newLength;
  s[length] = '\0';
}

GooString* GooString::Set(const char *s1, int s1Len, const char *s2, int s2Len)
{
    int newLen = 0;
    char *p;

    if (s1) {
        if (CALC_STRING_LEN == s1Len) {
            s1Len = strlen(s1);
        } else
            assert(s1Len >= 0);
        newLen += s1Len;
    }

    if (s2) {
        if (CALC_STRING_LEN == s2Len) {
            s2Len = strlen(s2);
        } else
            assert(s2Len >= 0);
        newLen += s2Len;
    }

    resize(newLen);
    p = s;
    if (s1) {
        memcpy(p, s1, s1Len);
        p += s1Len;
    }
    if (s2) {
        memcpy(p, s2, s2Len);
        p += s2Len;
    }
    return this;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
97 98 99 100
}

GooString::GooString() {
  s = NULL;
Albert Astals Cid's avatar
Albert Astals Cid committed
101 102
  length = 0;
  Set(NULL);
Kristian Høgsberg's avatar
Kristian Høgsberg committed
103 104 105 106
}

GooString::GooString(const char *sA) {
  s = NULL;
Albert Astals Cid's avatar
Albert Astals Cid committed
107 108
  length = 0;
  Set(sA, CALC_STRING_LEN);
Kristian Høgsberg's avatar
Kristian Høgsberg committed
109 110 111 112
}

GooString::GooString(const char *sA, int lengthA) {
  s = NULL;
Albert Astals Cid's avatar
Albert Astals Cid committed
113 114
  length = 0;
  Set(sA, lengthA);
Kristian Høgsberg's avatar
Kristian Høgsberg committed
115 116 117 118
}

GooString::GooString(GooString *str, int idx, int lengthA) {
  s = NULL;
Albert Astals Cid's avatar
Albert Astals Cid committed
119 120 121
  length = 0;
  assert(idx + lengthA < str->length);
  Set(str->getCString() + idx, lengthA);
Kristian Høgsberg's avatar
Kristian Høgsberg committed
122 123 124 125
}

GooString::GooString(GooString *str) {
  s = NULL;
Albert Astals Cid's avatar
Albert Astals Cid committed
126 127
  length = 0;
  Set(str->getCString(), str->length);
Kristian Høgsberg's avatar
Kristian Høgsberg committed
128 129 130 131
}

GooString::GooString(GooString *str1, GooString *str2) {
  s = NULL;
Albert Astals Cid's avatar
Albert Astals Cid committed
132 133
  length = 0;
  Set(str1->getCString(), str1->length, str2->getCString(), str2->length);
Kristian Høgsberg's avatar
Kristian Høgsberg committed
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
}

GooString *GooString::fromInt(int x) {
  char buf[24]; // enough space for 64-bit ints plus a little extra
  GBool neg;
  Guint y;
  int i;

  i = 24;
  if (x == 0) {
    buf[--i] = '0';
  } else {
    if ((neg = x < 0)) {
      y = (Guint)-x;
    } else {
      y = (Guint)x;
    }
    while (i > 0 && y > 0) {
      buf[--i] = '0' + y % 10;
      y /= 10;
    }
    if (neg && i > 0) {
      buf[--i] = '-';
    }
  }
  return new GooString(buf + i, 24 - i);
}

GooString::~GooString() {
Albert Astals Cid's avatar
Albert Astals Cid committed
163 164
  if (s != sStatic)
    delete[] s;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
165 166 167 168 169 170 171 172
}

GooString *GooString::clear() {
  resize(0);
  return this;
}

GooString *GooString::append(char c) {
Albert Astals Cid's avatar
Albert Astals Cid committed
173
  return append((const char*)&c, 1);
Kristian Høgsberg's avatar
Kristian Høgsberg committed
174 175 176
}

GooString *GooString::append(GooString *str) {
Albert Astals Cid's avatar
Albert Astals Cid committed
177
  return append(str->getCString(), str->getLength());
Kristian Høgsberg's avatar
Kristian Høgsberg committed
178 179 180
}

GooString *GooString::append(const char *str, int lengthA) {
Albert Astals Cid's avatar
Albert Astals Cid committed
181 182 183
  int prevLen = length;
  if (CALC_STRING_LEN == lengthA)
    lengthA = strlen(str);
Kristian Høgsberg's avatar
Kristian Høgsberg committed
184
  resize(length + lengthA);
Albert Astals Cid's avatar
Albert Astals Cid committed
185
  memcpy(s + prevLen, str, lengthA);
Kristian Høgsberg's avatar
Kristian Høgsberg committed
186 187 188 189
  return this;
}

GooString *GooString::insert(int i, char c) {
Albert Astals Cid's avatar
Albert Astals Cid committed
190
  return insert(i, (const char*)&c, 1);
Kristian Høgsberg's avatar
Kristian Høgsberg committed
191 192 193
}

GooString *GooString::insert(int i, GooString *str) {
Albert Astals Cid's avatar
Albert Astals Cid committed
194
  return insert(i, str->getCString(), str->getLength());
Kristian Høgsberg's avatar
Kristian Høgsberg committed
195 196 197 198
}

GooString *GooString::insert(int i, const char *str, int lengthA) {
  int j;
Albert Astals Cid's avatar
Albert Astals Cid committed
199 200 201
  int prevLen = length;
  if (CALC_STRING_LEN == lengthA)
    lengthA = strlen(str);
Kristian Høgsberg's avatar
Kristian Høgsberg committed
202 203

  resize(length + lengthA);
Albert Astals Cid's avatar
Albert Astals Cid committed
204
  for (j = prevLen; j >= i; --j)
Kristian Høgsberg's avatar
Kristian Høgsberg committed
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
    s[j+lengthA] = s[j];
  memcpy(s+i, str, lengthA);
  return this;
}

GooString *GooString::del(int i, int n) {
  int j;

  if (n > 0) {
    if (i + n > length) {
      n = length - i;
    }
    for (j = i; j <= length - n; ++j) {
      s[j] = s[j + n];
    }
Albert Astals Cid's avatar
Albert Astals Cid committed
220
    resize(length - n);
Kristian Høgsberg's avatar
Kristian Høgsberg committed
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
  }
  return this;
}

GooString *GooString::upperCase() {
  int i;

  for (i = 0; i < length; ++i) {
    if (islower(s[i]))
      s[i] = toupper(s[i]);
  }
  return this;
}

GooString *GooString::lowerCase() {
  int i;

  for (i = 0; i < length; ++i) {
    if (isupper(s[i]))
      s[i] = tolower(s[i]);
  }
  return this;
}
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321

int GooString::cmp(GooString *str) {
  int n1, n2, i, x;
  char *p1, *p2;

  n1 = length;
  n2 = str->length;
  for (i = 0, p1 = s, p2 = str->s; i < n1 && i < n2; ++i, ++p1, ++p2) {
    x = *p1 - *p2;
    if (x != 0) {
      return x;
    }
  }
  return n1 - n2;
}

int GooString::cmpN(GooString *str, int n) {
  int n1, n2, i, x;
  char *p1, *p2;

  n1 = length;
  n2 = str->length;
  for (i = 0, p1 = s, p2 = str->s;
       i < n1 && i < n2 && i < n;
       ++i, ++p1, ++p2) {
    x = *p1 - *p2;
    if (x != 0) {
      return x;
    }
  }
  if (i == n) {
    return 0;
  }
  return n1 - n2;
}

int GooString::cmp(const char *sA) {
  int n1, i, x;
  const char *p1, *p2;

  n1 = length;
  for (i = 0, p1 = s, p2 = sA; i < n1 && *p2; ++i, ++p1, ++p2) {
    x = *p1 - *p2;
    if (x != 0) {
      return x;
    }
  }
  if (i < n1) {
    return 1;
  }
  if (*p2) {
    return -1;
  }
  return 0;
}

int GooString::cmpN(const char *sA, int n) {
  int n1, i, x;
  const char *p1, *p2;

  n1 = length;
  for (i = 0, p1 = s, p2 = sA; i < n1 && *p2 && i < n; ++i, ++p1, ++p2) {
    x = *p1 - *p2;
    if (x != 0) {
      return x;
    }
  }
  if (i == n) {
    return 0;
  }
  if (i < n1) {
    return 1;
  }
  if (*p2) {
    return -1;
  }
  return 0;
}
322 323 324 325 326

GBool GooString::hasUnicodeMarker(void)
{
    return (s[0] & 0xff) == 0xfe && (s[1] & 0xff) == 0xff;
}