1
/***************************************************************************
2
copyright : (C) 2002 - 2008 by Scott Wheeler
3
email : wheeler@kde.org
4
***************************************************************************/
6
/***************************************************************************
7
* This library is free software; you can redistribute it and/or modify *
8
* it under the terms of the GNU Lesser General Public License version *
9
* 2.1 as published by the Free Software Foundation. *
11
* This library is distributed in the hope that it will be useful, but *
12
* WITHOUT ANY WARRANTY; without even the implied warranty of *
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14
* Lesser General Public License for more details. *
16
* You should have received a copy of the GNU Lesser General Public *
17
* License along with this library; if not, write to the Free Software *
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
21
* Alternatively, this file is available under the Mozilla Public *
22
* License Version 1.1. You may obtain a copy of the License at *
23
* http://www.mozilla.org/MPL/ *
24
***************************************************************************/
36
inline unsigned short byteSwap(unsigned short x)
38
return (((x) >> 8) & 0xff) | (((x) & 0xff) << 8);
41
inline unsigned short combine(unsigned char c1, unsigned char c2)
43
return (c1 << 8) | c2;
47
using namespace TagLib;
49
class String::StringPrivate : public RefCounter
52
StringPrivate(const wstring &s) :
68
* This is only used to hold the a pointer to the most recent value of
76
////////////////////////////////////////////////////////////////////////////////
80
d = new StringPrivate;
83
String::String(const String &s) : d(s.d)
88
String::String(const std::string &s, Type t)
90
d = new StringPrivate;
92
if(t == UTF16 || t == UTF16BE || t == UTF16LE) {
93
debug("String::String() -- A std::string should not contain UTF16.");
97
int length = s.length();
98
d->data.resize(length);
99
wstring::iterator targetIt = d->data.begin();
101
for(std::string::const_iterator it = s.begin(); it != s.end(); it++) {
102
*targetIt = uchar(*it);
109
String::String(const wstring &s, Type t)
111
d = new StringPrivate(s);
115
String::String(const wchar_t *s, Type t)
117
d = new StringPrivate(s);
121
String::String(const char *s, Type t)
123
d = new StringPrivate;
125
if(t == UTF16 || t == UTF16BE || t == UTF16LE) {
126
debug("String::String() -- A const char * should not contain UTF16.");
130
int length = ::strlen(s);
131
d->data.resize(length);
133
wstring::iterator targetIt = d->data.begin();
135
for(int i = 0; i < length; i++) {
136
*targetIt = uchar(s[i]);
143
String::String(wchar_t c, Type t)
145
d = new StringPrivate;
150
String::String(char c, Type t)
152
d = new StringPrivate;
154
if(t == UTF16 || t == UTF16BE || t == UTF16LE) {
155
debug("String::String() -- A std::string should not contain UTF16.");
163
String::String(const ByteVector &v, Type t)
165
d = new StringPrivate;
170
if(t == Latin1 || t == UTF8) {
173
d->data.resize(v.size());
174
wstring::iterator targetIt = d->data.begin();
175
for(ByteVector::ConstIterator it = v.begin(); it != v.end() && (*it); ++it) {
176
*targetIt = uchar(*it);
180
d->data.resize(length);
183
d->data.resize(v.size() / 2);
184
wstring::iterator targetIt = d->data.begin();
186
for(ByteVector::ConstIterator it = v.begin();
187
it != v.end() && it + 1 != v.end() && combine(*it, *(it + 1));
190
*targetIt = combine(*it, *(it + 1));
197
////////////////////////////////////////////////////////////////////////////////
205
std::string String::to8Bit(bool unicode) const
208
s.resize(d->data.size());
211
std::string::iterator targetIt = s.begin();
212
for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) {
213
*targetIt = char(*it);
219
const int outputBufferSize = d->data.size() * 3 + 1;
221
Unicode::UTF16 *sourceBuffer = new Unicode::UTF16[d->data.size() + 1];
222
Unicode::UTF8 *targetBuffer = new Unicode::UTF8[outputBufferSize];
224
for(unsigned int i = 0; i < d->data.size(); i++)
225
sourceBuffer[i] = Unicode::UTF16(d->data[i]);
227
const Unicode::UTF16 *source = sourceBuffer;
228
Unicode::UTF8 *target = targetBuffer;
230
Unicode::ConversionResult result =
231
Unicode::ConvertUTF16toUTF8(&source, sourceBuffer + d->data.size(),
232
&target, targetBuffer + outputBufferSize,
233
Unicode::lenientConversion);
235
if(result != Unicode::conversionOK) {
236
debug("String::to8Bit() - Unicode conversion error.");
239
int newSize = target - targetBuffer;
241
targetBuffer[newSize] = 0;
243
s = (char *) targetBuffer;
245
delete [] sourceBuffer;
246
delete [] targetBuffer;
251
TagLib::wstring String::toWString() const
256
const char *String::toCString(bool unicode) const
258
delete [] d->CString;
260
std::string buffer = to8Bit(unicode);
261
d->CString = new char[buffer.size() + 1];
262
strcpy(d->CString, buffer.c_str());
267
String::Iterator String::begin()
269
return d->data.begin();
272
String::ConstIterator String::begin() const
274
return d->data.begin();
277
String::Iterator String::end()
279
return d->data.end();
282
String::ConstIterator String::end() const
284
return d->data.end();
287
int String::find(const String &s, int offset) const
289
wstring::size_type position = d->data.find(s.d->data, offset);
291
if(position != wstring::npos)
297
bool String::startsWith(const String &s) const
299
if(s.length() > length())
302
return substr(0, s.length()) == s;
305
String String::substr(uint position, uint n) const
307
if(n > position + d->data.size())
308
n = d->data.size() - position;
311
s.d->data = d->data.substr(position, n);
315
String &String::append(const String &s)
318
d->data += s.d->data;
322
String String::upper() const
326
static int shift = 'A' - 'a';
328
for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); ++it) {
329
if(*it >= 'a' && *it <= 'z')
330
s.d->data.push_back(*it + shift);
332
s.d->data.push_back(*it);
338
TagLib::uint String::size() const
340
return d->data.size();
343
TagLib::uint String::length() const
348
bool String::isEmpty() const
350
return d->data.size() == 0;
353
bool String::isNull() const
358
ByteVector String::data(Type t) const
366
for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++)
372
std::string s = to8Bit(true);
373
v.setData(s.c_str(), s.length());
378
// Assume that if we're doing UTF16 and not UTF16BE that we want little
379
// endian encoding. (Byte Order Mark)
381
v.append(char(0xff));
382
v.append(char(0xfe));
384
for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) {
386
char c1 = *it & 0xff;
396
for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) {
399
char c2 = *it & 0xff;
408
for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) {
410
char c1 = *it & 0xff;
423
int String::toInt() const
427
bool negative = d->data[0] == '-';
428
uint i = negative ? 1 : 0;
430
for(; i < d->data.size() && d->data[i] >= '0' && d->data[i] <= '9'; i++)
431
value = value * 10 + (d->data[i] - '0');
439
String String::stripWhiteSpace() const
441
wstring::const_iterator begin = d->data.begin();
442
wstring::const_iterator end = d->data.end();
444
while(begin != end &&
445
(*begin == '\t' || *begin == '\n' || *begin == '\f' ||
446
*begin == '\r' || *begin == ' '))
454
// There must be at least one non-whitespace character here for us to have
455
// gotten this far, so we should be safe not doing bounds checking.
459
} while(*end == '\t' || *end == '\n' ||
460
*end == '\f' || *end == '\r' || *end == ' ');
462
return String(wstring(begin, end + 1));
465
bool String::isLatin1() const
467
for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) {
474
bool String::isAscii() const
476
for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) {
483
String String::number(int n) // static
490
bool negative = n < 0;
496
int remainder = n % 10;
497
charStack += char(remainder + '0');
498
n = (n - remainder) / 10;
506
for(int i = charStack.d->data.size() - 1; i >= 0; i--)
507
s += charStack.d->data[i];
512
TagLib::wchar &String::operator[](int i)
517
const TagLib::wchar &String::operator[](int i) const
522
bool String::operator==(const String &s) const
524
return d == s.d || d->data == s.d->data;
527
String &String::operator+=(const String &s)
531
d->data += s.d->data;
535
String &String::operator+=(const wchar_t *s)
543
String &String::operator+=(const char *s)
547
for(int i = 0; s[i] != 0; i++)
548
d->data += uchar(s[i]);
552
String &String::operator+=(wchar_t c)
560
String &String::operator+=(char c)
566
String &String::operator=(const String &s)
578
String &String::operator=(const std::string &s)
583
d = new StringPrivate;
585
d->data.resize(s.size());
587
wstring::iterator targetIt = d->data.begin();
588
for(std::string::const_iterator it = s.begin(); it != s.end(); it++) {
589
*targetIt = uchar(*it);
596
String &String::operator=(const wstring &s)
600
d = new StringPrivate(s);
604
String &String::operator=(const wchar_t *s)
608
d = new StringPrivate(s);
612
String &String::operator=(char c)
616
d = new StringPrivate;
621
String &String::operator=(wchar_t c)
625
d = new StringPrivate;
630
String &String::operator=(const char *s)
635
d = new StringPrivate;
637
int length = ::strlen(s);
638
d->data.resize(length);
640
wstring::iterator targetIt = d->data.begin();
641
for(int i = 0; i < length; i++) {
642
*targetIt = uchar(s[i]);
649
String &String::operator=(const ByteVector &v)
654
d = new StringPrivate;
655
d->data.resize(v.size());
656
wstring::iterator targetIt = d->data.begin();
660
for(ByteVector::ConstIterator it = v.begin(); it != v.end() && (*it); ++it) {
661
*targetIt = uchar(*it);
666
// If we hit a null in the ByteVector, shrink the string again.
673
bool String::operator<(const String &s) const
675
return d->data < s.d->data;
678
////////////////////////////////////////////////////////////////////////////////
680
////////////////////////////////////////////////////////////////////////////////
682
void String::detach()
686
d = new StringPrivate(d->data);
690
////////////////////////////////////////////////////////////////////////////////
692
////////////////////////////////////////////////////////////////////////////////
694
void String::prepare(Type t)
699
if(d->data.size() >= 1 && (d->data[0] == 0xfeff || d->data[0] == 0xfffe)) {
700
bool swap = d->data[0] != 0xfeff;
701
d->data.erase(d->data.begin(), d->data.begin() + 1);
703
for(uint i = 0; i < d->data.size(); i++)
704
d->data[i] = byteSwap((unsigned short)d->data[i]);
708
debug("String::prepare() - Invalid UTF16 string.");
709
d->data.erase(d->data.begin(), d->data.end());
715
int bufferSize = d->data.size() + 1;
716
Unicode::UTF8 *sourceBuffer = new Unicode::UTF8[bufferSize];
717
Unicode::UTF16 *targetBuffer = new Unicode::UTF16[bufferSize];
720
for(; i < d->data.size(); i++)
721
sourceBuffer[i] = Unicode::UTF8(d->data[i]);
724
const Unicode::UTF8 *source = sourceBuffer;
725
Unicode::UTF16 *target = targetBuffer;
727
Unicode::ConversionResult result =
728
Unicode::ConvertUTF8toUTF16(&source, sourceBuffer + bufferSize,
729
&target, targetBuffer + bufferSize,
730
Unicode::lenientConversion);
732
if(result != Unicode::conversionOK) {
733
debug("String::prepare() - Unicode conversion error.");
737
int newSize = target != targetBuffer ? target - targetBuffer - 1 : 0;
738
d->data.resize(newSize);
740
for(int i = 0; i < newSize; i++)
741
d->data[i] = targetBuffer[i];
743
delete [] sourceBuffer;
744
delete [] targetBuffer;
750
for(uint i = 0; i < d->data.size(); i++)
751
d->data[i] = byteSwap((unsigned short)d->data[i]);
759
////////////////////////////////////////////////////////////////////////////////
761
////////////////////////////////////////////////////////////////////////////////
763
const TagLib::String operator+(const TagLib::String &s1, const TagLib::String &s2)
770
const TagLib::String operator+(const char *s1, const TagLib::String &s2)
777
const TagLib::String operator+(const TagLib::String &s1, const char *s2)
784
std::ostream &operator<<(std::ostream &s, const String &str)