/*----------------------------------------------------------------------------- * bytearray.cpp * Copyright (C) 2003, 2004, 2005 Akito Nozaki * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include #include #include #include #include #include NAMESPACE_TANOSHI { ByteArray::ByteArray() : d(new ByteArrayData) { _rwlock.writeLock(); d->rwlock.writeLock(); // set default d->data = NULL; d->size = 0; d->length = 0; d->reference = 0; d->rwlock.readWriteUnlock(); _rwlock.readWriteUnlock(); } ByteArray::ByteArray(const ByteArray &ba) { _rwlock.writeLock(); d = ba.d; d->rwlock.writeLock(); d->reference++; d->rwlock.readWriteUnlock(); _rwlock.readWriteUnlock(); } ByteArray::ByteArray(const char *data, unsigned int size) : d(new ByteArrayData) { _rwlock.writeLock(); d->rwlock.writeLock(); // set default d->data = NULL; d->size = 0; d->length = 0; d->reference = 0; d->rwlock.readWriteUnlock(); _rwlock.readWriteUnlock(); // deep copy append(data,size); } ByteArray::ByteArray(unsigned int presize) : d(new ByteArrayData) { _rwlock.writeLock(); d->rwlock.writeLock(); // set default d->data = NULL; d->size = 0; d->length = 0; d->reference = 0; d->rwlock.readWriteUnlock(); _rwlock.readWriteUnlock(); alloc(presize); } ByteArray::~ByteArray() { _rwlock.writeLock(); dereference(); _rwlock.readWriteUnlock(); } unsigned int ByteArray::size() const { return d->length; } void ByteArray::resize(unsigned int size) { if(size) dealloc(size); else clear(); } ByteArray ByteArray::take(int getsize, bool del) { ByteArray a; if(getsize == 0) { a = *this; if(del) resize(0); } else { if(getsize > (int)size()) a.resize(getsize); a.append(data(), size()); if(del) { detach(); int newsize = size() - getsize; memmove(data(), data()+getsize, newsize); resize(newsize); } } return a; } void ByteArray::append(char append) { detach(); if(d->size == d->length || d->size == 0) alloc(BA_PAD_SIZE); _rwlock.writeLock(); d->rwlock.writeLock(); d->data[d->length] = append; d->length++; d->rwlock.readWriteUnlock(); _rwlock.readWriteUnlock(); } void ByteArray::append(const char *bin, unsigned int size) { detach(); if(d->size <= d->length+size) alloc(( (d->length + size) - d->size ) + BA_PAD_SIZE); _rwlock.writeLock(); d->rwlock.writeLock(); memcpy(&d->data[d->length], bin, size); d->length += size; d->rwlock.readWriteUnlock(); _rwlock.readWriteUnlock(); } void ByteArray::clear() { detach(); _rwlock.writeLock(); d->rwlock.writeLock(); if(d->size) { delete [] d->data; d->data = NULL; } d->size=0; d->length=0; d->rwlock.readWriteUnlock(); _rwlock.readWriteUnlock(); } void ByteArray::append(const ByteArray &appendarray) { detach(); append(appendarray.data(), appendarray.size()); } // not sure how to make this thread safe :( char *ByteArray::data() const { return d->data; } char &ByteArray::operator[](unsigned int i) const { return d->data[i]; } void ByteArray::detach() { _rwlock.writeLock(); d->rwlock.writeLock(); if(d->reference) { // decrease the original reference counter since we are going to // detach from it. d->reference--; ByteArrayData *td = new ByteArrayData; td->data = new char[d->size]; td->size = d->size; td->length = d->length; td->reference = 0; memcpy(td->data, d->data, d->length); d->rwlock.readWriteUnlock(); // update d with out deleting d. d = td; } else d->rwlock.readWriteUnlock(); _rwlock.readWriteUnlock(); } void ByteArray::alloc(unsigned int n) { // should be detached by here but just in case... detach(); _rwlock.writeLock(); d->rwlock.writeLock(); char *temp = new char[d->size+n]; if(d->length) { // copy all the data over to td memcpy(temp, d->data, d->length); } if(d->data) delete [] d->data; // update the information d->data = temp; d->size += n; d->rwlock.readWriteUnlock(); _rwlock.readWriteUnlock(); } void ByteArray::dealloc(unsigned int n) { _rwlock.writeLock(); d->rwlock.writeLock(); if(n == d->size) return; if(n) { char *temp = new char[n]; memset(temp, 0, n); memcpy(temp, d->data, n); delete [] d->data; d->size = n; d->length = n; d->data = temp; } d->rwlock.readWriteUnlock(); _rwlock.readWriteUnlock(); } ByteArray &ByteArray::operator=(const ByteArray &ba) { dereference(); _rwlock.writeLock(); ba.d->rwlock.writeLock(); d = ba.d; d->reference++; d->rwlock.readWriteUnlock(); _rwlock.readWriteUnlock(); return *this; } void ByteArray::dereference() { _rwlock.writeLock(); d->rwlock.writeLock(); if(d->reference) { // there still other class using this buffer d->reference--; d->rwlock.readWriteUnlock(); } else { if(d->size) { delete [] d->data; d->data = NULL; d->size = 0; d->length = 0; d->reference = 0; } d->rwlock.readWriteUnlock(); // if anything was waiting... it would crash!! delete d; d = NULL; } _rwlock.readWriteUnlock(); } void ByteArray::dump() { _rwlock.readLock(); d->rwlock.readLock(); char temp[5]; char temp2[1000]; int dcount = 0; int j = 0; for(unsigned int i=0; ilength; i++) { printf("%02hhx ",d->data[i]); sprintf(temp, "%c", d->data[i] >= 32 && (unsigned char)d->data[i] < 127 ? d->data[i] : '.'); temp2[j++] = temp[0]; if(++dcount == 16*2) { temp2[j] = 0; printf(" | %s\n",temp2); j = 0; dcount = 0; } } if(dcount != 0) { while(dcount++ < 16*2) printf(" "); temp2[j] = 0; printf(" | %s\n",temp2); } d->rwlock.readWriteUnlock(); _rwlock.readWriteUnlock(); } }