1
// ---------------------------------------------------------------------------
3
// - standard object library - character 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. -
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
// ---------------------------------------------------------------------------
22
#include "Utility.hpp"
23
#include "Unicode.hpp"
24
#include "Integer.hpp"
25
#include "Boolean.hpp"
26
#include "QuarkZone.hpp"
27
#include "Exception.hpp"
32
// -------------------------------------------------------------------------
34
// -------------------------------------------------------------------------
36
// generate a random buffer
38
Buffer Buffer::random (const long size) {
39
// check for valid size
41
throw Exception ("size-error", "invalid random number size");
43
// create a buffer by size
45
// fill it with random bytes
46
for (long i = 0; i < size; i++) {
47
result.add ((char) Utility::byternd ());
53
// -------------------------------------------------------------------------
55
// -------------------------------------------------------------------------
57
// create a new buffer class with a default size of 1024 characters
59
Buffer::Buffer (void) {
60
d_size = System::blocksz ();
61
p_data = new char [d_size];
64
d_emod = Encoding::BYTE;
67
// create a new buffer with a predefined size
69
Buffer::Buffer (const long size) {
70
d_size = (size <= 0) ? System::blocksz () : size;
71
p_data = new char[d_size];
74
d_emod = Encoding::BYTE;
77
// create a new buffer by mode
79
Buffer::Buffer (const Encoding::t_emod emod) {
80
d_size = System::blocksz ();
81
p_data = new char[d_size];
87
// create a new buffer by size with a mode
89
Buffer::Buffer (const long size, const Encoding::t_emod emod) {
90
d_size = (size <= 0) ? System::blocksz () : size;
91
p_data = new char[d_size];
97
// create a new buffer and initialize it with a c string
99
Buffer::Buffer (const char* value) {
100
d_size = System::blocksz ();
101
p_data = new char[d_size];
104
d_emod = Encoding::UTF8;
105
add (value, Ascii::strlen (value));
108
// create a new buffer and initialize it with a string
110
Buffer::Buffer (const String& value) {
111
d_size = System::blocksz ();
112
p_data = new char[d_size];
115
d_emod = Encoding::UTF8;
119
// copy construct a buffer
121
Buffer::Buffer (const Buffer& that) {
124
d_size = that.d_size;
126
d_rflg = that.d_rflg;
127
d_emod = that.d_emod;
128
p_data = new char[d_size];
129
add (that.p_data, that.d_blen);
137
// destroy this buffer
139
Buffer::~Buffer (void) {
143
// return the class name
145
String Buffer::repr (void) const {
149
// assign a buffer to this one
151
Buffer& Buffer::operator = (const Buffer& that) {
152
if (this == &that) return *this;
156
// clean the old data
161
d_size = that.d_size;
162
d_rflg = that.d_rflg;
163
d_emod = that.d_emod;
164
p_data = new char[d_size];
165
add (that.p_data, that.d_blen);
176
// return a clone of this object
178
Object* Buffer::clone (void) const {
179
return new Buffer (*this);
182
// reset this buffer but do not change the size
184
void Buffer::reset (void) {
195
// return the size of this buffer
197
long Buffer::getsize (void) const {
200
long result = d_size;
209
// return the length of this buffer
211
long Buffer::length (void) const {
214
long result = d_blen;
223
// set the buffer encoding mode
225
void Buffer::setemod (const Encoding::t_emod emod) {
236
// get the buffer encoding
238
Encoding::t_emod Buffer::getemod (void) const {
241
Encoding::t_emod result = d_emod;
250
// set the resize flag
252
void Buffer::setrflg (const bool rflg) {
263
// return the resize flag
265
bool Buffer::getrflg (void) const {
268
bool result = d_rflg;
277
// return true if the buffer is empty
279
bool Buffer::empty (void) const {
282
bool result = (d_blen == 0);
291
// return true if the buffer is full
293
bool Buffer::full (void) const {
296
bool result = d_rflg ? false : (d_blen >= d_size);
305
// add a character in this buffer
307
long Buffer::add (const char value) {
310
// first check if we are at the buffer end
311
if (d_blen >= d_size) {
312
if (d_rflg == true) {
313
long size = d_size * 2;
314
char* buf = new char[size];
315
for (long i = 0; i < d_blen; i++) buf[i] = p_data[i];
324
p_data[d_blen++] = value;
333
// add a unicode character in the buffer
335
long Buffer::add (const t_quad value) {
339
// get the character encoding
340
cbuf = Unicode::encode (d_emod, value);
341
long size = Ascii::strlen (cbuf);
342
// add the coding in the buffer
343
long result = add (cbuf, size);
355
// add a c-string in this buffer
357
long Buffer::add (const char* s) {
360
long size = Ascii::strlen (s);
361
long result = add (s, size);
370
// add a character buffer in this buffer
372
long Buffer::add (const char* cbuf, const long size) {
373
if ((cbuf == nilp) || (size == 0)) return 0;
377
for (long i = 0; i < size; i++) {
378
result += add (cbuf[i]);
379
if (full () == true) break;
389
// add a string in this buffer
391
long Buffer::add (const String& s) {
396
cbuf = Unicode::encode (d_emod, s);
397
long size = Ascii::strlen (cbuf);
399
long result = add (cbuf, size);
411
// add a buffer object to this buffer
413
long Buffer::add (const Buffer& buffer) {
414
// do not add yourself
415
if (this == &buffer) return 0;
420
long result = add (buffer.p_data, buffer.d_blen);
431
// read a character in this buffer
433
char Buffer::read (void) {
436
// check for no character
441
// get value and shift
442
char value = p_data[0];
443
for (long i = 0; i < d_blen-1; i++) p_data[i] = p_data[i+1];
453
// get the next character but do not remove it
455
char Buffer::get (void) const {
458
char result = (d_blen == 0) ? nilc : p_data[0];
467
// get a character by index
469
char Buffer::get (const long index) const {
472
if ((index < 0) || (index >= d_blen)) {
473
throw Exception ("range-error", "out-of-bound buffer index");
475
char result = p_data[index];
484
// shift the buffer by a certain amount
486
void Buffer::shl (const long asl) {
491
// shift the old buffer
492
long blen = d_blen - asl;
493
long size = d_rflg ? d_size : blen;
494
char* data = new char[size];
495
for (long i = asl; i < d_blen; i++) data[i-asl] = p_data[i];
511
// read a line from this buffer
513
String Buffer::readln (void) {
516
// create a buffer to accumulate characters
519
// read the character in the buffer
520
while (empty () == false) {
526
if (c == eolc) break;
534
return buf.tostring ();
541
// pushback a character in this buffer
543
long Buffer::pushback (const char value) {
546
// check if we are full
547
if (d_blen >= d_size) {
548
if (d_rflg == true) {
549
long size = d_size * 2;
550
char* buf = new char[size];
551
for (long i = 0; i < d_blen; i++) buf[i] = p_data[i];
560
// shift the buffer by one
561
for (long i = d_blen; i > 0; i--) p_data[i] = p_data[i-1];
572
// pushback a unicode character in the buffer
574
long Buffer::pushback (const t_quad value) {
578
// get the character encoding
579
cbuf = Unicode::encode (d_emod, value);
580
long size = Ascii::strlen (cbuf);
581
// pushback the coding in the buffer
582
pushback (cbuf, size);
594
// pushback a character string to this buffer
596
long Buffer::pushback (const char* s) {
599
long size = Ascii::strlen (s);
600
long result = pushback (s, size);
609
// pushback a buffer in this buffer
611
long Buffer::pushback (const char* s, const long size) {
612
if ((s == nilp) || (size == 0)) return 0;
617
for (long i = len; i >= 0; i--) {
618
result += pushback (s[i]);
619
if (full () == true) break;
629
// pushback a string in this buffer
631
long Buffer::pushback (const String& value) {
636
cbuf = Unicode::encode (d_emod, value);
637
long size = Ascii::strlen (cbuf);
638
// pushback the string
639
long result = pushback (cbuf, size);
651
// pushback a buffer in this buffer
653
long Buffer::pushback (const Buffer& buffer) {
654
// do not pushback yourself
655
if (this == &buffer) return 0;
660
long result = pushback (buffer.p_data, buffer.d_blen);
671
// return the corresponding string accumulated in this buffer
673
String Buffer::tostring (void) const {
677
t_quad* sbuf = Unicode::decode (d_emod, p_data, d_blen);
678
// map the result string
679
String result = sbuf;
690
// format the buffer content as an octet string
692
String Buffer::format (void) const {
696
String result = Ascii::btos ((const t_byte*) p_data, d_blen);
705
// map this buffer to an anonymous data structure
707
long Buffer::tomap (void* data, const long size) const {
710
// check for a null content
715
// process normal size
716
long result = (size < d_blen) ? size : d_blen;
717
char* ptr = reinterpret_cast <char*> (data);
718
// copy the buffer content
719
for (long i = 0; i < result; i++) ptr[i] = p_data[i];
729
// add a word in natural format to this buffer
731
void Buffer::addnw (const t_word wval) {
734
add ((char) ((wval >> 8) & 0x00FFU));
735
add ((char) (wval & 0x00FFU));
743
// add a quad in natural format to this buffer
745
void Buffer::addnq (const t_quad qval) {
748
add ((char) ((qval >> 24) & 0x000000FFU));
749
add ((char) ((qval >> 16) & 0x000000FFU));
750
add ((char) ((qval >> 8) & 0x000000FFU));
751
add ((char) (qval & 0x000000FFU));
759
// add an octa in natural format to this buffer
761
void Buffer::addno (const t_octa oval) {
764
add ((char) ((oval >> 56) & 0x00000000000000FFU));
765
add ((char) ((oval >> 48) & 0x00000000000000FFU));
766
add ((char) ((oval >> 40) & 0x00000000000000FFU));
767
add ((char) ((oval >> 32) & 0x00000000000000FFU));
768
add ((char) ((oval >> 24) & 0x00000000000000FFU));
769
add ((char) ((oval >> 16) & 0x00000000000000FFU));
770
add ((char) ((oval >> 8) & 0x00000000000000FFU));
771
add ((char) (oval & 0x00000000000000FFU));
779
// get a word in natural format from this buffer
781
t_word Buffer::getnw (void) {
784
// check valid buffer size
786
throw Exception ("buffer-error", "small buffer size with getnw");
789
t_word result = 0x0000U;
791
result |= (t_byte) read ();
793
result |= (t_byte) read ();
803
// get a quad in natural format from this buffer
805
t_quad Buffer::getnq (void) {
808
// check valid buffer size
810
throw Exception ("buffer-error", "small buffer size with getnq");
813
t_quad result = nilq;
815
result |= (t_byte) read ();
817
result |= (t_byte) read ();
819
result |= (t_byte) read ();
821
result |= (t_byte) read ();
831
// get an octa in natural format from this buffer
833
t_octa Buffer::getno (void) {
836
// check valid buffer size
838
throw Exception ("buffer-error", "small buffer size with getno");
841
t_octa result = 0ULL;
843
result |= (t_byte) read ();
845
result |= (t_byte) read ();
847
result |= (t_byte) read ();
849
result |= (t_byte) read ();
851
result |= (t_byte) read ();
853
result |= (t_byte) read ();
855
result |= (t_byte) read ();
857
result |= (t_byte) read ();
867
// get a word in host format from this buffer
869
t_word Buffer::gethw (void) {
872
// check valid buffer size
874
throw Exception ("buffer-error", "small buffer size with gethw");
876
// extract the character buffer
878
for (long i = 0; i < 2; i++) buf[i] = read ();
879
// convert it in host format
880
t_word result = c_wntoh (buf);
889
// get a quad in host format from this buffer
891
t_quad Buffer::gethq (void) {
894
// check valid buffer size
896
throw Exception ("buffer-error", "small buffer size with gethq");
898
// extract the character buffer
900
for (long i = 0; i < 4; i++) buf[i] = read ();
901
// convert it in host format
902
t_quad result = c_qntoh (buf);
911
// get an octa in host format from this buffer
913
t_octa Buffer::getho (void) {
916
// check valid buffer size
918
throw Exception ("buffer-error", "small buffer size with getho");
920
// extract the character buffer
922
for (long i = 0; i < 8; i++) buf[i] = read ();
923
// convert it in host format
924
t_octa result = c_ontoh (buf);
933
// -------------------------------------------------------------------------
934
// - object section -
935
// -------------------------------------------------------------------------
938
static const long QUARK_ZONE_LENGTH = 17;
939
static QuarkZone zone (QUARK_ZONE_LENGTH);
941
// the object supported quarks
942
static const long QUARK_ADD = zone.intern ("add");
943
static const long QUARK_GET = zone.intern ("get");
944
static const long QUARK_SHL = zone.intern ("shl");
945
static const long QUARK_READ = zone.intern ("read");
946
static const long QUARK_RESET = zone.intern ("reset");
947
static const long QUARK_LENGTH = zone.intern ("length");
948
static const long QUARK_ISFULL = zone.intern ("full-p");
949
static const long QUARK_EMPTYP = zone.intern ("empty-p");
950
static const long QUARK_FORMAT = zone.intern ("format");
951
static const long QUARK_GETSIZE = zone.intern ("get-size");
952
static const long QUARK_GETHW = zone.intern ("get-host-word");
953
static const long QUARK_GETHQ = zone.intern ("get-host-quad");
954
static const long QUARK_GETHO = zone.intern ("get-host-octa");
955
static const long QUARK_SETRFLG = zone.intern ("set-resize");
956
static const long QUARK_TOSTRING = zone.intern ("to-string");
957
static const long QUARK_PUSHBACK = zone.intern ("pushback");
958
static const long QUARK_ISRESIZE = zone.intern ("resize-p");
960
// create a new object in a generic way
962
Object* Buffer::mknew (Vector* argv) {
963
long argc = (argv == nilp) ? 0 : argv->length ();
964
// create an empty buffer with 0 arguments
965
Buffer* result = new Buffer;
966
// loop with literal objects
967
for (long i = 0; i < argc; i++) {
968
Object* obj = argv->get (i);
969
// check for a literal
970
Literal* lobj = dynamic_cast <Literal*> (obj);
972
result->add (lobj->tostring ());
975
// check for a vector
976
Vector* vobj = dynamic_cast <Vector*> (obj);
978
long vlen = vobj->length ();
979
for (long j = 0; j < vlen; j++) {
980
result->add ((char) vobj->getbyte (j));
984
throw Exception ("type-error", "invalid object with buffer",
990
// return true if the given quark is defined
992
bool Buffer::isquark (const long quark, const bool hflg) const {
994
if (zone.exists (quark) == true) {
998
bool result = hflg ? Object::isquark (quark, hflg) : false;
1003
// apply this object with a set of arguments and a quark
1005
Object* Buffer::apply (Runnable* robj, Nameset* nset, const long quark,
1007
// get the number of arguments
1008
long argc = (argv == nilp) ? 0 : argv->length ();
1010
// dispatch 0 argument
1012
if (quark == QUARK_GET) return new Byte (get ());
1013
if (quark == QUARK_READ) return new Byte (read ());
1014
if (quark == QUARK_GETHW) return new Integer (gethw ());
1015
if (quark == QUARK_GETHQ) return new Integer (gethq ());
1016
if (quark == QUARK_GETHO) return new Integer (getho ());
1017
if (quark == QUARK_LENGTH) return new Integer (length ());
1018
if (quark == QUARK_ISFULL) return new Boolean (full ());
1019
if (quark == QUARK_EMPTYP) return new Boolean (empty ());
1020
if (quark == QUARK_FORMAT) return new String (format ());
1021
if (quark == QUARK_GETSIZE) return new Integer (getsize ());
1022
if (quark == QUARK_TOSTRING) return new String (tostring ());
1023
if (quark == QUARK_ISRESIZE) return new Boolean (getrflg ());
1024
if (quark == QUARK_RESET) {
1030
// dispatch 1 argument
1032
if (quark == QUARK_GET) {
1033
long index = argv->getlong (0);
1034
return new Byte (get (index));
1036
if (quark == QUARK_SETRFLG) {
1037
bool rflg = argv->getbool (0);
1041
if (quark == QUARK_ADD) {
1042
Object* obj = argv->get (0);
1044
Byte* bobj = dynamic_cast<Byte*> (obj);
1046
long result = add ((char) bobj->tobyte ());
1047
return new Integer (result);
1049
// check for a literal
1050
Literal* lobj = dynamic_cast<Literal*> (obj);
1052
long result = add (lobj->tostring ());
1053
return new Integer (result);
1055
// check for a buffer
1056
Buffer* uobj = dynamic_cast<Buffer*> (obj);
1058
long result = add (*uobj);
1059
return new Integer (result);
1061
throw Exception ("type-error", "invalid object to add in buffer");
1063
if (quark == QUARK_PUSHBACK) {
1064
Object* obj = argv->get (0);
1066
Byte* bobj = dynamic_cast<Byte*> (obj);
1068
long result = pushback ((char) bobj->tobyte ());
1069
return new Integer (result);
1071
// check for a literal
1072
Literal* lobj = dynamic_cast<Literal*> (obj);
1074
long result = pushback (lobj->tostring ());
1075
return new Integer (result);
1077
// check for a buffer
1078
Buffer* uobj = dynamic_cast<Buffer*> (obj);
1080
long result = pushback (*uobj);
1081
return new Integer (result);
1083
throw Exception ("type-error", "invalid object to pushback in buffer");
1085
if (quark == QUARK_SHL) {
1086
long asl = argv->getlong (0);
1091
// call the object method
1092
return Object::apply (robj, nset, quark, argv);