Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

ByteArray.cc

Go to the documentation of this file.
00001 /*
00002  * ByteArray.cc
00003  *
00004  * Smalltalk like class library for C++
00005  * Array of bytes.
00006  *
00007  * Copyright (c) 2003 Jan Vrany
00008  * Copyright (c) 2005 Milan Cermak
00009  */
00010 /*
00011  * This library is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU Lesser General Public
00013  * License as published by the Free Software Foundation; either
00014  * version 2.1 of the License, or (at your option) any later version.
00015  *
00016  * This library is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019  * Lesser General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU Lesser General Public
00022  * License along with this library; if not, write to the Free Software
00023  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024  */
00025 #include <stlib/ByteArray.h>
00026 #include <stlib/EncodedStream.h>
00027 #include <stlib/Integer.h>
00028 #include <stlib/InternalEncodedStreamFactory.h>
00029 #include <stlib/String.h>
00030 #include <stlib/SOOBoundsError.h>
00031 
00032 #include <string.h>
00033 
00034 ByteArray::ByteArray(int size)
00035 {
00036     bytes = NULL;
00037     tally = size;
00038     if (tally) {
00039         bytes = (unsigned char *) GC_malloc(tally * sizeof(unsigned char));
00040         bzero(bytes, tally);
00041     }
00042 }
00043 
00044 ByteArray::ByteArray(const ByteArray &origin)
00045 {
00046     bytes = NULL;
00047     tally = origin.tally;
00048     if (tally) {
00049         bytes = (unsigned char *) GC_malloc(tally * sizeof(unsigned char));
00050         memcpy(bytes, origin.bytes, tally);
00051     }
00052 }
00053 
00054 ByteArray::ByteArray(const char *buffer, int size)
00055 {
00056     bytes = NULL;
00057     tally = size;
00058     if (tally) {
00059         bytes = (unsigned char *) GC_malloc(tally * sizeof(unsigned char));
00060         memcpy(bytes, buffer, tally);
00061     }
00062 }
00063 
00064 ByteArray::~ByteArray()
00065 {
00066     if (tally)
00067         GC_free(bytes);
00068 }
00069 
00070 /* Instance creation protocol */
00071 ByteArray *ByteArray::fromStringEncoding(const String *string, String *encoding)
00072 {
00073     EncodedStream *stream = (new ByteArray(string->size()))->withEncoding(encoding)->writeStream();
00074     stream->nextPutAll(string);
00075     return dynamic_cast<ByteArray *>(stream->contents());
00076 }
00077 
00078 /* Accessing protocol */
00079 Object* ByteArray::at(int index) const
00080 {
00081     if (index < 0 || index >= tally) {
00082         SubscriptOutOfBoundsError *ex;
00083         ex = new SubscriptOutOfBoundsError(__PRETTY_FUNCTION__, index);
00084         ex->raiseFrom(this);
00085     }
00086     return Integer::value(bytes[index] & 0xFF);
00087 }
00088 
00089 void ByteArray::put(int index, Object* obj)
00090 {
00091     if (index < 0 || index >= tally) {
00092         SubscriptOutOfBoundsError *ex;
00093         ex = new SubscriptOutOfBoundsError(__PRETTY_FUNCTION__, index);
00094         ex->raiseFrom(this);
00095     }
00096     checkObject(obj, __PRETTY_FUNCTION__);
00097     unsigned char val = ((Number *) obj)->asLong();
00098     bytes[index] = val & 0xFF;
00099 }
00100 
00101 void ByteArray::replace(long start, long stop, unsigned char *collection)
00102 {
00103     replace(start, stop, collection, 0);
00104 }
00105 
00106 void ByteArray::replace(long start, long stop,
00107                         unsigned char *collection, long startIndex)
00108 {
00109     memcpy(&bytes[start], &collection[startIndex], stop - start);
00110 }
00111 
00112 void ByteArray::changeSize(long newSize)
00113 {
00114     unsigned char *oldBytes = bytes;
00115     long i;
00116 
00117     bytes = (unsigned char *) GC_malloc(newSize * sizeof(unsigned char));
00118     // MC: This will fail when shinking the content
00119 //    memset(bytes, 0, newSize);
00120 //    memcpy(bytes, oldBytes, (newSize > tally) ? newSize : tally);
00121     /* Copy old content or the part that fits */
00122     for (i = 0; i < newSize && i < tally; i++) {
00123         bytes[i] = oldBytes[i];
00124     }
00125     /* Fill the rest with 0s */
00126     for (; i < newSize; i++) {
00127         bytes[i] = 0;
00128     }
00129     tally = newSize;
00130     GC_free(oldBytes);
00131 }
00132 
00133 void ByteArray::add(Object *obj)
00134 {
00135     shouldNotImplement(__PRETTY_FUNCTION__);
00136 }
00137 
00138 Object* ByteArray::copy(void)
00139 {
00140     return new ByteArray(*this);
00141 }
00142 
00143 Object* ByteArray::copyEmpty(long int size)
00144 {
00145     return new ByteArray(size);
00146 }
00147 
00148 /* Comparing protocol */
00149 long ByteArray::hash(void) const
00150 {
00151     long hashConst = 0x23451;
00152     int length = size();
00153 
00154     if (length > 0) {
00155         hashConst ^= bytes[0];
00156         if (length > 1) {
00157             hashConst ^= bytes[length-1];
00158             if (length > 3) {
00159                 hashConst ^= bytes[length/2-1] ^ bytes[length/2+1];
00160             }
00161         }
00162     }
00163     return hashConst;
00164 }
00165 
00166 bool ByteArray::isEqual(const Object *object) const
00167 {
00168     return object->isEqualToByteArray(this);
00169 }
00170 
00171 bool ByteArray::isEqual(const char *array, int size) const
00172 {
00173     if (size != tally) return false;
00174     return memcmp(bytes, array, tally) == 0;
00175 }
00176 
00177 bool ByteArray::isEqualToByteArray(const Object *array) const
00178 {
00179     return dynamic_cast<const ByteArray *>(array)->isEqual((char *) bytes, tally);
00180 }
00181 
00182 /* Converting protocol */
00183 ByteArray *ByteArray::asByteArray(void)
00184 {
00185     return this;
00186 }
00187 
00188 char *ByteArray::asCString(void)
00189 {
00190     char *cString = (char *) GC_malloc((tally + 1) * sizeof(char));
00191     memcpy(cString, bytes, tally);
00192     cString[tally] = 0;
00193     return cString;
00194 }
00195 
00196 String *ByteArray::asString(void)
00197 {
00198     return new String(this);
00199 }
00200 
00201 String *ByteArray::asStringWithEncoding(String *encoding)
00202 {
00203     return dynamic_cast<String *>(withEncoding(encoding)->readStream()->upToEnd());
00204 }
00205 
00206 String *ByteArray::asStringWithEncoding(const char *encoding)
00207 {
00208     return asStringWithEncoding(new String(encoding));
00209 }
00210 
00211 unsigned long ByteArray::asInteger(void)
00212 {
00213     return asNumberWithRadix(256);
00214 }
00215 
00216 unsigned long ByteArray::asNumberWithRadix(int radix)
00217 {
00218     unsigned long number = 0;
00219 
00220     for (long i = 0; i < tally; i++) {
00221         number = number * radix + bytes[i];
00222     }
00223     return number;
00224 }
00225 
00226 unsigned char *ByteArray::rawBytes(void) const
00227 {
00228 //#ifdef NOGC
00229 //    unsigned char *retbytes = (unsigned char *) malloc(tally);
00230 //#else
00231     unsigned char *retbytes = (unsigned char *) GC_malloc(tally * sizeof(unsigned char *));
00232 //#endif
00233     memcpy(retbytes, bytes, tally);
00234     return retbytes;
00235 }
00236 
00237 const unsigned char *ByteArray::rawBytesReadOnly(void) const
00238 {
00239     return bytes;
00240 }
00241 
00242 /* Stream construction protocol */
00243 InternalEncodedStreamFactory *ByteArray::withEncoding(String *encoding)
00244 {
00245     return new InternalEncodedStreamFactory(this, encoding);
00246 }
00247 
00248 InternalEncodedStreamFactory *ByteArray::withEncoding(const char *encoding)
00249 {
00250     return withEncoding(new String(encoding));
00251 }
00252 
00253 /* Testing protocol */
00254 bool ByteArray::isByteArray(void)
00255 {
00256     return true;
00257 }
00258 
00259 /* Private protocol */
00260 void ByteArray::checkObject(Object *obj, const char *sel)
00261 {
00262     if (obj->isNumber()) {
00263         Number* n = (Number *) obj;
00264         long long l = n->asLongLong();
00265         if (l < 0 || l > 255) {
00266             Error *e = new Error(new String("Invalid value!"), new String(sel), obj);
00267             e->raiseFrom(this);
00268         }
00269     } else {
00270         Error *e = new Error(new String("Not a Number instance!"), new String(sel), obj);
00271         e->raiseFrom(this);
00272     }
00273 }

Generated on Mon Nov 27 09:47:54 2006 for Smalltalk like C++ Class Library by  doxygen 1.4.2