# sqstdblobimpl.h

    00001 /*  see copyright notice in squirrel.h */
    00002 #ifndef _SQSTD_BLOBIMPL_H_
    00003 #define _SQSTD_BLOBIMPL_H_
    00004
    00005 struct SQBlob : public SQStream
    00006 {
    00007   SQBlob(SQInteger size) {
    00008     _size = size;
    00009     _allocated = size;
    00010     _buf = (unsigned char *)sq_malloc(size);
    00011     memset(_buf, 0, _size);
    00012     _ptr = 0;
    00013     _owns = true;
    00014   }
    00015   virtual ~SQBlob() {
    00016     sq_free(_buf, _allocated);
    00017   }
    00018   SQInteger Write(void *buffer, SQInteger size) {
    00019     if(!CanAdvance(size)) {
    00020       GrowBufOf(_ptr + size - _size);
    00021     }
    00022     memcpy(&_buf[_ptr], buffer, size);
    00023     _ptr += size;
    00024     return size;
    00025   }
    00026   SQInteger Read(void *buffer,SQInteger size) {
    00027     SQInteger n = size;
    00028     if(!CanAdvance(size)) {
    00029       if((_size - _ptr) > 0)
    00030         n = _size - _ptr;
    00031       else return 0;
    00032     }
    00033     memcpy(buffer, &_buf[_ptr], n);
    00034     _ptr += n;
    00035     return n;
    00036   }
    00037   bool Resize(SQInteger n) {
    00038     if(!_owns) return false;
    00039     if(n != _allocated) {
    00040       unsigned char *newbuf = (unsigned char *)sq_malloc(n);
    00041       memset(newbuf,0,n);
    00042       if(_size > n)
    00043         memcpy(newbuf,_buf,n);
    00044       else
    00045         memcpy(newbuf,_buf,_size);
    00046       sq_free(_buf,_allocated);
    00047       _buf=newbuf;
    00048       _allocated = n;
    00049       if(_size > _allocated)
    00050         _size = _allocated;
    00051       if(_ptr > _allocated)
    00052         _ptr = _allocated;
    00053     }
    00054     return true;
    00055   }
    00056   bool GrowBufOf(SQInteger n)
    00057   {
    00058     bool ret = true;
    00059     if(_size + n > _allocated) {
    00060       if(_size + n > _size * 2)
    00061         ret = Resize(_size + n);
    00062       else
    00063         ret = Resize(_size * 2);
    00064     }
    00065     _size = _size + n;
    00066     return ret;
    00067   }
    00068   bool CanAdvance(SQInteger n) {
    00069     if(_ptr+n>_size)return false;
    00070     return true;
    00071   }
    00072   SQInteger Seek(SQInteger offset, SQInteger origin) {
    00073     switch(origin) {
    00074       case SQ_SEEK_SET:
    00075         if(offset > _size || offset < 0) return -1;
    00076         _ptr = offset;
    00077         break;
    00078       case SQ_SEEK_CUR:
    00079         if(_ptr + offset > _size || _ptr + offset < 0) return -1;
    00080         _ptr += offset;
    00081         break;
    00082       case SQ_SEEK_END:
    00083         if(_size + offset > _size || _size + offset < 0) return -1;
    00084         _ptr = _size + offset;
    00085         break;
    00086       default: return -1;
    00087     }
    00088     return 0;
    00089   }
    00090   bool IsValid() {
    00091     return _buf?true:false;
    00092   }
    00093   bool EOS() {
    00094     return _ptr == _size;
    00095   }
    00096   SQInteger Flush() { return 0; }
    00097   SQInteger Tell() { return _ptr; }
    00098   SQInteger Len() { return _size; }
    00099   SQUserPointer GetBuf(){ return _buf; }
    00100 private:
    00101   SQInteger _size;
    00102   SQInteger _allocated;
    00103   SQInteger _ptr;
    00104   unsigned char *_buf;
    00105   bool _owns;
    00106 };
    00107
    00108 #endif //_SQSTD_BLOBIMPL_H_