source: golgotha/src/i4/file/buf_file.cc @ 608

Last change on this file since 608 was 80, checked in by Sam Hocevar, 15 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 5.3 KB
Line 
1/********************************************************************** <BR>
2  This file is part of Crack dot Com's free source code release of
3  Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
4  information about compiling & licensing issues visit this URL</a>
5  <PRE> If that doesn't help, contact Jonathan Clark at
6  golgotha_source@usa.net (Subject should have "GOLG" in it)
7***********************************************************************/
8
9#include "file/buf_file.hh"
10#include "memory/malloc.hh"
11#include "error/error.hh"
12#include <memory.h>
13
14
15
16w32 i4_buffered_file_class::read(void *buffer, w32 size)
17{
18  w32 total_read=0;
19  while (size)
20  {
21    if (offset>=buf_start && offset<buf_end)
22    {
23      w32 copy_size;
24      if (buf_end-offset<size)
25        copy_size=buf_end-offset;
26      else copy_size=size;
27      memcpy(buffer,((w8 *)buf)+offset-buf_start,copy_size);
28      size-=copy_size;
29      buffer=(void *)(((w8 *)buffer)+copy_size);
30      offset+=copy_size;
31      total_read+=copy_size;
32    } else if (offset==buf_end)      // sequentially read more into the buffer
33    {
34      buf_start=offset;
35      buf_end=offset+from->read(buf,buf_size);
36      if (buf_end==buf_start)
37        return total_read;
38    } else                          // need to seek from file to a new spot
39    {
40      from->seek(offset);
41      buf_start=buf_end=offset;
42    }
43  }
44  return total_read;
45}
46
47
48w32 i4_buffered_file_class::write(const void *buffer, w32 size)
49{
50  w32 total_write=0;
51
52  while (size)
53  {     
54    write_file=i4_T;
55    if (offset>=buf_start && offset<=buf_end)
56    {
57      w32 copy_size;
58      if (offset+size<buf_start+buf_size)
59        copy_size=size;
60      else
61        copy_size=buf_start+buf_size-offset;
62
63      memcpy(((w8 *)buf)+offset-buf_start,buffer,copy_size);
64
65      size-=copy_size;
66      buffer=(void *)(((w8 *)buffer)+copy_size);
67      offset+=copy_size;
68      total_write+=copy_size;
69
70      if (offset>buf_end)
71      {
72        buf_end=offset;
73        if (buf_end-buf_start==buf_size)
74        {
75          from->write(buf, buf_end-buf_start);
76          buf_start=buf_end;
77        }
78      }
79
80    }
81    else if (buf_end!=buf_start)      // flush the buffer
82    {
83      from->write(buf, buf_end-buf_start);
84      buf_start=buf_end;
85    } else
86    {
87      from->seek(offset);
88      buf_start=buf_end=offset;
89    }
90  }
91
92  return total_write;
93}
94
95
96w32 i4_buffered_file_class::seek (w32 offset)
97{
98  i4_buffered_file_class::offset=offset;
99  return offset;
100}
101
102
103w32 i4_buffered_file_class::size ()
104{
105  return from->size();
106}
107
108
109w32 i4_buffered_file_class::tell ()
110{
111  return offset;
112}
113
114
115i4_buffered_file_class::~i4_buffered_file_class()
116{
117  if (write_file && buf_start!=buf_end)
118    from->write(buf, buf_end-buf_start);
119
120  delete from;
121  i4_free(buf);
122}
123
124
125i4_buffered_file_class::i4_buffered_file_class(i4_file_class *from,
126                                               w32 buffer_size,
127                                               w32 current_offset)
128  : from(from), buf_size(buffer_size), offset(current_offset)
129{
130  write_file=i4_F;
131  buf=i4_malloc(buf_size,"file buffer");
132  buf_start=buf_end=0;
133}
134
135struct callback_context
136{
137  i4_bool in_use;
138  w32 prev_read;
139  void *prev_context;
140  i4_file_class::async_callback prev_callback;
141  i4_buffered_file_class *bfile;
142} ;
143
144
145// Maximum number async reads going on at the same time
146enum { MAX_ASYNC_READS = 4 };
147static callback_context contexts[MAX_ASYNC_READS];
148static w32 t_callbacks_used=0;
149
150void i4_async_buf_read_callback(w32 count, void *context)
151{
152  callback_context *c=(callback_context *)context;
153  c->bfile->offset+=count;
154
155  i4_file_class::async_callback call=c->prev_callback;
156  count += c->prev_read;
157  void *ctext=c->prev_context;
158  c->in_use=i4_F;
159
160  t_callbacks_used--;
161 
162  call(count, ctext);
163}
164
165
166
167i4_bool i4_buffered_file_class::async_read (void *buffer, w32 size,
168                                            async_callback call,
169                                            void *context)
170{
171  if (!(offset>=buf_start && offset<buf_end))
172  {
173    from->seek(offset);
174    buf_start=buf_end=0;
175  }
176
177
178  if (t_callbacks_used>=MAX_ASYNC_READS)
179    return i4_file_class::async_read(buffer, size, call, context);
180  else
181  {   
182    w32 avail_size;
183
184    if (offset>=buf_start && offset<buf_end)   
185      avail_size=buf_end-offset;
186    else
187      avail_size=0;
188
189    if (avail_size < size)
190    {
191      callback_context *c=0;
192      for (w32 i=0; !c && i<MAX_ASYNC_READS; i++)
193        if (!contexts[i].in_use)
194        {
195          c=contexts+i;
196          c->in_use=i4_T;
197        }
198
199      if (c==0)
200        i4_error("didn't find a free context");
201
202      t_callbacks_used++;
203
204      if (avail_size)
205        c->prev_read=read(buffer,avail_size);
206      else
207        c->prev_read=0;
208
209      c->prev_context=context;
210      c->prev_callback=call;
211      c->bfile=this;
212      return from->async_read((w8 *)buffer + avail_size, size-avail_size,
213                              i4_async_buf_read_callback, c);
214    }
215    else
216    {
217      call(read(buffer,avail_size), context);
218      return i4_T;
219    }
220
221  }
222}
223
224
225//{{{ Emacs Locals
226// Local Variables:
227// folded-file: t
228// End:
229//}}}
230
Note: See TracBrowser for help on using the repository browser.