1 | /* see copyright notice in squirrel.h */ |
2 | #ifndef _SQSTD_BLOBIMPL_H_ |
3 | #define _SQSTD_BLOBIMPL_H_ |
4 | |
5 | struct SQBlob : public SQStream |
6 | { |
7 | SQBlob(SQInteger size) { |
8 | _size = size; |
9 | _allocated = size; |
10 | _buf = (unsigned char *)sq_malloc(size); |
11 | memset(_buf, 0, _size); |
12 | _ptr = 0; |
13 | _owns = true; |
14 | } |
15 | virtual ~SQBlob() { |
16 | sq_free(_buf, _allocated); |
17 | } |
18 | SQInteger Write(void *buffer, SQInteger size) { |
19 | if(!CanAdvance(size)) { |
20 | GrowBufOf(_ptr + size - _size); |
21 | } |
22 | memcpy(&_buf[_ptr], buffer, size); |
23 | _ptr += size; |
24 | return size; |
25 | } |
26 | SQInteger Read(void *buffer,SQInteger size) { |
27 | SQInteger n = size; |
28 | if(!CanAdvance(size)) { |
29 | if((_size - _ptr) > 0) |
30 | n = _size - _ptr; |
31 | else return 0; |
32 | } |
33 | memcpy(buffer, &_buf[_ptr], n); |
34 | _ptr += n; |
35 | return n; |
36 | } |
37 | bool Resize(SQInteger n) { |
38 | if(!_owns) return false; |
39 | if(n != _allocated) { |
40 | unsigned char *newbuf = (unsigned char *)sq_malloc(n); |
41 | memset(newbuf,0,n); |
42 | if(_size > n) |
43 | memcpy(newbuf,_buf,n); |
44 | else |
45 | memcpy(newbuf,_buf,_size); |
46 | sq_free(_buf,_allocated); |
47 | _buf=newbuf; |
48 | _allocated = n; |
49 | if(_size > _allocated) |
50 | _size = _allocated; |
51 | if(_ptr > _allocated) |
52 | _ptr = _allocated; |
53 | } |
54 | return true; |
55 | } |
56 | bool GrowBufOf(SQInteger n) |
57 | { |
58 | bool ret = true; |
59 | if(_size + n > _allocated) { |
60 | if(_size + n > _size * 2) |
61 | ret = Resize(_size + n); |
62 | else |
63 | ret = Resize(_size * 2); |
64 | } |
65 | _size = _size + n; |
66 | return ret; |
67 | } |
68 | bool CanAdvance(SQInteger n) { |
69 | if(_ptr+n>_size)return false; |
70 | return true; |
71 | } |
72 | SQInteger Seek(SQInteger offset, SQInteger origin) { |
73 | switch(origin) { |
74 | case SQ_SEEK_SET: |
75 | if(offset > _size || offset < 0) return -1; |
76 | _ptr = offset; |
77 | break; |
78 | case SQ_SEEK_CUR: |
79 | if(_ptr + offset > _size || _ptr + offset < 0) return -1; |
80 | _ptr += offset; |
81 | break; |
82 | case SQ_SEEK_END: |
83 | if(_size + offset > _size || _size + offset < 0) return -1; |
84 | _ptr = _size + offset; |
85 | break; |
86 | default: return -1; |
87 | } |
88 | return 0; |
89 | } |
90 | bool IsValid() { |
91 | return _size == 0 || _buf?true:false; |
92 | } |
93 | bool EOS() { |
94 | return _ptr == _size; |
95 | } |
96 | SQInteger Flush() { return 0; } |
97 | SQInteger Tell() { return _ptr; } |
98 | SQInteger Len() { return _size; } |
99 | SQUserPointer GetBuf(){ return _buf; } |
100 | private: |
101 | SQInteger _size; |
102 | SQInteger _allocated; |
103 | SQInteger _ptr; |
104 | unsigned char *_buf; |
105 | bool _owns; |
106 | }; |
107 | |
108 | #endif //_SQSTD_BLOBIMPL_H_ |
109 | |