//
// http://www.informit.com/isapi/product_id~{9C84DAB4-FE6E-49C5-BB0A-FB50331233EA}/content/index.asp
-#define DATA(x) (&(x->data->data[0]))
+#define DATA(x) (&(*(x)->data)[0])
namespace TagLib {
template <Utils::ByteOrder ENDIAN>
long double toFloat80(const ByteVector &v, size_t offset)
{
+ using std::swap;
+
if(offset > v.size() - 10) {
debug("toFloat80() - offset is out of range. Returning 0.");
return 0.0;
::memcpy(bytes, v.data() + offset, 10);
if(ENDIAN == Utils::LittleEndian) {
- std::swap(bytes[0], bytes[9]);
- std::swap(bytes[1], bytes[8]);
- std::swap(bytes[2], bytes[7]);
- std::swap(bytes[3], bytes[6]);
- std::swap(bytes[4], bytes[5]);
+ swap(bytes[0], bytes[9]);
+ swap(bytes[1], bytes[8]);
+ swap(bytes[2], bytes[7]);
+ swap(bytes[3], bytes[6]);
+ swap(bytes[4], bytes[5]);
}
// 1-bit sign
return val;
}
-class DataPrivate : public RefCounter
-{
-public:
- DataPrivate()
- {
- }
-
- DataPrivate(const std::vector<char> &v, uint offset, uint length)
- : data(v.begin() + offset, v.begin() + offset + length)
- {
- }
-
- // A char* can be an iterator.
- DataPrivate(const char *begin, const char *end)
- : data(begin, end)
- {
- }
-
- DataPrivate(uint len, char c)
- : data(len, c)
- {
- }
-
- std::vector<char> data;
-};
-
-class ByteVector::ByteVectorPrivate : public RefCounter
+class ByteVector::ByteVectorPrivate
{
public:
- ByteVectorPrivate()
- : RefCounter()
- , data(new DataPrivate())
- , offset(0)
- , length(0)
- {
- }
-
- ByteVectorPrivate(ByteVectorPrivate *d, uint o, uint l)
- : RefCounter()
- , data(d->data)
- , offset(d->offset + o)
- , length(l)
- {
- data->ref();
- }
-
- ByteVectorPrivate(const std::vector<char> &v, uint o, uint l)
- : RefCounter()
- , data(new DataPrivate(v, o, l))
- , offset(0)
- , length(l)
- {
- }
-
- ByteVectorPrivate(uint l, char c)
- : RefCounter()
- , data(new DataPrivate(l, c))
- , offset(0)
- , length(l)
- {
- }
-
- ByteVectorPrivate(const char *s, uint l)
- : RefCounter()
- , data(new DataPrivate(s, s + l))
- , offset(0)
- , length(l)
+ ByteVectorPrivate(uint l, char c) :
+ counter(new RefCounter()),
+ data(new std::vector<char>(l, c)),
+ offset(0),
+ length(l) {}
+
+ ByteVectorPrivate(const char *s, uint l) :
+ counter(new RefCounter()),
+ data(new std::vector<char>(s, s + l)),
+ offset(0),
+ length(l) {}
+
+ ByteVectorPrivate(const ByteVectorPrivate &d, uint o, uint l) :
+ counter(d.counter),
+ data(d.data),
+ offset(d.offset + o),
+ length(l)
{
- }
-
- void detach()
- {
- if(data->count() > 1) {
- data->deref();
- data = new DataPrivate(data->data, offset, length);
- offset = 0;
- }
+ counter->ref();
}
~ByteVectorPrivate()
{
- if(data->deref())
+ if(counter->deref()) {
+ delete counter;
delete data;
- }
-
- ByteVectorPrivate &operator=(const ByteVectorPrivate &x)
- {
- if(&x != this)
- {
- if(data->deref())
- delete data;
-
- data = x.data;
- data->ref();
}
-
- return *this;
}
- DataPrivate *data;
- uint offset;
- uint length;
+ RefCounter *counter;
+ std::vector<char> *data;
+ uint offset;
+ uint length;
};
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
-ByteVector::ByteVector()
- : d(new ByteVectorPrivate())
+ByteVector::ByteVector() :
+ d(new ByteVectorPrivate(0, '\0'))
{
}
-ByteVector::ByteVector(uint size, char value)
- : d(new ByteVectorPrivate(size, value))
+ByteVector::ByteVector(uint size, char value) :
+ d(new ByteVectorPrivate(size, value))
{
}
-ByteVector::ByteVector(const ByteVector &v)
- : d(v.d)
+ByteVector::ByteVector(const ByteVector &v) :
+ d(new ByteVectorPrivate(*v.d, 0, v.d->length))
{
- d->ref();
}
-ByteVector::ByteVector(const ByteVector &v, uint offset, uint length)
- : d(new ByteVectorPrivate(v.d, offset, length))
+ByteVector::ByteVector(const ByteVector &v, uint offset, uint length) :
+ d(new ByteVectorPrivate(*v.d, offset, length))
{
}
-ByteVector::ByteVector(char c)
- : d(new ByteVectorPrivate(1, c))
+ByteVector::ByteVector(char c) :
+ d(new ByteVectorPrivate(1, c))
{
}
-ByteVector::ByteVector(const char *data, uint length)
- : d(new ByteVectorPrivate(data, length))
+ByteVector::ByteVector(const char *data, uint length) :
+ d(new ByteVectorPrivate(data, length))
{
}
-ByteVector::ByteVector(const char *data)
- : d(new ByteVectorPrivate(data, ::strlen(data)))
+ByteVector::ByteVector(const char *data) :
+ d(new ByteVectorPrivate(data, ::strlen(data)))
{
}
ByteVector::~ByteVector()
{
- if(d->deref())
- delete d;
+ delete d;
}
ByteVector &ByteVector::setData(const char *s, uint length)
{
- *this = ByteVector(s, length);
+ ByteVector(s, length).swap(*this);
return *this;
}
ByteVector &ByteVector::setData(const char *data)
{
- *this = ByteVector(data);
+ ByteVector(data).swap(*this);
return *this;
}
char *ByteVector::data()
{
detach();
- return size() > 0 ? (DATA(d) + d->offset) : 0;
+ return (size() > 0) ? (DATA(d) + d->offset) : 0;
}
const char *ByteVector::data() const
{
- return size() > 0 ? (DATA(d) + d->offset) : 0;
+ return (size() > 0) ? (DATA(d) + d->offset) : 0;
}
ByteVector ByteVector::mid(uint index, uint length) const
char ByteVector::at(uint index) const
{
- return index < size() ? DATA(d)[d->offset + index] : 0;
+ return (index < size()) ? DATA(d)[d->offset + index] : 0;
}
int ByteVector::find(const ByteVector &pattern, uint offset, int byteAlign) const
ByteVector &ByteVector::append(const ByteVector &v)
{
- if(v.d->length != 0)
- {
+ if(v.d->length != 0) {
detach();
-
uint originalSize = size();
resize(originalSize + v.size());
::memcpy(data() + originalSize, v.data(), v.size());
return *this;
}
+ByteVector &ByteVector::append(char c)
+{
+ resize(size() + 1, c);
+ return *this;
+}
+
ByteVector &ByteVector::clear()
{
- *this = ByteVector();
+ ByteVector().swap(*this);
return *this;
}
// This doesn't reallocate the buffer, since std::vector::resize() doesn't
// reallocate the buffer when shrinking.
- d->data->data.resize(d->offset + d->length);
- d->data->data.resize(d->offset + size, padding);
+ d->data->resize(d->offset + d->length);
+ d->data->resize(d->offset + size, padding);
d->length = size;
}
ByteVector::Iterator ByteVector::begin()
{
detach();
- return d->data->data.begin() + d->offset;
+ return d->data->begin() + d->offset;
}
ByteVector::ConstIterator ByteVector::begin() const
{
- return d->data->data.begin() + d->offset;
+ return d->data->begin() + d->offset;
}
ByteVector::Iterator ByteVector::end()
{
detach();
- return d->data->data.begin() + d->offset + d->length;
+ return d->data->begin() + d->offset + d->length;
}
ByteVector::ConstIterator ByteVector::end() const
{
- return d->data->data.begin() + d->offset + d->length;
+ return d->data->begin() + d->offset + d->length;
}
ByteVector::ReverseIterator ByteVector::rbegin()
{
detach();
- return d->data->data.rbegin() + (d->data->data.size() - (d->offset + d->length));
+ return d->data->rbegin() + (d->data->size() - (d->offset + d->length));
}
ByteVector::ConstReverseIterator ByteVector::rbegin() const
ByteVector::ReverseIterator ByteVector::rend()
{
detach();
- return d->data->data.rbegin() + (d->data->data.size() - d->offset);
+ return d->data->rbegin() + (d->data->size() - d->offset);
}
ByteVector::ConstReverseIterator ByteVector::rend() const
const char &ByteVector::operator[](int index) const
{
- return d->data->data[d->offset + index];
+ return DATA(d)[d->offset + index];
}
char &ByteVector::operator[](int index)
{
detach();
- return d->data->data[d->offset + index];
+ return DATA(d)[d->offset + index];
}
bool ByteVector::operator==(const ByteVector &v) const
bool ByteVector::operator!=(const ByteVector &v) const
{
- return !operator==(v);
+ return !(*this == v);
}
bool ByteVector::operator==(const char *s) const
bool ByteVector::operator!=(const char *s) const
{
- return !operator==(s);
+ return !(*this == s);
}
bool ByteVector::operator<(const ByteVector &v) const
bool ByteVector::operator>(const ByteVector &v) const
{
- return v < *this;
+ return (v < *this);
}
ByteVector ByteVector::operator+(const ByteVector &v) const
ByteVector &ByteVector::operator=(const ByteVector &v)
{
- if(&v == this)
- return *this;
-
- if(d->deref())
- delete d;
-
- d = v.d;
- d->ref();
+ ByteVector(v).swap(*this);
return *this;
}
ByteVector &ByteVector::operator=(char c)
{
- *this = ByteVector(c);
+ ByteVector(c).swap(*this);
return *this;
}
ByteVector &ByteVector::operator=(const char *data)
{
- *this = ByteVector(data);
+ ByteVector(data).swap(*this);
return *this;
}
+void ByteVector::swap(ByteVector &v)
+{
+ using std::swap;
+
+ swap(d, v.d);
+}
+
ByteVector ByteVector::toHex() const
{
ByteVector encoded(size() * 2);
void ByteVector::detach()
{
- if(d->data->count() > 1) {
- d->data->deref();
- d->data = new DataPrivate(d->data->data, d->offset, d->length);
- d->offset = 0;
- }
-
- if(d->count() > 1) {
- d->deref();
- d = new ByteVectorPrivate(d->data->data, d->offset, d->length);
+ if(d->counter->count() > 1) {
+ if(!isEmpty())
+ ByteVector(DATA(d) + d->offset, d->length).swap(*this);
+ else
+ ByteVector().swap(*this);
}
}
}