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.");
238 int newSize = target - targetBuffer;
240 targetBuffer[newSize] = 0;
242 s = (char *) targetBuffer;
244 delete [] sourceBuffer;
245 delete [] targetBuffer;
250 TagLib::wstring String::toWString() const
255 const char *String::toCString(bool unicode) const
257 delete [] d->CString;
259 std::string buffer = to8Bit(unicode);
260 d->CString = new char[buffer.size() + 1];
261 strcpy(d->CString, buffer.c_str());
266 String::Iterator String::begin()
268 return d->data.begin();
271 String::ConstIterator String::begin() const
273 return d->data.begin();
276 String::Iterator String::end()
278 return d->data.end();
281 String::ConstIterator String::end() const
283 return d->data.end();
286 int String::find(const String &s, int offset) const
288 wstring::size_type position = d->data.find(s.d->data, offset);
290 if(position != wstring::npos)
296 int String::rfind(const String &s, int offset) const
298 wstring::size_type position =
299 d->data.rfind(s.d->data, offset == -1 ? wstring::npos : offset);
301 if(position != wstring::npos)
307 bool String::startsWith(const String &s) const
309 if(s.length() > length())
312 return substr(0, s.length()) == s;
315 String String::substr(uint position, uint n) const
317 if(n > position + d->data.size())
318 n = d->data.size() - position;
321 s.d->data = d->data.substr(position, n);
325 String &String::append(const String &s)
328 d->data += s.d->data;
332 String String::upper() const
336 static int shift = 'A' - 'a';
338 for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); ++it) {
339 if(*it >= 'a' && *it <= 'z')
340 s.d->data.push_back(*it + shift);
342 s.d->data.push_back(*it);
348 TagLib::uint String::size() const
350 return d->data.size();
353 TagLib::uint String::length() const
358 bool String::isEmpty() const
360 return d->data.size() == 0;
363 bool String::isNull() const
368 ByteVector String::data(Type t) const
376 for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++)
382 std::string s = to8Bit(true);
383 v.setData(s.c_str(), s.length());
388 // Assume that if we're doing UTF16 and not UTF16BE that we want little
389 // endian encoding. (Byte Order Mark)
391 v.append(char(0xff));
392 v.append(char(0xfe));
394 for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) {
396 char c1 = *it & 0xff;
406 for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) {
409 char c2 = *it & 0xff;
418 for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) {
420 char c1 = *it & 0xff;
433 int String::toInt() const
438 int String::toInt(bool *ok) const
442 uint size = d->data.size();
443 bool negative = size > 0 && d->data[0] == '-';
444 uint start = negative ? 1 : 0;
447 for(; i < size && d->data[i] >= '0' && d->data[i] <= '9'; i++)
448 value = value * 10 + (d->data[i] - '0');
454 *ok = (size > start && i == size);
459 String String::stripWhiteSpace() const
461 wstring::const_iterator begin = d->data.begin();
462 wstring::const_iterator end = d->data.end();
464 while(begin != end &&
465 (*begin == '\t' || *begin == '\n' || *begin == '\f' ||
466 *begin == '\r' || *begin == ' '))
474 // There must be at least one non-whitespace character here for us to have
475 // gotten this far, so we should be safe not doing bounds checking.
479 } while(*end == '\t' || *end == '\n' ||
480 *end == '\f' || *end == '\r' || *end == ' ');
482 return String(wstring(begin, end + 1));
485 bool String::isLatin1() const
487 for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) {
494 bool String::isAscii() const
496 for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) {
503 String String::number(int n) // static
510 bool negative = n < 0;
516 int remainder = n % 10;
517 charStack += char(remainder + '0');
518 n = (n - remainder) / 10;
526 for(int i = charStack.d->data.size() - 1; i >= 0; i--)
527 s += charStack.d->data[i];
532 TagLib::wchar &String::operator[](int i)
539 const TagLib::wchar &String::operator[](int i) const
544 bool String::operator==(const String &s) const
546 return d == s.d || d->data == s.d->data;
549 String &String::operator+=(const String &s)
553 d->data += s.d->data;
557 String &String::operator+=(const wchar_t *s)
565 String &String::operator+=(const char *s)
569 for(int i = 0; s[i] != 0; i++)
570 d->data += uchar(s[i]);
574 String &String::operator+=(wchar_t c)
582 String &String::operator+=(char c)
590 String &String::operator=(const String &s)
602 String &String::operator=(const std::string &s)
607 d = new StringPrivate;
609 d->data.resize(s.size());
611 wstring::iterator targetIt = d->data.begin();
612 for(std::string::const_iterator it = s.begin(); it != s.end(); it++) {
613 *targetIt = uchar(*it);
620 String &String::operator=(const wstring &s)
624 d = new StringPrivate(s);
628 String &String::operator=(const wchar_t *s)
632 d = new StringPrivate(s);
636 String &String::operator=(char c)
640 d = new StringPrivate;
645 String &String::operator=(wchar_t c)
649 d = new StringPrivate;
654 String &String::operator=(const char *s)
659 d = new StringPrivate;
661 int length = ::strlen(s);
662 d->data.resize(length);
664 wstring::iterator targetIt = d->data.begin();
665 for(int i = 0; i < length; i++) {
666 *targetIt = uchar(s[i]);
673 String &String::operator=(const ByteVector &v)
678 d = new StringPrivate;
679 d->data.resize(v.size());
680 wstring::iterator targetIt = d->data.begin();
684 for(ByteVector::ConstIterator it = v.begin(); it != v.end() && (*it); ++it) {
685 *targetIt = uchar(*it);
690 // If we hit a null in the ByteVector, shrink the string again.
697 bool String::operator<(const String &s) const
699 return d->data < s.d->data;
702 ////////////////////////////////////////////////////////////////////////////////
704 ////////////////////////////////////////////////////////////////////////////////
706 void String::detach()
710 d = new StringPrivate(d->data);
714 ////////////////////////////////////////////////////////////////////////////////
716 ////////////////////////////////////////////////////////////////////////////////
718 void String::prepare(Type t)
723 if(d->data.size() >= 1 && (d->data[0] == 0xfeff || d->data[0] == 0xfffe)) {
724 bool swap = d->data[0] != 0xfeff;
725 d->data.erase(d->data.begin(), d->data.begin() + 1);
727 for(uint i = 0; i < d->data.size(); i++)
728 d->data[i] = byteSwap((unsigned short)d->data[i]);
732 debug("String::prepare() - Invalid UTF16 string.");
733 d->data.erase(d->data.begin(), d->data.end());
739 int bufferSize = d->data.size() + 1;
740 Unicode::UTF8 *sourceBuffer = new Unicode::UTF8[bufferSize];
741 Unicode::UTF16 *targetBuffer = new Unicode::UTF16[bufferSize];
744 for(; i < d->data.size(); i++)
745 sourceBuffer[i] = Unicode::UTF8(d->data[i]);
748 const Unicode::UTF8 *source = sourceBuffer;
749 Unicode::UTF16 *target = targetBuffer;
751 Unicode::ConversionResult result =
752 Unicode::ConvertUTF8toUTF16(&source, sourceBuffer + bufferSize,
753 &target, targetBuffer + bufferSize,
754 Unicode::lenientConversion);
756 if(result != Unicode::conversionOK)
757 debug("String::prepare() - Unicode conversion error.");
760 int newSize = target != targetBuffer ? target - targetBuffer - 1 : 0;
761 d->data.resize(newSize);
763 for(int i = 0; i < newSize; i++)
764 d->data[i] = targetBuffer[i];
766 delete [] sourceBuffer;
767 delete [] targetBuffer;
773 for(uint i = 0; i < d->data.size(); i++)
774 d->data[i] = byteSwap((unsigned short)d->data[i]);
782 ////////////////////////////////////////////////////////////////////////////////
784 ////////////////////////////////////////////////////////////////////////////////
786 const TagLib::String operator+(const TagLib::String &s1, const TagLib::String &s2)
793 const TagLib::String operator+(const char *s1, const TagLib::String &s2)
800 const TagLib::String operator+(const TagLib::String &s1, const char *s2)
807 std::ostream &operator<<(std::ostream &s, const String &str)