filters

kpresenter/powerpoint/libppt/ustring.cpp
1/*
2 * This file is part of the KDE libraries
3 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21#include "ustring.h"
22
23#ifdef HAVE_CONFIG_H
24#include <config.h>
25#endif
26
27
28#define USTRING_SIMPLIFIED
29
30#ifdef USTRING_SIMPLIFIED
31#include <string.h>
32#include <ctype.h>
33#include <stdlib.h>
34#include <stdio.h>
35#include <math.h>
36#endif
37
38
39#ifndef USTRING_SIMPLIFIED
40
41#include <stdlib.h>
42#include <stdio.h>
43#include <ctype.h>
44#ifdef HAVE_STRING_H
45#include <string.h>
46#endif
47#ifdef HAVE_STRINGS_H
48#include <strings.h>
49#endif
50
51#ifdef HAVE_MATH_H
52#include <math.h>
53#endif
54#ifdef HAVE_FLOAT_H
55#include <float.h>
56#endif
57#ifdef HAVE_IEEEFP_H
58#include <ieeefp.h>
59#endif
60
61#endif
62
63namespace Libppt {
64#ifdef WORDS_BIGENDIAN
65 unsigned char NaN_Bytes[] = { 0x7f, 0xf8, 0, 0, 0, 0, 0, 0 };
66 unsigned char Inf_Bytes[] = { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 };
67#elif defined(arm)
68 unsigned char NaN_Bytes[] = { 0, 0, 0xf8, 0x7f, 0, 0, 0, 0 };
69 unsigned char Inf_Bytes[] = { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 };
70#else
71 unsigned char NaN_Bytes[] = { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f };
72 unsigned char Inf_Bytes[] = { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f };
73#endif
74
75 const double NaN = *( reinterpret_cast<const double*>( NaN_Bytes ) );
76 const double Inf = *( reinterpret_cast<const double*>( Inf_Bytes ) );
77}
78
79using namespace Libppt;
80
81#ifdef USTRING_SIMPLIFIED
82bool Libppt::isNaN(double)
83{
84 return false;
85}
86#else
87bool Libppt::isNaN(double d)
88{
89#ifdef HAVE_FUNC_ISNAN
90 return isnan(d);
91#elif defined HAVE_FLOAT_H
92 return _isnan(d) != 0;
93#else
94 return !(d == d);
95#endif
96}
97#endif
98
99#ifdef USTRING_SIMPLIFIED
100bool Libppt::isPosInf(double)
101{
102 return false;
103}
104#else
105bool Libppt::isPosInf(double d)
106{
107#if defined(HAVE_FUNC_ISINF)
108 return (isinf(d) == 1);
109#elif HAVE_FUNC_FINITE
110 return finite(d) == 0 && d == d; // ### can we distinguish between + and - ?
111#elif HAVE_FUNC__FINITE
112 return _finite(d) == 0 && d == d; // ###
113#else
114 return false;
115#endif
116}
117#endif
118
119#ifdef USTRING_SIMPLIFIED
120bool Libppt::isNegInf(double)
121{
122 return false;
123}
124#else
125bool Libppt::isNegInf(double d)
126{
127#if defined(HAVE_FUNC_ISINF)
128 return (isinf(d) == -1);
129#elif HAVE_FUNC_FINITE
130 return finite(d) == 0 && d == d; // ###
131#elif HAVE_FUNC__FINITE
132 return _finite(d) == 0 && d == d; // ###
133#else
134 return false;
135#endif
136}
137#endif
138
139CString::CString(const char *c)
140{
141 data = new char[strlen(c)+1];
142 strcpy(data, c);
143}
144
145CString::CString(const CString &b)
146{
147 data = new char[b.length()+1];
148 strcpy(data, b.c_str());
149}
150
151CString::~CString()
152{
153 delete [] data;
154}
155
156CString &CString::append(const CString &t)
157{
158 char *n;
159 if (data) {
160 n = new char[strlen(data)+t.length()+1];
161 strcpy(n, data);
162 } else {
163 n = new char[t.length()+1];
164 n[0] = '\0';
165 }
166 strcat(n, t.c_str());
167
168 delete [] data;
169 data = n;
170
171 return *this;
172}
173
174CString &CString::operator=(const char *c)
175{
176 if (data)
177 delete [] data;
178 data = new char[strlen(c)+1];
179 strcpy(data, c);
180
181 return *this;
182}
183
184CString &CString::operator=(const CString &str)
185{
186 if (this == &str)
187 return *this;
188
189 if (data)
190 delete [] data;
191 data = new char[str.length()+1];
192 strcpy(data, str.c_str());
193
194 return *this;
195}
196
197CString &CString::operator+=(const CString &str)
198{
199 return append(CString(str.c_str()));
200}
201
202int CString::length() const
203{
204 return strlen(data);
205}
206
207bool Libppt::operator==(const Libppt::CString& c1, const Libppt::CString& c2)
208{
209 return (strcmp(c1.c_str(), c2.c_str()) == 0);
210}
211
213UString::Rep UString::Rep::null = { 0, 0, 1 };
215static char *statBuffer = 0L;
216
218 : uc( c.unicode() )
219{
220}
221
223{
224 // ### properly support unicode tolower
225 if (uc >= 256 || islower(uc))
226 return *this;
227
228 return UChar(tolower(uc));
229}
230
232{
233 if (uc >= 256 || isupper(uc))
234 return *this;
235
236 return UChar(toupper(uc));
237}
238
240{
241 str->detach();
242 if (offset < str->rep->len)
243 *(str->rep->dat + offset) = c;
244 /* TODO: lengthen string ? */
245 return *this;
246}
247
248UChar& UCharReference::ref() const
249{
250 if (offset < str->rep->len)
251 return *(str->rep->dat + offset);
252 else
253 return UChar::null;
254}
255
256namespace {
257 // return an uninitialized UChar array of size s
258 static inline UChar* allocateChars(int s)
259 {
260 // work around default UChar constructor code
261 return reinterpret_cast<UChar*>(new short[s]);
262 }
263}
264
265UString::Rep *UString::Rep::create(UChar *d, int l)
266{
267 Rep *r = new Rep;
268 r->dat = d;
269 r->len = l;
270 r->rc = 1;
271
272 return r;
273}
274
276{
277 null.rep = &Rep::null;
278 attach(&Rep::null);
279}
280
282{
283 UChar *d = allocateChars( 1 );
284 d[0] = UChar(0, c);
285 rep = Rep::create(d, 1);
286}
287
289{
290 UChar *d = allocateChars( 1 );
291 d[0] = c;
292 rep = Rep::create(d, 1);
293}
294
295UString::UString(const char *c)
296{
297 attach(&Rep::null);
298 operator=(c);
299}
300
302{
303 UChar *d = allocateChars( length );
304 memcpy(d, c, length * sizeof(UChar));
305 rep = Rep::create(d, length);
306}
307
308UString::UString(UChar *c, int length, bool copy)
309{
310 UChar *d;
311 if (copy) {
312 d = allocateChars( length );
313 memcpy(d, c, length * sizeof(UChar));
314 } else
315 d = c;
316 rep = Rep::create(d, length);
317}
318
320{
321 attach(b.rep);
322}
323
325{
326 release();
327}
328
330{
331 char buf[40];
332 sprintf(buf, "%d", i);
333
334 return UString(buf);
335}
336
337UString UString::from(unsigned int u)
338{
339 char buf[40];
340 sprintf(buf, "%u", u);
341
342 return UString(buf);
343}
344
346{
347 char buf[40];
348
349 if (d == -0)
350 strcpy(buf,"0");
351 else if (isNaN(d))
352 strcpy(buf,"NaN");
353 else if (isPosInf(d))
354 strcpy(buf,"Infinity");
355 else if (isNegInf(d))
356 strcpy(buf,"-Infinity");
357 else
358 sprintf(buf, "%.16g", d); // does the right thing
359
360 // ECMA 3rd ed. 9.8.1 9 e: "with no leading zeros"
361 int buflen = strlen(buf);
362 if (buflen >= 4 && buf[buflen-4] == 'e' && buf[buflen-2] == '0') {
363 buf[buflen-2] = buf[buflen-1];
364 buf[buflen-1] = 0;
365 }
366
367 return UString(buf);
368}
369
371{
372 int l = length();
373 UChar *n = allocateChars( l+t.length() );
374 memcpy(n, data(), l * sizeof(UChar));
375 memcpy(n+l, t.data(), t.length() * sizeof(UChar));
376 release();
377 rep = Rep::create(n, l + t.length());
378
379 return *this;
380}
381
383{
384 return CString(ascii());
385}
386
387char *UString::ascii() const
388{
389 if (statBuffer)
390 delete [] statBuffer;
391
392 statBuffer = new char[length()+1];
393 for(int i = 0; i < length(); i++)
394 statBuffer[i] = data()[i].low();
395 statBuffer[length()] = '\0';
396
397 return statBuffer;
398}
399
401{
402 release();
403 int l = c ? strlen(c) : 0;
404 UChar *d = allocateChars( l );
405 for (int i = 0; i < l; i++)
406 d[i].uc = static_cast<unsigned char>( c[i] );
407 rep = Rep::create(d, l);
408
409 return *this;
410}
411
413{
414 str.rep->ref();
415 release();
416 rep=str.rep;
417
418 return *this;
419}
420
422{
423 return append(s);
424}
425
426bool UString::is8Bit() const
427{
428 const UChar *u = data();
429 for(int i = 0; i < length(); i++, u++)
430 if (u->uc > 0xFF)
431 return false;
432
433 return true;
434}
435
437{
438 if (pos >= length())
439 return UChar::null;
440
441 return static_cast<const UChar *>( data() )[pos];
442}
443
444UCharReference UString::operator[](int pos)
445{
446 /* TODO: boundary check */
447 return UCharReference(this, pos);
448}
449
450double UString::toDouble( bool tolerant ) const
451{
452 double d;
453
454 if (!is8Bit())
455 return NaN;
456
457 CString str = cstring();
458 const char *c = str.c_str();
459
460 // skip leading white space
461 while (isspace(*c))
462 c++;
463
464 // empty string ?
465 if (*c == '\0')
466 return tolerant ? NaN : 0.0;
467
468 // hex number ?
469 if (*c == '0' && (*(c+1) == 'x' || *(c+1) == 'X')) {
470 c++;
471 d = 0.0;
472 while (*(++c)) {
473 if (*c >= '0' && *c <= '9')
474 d = d * 16.0 + *c - '0';
475 else if ((*c >= 'A' && *c <= 'F') || (*c >= 'a' && *c <= 'f'))
476 d = d * 16.0 + (*c & 0xdf) - 'A' + 10.0;
477 else
478 break;
479 }
480 } else {
481 // regular number ?
482 char *end;
483 d = strtod(c, &end);
484 if ((d != 0.0 || end != c) && d != HUGE_VAL && d != -HUGE_VAL) {
485 c = end;
486 } else {
487 // infinity ?
488 d = 1.0;
489 if (*c == '+')
490 c++;
491 else if (*c == '-') {
492 d = -1.0;
493 c++;
494 }
495 if (strncmp(c, "Infinity", 8) != 0)
496 return NaN;
497 d = d * Inf;
498 c += 8;
499 }
500 }
501
502 // allow trailing white space
503 while (isspace(*c))
504 c++;
505 // don't allow anything after - unless tolerant=true
506 if ( !tolerant && *c != '\0')
507 d = NaN;
508
509 return d;
510}
511
512unsigned long UString::toULong(bool *ok) const
513{
514 double d = toDouble();
515 bool b = true;
516
517 if (isNaN(d) || d != static_cast<unsigned long>(d)) {
518 b = false;
519 d = 0;
520 }
521
522 if (ok)
523 *ok = b;
524
525 return static_cast<unsigned long>(d);
526}
527
528int UString::find(const UString &f, int pos) const
529{
530 if (isNull())
531 return -1;
532 long fsize = f.length() * sizeof(UChar);
533 if (pos < 0)
534 pos = 0;
535 const UChar *end = data() + length() - f.length();
536 for (const UChar *c = data() + pos; c <= end; c++)
537 if (!memcmp(c, f.data(), fsize))
538 return (c-data());
539
540 return -1;
541}
542
543int UString::rfind(const UString &f, int pos) const
544{
545 if (isNull())
546 return -1;
547 if (pos + f.length() >= length())
548 pos = length() - f.length();
549 long fsize = f.length() * sizeof(UChar);
550 for (const UChar *c = data() + pos; c >= data(); c--) {
551 if (!memcmp(c, f.data(), fsize))
552 return (c-data());
553 }
554
555 return -1;
556}
557
558UString UString::substr(int pos, int len) const
559{
560 if (isNull())
561 return UString();
562 if (pos < 0)
563 pos = 0;
564 else if (pos >= static_cast<int>( length() ))
565 pos = length();
566 if (len < 0)
567 len = length();
568 if (pos + len >= static_cast<int>( length() ))
569 len = length() - pos;
570
571 UChar *tmp = allocateChars( len );
572 memcpy(tmp, data()+pos, len * sizeof(UChar));
573 UString result(tmp, len);
574 delete [] tmp;
575
576 return result;
577}
578
579void UString::attach(Rep *r)
580{
581 rep = r;
582 rep->ref();
583}
584
585void UString::detach()
586{
587 if (rep->rc > 1) {
588 int l = length();
589 UChar *n = allocateChars( l );
590 memcpy(n, data(), l * sizeof(UChar));
591 release();
592 rep = Rep::create(n, l);
593 }
594}
595
596void UString::release()
597{
598 if (!rep->deref()) {
599 delete [] rep->dat;
600 delete rep;
601 }
602}
603
604bool Libppt::operator==(const UString& s1, const UString& s2)
605{
606 if (s1.rep->len != s2.rep->len)
607 return false;
608
609 return (memcmp(s1.rep->dat, s2.rep->dat,
610 s1.rep->len * sizeof(UChar)) == 0);
611}
612
613bool Libppt::operator==(const UString& s1, const char *s2)
614{
615 if (s2 == 0L && s1.isNull())
616 return true;
617
618 if (s1.length() != static_cast<int>( strlen(s2) ))
619 return false;
620
621 const UChar *u = s1.data();
622 while (*s2) {
623 if (u->uc != *s2 )
624 return false;
625 s2++;
626 u++;
627 }
628
629 return true;
630}
631
632bool Libppt::operator<(const UString& s1, const UString& s2)
633{
634 const int l1 = s1.length();
635 const int l2 = s2.length();
636 const int lmin = l1 < l2 ? l1 : l2;
637 const UChar *c1 = s1.data();
638 const UChar *c2 = s2.data();
639 int l = 0;
640 while (l < lmin && *c1 == *c2) {
641 c1++;
642 c2++;
643 l++;
644 }
645 if (l < lmin)
646 return (c1->unicode() < c2->unicode());
647
648 return (l1 < l2);
649}
650
651UString Libppt::operator+(const UString& s1, const UString& s2)
652{
653 UString tmp(s1);
654 tmp.append(s2);
655
656 return tmp;
657}
658
659
660UConstString::UConstString( UChar* data, unsigned int length ) : UString( data, length, false )
661{
662}
663
664UConstString::~UConstString()
665{
666 if ( rep->rc > 1 ) {
667 int l = length();
668 UChar* n = allocateChars( l );
669 memcpy( n, data(), l * sizeof( UChar ) );
670 rep->dat = n;
671 }
672 else
673 rep->dat = 0;
674}
8 bit char based string class
Dynamic reference to a string character.
UCharReference & operator=(UChar c)
Set the referenced character to c.
bool is8Bit() const
Use this if you want to make sure that this string is a plain ASCII string.
int find(const UString &f, int pos=0) const
int rfind(const UString &f, int pos) const
UString & operator=(const char *c)
Assignment operator.
char * ascii() const
Convert the Unicode string to plain ASCII chars chopping of any higher bytes.
UString & operator+=(const UString &s)
Appends the specified string.
double toDouble(bool tolerant=false) const
Attempts an conversion to a number.
static UString null
Static instance of a null string.
UString substr(int pos=0, int len=-1) const
unsigned long toULong(bool *ok=0L) const
Attempts an conversion to an unsigned long integer.
UChar operator[](int pos) const
Const character at specified position.
UString & append(const UString &)
Append another string.
static UString from(int i)
Constructs a string from an int.
static UChar null
A static instance of UChar(0).
UChar()
Construct a character with value 0.