1#pike __REAL_VERSION__ 2 3//! A string wrapper that pretends to be a @[Stdio.File] object 4//! in addition to some features of a @[Stdio.FILE] object. 5 6 7//! This constant can be used to distinguish a FakeFile object 8//! from a real @[Stdio.File] object. 9constant is_fake_file = 1; 10 11protected string data; 12protected int ptr; 13protected int(0..1) r; 14protected int(0..1) w; 15protected int mtime; 16 17protected function read_cb; 18protected function read_oob_cb; 19protected function write_cb; 20protected function write_oob_cb; 21protected function close_cb; 22 23//! @seealso 24//! @[Stdio.File()->close()] 25int close(void|string direction) { 26 direction = lower_case(direction||"rw"); 27 int cr = has_value(direction, "r"); 28 int cw = has_value(direction, "w"); 29 30 if(cr) { 31 r = 0; 32 } 33 34 if(cw) { 35 w = 0; 36 } 37 38 // FIXME: Close callback 39 return 1; 40} 41 42//! @decl void create(string data, void|string type, void|int pointer) 43//! @seealso 44//! @[Stdio.File()->create()] 45void create(string _data, void|string type, int|void _ptr) { 46 if(!_data) error("No data string given to FakeFile.\n"); 47 data = _data; 48 ptr = _ptr; 49 mtime = time(); 50 if(type) { 51 type = lower_case(type); 52 if(has_value(type, "r")) 53 r = 1; 54 if(has_value(type, "w")) 55 w = 1; 56 } 57 else 58 r = w = 1; 59} 60 61protected string make_type_str() { 62 string type = ""; 63 if(r) type += "r"; 64 if(w) type += "w"; 65 return type; 66} 67 68//! @seealso 69//! @[Stdio.File()->dup()] 70this_program dup() { 71 return this_program(data, make_type_str(), ptr); 72} 73 74//! Always returns 0. 75//! @seealso 76//! @[Stdio.File()->errno()] 77int errno() { return 0; } 78 79//! Returns size and the creation time of the string. 80Stdio.Stat stat() { 81 Stdio.Stat st = Stdio.Stat(); 82 st->size = sizeof(data); 83 st->mtime=st->ctime=mtime; 84 st->atime=time(); 85 return st; 86} 87 88//! @seealso 89//! @[Stdio.File()->line_iterator()] 90String.SplitIterator line_iterator(int|void trim) { 91 if(trim) 92 return String.SplitIterator( data-"\r", '\n' ); 93 return String.SplitIterator( data, '\n' ); 94} 95 96protected mixed id; 97 98//! @seealso 99//! @[Stdio.File()->query_id()] 100mixed query_id() { return id; } 101 102//! @seealso 103//! @[Stdio.File()->set_id()] 104void set_id(mixed _id) { id = _id; } 105 106//! @seealso 107//! @[Stdio.File()->read_function()] 108function(:string) read_function(int nbytes) { 109 return lambda() { return read(nbytes); }; 110} 111 112//! @seealso 113//! @[Stdio.File()->peek()] 114int(-1..1) peek(int|float|void timeout) { 115 if(!r) return -1; 116 if(ptr >= sizeof(data)) return 0; 117 return 1; 118} 119 120//! Always returns 0. 121//! @seealso 122//! @[Stdio.File()->query_address()] 123string query_address(void|int(0..1) is_local) { return 0; } 124 125//! @seealso 126//! @[Stdio.File()->read()] 127string read(void|int(0..) len, void|int(0..1) not_all) { 128 if(!r) return 0; 129 if (len < 0) error("Cannot read negative number of characters.\n"); 130 int start=ptr; 131 ptr += len; 132 if(zero_type(len) || ptr>sizeof(data)) 133 ptr = sizeof(data); 134 135 // FIXME: read callback 136 return data[start..ptr-1]; 137} 138 139//! @seealso 140//! @[Stdio.FILE()->gets()] 141string gets() { 142 if(!r) return 0; 143 string ret; 144 sscanf(data,"%*"+(string)ptr+"s%[^\n]",ret); 145 if(ret) 146 { 147 ptr+=sizeof(ret)+1; 148 if(ptr>sizeof(data)) 149 { 150 ptr=sizeof(data); 151 if(!sizeof(ret)) 152 ret = 0; 153 } 154 } 155 156 // FIXME: read callback 157 return ret; 158} 159 160//! @seealso 161//! @[Stdio.FILE()->getchar()] 162int getchar() { 163 if(!r) return 0; 164 int c; 165 if(catch(c=data[ptr])) 166 c=-1; 167 else 168 ptr++; 169 170 // FIXME: read callback 171 return c; 172} 173 174//! @seealso 175//! @[Stdio.FILE()->unread()] 176void unread(string s) { 177 if(!r) return; 178 if(data[ptr-sizeof(s)..ptr-1]==s) 179 ptr-=sizeof(s); 180 else 181 { 182 data=s+data[ptr..]; 183 ptr=0; 184 } 185} 186 187//! @seealso 188//! @[Stdio.File()->seek()] 189int seek(int pos, void|int mult, void|int add) { 190 if(mult) 191 pos = pos*mult+add; 192 if(pos<0) 193 { 194 pos = sizeof(data)+pos; 195 if( pos < 0 ) 196 pos = 0; 197 } 198 ptr = pos; 199 if( ptr > strlen( data ) ) 200 ptr = strlen(data); 201 return ptr; 202} 203 204//! Always returns 1. 205//! @seealso 206//! @[Stdio.File()->sync()] 207int(1..1) sync() { return 1; } 208 209//! @seealso 210//! @[Stdio.File()->tell()] 211int tell() { return ptr; } 212 213//! @seealso 214//! @[Stdio.File()->truncate()] 215int(0..1) truncate(int length) { 216 data = data[..length-1]; 217 return sizeof(data)==length; 218} 219 220//! @seealso 221//! @[Stdio.File()->write()] 222int(-1..) write(string|array(string) str, mixed ... extra) { 223 if(!w) return -1; 224 if(arrayp(str)) str=str*""; 225 if(sizeof(extra)) str=sprintf(str, @extra); 226 227 if(ptr==sizeof(data)) { 228 data += str; 229 ptr = sizeof(data); 230 } 231 else if(sizeof(str)==1) 232 data[ptr++] = str[0]; 233 else { 234 data = data[..ptr-1] + str + data[ptr+sizeof(str)..]; 235 ptr += sizeof(str); 236 } 237 238 // FIXME: write callback 239 return sizeof(str); 240} 241 242//! @seealso 243//! @[Stdio.File()->set_blocking] 244void set_blocking() { 245 close_cb = 0; 246 read_cb = 0; 247 read_oob_cb = 0; 248 write_cb = 0; 249 write_oob_cb = 0; 250} 251 252//! @seealso 253//! @[Stdio.File()->set_blocking_keep_callbacks] 254void set_blocking_keep_callbacks() { } 255 256//! @seealso 257//! @[Stdio.File()->set_blocking] 258void set_nonblocking(function rcb, function wcb, function ccb, 259 function rocb, function wocb) { 260 read_cb = rcb; 261 write_cb = wcb; 262 close_cb = ccb; 263 read_oob_cb = rocb; 264 write_oob_cb = wocb; 265} 266 267//! @seealso 268//! @[Stdio.File()->set_blocking_keep_callbacks] 269void set_nonblocking_keep_callbacks() { } 270 271 272//! @seealso 273//! @[Stdio.File()->set_close_callback] 274void set_close_callback(function cb) { close_cb = cb; } 275 276//! @seealso 277//! @[Stdio.File()->set_read_callback] 278void set_read_callback(function cb) { read_cb = cb; } 279 280//! @seealso 281//! @[Stdio.File()->set_read_oob_callback] 282void set_read_oob_callback(function cb) { read_oob_cb = cb; } 283 284//! @seealso 285//! @[Stdio.File()->set_write_callback] 286void set_write_callback(function cb) { write_cb = cb; } 287 288//! @seealso 289//! @[Stdio.File()->set_write_oob_callback] 290void set_write_oob_callback(function cb) { write_oob_cb = cb; } 291 292 293//! @seealso 294//! @[Stdio.File()->query_close_callback] 295function query_close_callback() { return close_cb; } 296 297//! @seealso 298//! @[Stdio.File()->query_read_callback] 299function query_read_callback() { return read_cb; } 300 301//! @seealso 302//! @[Stdio.File()->query_read_oob_callback] 303function query_read_oob_callback() { return read_oob_cb; } 304 305//! @seealso 306//! @[Stdio.File()->query_write_callback] 307function query_write_callback() { return write_cb; } 308 309//! @seealso 310//! @[Stdio.File()->query_write_oob_callback] 311function query_write_oob_callback() { return write_oob_cb; } 312 313string _sprintf(int t) { 314 return t=='O' && sprintf("%O(%d,%O)", this_program, sizeof(data), 315 make_type_str()); 316} 317 318 319// FakeFile specials. 320 321//! A FakeFile can be casted to a string. 322mixed cast(string to) { 323 switch(to) { 324 case "string": return data; 325 case "object": return this; 326 } 327 error("Can not cast object to %O.\n", to); 328} 329 330//! Sizeof on a FakeFile returns the size of its contents. 331int(0..) _sizeof() { 332 return sizeof(data); 333} 334 335//! @ignore 336 337#define NOPE(X) mixed X (mixed ... args) { error("This is a FakeFile. %s is not available.\n", #X); } 338NOPE(assign); 339NOPE(async_connect); 340NOPE(connect); 341NOPE(connect_unix); 342NOPE(open); 343NOPE(open_socket); 344NOPE(pipe); 345NOPE(tcgetattr); 346NOPE(tcsetattr); 347 348// Stdio.Fd 349NOPE(dup2); 350NOPE(lock); // We could implement this 351NOPE(mode); // We could implement this 352NOPE(proxy); // We could implement this 353NOPE(query_fd); 354NOPE(read_oob); 355NOPE(set_close_on_exec); 356NOPE(set_keepalive); 357NOPE(trylock); // We could implement this 358NOPE(write_oob); 359 360//! @endignore