0001
0002 #ifndef _PSSTD_BLOBIMPL_H_
0003 #define _PSSTD_BLOBIMPL_H_
0004
0005 struct PSBlob : public PSStream
0006 {
0007 PSBlob(PSInteger size) {
0008 _size = size;
0009 _allocated = size;
0010 _buf = (unsigned char *)ps_malloc(size);
0011 memset(_buf, 0, _size);
0012 _ptr = 0;
0013 _owns = true;
0014 }
0015 virtual ~PSBlob() {
0016 ps_free(_buf, _allocated);
0017 }
0018 PSInteger Write(void *buffer, PSInteger size) {
0019 if(!CanAdvance(size)) {
0020 GrowBufOf(_ptr + size - _size);
0021 }
0022 memcpy(&_buf[_ptr], buffer, size);
0023 _ptr += size;
0024 return size;
0025 }
0026 PSInteger Read(void *buffer,PSInteger size) {
0027 PSInteger n = size;
0028 if(!CanAdvance(size)) {
0029 if((_size - _ptr) > 0)
0030 n = _size - _ptr;
0031 else return 0;
0032 }
0033 memcpy(buffer, &_buf[_ptr], n);
0034 _ptr += n;
0035 return n;
0036 }
0037
0038 PSUserPointer ReadLine(void *buffer,PSInteger size) {
0039 return NULL;
0040 }
0041 bool Resize(PSInteger n) {
0042 if(!_owns) return false;
0043 if(n != _allocated) {
0044 unsigned char *newbuf = (unsigned char *)ps_malloc(n);
0045 memset(newbuf,0,n);
0046 if(_size > n)
0047 memcpy(newbuf,_buf,n);
0048 else
0049 memcpy(newbuf,_buf,_size);
0050 ps_free(_buf,_allocated);
0051 _buf=newbuf;
0052 _allocated = n;
0053 if(_size > _allocated)
0054 _size = _allocated;
0055 if(_ptr > _allocated)
0056 _ptr = _allocated;
0057 }
0058 return true;
0059 }
0060 bool GrowBufOf(PSInteger n)
0061 {
0062 bool ret = true;
0063 if(_size + n > _allocated) {
0064 if(_size + n > _size * 2)
0065 ret = Resize(_size + n);
0066 else
0067 ret = Resize(_size * 2);
0068 }
0069 _size = _size + n;
0070 return ret;
0071 }
0072 bool CanAdvance(PSInteger n) {
0073 if(_ptr+n>_size)return false;
0074 return true;
0075 }
0076 PSInteger Seek(PSInteger offset, PSInteger origin) {
0077 switch(origin) {
0078 case PS_SEEK_SET:
0079 if(offset > _size || offset < 0) return -1;
0080 _ptr = offset;
0081 break;
0082 case PS_SEEK_CUR:
0083 if(_ptr + offset > _size || _ptr + offset < 0) return -1;
0084 _ptr += offset;
0085 break;
0086 case PS_SEEK_END:
0087 if(_size + offset > _size || _size + offset < 0) return -1;
0088 _ptr = _size + offset;
0089 break;
0090 default: return -1;
0091 }
0092 return 0;
0093 }
0094 bool IsValid() {
0095 return _buf?true:false;
0096 }
0097 bool EOS() {
0098 return _ptr == _size;
0099 }
0100 PSInteger Flush() { return 0; }
0101 PSInteger Tell() { return _ptr; }
0102 PSInteger Len() { return _size; }
0103 PSUserPointer GetBuf(){ return _buf; }
0104 private:
0105 PSInteger _size;
0106 PSInteger _allocated;
0107 PSInteger _ptr;
0108 unsigned char *_buf;
0109 bool _owns;
0110 };
0111
0112 #endif