~ubuntu-branches/ubuntu/wily/afnix/wily

« back to all changes in this revision

Viewing changes to src/lib/std/shl/BlockBuffer.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Anibal Monsalve Salazar
  • Date: 2011-03-16 21:31:18 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20110316213118-gk4k3ez3e5d2huna
Tags: 2.0.0-1
* QA upload.
* New upstream release
* Debian source format is 3.0 (quilt)
* Fix debhelper-but-no-misc-depends
* Fix ancient-standards-version
* Fix package-contains-linda-override
* debhelper compatibility is 7
* Fix dh-clean-k-is-deprecated

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// ---------------------------------------------------------------------------
 
2
// - BlockBuffer.cpp                                                         -
 
3
// - standard object library - block buffer class implementation             -
 
4
// ---------------------------------------------------------------------------
 
5
// - This program is free software;  you can redistribute it  and/or  modify -
 
6
// - it provided that this copyright notice is kept intact.                  -
 
7
// -                                                                         -
 
8
// - This program  is  distributed in  the hope  that it will be useful, but -
 
9
// - without  any  warranty;  without  even   the   implied    warranty   of -
 
10
// - merchantability or fitness for a particular purpose.  In no event shall -
 
11
// - the copyright holder be liable for any  direct, indirect, incidental or -
 
12
// - special damages arising in any way out of the use of this software.     -
 
13
// ---------------------------------------------------------------------------
 
14
// - copyright (c) 1999-2011 amaury darsch                                   -
 
15
// ---------------------------------------------------------------------------
 
16
 
 
17
#include "Ascii.hpp"
 
18
#include "Vector.hpp"
 
19
#include "System.hpp"
 
20
#include "Unicode.hpp"
 
21
#include "Integer.hpp"
 
22
#include "QuarkZone.hpp"
 
23
#include "Exception.hpp"
 
24
#include "BlockBuffer.hpp"
 
