sio.h
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:9k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. #ifndef _SIO_H_
  36. #define _SIO_H_
  37. #include "hlxclib/errno.h"
  38. #include "debug.h"
  39. #include "fio.h"
  40. class IO;
  41. class SIO
  42. {
  43. public:
  44. SIO();
  45.     virtual ~SIO() = 0;
  46.     int error();
  47.     int end_of_file();
  48.     Byte* read_alloc(int& size);
  49.     virtual Byte* read_alloc(int& size, off_t seek, int whence)=0;
  50.     Byte* read_realloc(Byte* buf, int oldsize, int& size);
  51.     int read_undo(Byte* buf, int len);
  52.     void read_free(Byte* buf);
  53.     off_t read_offset();
  54.     virtual off_t read_seek(off_t off, int whence) = 0;
  55.     virtual int read_pushback(Byte* buf, int len) = 0;
  56.     int read_count();
  57.     Byte* write_alloc(int& size);
  58.     virtual Byte* write_alloc(int& size, off_t seek, int whence)=0;
  59.     Byte* write_realloc(Byte* buf, int oldsize, int& size);
  60.     int write_undo(Byte* buf, int len);
  61.     int write_free(Byte* buf);
  62.     off_t write_offset();
  63.     virtual off_t write_seek(off_t off, int whence) = 0;
  64.     int write_flush();
  65.     int write_flush_count();
  66.     BOOL write_flush_needed();
  67.     virtual off_t file_size() = 0;
  68.     void unset_eof();
  69.     virtual char * get_pathname() { return NULL;};
  70.     virtual int get_would_block() {return 0;}
  71.     void set_delete_io(int flag) { delete_io = flag; }
  72.     struct Region
  73.     {
  74. Region* next;
  75. Region* prev;
  76. off_t off;     // offset into file
  77. off_t flush_off;  // offset into file for writing
  78. Byte* base;     // this is where data starts
  79. Byte* limit;     // this is where data ends
  80. int refcount;
  81. Region();
  82. Region(Region* link);
  83. void set_buf(Byte* b, int size, off_t offset = 0);
  84.     };
  85. protected:
  86.     struct Region_list
  87.     {
  88. off_t off; // current offset into file
  89. Byte* ptr; // ptr to data on next access
  90. Byte* end; // data ends here
  91. Region* regs; // list of regions
  92. Region* creg; // current region
  93. int eof; // 1 if end of file
  94. Region_list();
  95. ~Region_list();
  96. Region* find(Byte* buf, Region**& rp);
  97. Region* find(off_t offt, Region**& rp);
  98. Byte* remove(Region* reg);
  99.     };
  100.     IO* io; // object that does the real io
  101.     int flags;
  102.     off_t write_off; // data written up to this point
  103.     Region_list reader;
  104.     Region_list writer;
  105.     int err; // last error
  106.     int delete_io;
  107.     virtual Byte* _read_alloc(int& size) = 0;
  108.     virtual void _read_free(Byte* buf) = 0;
  109.     int _read_count();
  110.     int _read_space();
  111.     virtual Byte* _write_alloc(int& size) = 0;
  112.     virtual int _write_free(Byte* buf) = 0;
  113.     virtual int _write_flush(Region* reg) = 0;
  114.     int _write_count();
  115.     int _write_space();
  116. };
  117. inline
  118. SIO::Region::Region() {
  119.     next = 0;
  120.     prev = 0;
  121.     refcount = 0;
  122. }
  123. inline
  124. SIO::Region::Region(SIO::Region* link) {
  125.     link->next = this;
  126.     prev = link;
  127.     next = 0;
  128.     refcount = 0;
  129. }
  130. inline void
  131. SIO::Region::set_buf(Byte* b, int size, off_t offset) {
  132.     base = b;
  133.     limit = b + size;
  134.     flush_off = off = offset;
  135. }
  136. inline
  137. SIO::Region_list::Region_list() {
  138.     creg = regs = new Region;
  139.     off = 0;
  140.     eof = 0;
  141. }
  142. inline
  143. SIO::Region_list::~Region_list() {
  144.     while (regs) {
  145. Region* next = regs->next;
  146. delete regs;
  147. regs = next;
  148.         if (next) next->prev = 0;
  149.     }
  150. }
  151. inline int
  152. SIO::error() {
  153.     return err;
  154. }
  155. inline int
  156. SIO::end_of_file() {
  157.     return reader.eof;
  158. }
  159. inline
  160. SIO::SIO() {
  161.     err = 0;
  162.     write_off = 0;
  163.     delete_io = 1;
  164. }
  165. inline
  166. SIO::~SIO() {
  167. }
  168. inline int
  169. SIO::_read_count() {
  170.     return reader.end - reader.ptr;
  171. }
  172. inline int
  173. SIO::_read_space() {
  174.     return reader.creg->limit - reader.end;
  175. }
  176. inline off_t
  177. SIO::read_offset() {
  178.     return reader.creg->off + (reader.ptr - reader.creg->base);
  179. }
  180. inline Byte*
  181. SIO::read_alloc(int& size) {
  182.     if (size < 0) {
  183. DPRINTF(D_ERROR,("illegal read_alloc request %d bytesn", size));
  184. err = EINVAL;
  185. return 0;
  186.     }
  187.     Byte* p = reader.ptr + size;
  188.     if (p <= reader.end) {
  189. reader.creg->refcount++;
  190. /*
  191.  * Return the base of the region if the user requests a
  192.  * read_alloc of 0 bytes. This avoids corrupting the region
  193.  * list when the corresponding call to read_free is made
  194.  *
  195.  * NOTE: read_undo and read_realloc may NOT be performed on
  196.  *  the pointer returned
  197.  */
  198. if (size == 0)
  199.     return reader.creg->base;
  200. Byte* b = reader.ptr;
  201. reader.ptr = p;
  202. return b;
  203.     }
  204.     return _read_alloc(size);
  205. }
  206. inline Byte*
  207. SIO::read_realloc(Byte* buf, int oldsize, int& size)
  208. {
  209.     // realloc allowed only on the very last allocation
  210.     if (buf + oldsize != reader.ptr) {
  211. size = oldsize;
  212. return buf;
  213.     }
  214.     // shrink case is easy, just unread the bytes beyond size
  215.     if (size <= oldsize) {
  216. reader.ptr -= oldsize - size;
  217. reader.eof = 0;
  218. return buf;
  219.     }
  220.     // essentially do an unread and a new read_alloc
  221.     reader.ptr = buf;
  222.     reader.creg->refcount--;
  223.     return read_alloc(size);
  224. }
  225. inline void
  226. SIO::read_free(Byte* buf)
  227. {
  228.     if (!buf)
  229. return;
  230.     /*
  231.      * If buf == reader.creg->base then it may have come from a read_alloc
  232.      * of 0 bytes. We must free this pointer even if it has the same address
  233.      * as reader.end
  234.      */
  235.     if (buf == reader.creg->base || (reader.creg->base < buf && buf < reader.end))
  236.     {
  237. reader.creg->refcount--;
  238. return;
  239.     }
  240.     DPRINTF(D_ALLOC, ("freeing %pn", buf));
  241.     _read_free(buf);
  242. }
  243. /*
  244.  * read_undo is same as
  245.  * buf = read_realloc(buf, len, 0); read_free(buf);
  246.  */
  247. inline int
  248. SIO::read_undo(Byte* buf, int len)
  249. {
  250.     // can not read undo in case of any error
  251.     if (err)
  252. return -1;
  253.     if (buf + len == reader.ptr) {
  254. reader.ptr = buf;
  255. reader.creg->refcount--;
  256.     } else {
  257. DPRINTF(D_ALLOC, ("freeing %p count %dn", buf, len));
  258. _read_free(buf);
  259.     }
  260.     // XXX err may need to be cleared
  261.     reader.eof = 0;
  262.     return 0;
  263. }
  264. inline int
  265. SIO::_write_count() {
  266.     return writer.end - writer.ptr;
  267. }
  268. inline int
  269. SIO::_write_space() {
  270.     return writer.creg->limit - writer.ptr;
  271. }
  272. inline Byte*
  273. SIO::write_alloc(int& size) {
  274.     // XXX this needs to be moved to the non file case.
  275.     // sio is a generic interface and can not assume
  276.     // any specific buffering scheme.
  277.     Byte* p = writer.ptr + size;
  278.     if (p <= writer.creg->limit) {
  279. writer.creg->refcount++;
  280. /*
  281.  * Return the base of the region if the user requests a
  282.  * write_alloc of 0 bytes. This keeps write_alloc orthogonal
  283.  * with read_alloc
  284.  *
  285.  * NOTE: write_undo and write_realloc may NOT be performed on
  286.  *  the pointer returned
  287.  */
  288. if (size == 0)
  289.     return writer.creg->base;
  290. Byte* b = writer.ptr;
  291. writer.end = writer.ptr = p;
  292. return b;
  293.     }
  294.     return _write_alloc(size);
  295. }
  296. inline Byte*
  297. SIO::write_realloc(Byte* buf, int oldsize, int& size)
  298. {
  299.     // XXX this code's been disabled since 1997 so it was removed
  300.     // XXX unsupported
  301.     return 0;
  302. }
  303. inline int
  304. SIO::write_free(Byte* buf)
  305. {
  306.     //
  307.     // let the derived class decide what to do with the data
  308.     //
  309.     return _write_free(buf);
  310. }
  311. /*
  312.  * write_undo is same as
  313.  * buf = write_realloc(buf, len, 0); write_free(buf);
  314.  */
  315. inline int
  316. SIO::write_undo(Byte* buf, int len)
  317. {
  318.     // XXX this code's been disabled since 1997 so it was removed
  319.     // XXX unsupported
  320.     return -1;
  321. }
  322. inline int
  323. SIO::write_flush()
  324. {
  325.     Region* reg = writer.regs;
  326.     if (reg == writer.creg)
  327. return 0;
  328.     if (_write_flush(reg) < 0)
  329.     {
  330. if (err)
  331.     return -1;
  332. return 0;
  333.     }
  334.     writer.regs = reg->next;
  335.     if (writer.regs) writer.regs->prev = 0;
  336.     delete[] reg->base;
  337.     delete reg;
  338.     
  339.     return 0;
  340. }
  341. inline off_t
  342. SIO::write_offset() {
  343.     return writer.creg->off + (writer.ptr - writer.creg->base);
  344. }
  345. inline void
  346. SIO::unset_eof() {
  347.     reader.eof = 0;
  348. }
  349. inline int
  350. SIO::read_count() {
  351.     return _read_count();
  352. }
  353. #endif/*_SIO_H*/