~ubuntu-branches/ubuntu/quantal/open-vm-tools/quantal-201210021442

« back to all changes in this revision

Viewing changes to services/plugins/dndcp/stringxx/string.cc

  • Committer: Bazaar Package Importer
  • Author(s): Serge Hallyn
  • Date: 2011-03-31 14:20:05 UTC
  • mfrom: (1.4.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20110331142005-3n9red91p7ogkweo
Tags: 2011.03.28-387002-0ubuntu1
* Merge latest upstream git tag.  This has the unlocked_ioctl change
  needed to fix dkms build failures (LP: #727342)
* Changes in debian/rules:
  - work around a bug in toolbox/Makefile, where install-exec-hook is
    not happening.  This needs to get fixed the right way.
  - don't install 'vmware-user' which seems to no longer exist
  - move /etc/xdg into open-vm-toolbox (which should be done using .install)
* debian/open-vm-tools.init: add 'modprobe [-r] vmblock'. (LP: #332323)
* debian/rules and debian/open-vm-toolbox.lintian-overrides:
  - Make vmware-user-suid-wrapper suid-root (LP: #332323)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*********************************************************
 
2
 * Copyright (C) 2008 VMware, Inc. All rights reserved.
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify it
 
5
 * under the terms of the GNU Lesser General Public License as published
 
6
 * by the Free Software Foundation version 2.1 and no later version.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful, but
 
9
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 
10
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the Lesser GNU General Public
 
11
 * License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU Lesser General Public License
 
14
 * along with this program; if not, write to the Free Software Foundation, Inc.,
 
15
 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA.
 
16
 *
 
17
 *********************************************************/
 
18
 
 
19
/*
 
20
 * string.cc --
 
21
 *
 
22
 *     A string wrapper for bora/lib/unicode. This class is intended to provide
 
23
 *     more c++ features such as operator overloading, automatic string conversion
 
24
 *     between different types of string classes.
 
25
 */
 
26
 
 
27
 
 
28
#include <sstream>
 
29
#include <iostream>
 
30
 
 
31
#include "string.hh"
 
32
#include "unicode.h"
 
33
#include "util.h"
 
34
 
 
35
namespace utf {
 
36
 
 
37
/*
 
38
 * Initialize static scope variables,
 
39
 *
 
40
 * Note that with the way this is done, it's important not to delay load glib
 
41
 * libraries. See bug 397373 for more details. If you're getting crazy values
 
42
 * for utf::string::npos, check your linker flags.
 
43
 */
 
44
const string::size_type string::npos = Glib::ustring::npos;
 
45
 
 
46
 
 
47
/*
 
48
 *-----------------------------------------------------------------------------
 
49
 *
 
50
 * utf::string::string --
 
51
 *
 
52
 *      Constructor.
 
53
 *
 
54
 * Results:
 
55
 *      None.
 
56
 *
 
57
 * Side effects:
 
58
 *      None
 
59
 *
 
60
 *-----------------------------------------------------------------------------
 
61
 */
 
62
 
 
63
string::string()
 
64
   : mUstr(),
 
65
     mUtf16Cache(NULL),
 
66
     mUtf16Length(npos)
 
67
{
 
68
}
 
69
 
 
70
 
 
71
/*
 
72
 *-----------------------------------------------------------------------------
 
73
 *
 
74
 * utf::string::string --
 
75
 *
 
76
 *      Constructor.
 
77
 *
 
78
 * Results:
 
79
 *      None.
 
80
 *
 
81
 * Side effects:
 
82
 *      None
 
83
 *
 
84
 *-----------------------------------------------------------------------------
 
85
 */
 
86
 
 
87
string::string(ConstUnicode s) // IN
 
88
   : mUstr(),
 
89
     mUtf16Cache(NULL),
 
90
     mUtf16Length(npos)
 
91
{
 
92
   ASSERT(s);
 
93
   mUstr = Unicode_GetUTF8(s);
 
94
   ASSERT(Validate(mUstr));
 
95
}
 
96
 
 
97
 
 
98
#ifdef _WIN32
 
99
 
 
100
/*
 
101
 *-----------------------------------------------------------------------------
 
102
 *
 
103
 * utf::string::init_bstr_t --
 
104
 *
 
105
 *      Utility function to construct from a _bstr_t object.
 
106
 *      Copies the UTF-16 representation of the _bstr_t.
 
107
 *
 
108
 * Results:
 
109
 *      None.
 
110
 *
 
111
 * Side effects:
 
112
 *      Makes a copy of the _bstr_t data and frees that data when
 
113
 *      the utf::string is destroyed.
 
114
 *
 
115
 * Note:
 
116
 *      WIN32 only call
 
117
 *
 
118
 *-----------------------------------------------------------------------------
 
119
 */
 
120
 
 
121
void
 
122
string::init_bstr_t(const _bstr_t &s) // IN
 
123
{
 
124
   // If the input is empty, then there's nothing to do.
 
125
   if (s.length() == 0) {
 
126
      return;
 
127
   }
 
128
 
 
129
   Unicode utf8 = Unicode_AllocWithUTF16(static_cast<const utf16_t *>(s));
 
130
 
 
131
   try {
 
132
      mUstr = utf8;
 
133
      Unicode_Free(utf8);
 
134
   } catch (...) {
 
135
      Unicode_Free(utf8);
 
136
      throw;
 
137
   }
 
138
 
 
139
   ASSERT(Validate(mUstr));
 
140
}
 
141
 
 
142
 
 
143
/*
 
144
 *-----------------------------------------------------------------------------
 
145
 *
 
146
 * utf::string::string --
 
147
 *
 
148
 *      Constructor from a ubstr_t object.  Copies the UTF-16 representation of
 
149
 *      the ubstr_t.
 
150
 *
 
151
 * Results:
 
152
 *      None.
 
153
 *
 
154
 * Side effects:
 
155
 *      Makes a copy of the ubstr_t data and frees that data when the
 
156
 *      utf::string is destroyed.
 
157
 *
 
158
 * Note:
 
159
 *      WIN32 only call
 
160
 *
 
161
 *-----------------------------------------------------------------------------
 
162
 */
 
163
 
 
164
string::string(const ubstr_t &s) // IN
 
165
   : mUstr(),
 
166
     mUtf16Cache(NULL),
 
167
     mUtf16Length(npos)
 
168
{
 
169
   // If the input is empty, then there's nothing to do.
 
170
   if (s.length() == 0) {
 
171
      return;
 
172
   }
 
173
 
 
174
   mUstr = static_cast<const char *>(s);
 
175
   ASSERT(Validate(mUstr));
 
176
}
 
177
 
 
178
 
 
179
/*
 
180
 *-----------------------------------------------------------------------------
 
181
 *
 
182
 * utf::string::string --
 
183
 *
 
184
 *      Constructor from a _bstr_t object.  Copies the UTF-16 representation of
 
185
 *      the _bstr_t.  Needed for dealing with _com_error::Description().
 
186
 *
 
187
 * Results:
 
188
 *      None.
 
189
 *
 
190
 * Side effects:
 
191
 *      Makes a copy of the _bstr_t data and frees that data when
 
192
 *      the utf::string is destroyed.
 
193
 *
 
194
 * Note:
 
195
 *      WIN32 only call
 
196
 *
 
197
 *-----------------------------------------------------------------------------
 
198
 */
 
199
 
 
200
string::string(const _bstr_t &s) // IN
 
201
   : mUstr(),
 
202
     mUtf16Cache(NULL),
 
203
     mUtf16Length(npos)
 
204
{
 
205
   init_bstr_t(s);
 
206
}
 
207
 
 
208
 
 
209
/*
 
210
 *-----------------------------------------------------------------------------
 
211
 *
 
212
 * utf::string::string --
 
213
 *
 
214
 *      Constructor from a uvariant_t object. Copies the UTF-16 representation
 
215
 *      of the ubstr_t interface.
 
216
 *
 
217
 * Results:
 
218
 *      None.
 
219
 *
 
220
 * Side effects:
 
221
 *      Makes a copy of the uvariant_t data and frees that data when the
 
222
 *      utf::string is destroyed.
 
223
 *
 
224
 * Note:
 
225
 *      WIN32 only call
 
226
 *
 
227
 *-----------------------------------------------------------------------------
 
228
 */
 
229
 
 
230
string::string(const uvariant_t &v) // IN
 
231
   : mUstr(),
 
232
     mUtf16Cache(NULL),
 
233
     mUtf16Length(npos)
 
234
{
 
235
   ubstr_t s;
 
236
 
 
237
   try {
 
238
      s = v;
 
239
   } catch (...) {
 
240
      Warning("Invalid uvariant_t to ubstr_t conversion.\n");
 
241
      throw;
 
242
   }
 
243
 
 
244
   // If the input is empty, then there's nothing to do.
 
245
   if (s.length() == 0) {
 
246
      return;
 
247
   }
 
248
 
 
249
   mUstr = static_cast<const char *>(s);
 
250
   ASSERT(Validate(mUstr));
 
251
}
 
252
 
 
253
 
 
254
/*
 
255
 *-----------------------------------------------------------------------------
 
256
 *
 
257
 * utf::string::string --
 
258
 *
 
259
 *      Constructor from a _variant_t object. Copies the UTF-16 representation
 
260
 *      of the _variant_t.
 
261
 *
 
262
 * Results:
 
263
 *      None.
 
264
 *
 
265
 * Side effects:
 
266
 *      Makes a copy of the _variant_t data and frees that data when
 
267
 *      the utf::string is destroyed.
 
268
 *
 
269
 * Note:
 
270
 *      WIN32 only call
 
271
 *
 
272
 *-----------------------------------------------------------------------------
 
273
 */
 
274
 
 
275
string::string(const _variant_t &v) // IN
 
276
   : mUstr(),
 
277
     mUtf16Cache(NULL),
 
278
     mUtf16Length(npos)
 
279
{
 
280
   _bstr_t s;
 
281
 
 
282
   try {
 
283
      s = v;
 
284
   } catch (...) {
 
285
      Warning("Invalid _variant_t to _bstr_t conversion.\n");
 
286
      throw;
 
287
   }
 
288
 
 
289
   init_bstr_t(s);
 
290
}
 
291
 
 
292
#endif
 
293
 
 
294
 
 
295
/*
 
296
 *-----------------------------------------------------------------------------
 
297
 *
 
298
 * utf::string::string --
 
299
 *
 
300
 *      Constructor.
 
301
 *
 
302
 * Results:
 
303
 *      None.
 
304
 *
 
305
 * Side effects:
 
306
 *      None
 
307
 *
 
308
 *-----------------------------------------------------------------------------
 
309
 */
 
310
 
 
311
string::string(const utf16string &s) // IN
 
312
   : mUstr(),
 
313
     mUtf16Cache(NULL),
 
314
     mUtf16Length(npos)
 
315
{
 
316
   // If the input is empty, then there's nothing to do.
 
317
   if (s.empty()) {
 
318
      return;
 
319
   }
 
320
 
 
321
   string copy(s.c_str());
 
322
   swap(copy);
 
323
}
 
324
 
 
325
 
 
326
/*
 
327
 *-----------------------------------------------------------------------------
 
328
 *
 
329
 * utf::string::string --
 
330
 *
 
331
 *      Constructor.
 
332
 *
 
333
 * Results:
 
334
 *      None.
 
335
 *
 
336
 * Side effects:
 
337
 *      None
 
338
 *
 
339
 *-----------------------------------------------------------------------------
 
340
 */
 
341
 
 
342
string::string(const utf16_t *s) // IN
 
343
   : mUstr(),
 
344
     mUtf16Cache(NULL),
 
345
     mUtf16Length(npos)
 
346
{
 
347
   ASSERT(s != NULL);
 
348
 
 
349
   /*
 
350
    * Since we already have a UTF-16 representation of the string, copy it
 
351
    * now.
 
352
    */
 
353
   mUtf16Cache = Unicode_UTF16Strdup(s);
 
354
 
 
355
   Unicode utf8 = Unicode_AllocWithUTF16(s);
 
356
 
 
357
   try {
 
358
      mUstr = utf8;
 
359
      Unicode_Free(utf8);
 
360
   } catch (...) {
 
361
      Unicode_Free(utf8);
 
362
      throw;
 
363
   }
 
364
 
 
365
   ASSERT(Validate(mUstr));
 
366
}
 
367
 
 
368
 
 
369
/*
 
370
 *-----------------------------------------------------------------------------
 
371
 *
 
372
 * utf::string::string --
 
373
 *
 
374
 *      Constructor.
 
375
 *
 
376
 * Results:
 
377
 *      None.
 
378
 *
 
379
 * Side effects:
 
380
 *      None
 
381
 *
 
382
 *-----------------------------------------------------------------------------
 
383
 */
 
384
 
 
385
string::string(const char *s,           // IN
 
386
               StringEncoding encoding) // IN
 
387
   : mUstr(),
 
388
     mUtf16Cache(NULL),
 
389
     mUtf16Length(npos)
 
390
{
 
391
   ASSERT(s != NULL);
 
392
 
 
393
   Unicode utf8 = Unicode_Alloc(s, encoding);
 
394
 
 
395
   try {
 
396
      mUstr = utf8;
 
397
      Unicode_Free(utf8);
 
398
   } catch (...) {
 
399
      Unicode_Free(utf8);
 
400
      throw;
 
401
   }
 
402
 
 
403
   ASSERT(Validate(mUstr));
 
404
}
 
405
 
 
406
 
 
407
/*
 
408
 *-----------------------------------------------------------------------------
 
409
 *
 
410
 * utf::string::string --
 
411
 *
 
412
 *      Constructor.
 
413
 *
 
414
 *      XXX: When initializing mUstr, we do a deep copy of the string data
 
415
 *      instead of just calling mUstr(s). This is because Glib::ustring is very
 
416
 *      smart about sharing storage, and zero_clear is very dumb. Once we get
 
417
 *      rid of zero_clear and have a separate sensitive-string class, this can
 
418
 *      go back to being simple.
 
419
 *
 
420
 * Results:
 
421
 *      None.
 
422
 *
 
423
 * Side effects:
 
424
 *      None
 
425
 *
 
426
 *-----------------------------------------------------------------------------
 
427
 */
 
428
 
 
429
string::string(const Glib::ustring &s)    // IN
 
430
   : mUstr(s.c_str()),
 
431
     mUtf16Cache(NULL),
 
432
     mUtf16Length(npos)
 
433
{
 
434
   ASSERT(Validate(s));
 
435
}
 
436
 
 
437
 
 
438
/*
 
439
 *-----------------------------------------------------------------------------
 
440
 *
 
441
 * utf::string::string --
 
442
 *
 
443
 *      Copy constructor.
 
444
 *
 
445
 *      XXX: When initializing mUstr, we do a deep copy of the string data
 
446
 *      instead of just calling mUstr(s). This is because Glib::ustring is very
 
447
 *      smart about sharing storage, and zero_clear is very dumb. Once we get
 
448
 *      rid of zero_clear and have a separate sensitive-string class, this can
 
449
 *      go back to being simple.
 
450
 *
 
451
 * Results:
 
452
 *      None.
 
453
 *
 
454
 * Side effects:
 
455
 *      None
 
456
 *
 
457
 *-----------------------------------------------------------------------------
 
458
 */
 
459
 
 
460
string::string(const string &s) // IN
 
461
   : mUstr(s.mUstr.c_str()),
 
462
     mUtf16Cache(NULL),
 
463
     mUtf16Length(npos)
 
464
{
 
465
}
 
466
 
 
467
 
 
468
/*
 
469
 *-----------------------------------------------------------------------------
 
470
 *
 
471
 * utf::string::~string --
 
472
 *
 
473
 *      Destructor.
 
474
 *
 
475
 * Results:
 
476
 *      None.
 
477
 *
 
478
 * Side effects:
 
479
 *      None.
 
480
 *
 
481
 *-----------------------------------------------------------------------------
 
482
 */
 
483
 
 
484
string::~string()
 
485
{
 
486
   InvalidateCache();
 
487
}
 
488
 
 
489
 
 
490
/*
 
491
 *-----------------------------------------------------------------------------
 
492
 *
 
493
 * utf::string::operator Glib::ustring --
 
494
 *
 
495
 *      Implicit conversion to Glib::ustring operator
 
496
 *
 
497
 * Results:
 
498
 *      The internal Glib::ustring object.
 
499
 *
 
500
 * Side effects:
 
501
 *      None.
 
502
 *
 
503
 *-----------------------------------------------------------------------------
 
504
 */
 
505
 
 
506
string::operator const Glib::ustring& ()
 
507
   const
 
508
{
 
509
   return ustr();
 
510
}
 
511
 
 
512
 
 
513
#ifdef _WIN32
 
514
 
 
515
/*
 
516
 *-----------------------------------------------------------------------------
 
517
 *
 
518
 * utf::string::operator ubstr_t --
 
519
 *
 
520
 *      Implicit conversion to ubstr_t
 
521
 *
 
522
 * Results:
 
523
 *      The current ubstr_t string. NUL-terminated.
 
524
 *
 
525
 * Side effects:
 
526
 *      None
 
527
 *
 
528
 * Note:
 
529
 *      This function is only defined in _WIN32
 
530
 *
 
531
 *-----------------------------------------------------------------------------
 
532
 */
 
533
 
 
534
string::operator const ubstr_t()
 
535
   const
 
536
{
 
537
   return ubstr_t(GetUtf16Cache());
 
538
}
 
539
 
 
540
#endif
 
541
 
 
542
 
 
543
/*
 
544
 *-----------------------------------------------------------------------------
 
545
 *
 
546
 * utf::string::operator= --
 
547
 *
 
548
 *      Assignment operator.
 
549
 *
 
550
 * Results:
 
551
 *      A reference to this string.
 
552
 *
 
553
 * Side effects:
 
554
 *      None
 
555
 *
 
556
 *-----------------------------------------------------------------------------
 
557
 */
 
558
 
 
559
string&
 
560
string::operator=(string copy) // IN
 
561
{
 
562
   swap(copy);
 
563
   return *this;
 
564
}
 
565
 
 
566
 
 
567
/*
 
568
 *-----------------------------------------------------------------------------
 
569
 *
 
570
 * utf::string::operator+= --
 
571
 *
 
572
 *      Append operator of the utf::string class.
 
573
 *
 
574
 * Results:
 
575
 *      A reference to this string.
 
576
 *
 
577
 * Side effects:
 
578
 *      None
 
579
 *
 
580
 *-----------------------------------------------------------------------------
 
581
 */
 
582
 
 
583
string&
 
584
string::operator+=(const string &s) // IN
 
585
{
 
586
   return append(s);
 
587
}
 
588
 
 
589
 
 
590
string&
 
591
string::operator+=(value_type uc) // IN
 
592
{
 
593
   push_back(uc);
 
594
   return *this;
 
595
}
 
596
 
 
597
 
 
598
/*
 
599
 *-----------------------------------------------------------------------------
 
600
 *
 
601
 * utf::string::swap --
 
602
 *
 
603
 *      Swaps the contents with a given utf::string.
 
604
 *
 
605
 * Results:
 
606
 *      None.
 
607
 *
 
608
 * Side effects:
 
609
 *      None
 
610
 *
 
611
 *-----------------------------------------------------------------------------
 
612
 */
 
613
 
 
614
void
 
615
string::swap(string &s) // IN/OUT
 
616
{
 
617
   mUstr.swap(s.mUstr);
 
618
   std::swap(mUtf16Cache, s.mUtf16Cache);
 
619
   std::swap(mUtf16Length, s.mUtf16Length);
 
620
}
 
621
 
 
622
 
 
623
/*
 
624
 *-----------------------------------------------------------------------------
 
625
 *
 
626
 * utf::string::resize --
 
627
 *
 
628
 *      Change the size of this utf::string.
 
629
 *
 
630
 * Results:
 
631
 *      None.
 
632
 *
 
633
 * Side effects:
 
634
 *      None
 
635
 *
 
636
 *-----------------------------------------------------------------------------
 
637
 */
 
638
 
 
639
void
 
640
string::resize(size_type n,  // IN
 
641
               value_type c) // IN/OPT
 
642
{
 
643
   InvalidateCache();
 
644
   mUstr.resize(n, c);
 
645
}
 
646
 
 
647
 
 
648
/*
 
649
 *-----------------------------------------------------------------------------
 
650
 *
 
651
 * utf::string::c_str --
 
652
 *
 
653
 *      Get the UTF-8 representation of this string.
 
654
 *
 
655
 * Results:
 
656
 *      The current string with UTF-8 encoding. NUL-terminated.
 
657
 *
 
658
 * Side effects:
 
659
 *      None
 
660
 *
 
661
 *-----------------------------------------------------------------------------
 
662
 */
 
663
 
 
664
const char *
 
665
string::c_str()
 
666
   const
 
667
{
 
668
   return mUstr.c_str();
 
669
}
 
670
 
 
671
 
 
672
/*
 
673
 *-----------------------------------------------------------------------------
 
674
 *
 
675
 * utf::string::w_str --
 
676
 *
 
677
 *      Get the UTF-16 representation of this string.
 
678
 *
 
679
 * Results:
 
680
 *      The current string with UTF-16 (host-endian) encoding. NUL-terminated.
 
681
 *
 
682
 * Side effects:
 
683
 *      None
 
684
 *
 
685
 *-----------------------------------------------------------------------------
 
686
 */
 
687
 
 
688
const utf16_t *
 
689
string::w_str()
 
690
   const
 
691
{
 
692
   return GetUtf16Cache();
 
693
}
 
694
 
 
695
 
 
696
/*
 
697
 *-----------------------------------------------------------------------------
 
698
 *
 
699
 * utf::string::ustr --
 
700
 *
 
701
 *      Get the Glib::ustring backing of this string.
 
702
 *
 
703
 * Results:
 
704
 *      The internal Glib::ustring object.
 
705
 *
 
706
 * Side effects:
 
707
 *      None
 
708
 *
 
709
 *-----------------------------------------------------------------------------
 
710
 */
 
711
 
 
712
const Glib::ustring&
 
713
string::ustr()
 
714
   const
 
715
{
 
716
   return mUstr;
 
717
}
 
718
 
 
719
 
 
720
/*
 
721
 *-----------------------------------------------------------------------------
 
722
 *
 
723
 * utf::string::empty --
 
724
 *
 
725
 *      Test if this is an empty string.
 
726
 *
 
727
 * Results:
 
728
 *      true if it's an empty string, otherwise false.
 
729
 *
 
730
 * Side effects:
 
731
 *      None
 
732
 *
 
733
 *-----------------------------------------------------------------------------
 
734
 */
 
735
 
 
736
bool
 
737
string::empty()
 
738
   const
 
739
{
 
740
   return mUstr.empty();
 
741
}
 
742
 
 
743
 
 
744
/*
 
745
 *-----------------------------------------------------------------------------
 
746
 *
 
747
 * utf::string::size --
 
748
 *
 
749
 * Results:
 
750
 *      Returns the length of this string, in characters (code points),
 
751
 *      excluding NUL.
 
752
 *
 
753
 * Side effects:
 
754
 *      None
 
755
 *
 
756
 *-----------------------------------------------------------------------------
 
757
 */
 
758
 
 
759
string::size_type
 
760
string::size()
 
761
   const
 
762
{
 
763
   return mUstr.size();
 
764
}
 
765
 
 
766
 
 
767
/*
 
768
 *-----------------------------------------------------------------------------
 
769
 *
 
770
 * utf::string::w_size --
 
771
 *
 
772
 * Results:
 
773
 *      Returns the length of this string, in UTF-16 code units,
 
774
 *      excluding NUL.
 
775
 *
 
776
 * Side effects:
 
777
 *      None
 
778
 *
 
779
 *-----------------------------------------------------------------------------
 
780
 */
 
781
 
 
782
string::size_type
 
783
string::w_size()
 
784
   const
 
785
{
 
786
   if (mUtf16Length == npos) {
 
787
      mUtf16Length = Unicode_UTF16Strlen(GetUtf16Cache());
 
788
   }
 
789
 
 
790
   return mUtf16Length;
 
791
}
 
792
 
 
793
 
 
794
/*
 
795
 *-----------------------------------------------------------------------------
 
796
 *
 
797
 * utf::string::length --
 
798
 *
 
799
 * Results:
 
800
 *      Returns the length of this string, in characters (code points),
 
801
 *      excluding NUL. (Same as size().)
 
802
 *
 
803
 * Side effects:
 
804
 *      None
 
805
 *
 
806
 *-----------------------------------------------------------------------------
 
807
 */
 
808
 
 
809
string::size_type
 
810
string::length()
 
811
   const
 
812
{
 
813
   return size();
 
814
}
 
815
 
 
816
 
 
817
/*
 
818
 *-----------------------------------------------------------------------------
 
819
 *
 
820
 * utf::string::bytes --
 
821
 *
 
822
 * Results:
 
823
 *      Returns the number of bytes used by the UTF-8 representation of this
 
824
 *      string, excluding NUL.
 
825
 *
 
826
 * Side effects:
 
827
 *      None
 
828
 *
 
829
 *-----------------------------------------------------------------------------
 
830
 */
 
831
 
 
832
string::size_type
 
833
string::bytes()
 
834
   const
 
835
{
 
836
   return mUstr.bytes();
 
837
}
 
838
 
 
839
 
 
840
/*
 
841
 *-----------------------------------------------------------------------------
 
842
 *
 
843
 * utf::string::foldCase --
 
844
 *
 
845
 *      Returns the case-folded string of this string.
 
846
 *
 
847
 * Results:
 
848
 *      The newly created string.
 
849
 *
 
850
 * Side effects:
 
851
 *      None
 
852
 *
 
853
 *-----------------------------------------------------------------------------
 
854
 */
 
855
 
 
856
string
 
857
string::foldCase()
 
858
   const
 
859
{
 
860
   return string(mUstr.casefold());
 
861
}
 
862
 
 
863
 
 
864
/*
 
865
 *-----------------------------------------------------------------------------
 
866
 *
 
867
 * utf::string::trim --
 
868
 *
 
869
 *      Returns the whitespace-trimmed version of this string.
 
870
 *
 
871
 * Results:
 
872
 *      The newly created string.
 
873
 *
 
874
 * Side effects:
 
875
 *      None
 
876
 *
 
877
 *-----------------------------------------------------------------------------
 
878
 */
 
879
 
 
880
string
 
881
string::trim()
 
882
   const
 
883
{
 
884
   Unicode trim = Unicode_Trim(c_str());
 
885
   string result(trim);
 
886
   Unicode_Free(trim);
 
887
   return result;
 
888
}
 
889
 
 
890
 
 
891
/*
 
892
 *-----------------------------------------------------------------------------
 
893
 *
 
894
 * utf::string::trimLeft --
 
895
 *
 
896
 *      Get the left-trimmed version of this string.
 
897
 *
 
898
 * Results:
 
899
 *      The newly created string.
 
900
 *
 
901
 * Side effects:
 
902
 *      None
 
903
 *
 
904
 *-----------------------------------------------------------------------------
 
905
 */
 
906
 
 
907
string
 
908
string::trimLeft()
 
909
   const
 
910
{
 
911
   Unicode trim = Unicode_TrimLeft(c_str());
 
912
   string result(trim);
 
913
   Unicode_Free(trim);
 
914
   return result;
 
915
}
 
916
 
 
917
 
 
918
/*
 
919
 *-----------------------------------------------------------------------------
 
920
 *
 
921
 * utf::string::trimRight --
 
922
 *
 
923
 *      Get the right-trimmed version of this string.
 
924
 *
 
925
 * Results:
 
926
 *      The newly created string.
 
927
 *
 
928
 * Side effects:
 
929
 *      None
 
930
 *
 
931
 *-----------------------------------------------------------------------------
 
932
 */
 
933
 
 
934
string
 
935
string::trimRight()
 
936
   const
 
937
{
 
938
   Unicode trim = Unicode_TrimRight(c_str());
 
939
   string result(trim);
 
940
   Unicode_Free(trim);
 
941
   return result;
 
942
}
 
943
 
 
944
 
 
945
/*
 
946
 *-----------------------------------------------------------------------------
 
947
 *
 
948
 * utf::string::normalize --
 
949
 *
 
950
 *      Creates a new string by normalizing the input string.
 
951
 *
 
952
 * Results:
 
953
 *      The newly created string.
 
954
 *
 
955
 * Side effects:
 
956
 *      None
 
957
 *
 
958
 *-----------------------------------------------------------------------------
 
959
 */
 
960
 
 
961
string
 
962
string::normalize(NormalizeMode mode) // IN
 
963
   const
 
964
{
 
965
   return mUstr.normalize((Glib::NormalizeMode)mode);
 
966
}
 
967
 
 
968
 
 
969
/*
 
970
 *-----------------------------------------------------------------------------
 
971
 *
 
972
 * utf::string::toLower --
 
973
 *
 
974
 *      Creates a new string by lower-casing the input string using
 
975
 *      the rules of the specified locale.
 
976
 *
 
977
 * Results:
 
978
 *      The newly created string.
 
979
 *
 
980
 * Side effects:
 
981
 *      None
 
982
 *
 
983
 *-----------------------------------------------------------------------------
 
984
 */
 
985
 
 
986
string
 
987
string::toLower(const char *locale) // IN
 
988
   const
 
989
{
 
990
#ifdef USE_ICU
 
991
   Unicode lower = Unicode_ToLower(c_str(), locale);
 
992
   string results(lower);
 
993
   Unicode_Free(lower);
 
994
#else
 
995
   string results(mUstr.lowercase());
 
996
#endif
 
997
 
 
998
   return results;
 
999
}
 
1000
 
 
1001
 
 
1002
/*
 
1003
 *-----------------------------------------------------------------------------
 
1004
 *
 
1005
 * utf::string::toUpper --
 
1006
 *
 
1007
 *      Creates a new string by upper-casing the input string using
 
1008
 *      the rules of the specified locale.
 
1009
 *
 
1010
 * Results:
 
1011
 *      The newly created string.
 
1012
 *
 
1013
 * Side effects:
 
1014
 *      None
 
1015
 *
 
1016
 *-----------------------------------------------------------------------------
 
1017
 */
 
1018
 
 
1019
string
 
1020
string::toUpper(const char *locale) // IN
 
1021
   const
 
1022
{
 
1023
#ifdef USE_ICU
 
1024
   Unicode upper = Unicode_ToUpper(c_str(), locale);
 
1025
   string results(upper);
 
1026
   Unicode_Free(upper);
 
1027
#else
 
1028
   string results(mUstr.uppercase());
 
1029
#endif
 
1030
 
 
1031
 
 
1032
   return results;
 
1033
}
 
1034
 
 
1035
 
 
1036
#ifdef USE_ICU
 
1037
 
 
1038
/*
 
1039
 *-----------------------------------------------------------------------------
 
1040
 *
 
1041
 * utf::string::toTitle --
 
1042
 *
 
1043
 *      Creates a new string by title-casing the input string using
 
1044
 *      the rules of the specified locale.
 
1045
 *
 
1046
 * Results:
 
1047
 *      The newly created string.
 
1048
 *
 
1049
 * Side effects:
 
1050
 *      None
 
1051
 *
 
1052
 *-----------------------------------------------------------------------------
 
1053
 */
 
1054
 
 
1055
string
 
1056
string::toTitle(const char *locale) // IN
 
1057
   const
 
1058
{
 
1059
   Unicode title = Unicode_ToTitle(c_str(), locale);
 
1060
   string results(title);
 
1061
   Unicode_Free(title);
 
1062
 
 
1063
   return results;
 
1064
}
 
1065
 
 
1066
#endif
 
1067
 
 
1068
 
 
1069
/*
 
1070
 *-----------------------------------------------------------------------------
 
1071
 *
 
1072
 * utf::string::append --
 
1073
 *
 
1074
 *      Appends the argument string to this utf::string.
 
1075
 *
 
1076
 * Results:
 
1077
 *      A reference to this object.
 
1078
 *
 
1079
 * Side effects:
 
1080
 *      None
 
1081
 *
 
1082
 *-----------------------------------------------------------------------------
 
1083
 */
 
1084
 
 
1085
string&
 
1086
string::append(const string &s) // IN
 
1087
{
 
1088
   InvalidateCache();
 
1089
   mUstr.append(s.mUstr);
 
1090
 
 
1091
   return *this;
 
1092
}
 
1093
 
 
1094
 
 
1095
string&
 
1096
string::append(const string &s, // IN
 
1097
               size_type i,     // IN
 
1098
               size_type n)     // IN
 
1099
{
 
1100
   InvalidateCache();
 
1101
   mUstr.append(s.mUstr, i, n);
 
1102
 
 
1103
   return *this;
 
1104
}
 
1105
 
 
1106
 
 
1107
string&
 
1108
string::append(const char *s,   // IN
 
1109
               size_type n)     // IN
 
1110
{
 
1111
   InvalidateCache();
 
1112
   mUstr.append(s, n);
 
1113
 
 
1114
   return *this;
 
1115
}
 
1116
 
 
1117
 
 
1118
/*
 
1119
 *-----------------------------------------------------------------------------
 
1120
 *
 
1121
 * utf::string::push_back --
 
1122
 *
 
1123
 *      Appends the character at the end of this string.
 
1124
 *
 
1125
 * Results:
 
1126
 *      None
 
1127
 *
 
1128
 * Side effects:
 
1129
 *      None
 
1130
 *
 
1131
 *-----------------------------------------------------------------------------
 
1132
 */
 
1133
 
 
1134
void
 
1135
string::push_back(value_type uc) // IN
 
1136
{
 
1137
   InvalidateCache();
 
1138
   mUstr.push_back(uc);
 
1139
}
 
1140
 
 
1141
 
 
1142
/*
 
1143
 *-----------------------------------------------------------------------------
 
1144
 *
 
1145
 * utf::string::assign --
 
1146
 *
 
1147
 *      Assigns the passed in string to this string.
 
1148
 *
 
1149
 *      Callers should prefer using operator= instead of assign().
 
1150
 *
 
1151
 * Results:
 
1152
 *      A reference to this object
 
1153
 *
 
1154
 * Side effects:
 
1155
 *      None
 
1156
 *
 
1157
 *-----------------------------------------------------------------------------
 
1158
 */
 
1159
 
 
1160
string&
 
1161
string::assign(const string &s) // IN
 
1162
{
 
1163
   return operator=(s);
 
1164
}
 
1165
 
 
1166
 
 
1167
/*
 
1168
 *-----------------------------------------------------------------------------
 
1169
 *
 
1170
 * utf::string::insert --
 
1171
 *
 
1172
 *      Inserts the argument string to this string at index i, return this
 
1173
 *      string.
 
1174
 *
 
1175
 *      These are passthrough calls to the Glib::insert calls.
 
1176
 *
 
1177
 * Results:
 
1178
 *      A reference to this object
 
1179
 *
 
1180
 * Side effects:
 
1181
 *      None
 
1182
 *
 
1183
 *-----------------------------------------------------------------------------
 
1184
 */
 
1185
 
 
1186
string&
 
1187
string::insert(size_type i,      // IN
 
1188
               const string &s)  // IN
 
1189
{
 
1190
   InvalidateCache();
 
1191
   mUstr.insert(i, s.mUstr);
 
1192
   return *this;
 
1193
}
 
1194
 
 
1195
 
 
1196
string&
 
1197
string::insert(size_type i,      // IN
 
1198
               size_type n,      // IN
 
1199
               value_type uc)
 
1200
{
 
1201
   InvalidateCache();
 
1202
   mUstr.insert(i, n, uc);
 
1203
   return *this;
 
1204
}
 
1205
 
 
1206
 
 
1207
/*
 
1208
 *-----------------------------------------------------------------------------
 
1209
 *
 
1210
 * utf::string::clear --
 
1211
 *
 
1212
 *      Clears this string.
 
1213
 *
 
1214
 * Results:
 
1215
 *      None
 
1216
 *
 
1217
 * Side effects:
 
1218
 *      None
 
1219
 *
 
1220
 *-----------------------------------------------------------------------------
 
1221
 */
 
1222
 
 
1223
void
 
1224
string::clear()
 
1225
{
 
1226
   InvalidateCache();
 
1227
   mUstr.clear();
 
1228
}
 
1229
 
 
1230
 
 
1231
/*
 
1232
 *-----------------------------------------------------------------------------
 
1233
 *
 
1234
 * utf::string::zero_clear --
 
1235
 *
 
1236
 *      Zeroes and clears this string.
 
1237
 *
 
1238
 *      XXX: This is temporary until we have a separate string class for
 
1239
 *      passwords.
 
1240
 *
 
1241
 * Results:
 
1242
 *      None
 
1243
 *
 
1244
 * Side effects:
 
1245
 *      None
 
1246
 *
 
1247
 *-----------------------------------------------------------------------------
 
1248
 */
 
1249
 
 
1250
void
 
1251
string::zero_clear()
 
1252
{
 
1253
   if (mUtf16Cache != NULL) {
 
1254
      Util_ZeroFree(mUtf16Cache,
 
1255
                    Unicode_UTF16Strlen(mUtf16Cache) * sizeof *mUtf16Cache);
 
1256
      mUtf16Cache = NULL;
 
1257
   }
 
1258
 
 
1259
   /*
 
1260
    * This is a best effort.  We aren't guaranteed that Glib::ustring doesn't
 
1261
    * leave behind any internal copies of the string.
 
1262
    */
 
1263
   if (mUstr.c_str() != mUstr.data()) {
 
1264
      Util_Zero(const_cast<char *>(mUstr.c_str()), mUstr.bytes());
 
1265
   }
 
1266
   Util_Zero(const_cast<char *>(mUstr.data()), mUstr.bytes());
 
1267
   mUstr.clear();
 
1268
}
 
1269
 
 
1270
 
 
1271
/*
 
1272
 *-----------------------------------------------------------------------------
 
1273
 *
 
1274
 * utf::string::erase --
 
1275
 *
 
1276
 *      Erase the contents of this string in the specified index range.
 
1277
 *
 
1278
 * Results:
 
1279
 *      A reference to this object
 
1280
 *
 
1281
 * Side effects:
 
1282
 *      None
 
1283
 *
 
1284
 *-----------------------------------------------------------------------------
 
1285
 */
 
1286
 
 
1287
string&
 
1288
string::erase(size_type i,    // IN
 
1289
              size_type n)    // IN
 
1290
{
 
1291
   InvalidateCache();
 
1292
   mUstr.erase(i, n);
 
1293
   return *this;
 
1294
}
 
1295
 
 
1296
 
 
1297
/*
 
1298
 *-----------------------------------------------------------------------------
 
1299
 *
 
1300
 * utf::string::erase --
 
1301
 *
 
1302
 *      Erase the contents of this string with given iterator.
 
1303
 *
 
1304
 * Results:
 
1305
 *      The current iterator.
 
1306
 *
 
1307
 * Side effects:
 
1308
 *      None
 
1309
 *
 
1310
 *-----------------------------------------------------------------------------
 
1311
 */
 
1312
 
 
1313
string::iterator
 
1314
string::erase(iterator p)    // IN
 
1315
{
 
1316
   InvalidateCache();
 
1317
   return mUstr.erase(p);
 
1318
}
 
1319
 
 
1320
 
 
1321
string::iterator
 
1322
string::erase(iterator pbegin,    // IN
 
1323
              iterator pend)      // IN
 
1324
{
 
1325
   InvalidateCache();
 
1326
   return mUstr.erase(pbegin, pend);
 
1327
}
 
1328
 
 
1329
/*
 
1330
 *-----------------------------------------------------------------------------
 
1331
 *
 
1332
 * utf::string::replace --
 
1333
 *
 
1334
 *      Replace the string contents specified by the range, with the passed in
 
1335
 *      string.
 
1336
 *
 
1337
 * Results:
 
1338
 *      A reference to this object.
 
1339
 *
 
1340
 * Side effects:
 
1341
 *      None
 
1342
 *
 
1343
 *-----------------------------------------------------------------------------
 
1344
 */
 
1345
 
 
1346
string&
 
1347
string::replace(size_type i,     // IN
 
1348
                size_type n,     // IN
 
1349
                const string &s) // IN
 
1350
{
 
1351
   InvalidateCache();
 
1352
   mUstr.replace(i, n, s.mUstr);
 
1353
   return *this;
 
1354
}
 
1355
 
 
1356
 
 
1357
/*
 
1358
 *-----------------------------------------------------------------------------
 
1359
 *
 
1360
 * utf::string::replace --
 
1361
 *
 
1362
 *      Mutates this string by replacing all occurrences of one string with
 
1363
 *      another.
 
1364
 *
 
1365
 * Results:
 
1366
 *      A reference to this object.
 
1367
 *
 
1368
 * Side effects:
 
1369
 *      None
 
1370
 *
 
1371
 *-----------------------------------------------------------------------------
 
1372
 */
 
1373
 
 
1374
string&
 
1375
string::replace(const string &from, // IN
 
1376
                const string &to)   // IN
 
1377
{
 
1378
   size_type end;
 
1379
   size_type start = 0;
 
1380
   size_type fromSize = from.length();
 
1381
   string result;
 
1382
 
 
1383
   while ((end = find(from, start)) != string::npos) {
 
1384
      result += substr(start, end - start);
 
1385
      result += to;
 
1386
 
 
1387
      start = end + fromSize;
 
1388
   }
 
1389
 
 
1390
   if (start < length()) {
 
1391
      result += substr(start);
 
1392
   }
 
1393
 
 
1394
   swap(result);
 
1395
   return *this;
 
1396
}
 
1397
 
 
1398
 
 
1399
/*
 
1400
 *-----------------------------------------------------------------------------
 
1401
 *
 
1402
 * utf::string::replace_copy --
 
1403
 *
 
1404
 * Results:
 
1405
 *      Returns a new string with all occurrences of one string replaced by
 
1406
 *      another.
 
1407
 *
 
1408
 * Side effects:
 
1409
 *      None
 
1410
 *
 
1411
 *-----------------------------------------------------------------------------
 
1412
 */
 
1413
 
 
1414
string
 
1415
string::replace_copy(const string& from, // IN
 
1416
                     const string& to)   // IN
 
1417
   const
 
1418
{
 
1419
   return string(*this).replace(from, to);
 
1420
}
 
1421
 
 
1422
 
 
1423
/*
 
1424
 *-----------------------------------------------------------------------------
 
1425
 *
 
1426
 * utf::string::compare --
 
1427
 *
 
1428
 *      A 3-way (output -1, 0, or 1) string comparison. Compares each Unicode
 
1429
 *      code point of this string to the argument string.
 
1430
 *
 
1431
 * Results:
 
1432
 *      -1 if *this < s, 0 if *this == s, 1 if *this > s.
 
1433
 *
 
1434
 * Side effects:
 
1435
 *      None
 
1436
 *
 
1437
 *-----------------------------------------------------------------------------
 
1438
 */
 
1439
 
 
1440
int
 
1441
string::compare(const string &s, // IN
 
1442
                bool ignoreCase) // IN/OPT: false by default
 
1443
   const
 
1444
{
 
1445
   return ignoreCase
 
1446
          ? Unicode_CompareIgnoreCase(c_str(), s.c_str())
 
1447
          : Unicode_Compare(c_str(), s.c_str());
 
1448
}
 
1449
 
 
1450
 
 
1451
int
 
1452
string::compare(size_type i,     // IN
 
1453
                size_type n,     // IN
 
1454
                const string &s) // IN
 
1455
   const
 
1456
{
 
1457
   return mUstr.compare(i, n, s.mUstr);
 
1458
}
 
1459
 
 
1460
 
 
1461
/*
 
1462
 *-----------------------------------------------------------------------------
 
1463
 *
 
1464
 * utf::string::compareLength --
 
1465
 *
 
1466
 *      A 3-way (output -1, 0, or 1) string comparison with given length.
 
1467
 *      Compares only the first len characters (in code units) of the strings.
 
1468
 *
 
1469
 * Results:
 
1470
 *      -1 if *this < s, 0 if *this == s, 1 if *this > s.
 
1471
 *
 
1472
 * Side effects:
 
1473
 *      None
 
1474
 *
 
1475
 *-----------------------------------------------------------------------------
 
1476
 */
 
1477
 
 
1478
int
 
1479
string::compareLength(const string &s, // IN
 
1480
                      size_type len,   // IN: length in code-point
 
1481
                      bool ignoreCase) // IN/OPT: false by default
 
1482
   const
 
1483
{
 
1484
   return substr(0, len).compare(s.substr(0, len), ignoreCase);
 
1485
}
 
1486
 
 
1487
 
 
1488
/*
 
1489
 *-----------------------------------------------------------------------------
 
1490
 *
 
1491
 * utf::string::compareRange --
 
1492
 *
 
1493
 *      A 3-way (output -1, 0, or 1) string comparison with given length.
 
1494
 *      Compares the substrings from this string [thisStart ~ thisStart + thisLength-1]
 
1495
 *      with the input string str [strStart ~ strStart + strLength - 1].
 
1496
 *
 
1497
 * Results:
 
1498
 *      -1 if *this < s, 0 if *this == s, 1 if *this > s.
 
1499
 *
 
1500
 * Side effects:
 
1501
 *      None
 
1502
 *
 
1503
 *-----------------------------------------------------------------------------
 
1504
 */
 
1505
 
 
1506
int
 
1507
string::compareRange(size_type thisStart,  // IN: index in code-point
 
1508
                     size_type thisLength, // IN: length in code-point
 
1509
                     const string &str,    // IN
 
1510
                     size_type strStart,   // IN: index in code-point
 
1511
                     size_type strLength,  // IN: length in code-point
 
1512
                     bool ignoreCase)      // IN/OPT: false by default
 
1513
   const
 
1514
{
 
1515
   return substr(thisStart, thisLength).compare(str.substr(strStart, strLength), ignoreCase);
 
1516
}
 
1517
 
 
1518
 
 
1519
/*
 
1520
 *-----------------------------------------------------------------------------
 
1521
 *
 
1522
 * utf::string::find --
 
1523
 *
 
1524
 *      Searches for the first occurrence of the input string inside this string.
 
1525
 *
 
1526
 * Results:
 
1527
 *      If s is found, then, it returns the first starting index of the input string.
 
1528
 *      Otherwise, returns npos.
 
1529
 *
 
1530
 * Side effects:
 
1531
 *      None
 
1532
 *
 
1533
 *-----------------------------------------------------------------------------
 
1534
 */
 
1535
 
 
1536
string::size_type
 
1537
string::find(const string &s,   // IN
 
1538
             size_type pos)     // IN/OPT
 
1539
   const
 
1540
{
 
1541
   return mUstr.find(s.mUstr, pos);
 
1542
}
 
1543
 
 
1544
 
 
1545
string::size_type
 
1546
string::find(value_type uc, // IN
 
1547
             size_type pos) // IN/OPT
 
1548
   const
 
1549
{
 
1550
   return mUstr.find(uc, pos);
 
1551
}
 
1552
 
 
1553
 
 
1554
/*
 
1555
 *-----------------------------------------------------------------------------
 
1556
 *
 
1557
 * utf::string::rfind --
 
1558
 *
 
1559
 *      Searches for the last occurrence of the input string inside this string.
 
1560
 *
 
1561
 * Results:
 
1562
 *      If s is found, then, it returns the last starting index of the input string.
 
1563
 *      Otherwise, returns npos.
 
1564
 *
 
1565
 * Side effects:
 
1566
 *      None
 
1567
 *
 
1568
 *-----------------------------------------------------------------------------
 
1569
 */
 
1570
 
 
1571
string::size_type
 
1572
string::rfind(const string &s,   // IN
 
1573
              size_type pos)     // IN/OPT
 
1574
   const
 
1575
{
 
1576
   return mUstr.rfind(s.mUstr, pos);
 
1577
}
 
1578
 
 
1579
 
 
1580
string::size_type
 
1581
string::rfind(value_type uc,     // IN
 
1582
              size_type pos)     // IN/OPT
 
1583
   const
 
1584
{
 
1585
   return mUstr.rfind(uc, pos);
 
1586
}
 
1587
 
 
1588
 
 
1589
/*
 
1590
 *-----------------------------------------------------------------------------
 
1591
 *
 
1592
 * utf::string::find_first_of --
 
1593
 *
 
1594
 *      Find the first occurrence of 's' in this string.  'i' determines where in
 
1595
 *      the current string we start searching for 's'
 
1596
 *
 
1597
 * Results:
 
1598
 *      If s is found, then, it returns the index where s occurs in this
 
1599
 *      string.
 
1600
 *      Otherwise, returns npos.
 
1601
 *
 
1602
 * Side effects:
 
1603
 *      None
 
1604
 *
 
1605
 *-----------------------------------------------------------------------------
 
1606
 */
 
1607
 
 
1608
string::size_type
 
1609
string::find_first_of(const string &s, // IN
 
1610
                      size_type i)     // IN/OPT
 
1611
   const
 
1612
{
 
1613
   return mUstr.find_first_of(s.mUstr, i);
 
1614
}
 
1615
 
 
1616
 
 
1617
string::size_type
 
1618
string::find_first_of(value_type uc,   // IN
 
1619
                      size_type i)     // IN/OPT
 
1620
   const
 
1621
{
 
1622
   return mUstr.find_first_of(uc, i);
 
1623
}
 
1624
 
 
1625
 
 
1626
/*
 
1627
 *-----------------------------------------------------------------------------
 
1628
 *
 
1629
 * utf::string::find_first_not_of --
 
1630
 *
 
1631
 *      Find the first occurrence of a string NOT in 's' in this string.  'i'
 
1632
 *      determines where in this string we start searching to NOT 's'.
 
1633
 *
 
1634
 * Results:
 
1635
 *      Returns the index of the first sequence in this string that is not 's'
 
1636
 *      Otherwise, returns npos.
 
1637
 *
 
1638
 * Side effects:
 
1639
 *      None
 
1640
 *
 
1641
 *-----------------------------------------------------------------------------
 
1642
 */
 
1643
 
 
1644
string::size_type
 
1645
string::find_first_not_of(const string &s, // IN
 
1646
                          size_type i)     // IN/OPT
 
1647
   const
 
1648
{
 
1649
   return mUstr.find_first_not_of(s.mUstr, i);
 
1650
}
 
1651
 
 
1652
 
 
1653
string::size_type
 
1654
string::find_first_not_of(value_type uc,   // IN
 
1655
                          size_type i)     // IN/OPT
 
1656
   const
 
1657
{
 
1658
   return mUstr.find_first_not_of(uc, i);
 
1659
}
 
1660
 
 
1661
 
 
1662
/*
 
1663
 *-----------------------------------------------------------------------------
 
1664
 *
 
1665
 * utf::string::find_last_of --
 
1666
 *
 
1667
 *      Does a reverse search in this string for 's'.  'i' determines where we
 
1668
 *      start the search for in this string.
 
1669
 *
 
1670
 * Results:
 
1671
 *      If s is found, then, it returns the index where s occurs in this
 
1672
 *      string.
 
1673
 *      Otherwise, returns npos.
 
1674
 *
 
1675
 * Side effects:
 
1676
 *      None
 
1677
 *
 
1678
 *-----------------------------------------------------------------------------
 
1679
 */
 
1680
 
 
1681
string::size_type
 
1682
string::find_last_of(const string &s, // IN
 
1683
                     size_type i)     // IN/OPT
 
1684
   const
 
1685
{
 
1686
   return mUstr.find_last_of(s.mUstr, i);
 
1687
}
 
1688
 
 
1689
 
 
1690
string::size_type
 
1691
string::find_last_of(value_type uc,   // IN
 
1692
                     size_type i)     // IN/OPT
 
1693
   const
 
1694
{
 
1695
   return mUstr.find_last_of(uc, i);
 
1696
}
 
1697
 
 
1698
 
 
1699
/*
 
1700
 *-----------------------------------------------------------------------------
 
1701
 *
 
1702
 * utf::string::find_last_not_of --
 
1703
 *
 
1704
 *      Searches for the last character within the current string that does
 
1705
 *      not match any characters in 's'.  'i' determines where we start the
 
1706
 *      search for in this string.  (moving backwards).
 
1707
 *
 
1708
 * Results:
 
1709
 *      If NOT 's' is found, then, it returns the index where s does not occurs
 
1710
 *      in this string.
 
1711
 *      Otherwise, returns npos.
 
1712
 *
 
1713
 * Side effects:
 
1714
 *      None
 
1715
 *
 
1716
 *-----------------------------------------------------------------------------
 
1717
 */
 
1718
 
 
1719
string::size_type
 
1720
string::find_last_not_of(const string &s, // IN
 
1721
                         size_type i)     // IN/OPT
 
1722
   const
 
1723
{
 
1724
   return mUstr.find_last_not_of(s.mUstr, i);
 
1725
}
 
1726
 
 
1727
 
 
1728
string::size_type
 
1729
string::find_last_not_of(value_type uc,   // IN
 
1730
                         size_type i)     // IN/OPT
 
1731
   const
 
1732
{
 
1733
   return mUstr.find_last_not_of(uc, i);
 
1734
}
 
1735
 
 
1736
 
 
1737
/*
 
1738
 *-----------------------------------------------------------------------------
 
1739
 *
 
1740
 * utf::string::substr --
 
1741
 *
 
1742
 *      Create a substring of this string with given range.
 
1743
 *
 
1744
 * Results:
 
1745
 *      The newly created string.
 
1746
 *
 
1747
 * Side effects:
 
1748
 *      None
 
1749
 *
 
1750
 *-----------------------------------------------------------------------------
 
1751
 */
 
1752
 
 
1753
string
 
1754
string::substr(size_type start, // IN
 
1755
               size_type len)   // IN
 
1756
   const
 
1757
{
 
1758
   return string(mUstr.substr(start, len));
 
1759
}
 
1760
 
 
1761
 
 
1762
/*
 
1763
 *-----------------------------------------------------------------------------
 
1764
 *
 
1765
 * utf::string::operator[] --
 
1766
 *
 
1767
 *      Get the UTF-32 character at given index in this string.
 
1768
 *
 
1769
 * Results:
 
1770
 *      UTF-32 character (gunichar).
 
1771
 *
 
1772
 * Side effects:
 
1773
 *      None
 
1774
 *
 
1775
 *-----------------------------------------------------------------------------
 
1776
 */
 
1777
 
 
1778
string::value_type
 
1779
string::operator[](size_type i)  // IN
 
1780
   const
 
1781
{
 
1782
   return mUstr[i];
 
1783
}
 
1784
 
 
1785
 
 
1786
/*
 
1787
 *-----------------------------------------------------------------------------
 
1788
 *
 
1789
 * utf::string::startsWith --
 
1790
 *
 
1791
 *      Tests if the current string starts with 's'
 
1792
 *
 
1793
 * Results:
 
1794
 *      true if current string starts with 's', false otherwise
 
1795
 *
 
1796
 * Side effects:
 
1797
 *      None
 
1798
 *
 
1799
 *-----------------------------------------------------------------------------
 
1800
 */
 
1801
 
 
1802
bool
 
1803
string::startsWith(const string &s, // IN
 
1804
                   bool ignoreCase) // IN/OPT: false by default
 
1805
   const
 
1806
{
 
1807
   return UnicodeStartsWith(c_str(), s.c_str(), ignoreCase);
 
1808
}
 
1809
 
 
1810
 
 
1811
/*
 
1812
 *-----------------------------------------------------------------------------
 
1813
 *
 
1814
 * utf::string::endsWith --
 
1815
 *
 
1816
 *      Tests if the current string ends with 's'
 
1817
 *
 
1818
 * Results:
 
1819
 *      true if current string ends with 's', false otherwise
 
1820
 *
 
1821
 * Side effects:
 
1822
 *      None
 
1823
 *
 
1824
 *-----------------------------------------------------------------------------
 
1825
 */
 
1826
 
 
1827
bool
 
1828
string::endsWith(const string &s, // IN
 
1829
                 bool ignoreCase) // IN/OPT: false by default
 
1830
   const
 
1831
{
 
1832
   return UnicodeEndsWith(c_str(), s.c_str(), ignoreCase);
 
1833
}
 
1834
 
 
1835
 
 
1836
/*
 
1837
 *-----------------------------------------------------------------------------
 
1838
 *
 
1839
 * utf::string::split --
 
1840
 *
 
1841
 *      Return a vector of utf::strings.  The vector contains the elements of
 
1842
 *      the string split by the passed in separator. Empty tokens are not
 
1843
 *      skipped.
 
1844
 *
 
1845
 *      "1,2,3".split(",") -> ["1", "2", "3"]
 
1846
 *      "1,,".split(",") -> ["1", "", ""]
 
1847
 *      "1".split(",") -> ["1"]
 
1848
 *
 
1849
 *      XXX If this is to be used for things like command line parsing, support
 
1850
 *      for quoted strings needs to be added.
 
1851
 *
 
1852
 * Results:
 
1853
 *      A vector of utf::strings
 
1854
 *
 
1855
 * Side effects:
 
1856
 *      None
 
1857
 *
 
1858
 *-----------------------------------------------------------------------------
 
1859
 */
 
1860
 
 
1861
std::vector<string>
 
1862
string::split(const string &sep) // IN
 
1863
   const
 
1864
{
 
1865
   std::vector<string> splitStrings;
 
1866
   size_type sIndex = 0;
 
1867
   size_type sepLen = sep.length();
 
1868
 
 
1869
   ASSERT(sepLen > 0);
 
1870
 
 
1871
   while (true) {
 
1872
      size_type index = find(sep, sIndex);
 
1873
      if (index == npos) {
 
1874
         splitStrings.push_back(substr(sIndex));
 
1875
         break;
 
1876
      }
 
1877
 
 
1878
      splitStrings.push_back(substr(sIndex, index - sIndex));
 
1879
      sIndex = index + sepLen;
 
1880
   }
 
1881
 
 
1882
   return splitStrings;
 
1883
}
 
1884
 
 
1885
 
 
1886
/*
 
1887
 *-----------------------------------------------------------------------------
 
1888
 *
 
1889
 * utf::string::GetUtf16Cache --
 
1890
 *
 
1891
 *      Return the UTF-16 representation of the current string, this value is
 
1892
 *      cached, in the object.  If the cache is not valid (NULL), then create
 
1893
 *      the cache value
 
1894
 *
 
1895
 * Results:
 
1896
 *      A UTF-16 representation of the current string
 
1897
 *
 
1898
 * Side effects:
 
1899
 *      Allocates a UTF16 string
 
1900
 *
 
1901
 *-----------------------------------------------------------------------------
 
1902
 */
 
1903
 
 
1904
const utf16_t *
 
1905
string::GetUtf16Cache()
 
1906
   const
 
1907
{
 
1908
   if (mUtf16Cache == NULL) {
 
1909
      mUtf16Cache = Unicode_GetAllocUTF16(c_str());
 
1910
   }
 
1911
 
 
1912
   return mUtf16Cache;
 
1913
}
 
1914
 
 
1915
 
 
1916
/*
 
1917
 *-----------------------------------------------------------------------------
 
1918
 *
 
1919
 * utf::string::InvalidateCache --
 
1920
 *
 
1921
 *      Frees the cache in this string.
 
1922
 *
 
1923
 * Results:
 
1924
 *      None
 
1925
 *
 
1926
 * Side effects:
 
1927
 *      None
 
1928
 *
 
1929
 *-----------------------------------------------------------------------------
 
1930
 */
 
1931
 
 
1932
void
 
1933
string::InvalidateCache()
 
1934
{
 
1935
   free(mUtf16Cache);
 
1936
   mUtf16Cache = NULL;
 
1937
   mUtf16Length = npos;
 
1938
}
 
1939
 
 
1940
 
 
1941
/*
 
1942
 *-----------------------------------------------------------------------------
 
1943
 *
 
1944
 * utf::string::operator+ --
 
1945
 *
 
1946
 *      Create a new string by appending the input string to this string.
 
1947
 *
 
1948
 *      NOTE: This is not the same as append.  append() will modify the
 
1949
 *      current object, while this will return a new object.
 
1950
 *
 
1951
 * Results:
 
1952
 *      The newly created string.
 
1953
 *
 
1954
 * Side effects:
 
1955
 *      None
 
1956
 *
 
1957
 *-----------------------------------------------------------------------------
 
1958
 */
 
1959
 
 
1960
string
 
1961
string::operator+(const string &rhs)     // IN
 
1962
   const
 
1963
{
 
1964
   return mUstr + rhs.mUstr;
 
1965
}
 
1966
 
 
1967
 
 
1968
string
 
1969
string::operator+(value_type uc)        // IN
 
1970
   const
 
1971
{
 
1972
   return mUstr + uc;
 
1973
}
 
1974
 
 
1975
 
 
1976
/*
 
1977
 *-----------------------------------------------------------------------------
 
1978
 *
 
1979
 * utf::string::operator== --
 
1980
 *
 
1981
 *      Equality operator for string objects
 
1982
 *
 
1983
 * Results:
 
1984
 *      true or false (true if equal)
 
1985
 *
 
1986
 * Side effects:
 
1987
 *      None
 
1988
 *
 
1989
 *-----------------------------------------------------------------------------
 
1990
 */
 
1991
 
 
1992
bool
 
1993
string::operator==(const string &rhs)     // IN
 
1994
   const
 
1995
{
 
1996
   return compare(rhs) == 0;
 
1997
}
 
1998
 
 
1999
 
 
2000
/*
 
2001
 *-----------------------------------------------------------------------------
 
2002
 *
 
2003
 * utf::string::operator!= --
 
2004
 *
 
2005
 *      Inequality operator for string objects
 
2006
 *
 
2007
 * Results:
 
2008
 *      true or false (true if not equal)
 
2009
 *
 
2010
 * Side effects:
 
2011
 *      None
 
2012
 *
 
2013
 *-----------------------------------------------------------------------------
 
2014
 */
 
2015
 
 
2016
bool
 
2017
string::operator!=(const string &rhs)     // IN
 
2018
   const
 
2019
{
 
2020
   return compare(rhs) != 0;
 
2021
}
 
2022
 
 
2023
 
 
2024
/*
 
2025
 *-----------------------------------------------------------------------------
 
2026
 *
 
2027
 * utf::string::operator< --
 
2028
 *
 
2029
 *      Less than operator for string objects
 
2030
 *
 
2031
 * Results:
 
2032
 *      true or false (true if lhs is < rhs)
 
2033
 *
 
2034
 * Side effects:
 
2035
 *      None
 
2036
 *
 
2037
 *-----------------------------------------------------------------------------
 
2038
 */
 
2039
 
 
2040
bool
 
2041
string::operator<(const string &rhs)     // IN
 
2042
   const
 
2043
{
 
2044
   return compare(rhs) < 0;
 
2045
}
 
2046
 
 
2047
 
 
2048
/*
 
2049
 *-----------------------------------------------------------------------------
 
2050
 *
 
2051
 * utf::string::operator> --
 
2052
 *
 
2053
 *      Greater than operator for string objects
 
2054
 *
 
2055
 * Results:
 
2056
 *      true or false (true if lhs is > rhs)
 
2057
 *
 
2058
 * Side effects:
 
2059
 *      None
 
2060
 *
 
2061
 *-----------------------------------------------------------------------------
 
2062
 */
 
2063
 
 
2064
bool
 
2065
string::operator>(const string &rhs)     // IN
 
2066
   const
 
2067
{
 
2068
   return compare(rhs) > 0;
 
2069
}
 
2070
 
 
2071
 
 
2072
/*
 
2073
 *-----------------------------------------------------------------------------
 
2074
 *
 
2075
 * utf::string::operator<= --
 
2076
 *
 
2077
 *      Less than or equal than operator for string objects
 
2078
 *
 
2079
 * Results:
 
2080
 *      true or false (true if lhs is <= rhs)
 
2081
 *
 
2082
 * Side effects:
 
2083
 *      None
 
2084
 *
 
2085
 *-----------------------------------------------------------------------------
 
2086
 */
 
2087
 
 
2088
bool
 
2089
string::operator<=(const string &rhs)     // IN
 
2090
   const
 
2091
{
 
2092
   return compare(rhs) <= 0;
 
2093
}
 
2094
 
 
2095
 
 
2096
/*
 
2097
 *-----------------------------------------------------------------------------
 
2098
 *
 
2099
 * utf::string::operator>= --
 
2100
 *
 
2101
 *      Greater than or equal than operator for string objects
 
2102
 *
 
2103
 * Results:
 
2104
 *      true or false (true if lhs is >= rhs)
 
2105
 *
 
2106
 * Side effects:
 
2107
 *      None
 
2108
 *
 
2109
 *-----------------------------------------------------------------------------
 
2110
 */
 
2111
 
 
2112
bool
 
2113
string::operator>=(const string &rhs)     // IN
 
2114
   const
 
2115
{
 
2116
   return compare(rhs) >= 0;
 
2117
}
 
2118
 
 
2119
 
 
2120
/*
 
2121
 *-----------------------------------------------------------------------------
 
2122
 *
 
2123
 * utf::string::begin --
 
2124
 *
 
2125
 *      Returns an iterator to the start of the string.
 
2126
 *
 
2127
 * Results:
 
2128
 *      iterator
 
2129
 *
 
2130
 * Side effects:
 
2131
 *      None
 
2132
 *
 
2133
 *-----------------------------------------------------------------------------
 
2134
 */
 
2135
 
 
2136
string::iterator
 
2137
string::begin()
 
2138
{
 
2139
   return mUstr.begin();
 
2140
}
 
2141
 
 
2142
 
 
2143
string::const_iterator
 
2144
string::begin()
 
2145
   const
 
2146
{
 
2147
   return mUstr.begin();
 
2148
}
 
2149
 
 
2150
 
 
2151
/*
 
2152
 *-----------------------------------------------------------------------------
 
2153
 *
 
2154
 * utf::string::end --
 
2155
 *
 
2156
 *      Returns an iterator to the end of the string.
 
2157
 *
 
2158
 * Results:
 
2159
 *      iterator
 
2160
 *
 
2161
 * Side effects:
 
2162
 *      None
 
2163
 *
 
2164
 *-----------------------------------------------------------------------------
 
2165
 */
 
2166
 
 
2167
string::iterator
 
2168
string::end()
 
2169
{
 
2170
   return mUstr.end();
 
2171
}
 
2172
 
 
2173
 
 
2174
string::const_iterator
 
2175
string::end()
 
2176
   const
 
2177
{
 
2178
   return mUstr.end();
 
2179
}
 
2180
 
 
2181
 
 
2182
/*
 
2183
 *-----------------------------------------------------------------------------
 
2184
 *
 
2185
 * utf::Validate --
 
2186
 *
 
2187
 *      Validates the string.
 
2188
 *
 
2189
 * Results:
 
2190
 *      true if the string contains is valid UTF-8, false otherwise.
 
2191
 *
 
2192
 * Side effects:
 
2193
 *      None
 
2194
 *
 
2195
 *-----------------------------------------------------------------------------
 
2196
 */
 
2197
 
 
2198
bool
 
2199
Validate(const Glib::ustring& s) // IN
 
2200
{
 
2201
   bool isValid = s.validate();
 
2202
   if (!isValid) {
 
2203
      char *escaped = Unicode_EscapeBuffer(s.c_str(), -1, STRING_ENCODING_UTF8);
 
2204
      Warning("Invalid UTF-8 string: \"%s\"\n", escaped);
 
2205
      free(escaped);
 
2206
   }
 
2207
   return isValid;
 
2208
}
 
2209
 
 
2210
 
 
2211
/*
 
2212
 *-----------------------------------------------------------------------------
 
2213
 *
 
2214
 * utf::CreateWithLength --
 
2215
 *
 
2216
 *      A wrapper function for Unicode_AllocWithLength() that returns a utf::string.
 
2217
 *
 
2218
 * Results:
 
2219
 *      A utf::string created with given parameters.
 
2220
 *
 
2221
 * Side effects:
 
2222
 *      None
 
2223
 *
 
2224
 *-----------------------------------------------------------------------------
 
2225
 */
 
2226
 
 
2227
string
 
2228
CreateWithLength(const void *buffer,      // IN
 
2229
                 ssize_t lengthInBytes,   // IN: NUL not included
 
2230
                 StringEncoding encoding) // IN
 
2231
{
 
2232
   if (!Unicode_IsBufferValid(buffer, lengthInBytes, encoding)) {
 
2233
      throw ConversionError();
 
2234
   }
 
2235
 
 
2236
   Unicode utf8 = Unicode_AllocWithLength(buffer, lengthInBytes, encoding);
 
2237
 
 
2238
   try {
 
2239
      string result(utf8);
 
2240
      Unicode_Free(utf8);
 
2241
      return result;
 
2242
   } catch (...) {
 
2243
      Unicode_Free(utf8);
 
2244
      throw;
 
2245
   }
 
2246
}
 
2247
 
 
2248
 
 
2249
/*
 
2250
 *----------------------------------------------------------------------
 
2251
 *
 
2252
 * utf::CreateWithBOMBuffer --
 
2253
 *
 
2254
 *       Convert a text buffer with BOM (byte-order mark) to utf::string.
 
2255
 *       If BOM not present, assume it's UTF-8.
 
2256
 *
 
2257
 * Results:
 
2258
 *       A utf::string containing the text buffer.
 
2259
 *
 
2260
 * Side Effect:
 
2261
 *       None.
 
2262
 *
 
2263
 *----------------------------------------------------------------------
 
2264
 */
 
2265
 
 
2266
string
 
2267
CreateWithBOMBuffer(const void *buffer,      // IN
 
2268
                    ssize_t lengthInBytes)   // IN: NUL not included
 
2269
{
 
2270
   struct BOMMap {
 
2271
      uint8 bom[4];              // BOM with max size.
 
2272
      ssize_t len;               // Length of BOM.
 
2273
      StringEncoding encoding;   // Encoding if a BOM is present.
 
2274
   };
 
2275
 
 
2276
   static const BOMMap mapBOM[] = {
 
2277
      {{0}, 0,                      STRING_ENCODING_UTF8     }, // Default encoding.
 
2278
      {{0xEF, 0xBB, 0xBF}, 3,       STRING_ENCODING_UTF8     },
 
2279
      {{0xFE, 0xFF}, 2,             STRING_ENCODING_UTF16_BE },
 
2280
      {{0xFF, 0xFE}, 2,             STRING_ENCODING_UTF16_LE },
 
2281
      {{0x00, 0x00, 0xFE, 0xFF}, 4, STRING_ENCODING_UTF32_BE },
 
2282
      {{0xFF, 0xFE, 0x00, 0x00}, 4, STRING_ENCODING_UTF32_LE }
 
2283
   };
 
2284
 
 
2285
   ASSERT(lengthInBytes >= 0);
 
2286
   unsigned int index = 0; // Default encoding, no need to check.
 
2287
   for (unsigned int i = 1; i < ARRAYSIZE(mapBOM); i++) {
 
2288
      if (   lengthInBytes >= mapBOM[i].len
 
2289
          && memcmp(mapBOM[i].bom, buffer, mapBOM[i].len) == 0) {
 
2290
         index = i;
 
2291
         break;
 
2292
      }
 
2293
   }
 
2294
 
 
2295
   return CreateWithLength(reinterpret_cast<const char*>(buffer) + mapBOM[index].len,
 
2296
                           lengthInBytes - mapBOM[index].len,
 
2297
                           mapBOM[index].encoding);
 
2298
}
 
2299
 
 
2300
 
 
2301
/*
 
2302
 *-----------------------------------------------------------------------------
 
2303
 *
 
2304
 * utf::IntToStr --
 
2305
 *
 
2306
 *      Converts an integer to a utf::string.
 
2307
 *
 
2308
 * Results:
 
2309
 *      A utf::string created with the given integer.
 
2310
 *
 
2311
 * Side effects:
 
2312
 *      None
 
2313
 *
 
2314
 *-----------------------------------------------------------------------------
 
2315
 */
 
2316
 
 
2317
string
 
2318
IntToStr(int64 val) // IN
 
2319
{
 
2320
   std::ostringstream ostream;
 
2321
   ostream << val;
 
2322
   return ostream.str().c_str();
 
2323
}
 
2324
 
 
2325
 
 
2326
/*
 
2327
 *-----------------------------------------------------------------------------
 
2328
 *
 
2329
 * utf::CopyArray --
 
2330
 *
 
2331
 *      Copies an array to a vector.
 
2332
 *      Guaranteed to not shrink the vector.
 
2333
 *
 
2334
 * Results:
 
2335
 *      A vector containing a shallow copy of the array.
 
2336
 *
 
2337
 * Side effects:
 
2338
 *      None
 
2339
 *
 
2340
 *-----------------------------------------------------------------------------
 
2341
 */
 
2342
 
 
2343
template<typename T>
 
2344
static void
 
2345
CopyArray(const T *p,          // IN:
 
2346
          size_t n,            // IN: The number of array elements to copy.
 
2347
          std::vector<T>& buf) // OUT:
 
2348
{
 
2349
   if (n > buf.size()) {
 
2350
      buf.resize(n);
 
2351
   }
 
2352
 
 
2353
   if (!buf.empty()) {
 
2354
      ASSERT(p != NULL);
 
2355
      memcpy(&buf[0], p, n * sizeof buf[0]);
 
2356
   }
 
2357
}
 
2358
 
 
2359
 
 
2360
/*
 
2361
 *-----------------------------------------------------------------------------
 
2362
 *
 
2363
 * utf::CreateWritableBuffer --
 
2364
 *
 
2365
 *      Copies a utf::string to a writable buffer.
 
2366
 *      Guaranteed to never shrink the size of the destination buffer.
 
2367
 *
 
2368
 * Results:
 
2369
 *      A std::vector containing the NUL-terminated string data.
 
2370
 *      The size of the resulting vector may exceed the length of the
 
2371
 *      NUL-terminated string.
 
2372
 *
 
2373
 * Side effects:
 
2374
 *      None
 
2375
 *
 
2376
 *-----------------------------------------------------------------------------
 
2377
 */
 
2378
 
 
2379
void
 
2380
CreateWritableBuffer(const string& s,        // IN:
 
2381
                     std::vector<char>& buf) // OUT: A copy of the string, as UTF-8.
 
2382
{
 
2383
   CopyArray(s.c_str(), s.bytes() + 1, buf);
 
2384
}
 
2385
 
 
2386
 
 
2387
void
 
2388
CreateWritableBuffer(const string& s,           // IN:
 
2389
                     std::vector<utf16_t>& buf) // OUT: A copy of the string, as UTF-16.
 
2390
{
 
2391
   CopyArray(s.w_str(), s.w_size() + 1, buf);
 
2392
}
 
2393
 
 
2394
 
 
2395
} // namespace utf