source: webkit/trunk/JavaScriptCore/kjs/ustring.cpp@ 1623

Last change on this file since 1623 was 1623, checked in by darin, 23 years ago

JavaScriptCore:

  • kjs/*: Roll KDE 3.0.2 changes in. Also switch to not using APPLE_CHANGES for some of the changes that we definitely want to contribute upstream.

WebCore:

  • khtml/*: Roll KDE 3.0.2 changes in. Also switch to not using APPLE_CHANGES for some of the changes that we definitely want to contribute upstream.
  • WebCore.pbproj/project.pbxproj: Add KWQStyle.mm, remove KWQStyle.h, moving contents into qstyle.h.
  • kwq/KWQApplication.mm: (QApplication::globalStrut): Remove _logNotYetImplemented().
  • kwq/KWQButton.mm: (QButton::QButton): Use plain release, not autorelease.
  • kwq/KWQComboBox.mm: (QComboBox::init): Use plain release, not autorelease.
  • kwq/KWQListBox.mm: (QListBox::QListBox): Use plain release, not autorelease.
  • kwq/KWQPainter.mm: (QPainter::drawArc): Use plain release, not autorelease.
  • kwq/KWQKHTMLPartBrowserExtension.mm: Remove import of KWQKHTMLPartImpl.h, now that it's always part of khtml_part.h.
  • kwq/KWQKHTMLPartImpl.cpp: Simplify.
  • kwq/KWQKHTMLPartImpl.h: Add wrapper to allow multiple inclusion. Don't include khtml_part.h any more, since that file now includes this one to minimize changes to KDE code that needs to get to functions in here.
  • kwq/KWQKHTMLPartImpl.mm: (KHTMLPart::onURL), (KHTMLPart::nodeActivated), (KHTMLPart::setStatusBarText): Moved here from khtml_part.cpp.
  • kwq/KWQLoaderImpl.mm: Include khtml_part.h instead of KWQKHTMLPartImpl.h.
  • kwq/KWQPushButton.mm: (buttonFontMetrics), (QPushButton::fontMetrics): Added. Used by the form code to size buttons.
  • kwq/KWQStyle.mm: Added. (QStyle::sizeFromContents): Added. Used by the form code to size buttons.
  • kwq/KWQStyle.h: Removed.
  • kwq/qt/qstyle.h: Moved contents of KWQStyle.h in here.
  • kwq/qt/qwidget.h: Include <qstyle.h> rather than KWQStyle.h.
  • kwq/WebCoreBridge.mm: (-[WebCoreBridge isFrameSet]): Call straight to impl.
  • kwq/kdeui/klineedit.h: Add KLineEdit::frameWidth().
  • kwq/qt/qnamespace.h: Remove GUIStyle, MacStyle, and WindowsStyle.
  • kwq/qt/qpaintdevice.h: Add QInternal, QInternal::Printer, and QPaintDevice::devType().
  • kwq/qt/qpainter.h: Add QPainter::device().
  • kwq/qt/qpushbutton.h: Add QPushButton::fontMetrics().
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.3 KB
Line 
1// -*- c-basic-offset: 2 -*-
2/*
3 * This file is part of the KDE libraries
4 * Copyright (C) 1999-2000 Harri Porten ([email protected])
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 *
21 */
22
23#ifdef HAVE_CONFIG_H
24#include <config.h>
25#endif
26
27#include <stdlib.h>
28#include <stdio.h>
29#include <ctype.h>
30#ifdef HAVE_STRING_H
31#include <string.h>
32#endif
33#ifdef HAVE_STRINGS_H
34#include <strings.h>
35#endif
36
37#include "ustring.h"
38#include "operations.h"
39#include <math.h>
40
41namespace KJS {
42 extern const double NaN;
43 extern const double Inf;
44};
45
46using namespace KJS;
47
48CString::CString(const char *c)
49{
50 data = new char[strlen(c)+1];
51 strcpy(data, c);
52}
53
54CString::CString(const CString &b)
55{
56 data = new char[b.size()+1];
57 strcpy(data, b.c_str());
58}
59
60CString::~CString()
61{
62 delete [] data;
63}
64
65CString &CString::append(const CString &t)
66{
67 char *n;
68 if (data) {
69 n = new char[strlen(data)+t.size()+1];
70 strcpy(n, data);
71 } else {
72 n = new char[t.size()+1];
73 n[0] = '\0';
74 }
75 strcat(n, t.c_str());
76
77 delete [] data;
78 data = n;
79
80 return *this;
81}
82
83CString &CString::operator=(const char *c)
84{
85 if (data)
86 delete [] data;
87 data = new char[strlen(c)+1];
88 strcpy(data, c);
89
90 return *this;
91}
92
93CString &CString::operator=(const CString &str)
94{
95 if (this == &str)
96 return *this;
97
98 if (data)
99 delete [] data;
100 data = new char[str.size()+1];
101 strcpy(data, str.c_str());
102
103 return *this;
104}
105
106CString &CString::operator+=(const CString &str)
107{
108 return append(str.c_str());
109}
110
111int CString::size() const
112{
113 return strlen(data);
114}
115
116bool KJS::operator==(const KJS::CString& c1, const KJS::CString& c2)
117{
118 return (strcmp(c1.c_str(), c2.c_str()) == 0);
119}
120
121UChar UChar::null;
122#ifdef APPLE_CHANGES
123UString::Rep UString::Rep::null = { 0, 0, 0, 1 };
124#else
125UString::Rep UString::Rep::null = { 0, 0, 1 };
126#endif
127UString UString::null;
128#ifdef APPLE_CHANGES
129static pthread_once_t statBufferKeyOnce = PTHREAD_ONCE_INIT;
130static pthread_key_t statBufferKey;
131#else
132static char *statBuffer = 0L;
133#endif
134
135UChar::UChar(const UCharReference &c)
136 : uc( c.unicode() )
137{
138}
139
140UChar UChar::toLower() const
141{
142 // ### properly supprot unicode tolower
143 if (uc >= 256 || islower(uc))
144 return *this;
145
146 return UChar(tolower(uc));
147}
148
149UChar UChar::toUpper() const
150{
151 if (uc >= 256 || isupper(uc))
152 return *this;
153
154 return UChar(toupper(uc));
155}
156
157UCharReference& UCharReference::operator=(UChar c)
158{
159 str->detach();
160 if (offset < str->rep->len)
161 *(str->rep->dat + offset) = c;
162 /* TODO: lengthen string ? */
163 return *this;
164}
165
166UChar& UCharReference::ref() const
167{
168 if (offset < str->rep->len)
169 return *(str->rep->dat + offset);
170 else
171 return UChar::null;
172}
173
174UString::Rep *UString::Rep::create(UChar *d, int l)
175{
176 Rep *r = new Rep;
177 r->dat = d;
178 r->len = l;
179#ifdef APPLE_CHANGES
180 r->capacity = l;
181#endif
182 r->rc = 1;
183
184 return r;
185}
186
187UString::UString()
188{
189 null.rep = &Rep::null;
190 attach(&Rep::null);
191}
192
193UString::UString(char c)
194{
195 UChar *d = new UChar[1];
196 d[0] = UChar(0, c);
197 rep = Rep::create(d, 1);
198}
199
200UString::UString(const char *c)
201{
202 attach(&Rep::null);
203 operator=(c);
204}
205
206UString::UString(const UChar *c, int length)
207{
208 UChar *d = new UChar[length];
209 memcpy(d, c, length * sizeof(UChar));
210 rep = Rep::create(d, length);
211}
212
213UString::UString(UChar *c, int length, bool copy)
214{
215 UChar *d;
216 if (copy) {
217 d = new UChar[length];
218 memcpy(d, c, length * sizeof(UChar));
219 } else
220 d = c;
221 rep = Rep::create(d, length);
222}
223
224UString::UString(const UString &b)
225{
226 attach(b.rep);
227}
228
229UString::~UString()
230{
231 release();
232}
233
234UString UString::from(int i)
235{
236 char buf[40];
237 sprintf(buf, "%d", i);
238
239 return UString(buf);
240}
241
242UString UString::from(unsigned int u)
243{
244 char buf[40];
245 sprintf(buf, "%u", u);
246
247 return UString(buf);
248}
249
250UString UString::from(double d)
251{
252 char buf[40];
253
254 if (d == -0)
255 strcpy(buf,"0");
256 else if (KJS::isNaN(d))
257 strcpy(buf,"NaN");
258 else if (KJS::isPosInf(d))
259 strcpy(buf,"Infinity");
260 else if (KJS::isNegInf(d))
261 strcpy(buf,"-Infinity");
262 else
263 sprintf(buf, "%.16g", d); // does the right thing
264
265 // ECMA 3rd ed. 9.8.1 9 e: "with no leading zeros"
266 int buflen = strlen(buf);
267 if (buflen >= 4 && buf[buflen-4] == 'e' && buf[buflen-2] == '0') {
268 buf[buflen-2] = buf[buflen-1];
269 buf[buflen-1] = 0;
270 }
271
272 return UString(buf);
273}
274
275UString &UString::append(const UString &t)
276{
277#ifdef APPLE_CHANGES
278 int l = size();
279 int tLen = t.size();
280 int newLen = l + tLen;
281 if (rep->rc == 1 && newLen <= rep->capacity) {
282 memcpy(rep->dat+l, t.data(), tLen * sizeof(UChar));
283 rep->len = newLen;
284 return *this;
285 }
286
287 int newCapacity = (newLen * 3 + 1) / 2;
288 UChar *n = new UChar[newCapacity];
289 memcpy(n, data(), l * sizeof(UChar));
290 memcpy(n+l, t.data(), tLen * sizeof(UChar));
291 release();
292 rep = Rep::create(n, newLen);
293 rep->capacity = newCapacity;
294#else
295 int l = size();
296 UChar *n = new UChar[l+t.size()];
297 memcpy(n, data(), l * sizeof(UChar));
298 memcpy(n+l, t.data(), t.size() * sizeof(UChar));
299 release();
300 rep = Rep::create(n, l + t.size());
301#endif
302
303 return *this;
304}
305
306CString UString::cstring() const
307{
308 return CString(ascii());
309}
310
311#ifdef APPLE_CHANGES
312static void statBufferKeyCleanup(void *statBuffer)
313{
314 if (statBuffer != NULL)
315 delete [] (char *)statBuffer;
316}
317
318static void statBufferKeyInit(void)
319{
320 pthread_key_create(&statBufferKey, statBufferKeyCleanup);
321}
322#endif
323
324char *UString::ascii() const
325{
326#ifdef APPLE_CHANGES
327 pthread_once(&statBufferKeyOnce, statBufferKeyInit);
328 char *statBuffer = (char *)pthread_getspecific(statBufferKey);
329#endif
330 if (statBuffer)
331 delete [] statBuffer;
332
333 statBuffer = new char[size()+1];
334 for(int i = 0; i < size(); i++)
335 statBuffer[i] = data()[i].low();
336 statBuffer[size()] = '\0';
337
338#ifdef APPLE_CHANGES
339 pthread_setspecific(statBufferKey, statBuffer);
340#endif
341 return statBuffer;
342}
343
344#ifdef KJS_DEBUG_MEM
345void UString::globalClear()
346{
347 delete [] statBuffer;
348 statBuffer = 0L;
349}
350#endif
351
352UString &UString::operator=(const char *c)
353{
354#ifdef APPLE_CHANGES
355 int l = c ? strlen(c) : 0;
356 UChar *d;
357 if (rep->rc == 1 && l < rep->capacity) {
358 d = rep->dat;
359 } else {
360 release();
361 d = new UChar[l];
362 rep = Rep::create(d, l);
363 }
364 for (int i = 0; i < l; i++)
365 d[i].uc = (uchar)c[i];
366#else
367 release();
368 int l = c ? strlen(c) : 0;
369
370 UChar *d = new UChar[l];
371 for (int i = 0; i < l; i++)
372 d[i].uc = c[i];
373 rep = Rep::create(d, l);
374#endif
375
376 return *this;
377}
378
379UString &UString::operator=(const UString &str)
380{
381 str.rep->ref();
382 release();
383 rep = str.rep;
384
385 return *this;
386}
387
388UString &UString::operator+=(const UString &s)
389{
390 return append(s);
391}
392
393bool UString::is8Bit() const
394{
395 const UChar *u = data();
396 for(int i = 0; i < size(); i++, u++)
397 if (u->uc > 0xFF)
398 return false;
399
400 return true;
401}
402
403UChar UString::operator[](int pos) const
404{
405 if (pos >= size())
406 return UChar::null;
407
408 return ((UChar *)data())[pos];
409}
410
411UCharReference UString::operator[](int pos)
412{
413 /* TODO: boundary check */
414 return UCharReference(this, pos);
415}
416
417double UString::toDouble( bool tolerant ) const
418{
419 double d;
420
421 if (!is8Bit())
422 return NaN;
423
424 CString str = cstring();
425 const char *c = str.c_str();
426
427 // skip leading white space
428 while (isspace(*c))
429 c++;
430
431 // empty string ?
432 if (*c == '\0')
433 return tolerant ? NaN : 0.0;
434
435 // hex number ?
436 if (*c == '0' && (*(c+1) == 'x' || *(c+1) == 'X')) {
437 c++;
438 d = 0.0;
439 while (*(++c)) {
440 if (*c >= '0' && *c <= '9')
441 d = d * 16.0 + *c - '0';
442 else if ((*c >= 'A' && *c <= 'F') || (*c >= 'a' && *c <= 'f'))
443 d = d * 16.0 + (*c & 0xdf) - 'A' + 10.0;
444 else
445 break;
446 }
447 } else {
448 // regular number ?
449 char *end;
450 d = strtod(c, &end);
451 if ((d != 0.0 || end != c) && d != HUGE_VAL && d != -HUGE_VAL) {
452 c = end;
453 } else {
454 // infinity ?
455 d = 1.0;
456 if (*c == '+')
457 c++;
458 else if (*c == '-') {
459 d = -1.0;
460 c++;
461 }
462 if (strncmp(c, "Infinity", 8) != 0)
463 return NaN;
464 d = d * Inf;
465 c += 8;
466 }
467 }
468
469 // allow trailing white space
470 while (isspace(*c))
471 c++;
472 // don't allow anything after - unless tolerant=true
473 if ( !tolerant && *c != '\0')
474 d = NaN;
475
476 return d;
477}
478
479unsigned long UString::toULong(bool *ok) const
480{
481 double d = toDouble();
482 bool b = true;
483
484 if (isNaN(d) || d != static_cast<unsigned long>(d)) {
485 b = false;
486 d = 0;
487 }
488
489 if (ok)
490 *ok = b;
491
492 return static_cast<unsigned long>(d);
493}
494
495int UString::find(const UString &f, int pos) const
496{
497 if (isNull())
498 return -1;
499 long fsize = f.size() * sizeof(UChar);
500 if (pos < 0)
501 pos = 0;
502 const UChar *end = data() + size() - f.size();
503 for (const UChar *c = data() + pos; c <= end; c++)
504 if (!memcmp((void*)c, (void*)f.data(), fsize))
505 return (c-data());
506
507 return -1;
508}
509
510int UString::rfind(const UString &f, int pos) const
511{
512 if (isNull())
513 return -1;
514 if (pos + f.size() >= size())
515 pos = size() - f.size();
516 long fsize = f.size() * sizeof(UChar);
517 for (const UChar *c = data() + pos; c >= data(); c--) {
518 if (!memcmp((void*)c, (void*)f.data(), fsize))
519 return (c-data());
520 }
521
522 return -1;
523}
524
525UString UString::substr(int pos, int len) const
526{
527 if (isNull())
528 return UString();
529 if (pos < 0)
530 pos = 0;
531 else if (pos >= (int) size())
532 pos = size();
533 if (len < 0)
534 len = size();
535 if (pos + len >= (int) size())
536 len = size() - pos;
537
538 UChar *tmp = new UChar[len];
539 memcpy(tmp, data()+pos, len * sizeof(UChar));
540 UString result(tmp, len);
541 delete [] tmp;
542
543 return result;
544}
545
546void UString::attach(Rep *r)
547{
548 rep = r;
549 rep->ref();
550}
551
552void UString::detach()
553{
554 if (rep->rc > 1) {
555 int l = size();
556 UChar *n = new UChar[l];
557 memcpy(n, data(), l * sizeof(UChar));
558 release();
559 rep = Rep::create(n, l);
560 }
561}
562
563void UString::release()
564{
565 if (!rep->deref()) {
566 delete [] rep->dat;
567 delete rep;
568 }
569}
570
571bool KJS::operator==(const UString& s1, const UString& s2)
572{
573 if (s1.rep->len != s2.rep->len)
574 return false;
575
576 return (memcmp(s1.rep->dat, s2.rep->dat,
577 s1.rep->len * sizeof(UChar)) == 0);
578}
579
580bool KJS::operator==(const UString& s1, const char *s2)
581{
582 if (s2 == 0L && s1.isNull())
583 return true;
584
585 if (s1.size() != (int) strlen(s2))
586 return false;
587
588 const UChar *u = s1.data();
589 while (*s2) {
590 if (u->uc != *s2 )
591 return false;
592 s2++;
593 u++;
594 }
595
596 return true;
597}
598
599bool KJS::operator<(const UString& s1, const UString& s2)
600{
601 const int l1 = s1.size();
602 const int l2 = s2.size();
603 const int lmin = l1 < l2 ? l1 : l2;
604 const UChar *c1 = s1.data();
605 const UChar *c2 = s2.data();
606 int l = 0;
607 while (l < lmin && *c1 == *c2) {
608 c1++;
609 c2++;
610 l++;
611 }
612 if (l < lmin)
613 return (c1->unicode() < c2->unicode());
614
615 return (l1 < l2);
616}
617
618UString KJS::operator+(const UString& s1, const UString& s2)
619{
620 UString tmp(s1);
621 tmp.append(s2);
622
623 return tmp;
624}
Note: See TracBrowser for help on using the repository browser.