Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(987)

Side by Side Diff: skia/sgl/SkString.cpp

Issue 113827: Remove the remainder of the skia source code from the Chromium repo.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 11 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « skia/sgl/SkSpriteBlitter_RGB16.cpp ('k') | skia/sgl/SkStroke.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /* libs/graphics/sgl/SkString.cpp
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 ** http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17
18 #include "SkString.h"
19 #include "SkFixed.h"
20 #include "SkUtils.h"
21 #include <stdarg.h>
22
23 bool SkStrStartsWith(const char string[], const char prefix[])
24 {
25 SkASSERT(string);
26 SkASSERT(prefix);
27 return !strncmp(string, prefix, strlen(prefix));
28 }
29
30 bool SkStrEndsWith(const char string[], const char suffix[])
31 {
32 SkASSERT(string);
33 SkASSERT(suffix);
34 size_t strLen = strlen(string);
35 size_t suffixLen = strlen(suffix);
36 return strLen >= suffixLen &&
37 !strncmp(string + strLen - suffixLen, suffix, suffixLen);
38 }
39
40 int SkStrStartsWithOneOf(const char string[], const char prefixes[])
41 {
42 int index = 0;
43 do {
44 const char* limit = strchr(prefixes, '\0');
45 if (!strncmp(string, prefixes, limit - prefixes))
46 return index;
47 prefixes = limit + 1;
48 index++;
49 } while (prefixes[0]);
50 return -1;
51 }
52
53 char* SkStrAppendS32(char string[], int32_t dec)
54 {
55 SkDEBUGCODE(char* start = string;)
56
57 char buffer[SkStrAppendS32_MaxSize];
58 char* p = buffer + sizeof(buffer);
59 bool neg = false;
60
61 if (dec < 0)
62 {
63 neg = true;
64 dec = -dec;
65 }
66 do {
67 *--p = SkToU8('0' + dec % 10);
68 dec /= 10;
69 } while (dec != 0);
70 if (neg)
71 *--p = '-';
72
73 SkASSERT(p >= buffer);
74 char* stop = buffer + sizeof(buffer);
75 while (p < stop)
76 *string++ = *p++;
77
78 SkASSERT(string - start <= SkStrAppendS32_MaxSize);
79 return string;
80 }
81
82 char* SkStrAppendScalar(char string[], SkScalar value)
83 {
84 SkDEBUGCODE(char* start = string;)
85
86 SkFixed x = SkScalarToFixed(value);
87
88 if (x < 0)
89 {
90 *string++ = '-';
91 x = -x;
92 }
93
94 unsigned frac = x & 0xFFFF;
95 x >>= 16;
96 if (frac == 0xFFFF) // need to do this to "round up", since 65535/65536 is c loser to 1 than to .9999
97 {
98 x += 1;
99 frac = 0;
100 }
101 string = SkStrAppendS32(string, x);
102
103 // now handle the fractional part (if any)
104 if (frac)
105 {
106 static const uint16_t gTens[] = { 1000, 100, 10, 1 };
107 const uint16_t* tens = gTens;
108
109 x = SkFixedRound(frac * 10000);
110 SkASSERT(x <= 10000);
111 if (x == 10000) {
112 x -= 1;
113 }
114 *string++ = '.';
115 do {
116 unsigned powerOfTen = *tens++;
117 *string++ = SkToU8('0' + x / powerOfTen);
118 x %= powerOfTen;
119 } while (x != 0);
120 }
121
122 SkASSERT(string - start <= SkStrAppendScalar_MaxSize);
123 return string;
124 }
125
126 //////////////////////////////////////////////////////////////////////////////// ////
127
128 #define kMaxRefCnt_SkString SK_MaxU16
129
130 // the 3 values are [length] [refcnt] [terminating zero data]
131 const SkString::Rec SkString::gEmptyRec = { 0, 0, 0 };
132
133 #define SizeOfRec() (gEmptyRec.data() - (const char*)&gEmptyRec)
134
135 SkString::Rec* SkString::AllocRec(const char text[], U16CPU len)
136 {
137 Rec* rec;
138
139 if (len == 0)
140 rec = const_cast<Rec*>(&gEmptyRec);
141 else
142 {
143 // add 1 for terminating 0, then align4 so we can have some slop when gr owing the string
144 rec = (Rec*)sk_malloc_throw(SizeOfRec() + SkAlign4(len + 1));
145 rec->fLength = SkToU16(len);
146 rec->fRefCnt = 1;
147 if (text)
148 memcpy(rec->data(), text, len);
149 rec->data()[len] = 0;
150 }
151 return rec;
152 }
153
154 SkString::Rec* SkString::RefRec(Rec* src)
155 {
156 if (src != &gEmptyRec)
157 {
158 if (src->fRefCnt == kMaxRefCnt_SkString) {
159 src = AllocRec(src->data(), src->fLength);
160 } else
161 src->fRefCnt += 1;
162 }
163 return src;
164 }
165
166 #ifdef SK_DEBUG
167 void SkString::validate() const
168 {
169 // make sure know one has written over our global
170 SkASSERT(gEmptyRec.fLength == 0);
171 SkASSERT(gEmptyRec.fRefCnt == 0);
172 SkASSERT(gEmptyRec.data()[0] == 0);
173
174 if (fRec != &gEmptyRec)
175 {
176 SkASSERT(fRec->fLength > 0);
177 SkASSERT(fRec->fRefCnt > 0);
178 SkASSERT(fRec->data()[fRec->fLength] == 0);
179 }
180 SkASSERT(fStr == c_str());
181 }
182 #endif
183
184 ///////////////////////////////////////////////////////////////////////
185
186 SkString::SkString() : fRec(const_cast<Rec*>(&gEmptyRec)) {
187 #ifdef SK_DEBUG
188 fStr = fRec->data();
189 #endif
190 }
191
192 SkString::SkString(size_t len)
193 {
194 SkASSERT(SkToU16(len) == len); // can't handle larger than 64K
195
196 fRec = AllocRec(NULL, (U16CPU)len);
197 #ifdef SK_DEBUG
198 fStr = fRec->data();
199 #endif
200 }
201
202 SkString::SkString(const char text[])
203 {
204 size_t len = text ? strlen(text) : 0;
205
206 fRec = AllocRec(text, (U16CPU)len);
207 #ifdef SK_DEBUG
208 fStr = fRec->data();
209 #endif
210 }
211
212 SkString::SkString(const char text[], size_t len)
213 {
214 fRec = AllocRec(text, (U16CPU)len);
215 #ifdef SK_DEBUG
216 fStr = fRec->data();
217 #endif
218 }
219
220 SkString::SkString(const SkString& src)
221 {
222 src.validate();
223
224 fRec = RefRec(src.fRec);
225 #ifdef SK_DEBUG
226 fStr = fRec->data();
227 #endif
228 }
229
230 SkString::~SkString()
231 {
232 this->validate();
233
234 if (fRec->fLength)
235 {
236 SkASSERT(fRec->fRefCnt > 0);
237 if (--fRec->fRefCnt == 0)
238 sk_free(fRec);
239 }
240 }
241
242 bool SkString::equals(const SkString& src) const
243 {
244 return fRec == src.fRec || this->equals(src.c_str(), src.size());
245 }
246
247 bool SkString::equals(const char text[]) const
248 {
249 return this->equals(text, text ? strlen(text) : 0);
250 }
251
252 bool SkString::equals(const char text[], size_t len) const
253 {
254 SkASSERT(len == 0 || text != NULL);
255
256 return fRec->fLength == len && !memcmp(fRec->data(), text, len);
257 }
258
259 SkString& SkString::operator=(const SkString& src)
260 {
261 this->validate();
262
263 if (fRec != src.fRec)
264 {
265 SkString tmp(src);
266 this->swap(tmp);
267 }
268 return *this;
269 }
270
271 void SkString::reset()
272 {
273 this->validate();
274
275 if (fRec->fLength)
276 {
277 SkASSERT(fRec->fRefCnt > 0);
278 if (--fRec->fRefCnt == 0)
279 sk_free(fRec);
280 }
281
282 fRec = const_cast<Rec*>(&gEmptyRec);
283 #ifdef SK_DEBUG
284 fStr = fRec->data();
285 #endif
286 }
287
288 char* SkString::writable_str()
289 {
290 this->validate();
291
292 if (fRec->fLength)
293 {
294 if (fRec->fRefCnt > 1)
295 {
296 fRec->fRefCnt -= 1;
297 fRec = AllocRec(fRec->data(), fRec->fLength);
298 #ifdef SK_DEBUG
299 fStr = fRec->data();
300 #endif
301 }
302 }
303 return fRec->data();
304 }
305
306 void SkString::set(const char text[])
307 {
308 this->set(text, text ? strlen(text) : 0);
309 }
310
311 void SkString::set(const char text[], size_t len)
312 {
313 if (len == 0)
314 this->reset();
315 else if (fRec->fRefCnt == 1 && len <= fRec->fLength) // should we resize if len <<<< fLength, to save RAM? (e.g. len < (fLength>>1))
316 {
317 // just use less of the buffer without allocating a smaller one
318 char* p = this->writable_str();
319 if (text)
320 memcpy(p, text, len);
321 p[len] = 0;
322 fRec->fLength = SkToU16(len);
323 }
324 else if (fRec->fRefCnt == 1 && ((unsigned)fRec->fLength >> 2) == (len >> 2))
325 {
326 // we have spare room in the current allocation, so don't alloc a larger one
327 char* p = this->writable_str();
328 if (text)
329 memcpy(p, text, len);
330 p[len] = 0;
331 fRec->fLength = SkToU16(len);
332 }
333 else
334 {
335 SkString tmp(text, len);
336 this->swap(tmp);
337 }
338 }
339
340 void SkString::setUTF16(const uint16_t src[])
341 {
342 int count = 0;
343
344 while (src[count])
345 count += 1;
346 setUTF16(src, count);
347 }
348
349 void SkString::setUTF16(const uint16_t src[], size_t count)
350 {
351 if (count == 0)
352 this->reset();
353 else if (count <= fRec->fLength) // should we resize if len <<<< fLength, to save RAM? (e.g. len < (fLength>>1))
354 {
355 if (count < fRec->fLength)
356 this->resize(count);
357 char* p = this->writable_str();
358 for (size_t i = 0; i < count; i++)
359 p[i] = SkToU8(src[i]);
360 p[count] = 0;
361 }
362 else
363 {
364 SkString tmp(count); // puts a null terminator at the end of the stri ng
365 char* p = tmp.writable_str();
366
367 for (size_t i = 0; i < count; i++)
368 p[i] = SkToU8(src[i]);
369
370 this->swap(tmp);
371 }
372 }
373
374 void SkString::insert(size_t offset, const char text[])
375 {
376 this->insert(offset, text, text ? strlen(text) : 0);
377 }
378
379 void SkString::insert(size_t offset, const char text[], size_t len)
380 {
381 if (len)
382 {
383 size_t length = fRec->fLength;
384 if (offset > length)
385 offset = length;
386
387 /* If we're the only owner, and we have room in our allocation for the insert,
388 do it in place, rather than allocating a new buffer.
389
390 To know we have room, compare the allocated sizes
391 beforeAlloc = SkAlign4(length + 1)
392 afterAlloc = SkAligh4(length + 1 + len)
393 but SkAlign4(x) is (x + 3) >> 2 << 2
394 which is equivalent for testing to (length + 1 + 3) >> 2 == (length + 1 + 3 + len) >> 2
395 and we can then eliminate the +1+3 since that doesn't affec the answ er
396 */
397 if (fRec->fRefCnt == 1 && (length >> 2) == ((length + len) >> 2))
398 {
399 char* dst = this->writable_str();
400
401 if (offset < length)
402 memmove(dst + offset + len, dst + offset, length - offset);
403 memcpy(dst + offset, text, len);
404
405 dst[length + len] = 0;
406 fRec->fLength = SkToU16(length + len);
407 }
408 else
409 {
410 /* Seems we should use realloc here, since that is safe if it fails
411 (we have the original data), and might be faster than alloc/copy /free.
412 */
413 SkString tmp(fRec->fLength + len);
414 char* dst = tmp.writable_str();
415
416 if (offset > 0)
417 memcpy(dst, fRec->data(), offset);
418 memcpy(dst + offset, text, len);
419 if (offset < fRec->fLength)
420 memcpy(dst + offset + len, fRec->data() + offset, fRec->fLength - offset);
421
422 this->swap(tmp);
423 }
424 }
425 }
426
427 void SkString::insertUnichar(size_t offset, SkUnichar uni)
428 {
429 char buffer[kMaxBytesInUTF8Sequence];
430 size_t len = SkUTF8_FromUnichar(uni, buffer);
431
432 if (len)
433 this->insert(offset, buffer, len);
434 }
435
436 void SkString::insertS32(size_t offset, int32_t dec)
437 {
438 char buffer[SkStrAppendS32_MaxSize];
439 char* stop = SkStrAppendS32(buffer, dec);
440 this->insert(offset, buffer, stop - buffer);
441 }
442
443 void SkString::insertHex(size_t offset, uint32_t hex, int minDigits)
444 {
445 minDigits = SkPin32(minDigits, 0, 8);
446
447 static const char gHex[] = "0123456789ABCDEF";
448
449 char buffer[8];
450 char* p = buffer + sizeof(buffer);
451
452 do {
453 *--p = gHex[hex & 0xF];
454 hex >>= 4;
455 minDigits -= 1;
456 } while (hex != 0);
457 while (--minDigits >= 0)
458 *--p = '0';
459
460 SkASSERT(p >= buffer);
461 this->insert(offset, p, buffer + sizeof(buffer) - p);
462 }
463
464 void SkString::insertScalar(size_t offset, SkScalar value)
465 {
466 char buffer[SkStrAppendScalar_MaxSize];
467 char* stop = SkStrAppendScalar(buffer, value);
468 this->insert(offset, buffer, stop - buffer);
469 }
470
471 ///////////////////////////////////////////////////////////////////////////
472
473 //#include <stdarg.h>
474 #if defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_F OR_UNIX)
475 #include <stdio.h>
476 #endif
477
478 void SkString::printf(const char format[], ...)
479 {
480 static const size_t kBufferSize = 100;
481
482 char buffer[kBufferSize + 1];
483
484 #ifdef SK_BUILD_FOR_WIN
485 va_list args;
486 va_start(args, format);
487 _vsnprintf(buffer, kBufferSize, format, args);
488 va_end(args);
489 #elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_UNIX)
490 va_list args;
491 va_start(args, format);
492 vsnprintf(buffer, kBufferSize, format, args);
493 va_end(args);
494 #else
495 buffer[0] = 0;
496 #endif
497
498 this->set(buffer, strlen(buffer));
499 }
500
501 ///////////////////////////////////////////////////////////////////////////
502
503 void SkString::remove(size_t offset, size_t length)
504 {
505 size_t size = this->size();
506
507 if (offset < size)
508 {
509 if (offset + length > size)
510 length = size - offset;
511 if (length > 0)
512 {
513 SkASSERT(size > length);
514 SkString tmp(size - length);
515 char* dst = tmp.writable_str();
516 const char* src = this->c_str();
517
518 if (offset)
519 {
520 SkASSERT(offset <= tmp.size());
521 memcpy(dst, src, offset);
522 }
523 size_t tail = size - offset - length;
524 SkASSERT((int32_t)tail >= 0);
525 if (tail)
526 {
527 // SkASSERT(offset + length <= tmp.size());
528 memcpy(dst + offset, src + offset + length, tail);
529 }
530 SkASSERT(dst[tmp.size()] == 0);
531 this->swap(tmp);
532 }
533 }
534 }
535
536 void SkString::swap(SkString& other)
537 {
538 this->validate();
539 other.validate();
540
541 SkTSwap<Rec*>(fRec, other.fRec);
542 #ifdef SK_DEBUG
543 SkTSwap<const char*>(fStr, other.fStr);
544 #endif
545 }
546
547 //////////////////////////////////////////////////////////////////////////////// /
548
549 SkAutoUCS2::SkAutoUCS2(const char utf8[])
550 {
551 size_t len = strlen(utf8);
552 fUCS2 = (uint16_t*)sk_malloc_throw((len + 1) * sizeof(uint16_t));
553
554 uint16_t* dst = fUCS2;
555 for (;;)
556 {
557 SkUnichar uni = SkUTF8_NextUnichar(&utf8);
558 *dst++ = SkToU16(uni);
559 if (uni == 0)
560 break;
561 }
562 fCount = (int)(dst - fUCS2);
563 }
564
565 SkAutoUCS2::~SkAutoUCS2()
566 {
567 delete[] fUCS2;
568 }
569
570 //////////////////////////////////////////////////////////////////////////////// /
571 //////////////////////////////////////////////////////////////////////////////// /
572
573 #ifdef SK_DEBUG
574
575 void SkString::UnitTest()
576 {
577 #ifdef SK_SUPPORT_UNITTEST
578 SkString a;
579 SkString b((size_t)0);
580 SkString c("");
581 SkString d(NULL, 0);
582
583 SkASSERT(a.isEmpty());
584 SkASSERT(a == b && a == c && a == d);
585
586 a.set("hello");
587 b.set("hellox", 5);
588 c.set(a);
589 d.resize(5);
590 memcpy(d.writable_str(), "helloz", 5);
591
592 SkASSERT(!a.isEmpty());
593 SkASSERT(a.size() == 5);
594 SkASSERT(a == b && a == c && a == d);
595 SkASSERT(a.equals("hello", 5));
596 SkASSERT(a.equals("hello"));
597 SkASSERT(!a.equals("help"));
598
599 SkString e(a);
600 SkString f("hello");
601 SkString g("helloz", 5);
602
603 SkASSERT(a == e && a == f && a == g);
604
605 b.set("world");
606 c = b;
607 SkASSERT(a != b && a != c && b == c);
608
609 a.append(" world");
610 e.append("worldz", 5);
611 e.insert(5, " ");
612 f.set("world");
613 f.prepend("hello ");
614 SkASSERT(a.equals("hello world") && a == e && a == f);
615
616 a.reset();
617 b.resize(0);
618 SkASSERT(a.isEmpty() && b.isEmpty() && a == b);
619
620 a.set("a");
621 a.set("ab");
622 a.set("abc");
623 a.set("abcd");
624 #endif
625 }
626
627 #endif
628
OLDNEW
« no previous file with comments | « skia/sgl/SkSpriteBlitter_RGB16.cpp ('k') | skia/sgl/SkStroke.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698