25
 
 
26
namespace afnix {
 
27
 
 
28
  // -------------------------------------------------------------------------
 
29
  // - class section                                                         -
 
30
  // -------------------------------------------------------------------------
 
31
  
 
32
  // create a default block buffer
 
33
 
 
34
  BlockBuffer::BlockBuffer (void) : Buffer (Encoding::BYTE){
 
35
    // set the block buffer
 
36
    d_rcnt = 0LL;
 
37
    d_wcnt = 0LL;
 
38
    // force non resizable
 
39
    setrflg (false);
 
40
  }
 
41
 
 
42
  // create a block buffer by size
 
43
 
 
44
  BlockBuffer::BlockBuffer (const long size) : Buffer (size, Encoding::BYTE) {
 
45
    // set the block buffer
 
46
    d_rcnt = 0LL;
 
47
    d_wcnt = 0LL;
 
48
    // force non resizable
 
49
    setrflg (false);
 
50
  }
 
51
    
 
52
  // return the class name
 
53
 
 
54
  String BlockBuffer::repr (void) const {
 
55
    return "BlockBuffer";
 
56
  }
 
57
 
 
58
  // reset this block buffer
 
59
 
 
60
  void BlockBuffer::reset (void) {
 
61
    wrlock ();
 
62
    try {
 
63
      // reset the base object
 
64
      Buffer::reset ();
 
65
      // reset the local members
 
66
      d_rcnt = 0LL;
 
67
      d_wcnt = 0LL;
 
68
      // unlock and return
 
69
      unlock ();
 
70
    } catch (...) {
 
71
      unlock ();
 
72
      throw;
 
73
    }
 
74
  }
 
75
 
 
76
  // get the buffer read count
 
77
 
 
78
  t_long BlockBuffer::getrcnt (void) const {
 
79
    rdlock ();
 
80
    try {
 
81
      t_long result = d_rcnt;
 
82
      unlock ();
 
83
      return result;
 
84
    } catch (...) {
 
85
      unlock ();
 
86
      throw;
 
87
    }
 
88
  }
 
89
 
 
90
  // get the buffer write count
 
91
 
 
92
  t_long BlockBuffer::getwcnt (void) const {
 
93
    rdlock ();
 
94
    try {
 
95
      t_long result = d_wcnt;
 
96
      unlock ();
 
97
      return result;
 
98
    } catch (...) {
 
99
      unlock ();
 
100
      throw;
 
101
    }
 
102
  }
 
103
 
 
104
  // add a character to this block buffer
 
105
 
 
106
  long BlockBuffer::add (const char value) {
 
107
    wrlock ();
 
108
    try {
 
109
      // add the character in the buffer
 
110
      long result = Buffer::add (value);
 
111
      // update the write counter
 
112
      d_wcnt += result;
 
113
      // unlock and return
 
114
      unlock ();
 
115
      return result;
 
116
    } catch (...) {
 
117
      unlock ();
 
118
      throw;
 
119
    } 
 
120
  }
 
121
 
 
122
  // get the next available character
 
123
 
 
124
  char BlockBuffer::read (void) {
 
125
    wrlock ();
 
126
    try {
 
127
      // read the next character
 
128
      char result = Buffer::read ();
 
129
      // update the read counter
 
130
      d_rcnt++;
 
131
      unlock ();
 
132
      return result;
 
133
    } catch (...) {
 
134
      unlock ();
 
135
      throw;
 
136
    } 
 
137
  }
 
138
 
 
139
  // pushback a character to this block buffer
 
140
 
 
141
  long BlockBuffer::pushback (const char value) {
 
142
    wrlock ();
 
143
    try {
 
144
      // add the character in the buffer
 
145
      long result = Buffer::pushback (value);
 
146
      // update the write counter
 
147
      d_wcnt += result;
 
148
      // unlock and return
 
149
      unlock ();
 
150
      return result;
 
151
    } catch (...) {
 
152
      unlock ();
 
153
      throw;
 
154
    } 
 
155
  }
 
156
 
 
157
  // copy a character array into the block buffer
 
158
 
 
159
  long BlockBuffer::copy (const char* data, const long size) {
 
160
    wrlock ();
 
161
    try {
 
162
      // reset the buffer in bound mode
 
163
      if (full () == true) Buffer::reset ();
 
164
      // add the buffer data
 
165
      long result = Buffer::add (data, size);
 
166
      // unlock and return
 
167
      unlock ();
 
168
      return result;
 
169
    } catch (...) {
 
170
      unlock ();
 
171
      throw;
 
172
    }
 
173
  }
 
174
 
 
175
  // add a string in this buffer
 
176
  
 
177
  long BlockBuffer::copy (const String& s) {
 
178
    wrlock ();
 
179
    char* cbuf = nilp;
 
180
    try {
 
181
      // encode the string
 
182
      cbuf = Unicode::encode (d_emod, s);
 
183
      long  size = Ascii::strlen (cbuf);
 
184
      // add the buffer
 
185
      long result = copy (cbuf, size);
 
186
      // clean and unlock
 
187
      delete [] cbuf;
 
188
      unlock ();
 
189
      return result;
 
190
    } catch (...) {
 
191
      delete [] cbuf;
 
192
      unlock ();
 
193
      throw;
 
194
    }
 
195
  }
 
196
 
 
197
  // copy a buffer into the block buffer
 
198
 
 
199
  long BlockBuffer::copy (Buffer& buffer) {
 
200
    wrlock ();
 
201
    try {
 
202
      // reset the buffer in bound mode
 
203
      if (full () == true) Buffer::reset ();
 
204
      // add the buffer
 
205
      long result = 0;
 
206
      while ((buffer.empty () == false) && (full () == false)) {
 
207
        result += add (buffer.read ());
 
208
      }
 
209
      // unlock and return
 
210
      unlock ();
 
211
      return result;
 
212
    } catch (...) {
 
213
      unlock ();
 
214
      throw;
 
215
    }
 
216
  }
 
217
 
 
218
  // copy an input stream into the block buffer
 
219
 
 
220
  long BlockBuffer::copy (InputStream& is) {
 
221
    wrlock ();
 
222
    try {
 
223
      // initialize result
 
224
      long result = 0;
 
225
      // reset the buffer if full (i.e bound mode)
 
226
      if (full () == true) Buffer::reset ();
 
227
      // copy directly the block
 
228
      if (empty () == true ) {
 
229
        // copy directly by block
 
230
        result = is.copy (p_data, d_size);
 
231
        // update indexes
 
232
        d_blen  = result;
 
233
        d_wcnt += result;
 
234
      } else {
 
235
        // add the buffer data
 
236
        while ((is.valid () == true) && (full () == false)) {
 
237
          result += add (is.read ());
 
238
        }
 
239
      }
 
240
      unlock ();
 
241
      return result;
 
242
    } catch (...) {
 
243
      unlock ();
 
244
      throw;
 
245
    }
 
246
  }
 
247
 
 
248
  // copy a block buffer to an output stream
 
249
 
 
250
  long BlockBuffer::copy (OutputStream& os) {
 
251
    wrlock ();
 
252
    try {
 
253
      long result = 0;
 
254
      // loop until empty
 
255
      while (empty () == false) {
 
256
        // copy the buffer
 
257
        long size = os.write (p_data, d_blen);
 
258
        // adjust by shifting
 
259
        shl (size);
 
260
        // update counter
 
261
        result += size;
 
262
      }
 
263
      d_rcnt += result;
 
264
      unlock ();
 
265
      return result;
 
266
    } catch (...) {
 
267
      unlock ();
 
268
      throw;
 
269
    }
 
270
  }
 
271
 
 
272
  // copy an input stream into an output stream
 
273
 
 
274
  long BlockBuffer::copy (OutputStream& os, InputStream& is) {
 
275
    wrlock ();
 
276
    try {
 
277
      long result = 0;
 
278
      while (is.valid () == true) {
 
279
        // copy the input stream
 
280
        long rdsz = copy (is);
 
281
        // copy to the output stream
 
282
        long wrsz = copy (os);
 
283
        if (rdsz != wrsz) {
 
284
          throw Exception ("buffer-error", "buffer copy size differences");
 
285
        }
 
286
        result += rdsz;
 
287
      }
 
288
      unlock ();
 
289
      return result;
 
290
    } catch (...) {
 
291
      unlock ();
 
292
      throw;
 
293
    }
 
294
  }
 
295
 
 
296
  // -------------------------------------------------------------------------
 
297
  // - object section                                                        -
 
298
  // -------------------------------------------------------------------------
 
299
 
 
300
  // the quark zone
 
301
  static const long QUARK_ZONE_LENGTH = 5;
 
302
  static QuarkZone  zone (QUARK_ZONE_LENGTH);
 
303
  
 
304
  // the object supported quarks
 
305
  static const long QUARK_COPY   = zone.intern ("copy");
 
306
  static const long QUARK_RCNT   = zone.intern ("read-count");
 
307
  static const long QUARK_WCNT   = zone.intern ("write-count");
 
308
  static const long QUARK_COPYIS = zone.intern ("copy-input-stream");
 
309
  static const long QUARK_COPYOS = zone.intern ("copy-output-stream");
 
310
 
 
311
  // create a new object in a generic way
 
312
 
 
313
  Object* BlockBuffer::mknew (Vector* argv) {
 
314
    long argc = (argv == nilp) ? 0 : argv->length ();
 
315
    // check 0 argument
 
316
    if (argc == 0) return new BlockBuffer;
 
317
    // check 1 argument
 
318
    if (argc == 1) {
 
319
      long size = argv->getlong (0);
 
320
      return new BlockBuffer (size);
 
321
    }
 
322
    throw Exception ("argument-error", "too many argument for block buffer");
 
323
  }
 
324
 
 
325
  // return true if the given quark is defined
 
326
 
 
327
  bool BlockBuffer::isquark (const long quark, const bool hflg) const {
 
328
    rdlock ();
 
329
    if (zone.exists (quark) == true) {
 
330
      unlock ();
 
331
      return true;
 
332
    }      
 
333
    bool result = hflg ? Buffer::isquark (quark, hflg) : false;
 
334
    unlock ();
 
335
    return result;
 
336
  }
 
337
 
 
338
  // apply this object with a set of arguments and a quark
 
339
 
 
340
  Object* BlockBuffer::apply (Runnable* robj, Nameset* nset, const long quark,
 
341
                              Vector* argv) {
 
342
    // get the number of arguments
 
343
    long argc = (argv == nilp) ? 0 : argv->length ();
 
344
 
 
345
    // dispatch 0 argument
 
346
    if (argc == 0) {
 
347
      if (quark == QUARK_RCNT) return new Integer (getrcnt ());
 
348
      if (quark == QUARK_WCNT) return new Integer (getwcnt ());
 
349
    }
 
350
 
 
351
    // dispatch 1 argument
 
352
    if (argc == 1) {
 
353
      if (quark == QUARK_COPY) {
 
354
        Object* obj = argv->get (0);
 
355
        // check for a string
 
356
        String* sobj = dynamic_cast<String*> (obj);
 
357
        if (sobj != nilp) {
 
358
          long result = copy (*sobj);
 
359
          return new Integer (result);
 
360
        }
 
361
        // check for a buffer
 
362
        Buffer* bobj = dynamic_cast<Buffer*> (obj);
 
363
        if (bobj != nilp) {
 
364
          long result = copy (*bobj);
 
365
          return new Integer (result);
 
366
        }
 
367
        // check for an input stream
 
368
        InputStream* is = dynamic_cast<InputStream*> (obj);
 
369
        if (is != nilp) {
 
370
          long result = copy (*is);
 
371
          return new Integer (result);
 
372
        }
 
373
        // check for an output stream
 
374
        OutputStream* os = dynamic_cast<OutputStream*> (obj);
 
375
        if (os != nilp) {
 
376
          long result = copy (*os);
 
377
          return new Integer (result);
 
378
        }
 
379
        throw Exception ("type-error", 
 
380
                         "invalid object to copy in block buffer",
 
381
                         Object::repr (obj));
 
382
      }
 
383
      if (quark == QUARK_COPYIS) {
 
384
        Object* obj = argv->get (0);
 
385
        // check for an input stream
 
386
        InputStream* is = dynamic_cast<InputStream*> (obj);
 
387
        if (is != nilp) {
 
388
          long result = copy (*is);
 
389
          return new Integer (result);
 
390
        }
 
391
        throw Exception ("type-error", 
 
392
                         "invalid object to copy in block buffer",
 
393
                         Object::repr (obj));
 
394
      }
 
395
      if (quark == QUARK_COPYOS) {
 
396
        Object* obj = argv->get (0);
 
397
        // check for an output stream
 
398
        OutputStream* os = dynamic_cast<OutputStream*> (obj);
 
399
        if (os != nilp) {
 
400
          long result = copy (*os);
 
401
          return new Integer (result);
 
402
        }
 
403
        throw Exception ("type-error", 
 
404
                         "invalid object to copy in block buffer",
 
405
                         Object::repr (obj));
 
406
      }
 
407
    }
 
408
 
 
409
    // dispatch 2 arguments
 
410
    if (argc == 2) {
 
411
      if (quark == QUARK_COPY) {
 
412
        Object* oobj = argv->get (0);
 
413
        // check for an output stream
 
414
        OutputStream* os = dynamic_cast<OutputStream*> (oobj);
 
415
        if (os == nilp) {
 
416
          throw Exception ("type-error", 
 
417
                           "invalid object to copy in block buffer",
 
418
                           Object::repr (oobj));
 
419
        }
 
420
        // check for an input stream
 
421
        Object* iobj = argv->get (1);
 
422
        InputStream* is = dynamic_cast<InputStream*> (iobj);
 
423
        if (is == nilp) {
 
424
          throw Exception ("type-error", 
 
425
                           "invalid object to copy in block buffer",
 
426
                           Object::repr (iobj));
 
427
        }
 
428
        long result = copy (*os, *is);
 
429
        return new Integer (result);
 
430
      }
 
431
    }
 
432
    // call the buffer method
 
433
    return Buffer::apply (robj, nset, quark, argv);
 
434
  }
 
435
}