blob: 8f9c9f72329e5b3f9eeb9df3199a09ff5fb9ec89 [file] [log] [blame]
The Android Open Source Projectcbb10112009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2005 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Abhishek Aryae0dce902015-08-20 17:38:16 -070017#define __STDC_LIMIT_MACROS
18#include <stdint.h>
19
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080020#include <utils/String8.h>
21
Elliott Hughes1f8bc862015-07-29 14:02:29 -070022#include <utils/Compat.h>
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080023#include <utils/Log.h>
24#include <utils/String16.h>
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080025
Steven Morelandd21cfab2017-03-10 08:58:36 -080026#include <ctype.h>
27
Sergio Girod2529f22015-09-23 16:22:59 +010028#include "SharedBuffer.h"
29
Daisuke Miyakawa44dad3e2009-06-30 20:40:42 +090030/*
31 * Functions outside android is below the namespace android, since they use
32 * functions and constants in android namespace.
33 */
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080034
35// ---------------------------------------------------------------------------
36
Daisuke Miyakawa44dad3e2009-06-30 20:40:42 +090037namespace android {
38
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080039// Separator used by resource paths. This is not platform dependent contrary
40// to OS_PATH_SEPARATOR.
41#define RES_PATH_SEPARATOR '/'
42
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080043static SharedBuffer* gEmptyStringBuf = NULL;
44static char* gEmptyString = NULL;
45
46extern int gDarwinCantLoadAllObjects;
47int gDarwinIsReallyAnnoying;
48
Mathias Agopian9eb2a3b2013-05-06 20:20:50 -070049void initialize_string8();
50
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080051static inline char* getEmptyString()
52{
53 gEmptyStringBuf->acquire();
54 return gEmptyString;
55}
56
57void initialize_string8()
58{
Dan Egnor88753ae2010-05-06 00:55:09 -070059 // HACK: This dummy dependency forces linking libutils Static.cpp,
60 // which is needed to initialize String8/String16 classes.
61 // These variables are named for Darwin, but are needed elsewhere too,
62 // including static linking on any platform.
63 gDarwinIsReallyAnnoying = gDarwinCantLoadAllObjects;
Daisuke Miyakawa44dad3e2009-06-30 20:40:42 +090064
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080065 SharedBuffer* buf = SharedBuffer::alloc(1);
66 char* str = (char*)buf->data();
67 *str = 0;
68 gEmptyStringBuf = buf;
69 gEmptyString = str;
70}
71
72void terminate_string8()
73{
74 SharedBuffer::bufferFromData(gEmptyString)->release();
75 gEmptyStringBuf = NULL;
76 gEmptyString = NULL;
77}
78
79// ---------------------------------------------------------------------------
80
81static char* allocFromUTF8(const char* in, size_t len)
82{
83 if (len > 0) {
Sergio Giroebabef22015-08-18 14:44:54 +010084 if (len == SIZE_MAX) {
85 return NULL;
86 }
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080087 SharedBuffer* buf = SharedBuffer::alloc(len+1);
Steve Blockae074452012-01-09 18:35:44 +000088 ALOG_ASSERT(buf, "Unable to allocate shared buffer");
The Android Open Source Projectcbb10112009-03-03 19:31:44 -080089 if (buf) {
90 char* str = (char*)buf->data();
91 memcpy(str, in, len);
92 str[len] = 0;
93 return str;
94 }
95 return NULL;
96 }
97
98 return getEmptyString();
99}
100
Daisuke Miyakawa44dad3e2009-06-30 20:40:42 +0900101static char* allocFromUTF16(const char16_t* in, size_t len)
102{
Kenny Root9a2d83e2009-12-04 09:38:48 -0800103 if (len == 0) return getEmptyString();
104
Sergio Giroc4966a32016-06-28 18:02:29 +0100105 // Allow for closing '\0'
106 const ssize_t resultStrLen = utf16_to_utf8_length(in, len) + 1;
107 if (resultStrLen < 1) {
Kenny Rootba0165b2010-11-09 14:37:23 -0800108 return getEmptyString();
109 }
Kenny Root9a2d83e2009-12-04 09:38:48 -0800110
Sergio Giroc4966a32016-06-28 18:02:29 +0100111 SharedBuffer* buf = SharedBuffer::alloc(resultStrLen);
Steve Blockae074452012-01-09 18:35:44 +0000112 ALOG_ASSERT(buf, "Unable to allocate shared buffer");
Kenny Rootba0165b2010-11-09 14:37:23 -0800113 if (!buf) {
114 return getEmptyString();
Kenny Root9a2d83e2009-12-04 09:38:48 -0800115 }
116
Sergio Giroc4966a32016-06-28 18:02:29 +0100117 char* resultStr = (char*)buf->data();
118 utf16_to_utf8(in, len, resultStr, resultStrLen);
119 return resultStr;
Daisuke Miyakawa44dad3e2009-06-30 20:40:42 +0900120}
121
122static char* allocFromUTF32(const char32_t* in, size_t len)
123{
Kenny Rootba0165b2010-11-09 14:37:23 -0800124 if (len == 0) {
125 return getEmptyString();
126 }
127
Sergio Giroc4966a32016-06-28 18:02:29 +0100128 const ssize_t resultStrLen = utf32_to_utf8_length(in, len) + 1;
129 if (resultStrLen < 1) {
Kenny Rootba0165b2010-11-09 14:37:23 -0800130 return getEmptyString();
131 }
132
Sergio Giroc4966a32016-06-28 18:02:29 +0100133 SharedBuffer* buf = SharedBuffer::alloc(resultStrLen);
Steve Blockae074452012-01-09 18:35:44 +0000134 ALOG_ASSERT(buf, "Unable to allocate shared buffer");
Kenny Rootba0165b2010-11-09 14:37:23 -0800135 if (!buf) {
136 return getEmptyString();
137 }
138
Sergio Giroc4966a32016-06-28 18:02:29 +0100139 char* resultStr = (char*) buf->data();
140 utf32_to_utf8(in, len, resultStr, resultStrLen);
Kenny Rootba0165b2010-11-09 14:37:23 -0800141
Sergio Giroc4966a32016-06-28 18:02:29 +0100142 return resultStr;
Daisuke Miyakawa44dad3e2009-06-30 20:40:42 +0900143}
144
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800145// ---------------------------------------------------------------------------
146
147String8::String8()
148 : mString(getEmptyString())
149{
150}
151
Mathias Agopian4485d0d2013-05-08 16:04:13 -0700152String8::String8(StaticLinkage)
153 : mString(0)
154{
155 // this constructor is used when we can't rely on the static-initializers
156 // having run. In this case we always allocate an empty string. It's less
157 // efficient than using getEmptyString(), but we assume it's uncommon.
158
159 char* data = static_cast<char*>(
160 SharedBuffer::alloc(sizeof(char))->data());
161 data[0] = 0;
162 mString = data;
163}
164
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800165String8::String8(const String8& o)
166 : mString(o.mString)
167{
168 SharedBuffer::bufferFromData(mString)->acquire();
169}
170
171String8::String8(const char* o)
172 : mString(allocFromUTF8(o, strlen(o)))
173{
174 if (mString == NULL) {
175 mString = getEmptyString();
176 }
177}
178
179String8::String8(const char* o, size_t len)
180 : mString(allocFromUTF8(o, len))
181{
182 if (mString == NULL) {
183 mString = getEmptyString();
184 }
185}
186
187String8::String8(const String16& o)
188 : mString(allocFromUTF16(o.string(), o.size()))
189{
190}
191
192String8::String8(const char16_t* o)
193 : mString(allocFromUTF16(o, strlen16(o)))
194{
195}
196
197String8::String8(const char16_t* o, size_t len)
198 : mString(allocFromUTF16(o, len))
199{
200}
201
Daisuke Miyakawa44dad3e2009-06-30 20:40:42 +0900202String8::String8(const char32_t* o)
203 : mString(allocFromUTF32(o, strlen32(o)))
204{
205}
206
207String8::String8(const char32_t* o, size_t len)
208 : mString(allocFromUTF32(o, len))
209{
210}
211
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800212String8::~String8()
213{
214 SharedBuffer::bufferFromData(mString)->release();
215}
216
Sergio Girod2529f22015-09-23 16:22:59 +0100217size_t String8::length() const
218{
219 return SharedBuffer::sizeFromData(mString)-1;
220}
221
Jeff Brown1d618d62010-12-02 13:50:46 -0800222String8 String8::format(const char* fmt, ...)
223{
224 va_list args;
225 va_start(args, fmt);
226
227 String8 result(formatV(fmt, args));
228
229 va_end(args);
230 return result;
231}
232
233String8 String8::formatV(const char* fmt, va_list args)
234{
235 String8 result;
236 result.appendFormatV(fmt, args);
237 return result;
238}
239
Jeff Brown48da31b2010-09-12 17:55:08 -0700240void String8::clear() {
241 SharedBuffer::bufferFromData(mString)->release();
242 mString = getEmptyString();
243}
244
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800245void String8::setTo(const String8& other)
246{
247 SharedBuffer::bufferFromData(other.mString)->acquire();
248 SharedBuffer::bufferFromData(mString)->release();
249 mString = other.mString;
250}
251
252status_t String8::setTo(const char* other)
253{
Andreas Huber10e5da52010-06-10 11:14:26 -0700254 const char *newString = allocFromUTF8(other, strlen(other));
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800255 SharedBuffer::bufferFromData(mString)->release();
Andreas Huber10e5da52010-06-10 11:14:26 -0700256 mString = newString;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800257 if (mString) return NO_ERROR;
258
259 mString = getEmptyString();
260 return NO_MEMORY;
261}
262
263status_t String8::setTo(const char* other, size_t len)
264{
Andreas Huber10e5da52010-06-10 11:14:26 -0700265 const char *newString = allocFromUTF8(other, len);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800266 SharedBuffer::bufferFromData(mString)->release();
Andreas Huber10e5da52010-06-10 11:14:26 -0700267 mString = newString;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800268 if (mString) return NO_ERROR;
269
270 mString = getEmptyString();
271 return NO_MEMORY;
272}
273
274status_t String8::setTo(const char16_t* other, size_t len)
275{
Andreas Huber10e5da52010-06-10 11:14:26 -0700276 const char *newString = allocFromUTF16(other, len);
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800277 SharedBuffer::bufferFromData(mString)->release();
Andreas Huber10e5da52010-06-10 11:14:26 -0700278 mString = newString;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800279 if (mString) return NO_ERROR;
280
281 mString = getEmptyString();
282 return NO_MEMORY;
283}
284
Daisuke Miyakawa44dad3e2009-06-30 20:40:42 +0900285status_t String8::setTo(const char32_t* other, size_t len)
286{
Andreas Huber10e5da52010-06-10 11:14:26 -0700287 const char *newString = allocFromUTF32(other, len);
Daisuke Miyakawa44dad3e2009-06-30 20:40:42 +0900288 SharedBuffer::bufferFromData(mString)->release();
Andreas Huber10e5da52010-06-10 11:14:26 -0700289 mString = newString;
Daisuke Miyakawa44dad3e2009-06-30 20:40:42 +0900290 if (mString) return NO_ERROR;
291
292 mString = getEmptyString();
293 return NO_MEMORY;
294}
295
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800296status_t String8::append(const String8& other)
297{
298 const size_t otherLen = other.bytes();
299 if (bytes() == 0) {
300 setTo(other);
301 return NO_ERROR;
302 } else if (otherLen == 0) {
303 return NO_ERROR;
304 }
305
306 return real_append(other.string(), otherLen);
307}
308
309status_t String8::append(const char* other)
310{
311 return append(other, strlen(other));
312}
313
314status_t String8::append(const char* other, size_t otherLen)
315{
316 if (bytes() == 0) {
317 return setTo(other, otherLen);
318 } else if (otherLen == 0) {
319 return NO_ERROR;
320 }
321
322 return real_append(other, otherLen);
323}
324
Jeff Brown35a154e2010-07-15 23:54:05 -0700325status_t String8::appendFormat(const char* fmt, ...)
326{
Jeff Brown647925d2010-11-10 16:03:06 -0800327 va_list args;
328 va_start(args, fmt);
Jeff Brown35a154e2010-07-15 23:54:05 -0700329
Jeff Brown647925d2010-11-10 16:03:06 -0800330 status_t result = appendFormatV(fmt, args);
331
332 va_end(args);
333 return result;
334}
335
336status_t String8::appendFormatV(const char* fmt, va_list args)
337{
Fengwei Yinfff9d112014-02-27 01:17:09 +0800338 int n, result = NO_ERROR;
339 va_list tmp_args;
340
341 /* args is undefined after vsnprintf.
342 * So we need a copy here to avoid the
343 * second vsnprintf access undefined args.
344 */
345 va_copy(tmp_args, args);
346 n = vsnprintf(NULL, 0, fmt, tmp_args);
347 va_end(tmp_args);
348
Steven Morelandee223842020-07-28 21:41:54 +0000349 if (n < 0) return UNKNOWN_ERROR;
350
351 if (n > 0) {
Jeff Brown35a154e2010-07-15 23:54:05 -0700352 size_t oldLength = length();
Steven Morelandee223842020-07-28 21:41:54 +0000353 if ((size_t)n > SIZE_MAX - 1 ||
354 oldLength > SIZE_MAX - (size_t)n - 1) {
355 return NO_MEMORY;
356 }
Jeff Brown35a154e2010-07-15 23:54:05 -0700357 char* buf = lockBuffer(oldLength + n);
358 if (buf) {
Jeff Brown647925d2010-11-10 16:03:06 -0800359 vsnprintf(buf + oldLength, n + 1, fmt, args);
Jeff Brown35a154e2010-07-15 23:54:05 -0700360 } else {
361 result = NO_MEMORY;
362 }
363 }
Jeff Brown35a154e2010-07-15 23:54:05 -0700364 return result;
365}
366
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800367status_t String8::real_append(const char* other, size_t otherLen)
368{
369 const size_t myLen = bytes();
Samuel Tan95fd5272016-02-18 16:56:21 -0800370
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800371 SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
372 ->editResize(myLen+otherLen+1);
373 if (buf) {
374 char* str = (char*)buf->data();
375 mString = str;
376 str += myLen;
377 memcpy(str, other, otherLen);
378 str[otherLen] = '\0';
379 return NO_ERROR;
380 }
381 return NO_MEMORY;
382}
383
384char* String8::lockBuffer(size_t size)
385{
386 SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
387 ->editResize(size+1);
388 if (buf) {
389 char* str = (char*)buf->data();
390 mString = str;
391 return str;
392 }
393 return NULL;
394}
395
396void String8::unlockBuffer()
397{
398 unlockBuffer(strlen(mString));
399}
400
401status_t String8::unlockBuffer(size_t size)
402{
403 if (size != this->size()) {
404 SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
405 ->editResize(size+1);
Jeff Brown35a154e2010-07-15 23:54:05 -0700406 if (! buf) {
407 return NO_MEMORY;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800408 }
Jeff Brown35a154e2010-07-15 23:54:05 -0700409
410 char* str = (char*)buf->data();
411 str[size] = 0;
412 mString = str;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800413 }
Jeff Brown35a154e2010-07-15 23:54:05 -0700414
415 return NO_ERROR;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800416}
417
418ssize_t String8::find(const char* other, size_t start) const
419{
420 size_t len = size();
421 if (start >= len) {
422 return -1;
423 }
424 const char* s = mString+start;
425 const char* p = strstr(s, other);
426 return p ? p-mString : -1;
427}
428
Jeff Brown5ee915a2014-06-06 19:30:15 -0700429bool String8::removeAll(const char* other) {
430 ssize_t index = find(other);
431 if (index < 0) return false;
432
433 char* buf = lockBuffer(size());
434 if (!buf) return false; // out of memory
435
436 size_t skip = strlen(other);
437 size_t len = size();
438 size_t tail = index;
439 while (size_t(index) < len) {
440 ssize_t next = find(other, index + skip);
441 if (next < 0) {
442 next = len;
443 }
444
Andreas Gampedd060f02014-11-13 15:50:17 -0800445 memmove(buf + tail, buf + index + skip, next - index - skip);
Jeff Brown5ee915a2014-06-06 19:30:15 -0700446 tail += next - index - skip;
447 index = next;
448 }
449 unlockBuffer(tail);
450 return true;
451}
452
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800453void String8::toLower()
454{
455 toLower(0, size());
456}
457
458void String8::toLower(size_t start, size_t length)
459{
460 const size_t len = size();
461 if (start >= len) {
462 return;
463 }
464 if (start+length > len) {
465 length = len-start;
466 }
467 char* buf = lockBuffer(len);
468 buf += start;
469 while (length > 0) {
470 *buf = tolower(*buf);
471 buf++;
472 length--;
473 }
474 unlockBuffer(len);
475}
476
477void String8::toUpper()
478{
479 toUpper(0, size());
480}
481
482void String8::toUpper(size_t start, size_t length)
483{
484 const size_t len = size();
485 if (start >= len) {
486 return;
487 }
488 if (start+length > len) {
489 length = len-start;
490 }
491 char* buf = lockBuffer(len);
492 buf += start;
493 while (length > 0) {
494 *buf = toupper(*buf);
495 buf++;
496 length--;
497 }
498 unlockBuffer(len);
499}
500
Daisuke Miyakawa44dad3e2009-06-30 20:40:42 +0900501size_t String8::getUtf32Length() const
502{
Kenny Rootba0165b2010-11-09 14:37:23 -0800503 return utf8_to_utf32_length(mString, length());
Daisuke Miyakawa44dad3e2009-06-30 20:40:42 +0900504}
505
506int32_t String8::getUtf32At(size_t index, size_t *next_index) const
507{
Kenny Rootba0165b2010-11-09 14:37:23 -0800508 return utf32_from_utf8_at(mString, length(), index, next_index);
Daisuke Miyakawa44dad3e2009-06-30 20:40:42 +0900509}
510
Kenny Rootba0165b2010-11-09 14:37:23 -0800511void String8::getUtf32(char32_t* dst) const
Daisuke Miyakawa44dad3e2009-06-30 20:40:42 +0900512{
Kenny Rootba0165b2010-11-09 14:37:23 -0800513 utf8_to_utf32(mString, length(), dst);
Daisuke Miyakawa44dad3e2009-06-30 20:40:42 +0900514}
515
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800516// ---------------------------------------------------------------------------
517// Path functions
518
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800519void String8::setPathName(const char* name)
520{
521 setPathName(name, strlen(name));
522}
523
524void String8::setPathName(const char* name, size_t len)
525{
526 char* buf = lockBuffer(len);
527
528 memcpy(buf, name, len);
529
530 // remove trailing path separator, if present
531 if (len > 0 && buf[len-1] == OS_PATH_SEPARATOR)
532 len--;
533
534 buf[len] = '\0';
535
536 unlockBuffer(len);
537}
538
539String8 String8::getPathLeaf(void) const
540{
541 const char* cp;
542 const char*const buf = mString;
543
544 cp = strrchr(buf, OS_PATH_SEPARATOR);
545 if (cp == NULL)
546 return String8(*this);
547 else
548 return String8(cp+1);
549}
550
551String8 String8::getPathDir(void) const
552{
553 const char* cp;
554 const char*const str = mString;
555
556 cp = strrchr(str, OS_PATH_SEPARATOR);
557 if (cp == NULL)
558 return String8("");
559 else
560 return String8(str, cp - str);
561}
562
563String8 String8::walkPath(String8* outRemains) const
564{
565 const char* cp;
566 const char*const str = mString;
567 const char* buf = str;
568
569 cp = strchr(buf, OS_PATH_SEPARATOR);
570 if (cp == buf) {
571 // don't include a leading '/'.
572 buf = buf+1;
573 cp = strchr(buf, OS_PATH_SEPARATOR);
574 }
575
576 if (cp == NULL) {
577 String8 res = buf != str ? String8(buf) : *this;
578 if (outRemains) *outRemains = String8("");
579 return res;
580 }
581
582 String8 res(buf, cp-buf);
583 if (outRemains) *outRemains = String8(cp+1);
584 return res;
585}
586
587/*
588 * Helper function for finding the start of an extension in a pathname.
589 *
590 * Returns a pointer inside mString, or NULL if no extension was found.
591 */
592char* String8::find_extension(void) const
593{
594 const char* lastSlash;
595 const char* lastDot;
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800596 const char* const str = mString;
597
598 // only look at the filename
599 lastSlash = strrchr(str, OS_PATH_SEPARATOR);
600 if (lastSlash == NULL)
601 lastSlash = str;
602 else
603 lastSlash++;
604
605 // find the last dot
606 lastDot = strrchr(lastSlash, '.');
607 if (lastDot == NULL)
608 return NULL;
609
610 // looks good, ship it
611 return const_cast<char*>(lastDot);
612}
613
614String8 String8::getPathExtension(void) const
615{
616 char* ext;
617
618 ext = find_extension();
619 if (ext != NULL)
620 return String8(ext);
621 else
622 return String8("");
623}
624
625String8 String8::getBasePath(void) const
626{
627 char* ext;
628 const char* const str = mString;
629
630 ext = find_extension();
631 if (ext == NULL)
632 return String8(*this);
633 else
634 return String8(str, ext - str);
635}
636
637String8& String8::appendPath(const char* name)
638{
639 // TODO: The test below will fail for Win32 paths. Fix later or ignore.
640 if (name[0] != OS_PATH_SEPARATOR) {
641 if (*name == '\0') {
642 // nothing to do
643 return *this;
644 }
645
646 size_t len = length();
647 if (len == 0) {
648 // no existing filename, just use the new one
649 setPathName(name);
650 return *this;
651 }
652
653 // make room for oldPath + '/' + newPath
654 int newlen = strlen(name);
655
656 char* buf = lockBuffer(len+1+newlen);
657
658 // insert a '/' if needed
659 if (buf[len-1] != OS_PATH_SEPARATOR)
660 buf[len++] = OS_PATH_SEPARATOR;
661
662 memcpy(buf+len, name, newlen+1);
663 len += newlen;
664
665 unlockBuffer(len);
666
667 return *this;
668 } else {
669 setPathName(name);
670 return *this;
671 }
672}
673
674String8& String8::convertToResPath()
675{
676#if OS_PATH_SEPARATOR != RES_PATH_SEPARATOR
677 size_t len = length();
678 if (len > 0) {
679 char * buf = lockBuffer(len);
680 for (char * end = buf + len; buf < end; ++buf) {
681 if (*buf == OS_PATH_SEPARATOR)
682 *buf = RES_PATH_SEPARATOR;
683 }
684 unlockBuffer(len);
685 }
686#endif
687 return *this;
688}
689
The Android Open Source Projectcbb10112009-03-03 19:31:44 -0800690}; // namespace android