File: bufext_ext.cpp

package info (click to toggle)
falconpl 0.9.6.9-git20120606-2
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 46,176 kB
  • sloc: cpp: 181,389; ansic: 109,025; yacc: 2,310; xml: 1,218; sh: 403; objc: 245; makefile: 82; sql: 20
file content (270 lines) | stat: -rw-r--r-- 8,011 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
/*
   FALCON - The Falcon Programming Language.
   FILE: bufext_ext.cpp

   Buffering extensions
   Interface extension functions
   -------------------------------------------------------------------
   Author: Maximilian Malek
   Begin: Sun, 20 Jun 2010 18:59:55 +0200

   -------------------------------------------------------------------
   (C) Copyright 2010: The above AUTHOR

         Licensed under the Falcon Programming Language License,
      Version 1.1 (the "License"); you may not use this file
      except in compliance with the License. You may obtain
      a copy of the License at

         http://www.falconpl.org/?page_id=license_1_1

      Unless required by applicable law or agreed to in writing,
      software distributed under the License is distributed on
      an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
      KIND, either express or implied. See the License for the
      specific language governing permissions and limitations
      under the License.

*/

/** \file
   Buffering extensions
   Interface extension functions
*/

/*#
	@beginmodule feathers.bufext 
*/

#include <falcon/engine.h>
#include "bufext_ext.h"
#include "bufext_st.h"

namespace Falcon { namespace Ext {


CoreString *ByteArrayToHex(byte *arr, uint32 size)
{
    CoreString *str = new CoreString; // each byte will be encoded to 2 chars
    str->reserve(size * 2);

    for(uint32 i = 0; i < size; i++)
    {
        int hexlet = (arr[i] >> 4) & 0xf ;
        str->append( hexlet < 10 ? '0' + hexlet : 'a' + (hexlet-10) );
        hexlet = arr[i] & 0xf ;
        str->append( hexlet < 10 ? '0' + hexlet : 'a' + (hexlet-10) );
    }
    return str;
}

/*#
@method bitCount BitBuf
@brief Sets or gets the bit count used in writeBits() and readBits()
@optparam bits The amount of bits to use
@return The BitBuf itself if @i bits was set, otherwise the amount of bits used in the bit-precise read/write functions.

Default is 8, if not explicitly set.
A bit count of 0 will not write anything, and read operations will always return 0.
Values > 64 are not recommended to use as they make no sense.

@code
    bb = BitBuf()
    bb.bitCount(3).writeBits(7,4,3).bitCount(5).writeBits(30,20,10) // write with variable bit sizes
@endcode
*/
FALCON_FUNC BitBuf_bitCount( ::Falcon::VMachine *vm )
{
    BitBuf& buf = vmGetBuf<BitBuf>(vm);

    if(Item *p0 = vm->param(0))
    {
        if(uint32 bc = (uint32)p0->forceIntegerEx())
            buf.bitcount(bc);
        vm->retval(vm->self());
    }
    else
    {
        vm->retval((int64)buf.bitcount());
    }
}

/*#
@method writeBits BitBuf
@brief Writes integers with a fixed bit width
@optparam ints An arbitrary amount of integers
@return The BitBuf itself.

This method writes the lowest @i n bits of the supplied integers, where @i n = bitCount().
Be sure to choose enough bits, otherwise the integers will be truncated.
To get the required amount of bits for an integer, use BitBuf.bitsForInt().

For numbers < 0, the sign is skipped and the number will be written as: (bitCount() + 1) - (abs(N) % bitCount()), where N is our negative number.
To restore a negative number, use readBits(true).

@note bitCount() >= 64 is the only mode that supports writing negative numbers *without* having to use readBits(true).

@code
    bb = BitBuf()
    bb.bitCount(3).writeBits(7,4,3).bitCount(5).writeBits(30,20,10) // write with variable bit sizes
@endcode
*/
FALCON_FUNC BitBuf_writeBits( ::Falcon::VMachine *vm )
{
    BitBuf& buf = vmGetBuf<BitBuf>(vm);
    register uint32 size = uint32(vm->paramCount());

    for(uint32 i = 0; i < size; i++)
    {
        Item *itm = vm->param(i);
        buf << itm->forceInteger(); // << operator makes it append with chosen bit size
    }

    vm->retval(vm->self());
}

/*#
@method readBits BitBuf
@brief Reads integers with a fixed bit width
@optparam neg An arbitrary amount of integers
@return An integer value.

Reads one integer of @i bitCount() bits from the buffer.
The returned integer is always positive, except if bitCount() is 64 and a negative number was written.
If @i is true, this method will set all upper missing bits to make the number negative,
to restore a previously written negative number.

@code
    bb = BitBuf().bitCount(3).writeBits(7,8,9)
    x = bb.readBits()
    y = bb.readBits()
    z = bb.readBits()
    // result: x == 7, y == 0, z == 1  (only the lowest 3 bits were written!)
@endcode

@note Unlike r8()..r64(), the boolean parameter for this method *forces* a negative number.
*/
FALCON_FUNC BitBuf_readBits( ::Falcon::VMachine *vm )
{
    BitBuf& buf = vmGetBuf<BitBuf>(vm);

    int64 val;
    buf >> val; // >> operator makes it read with chosen bit size

    if(vm->paramCount() && vm->param(0)->isTrue())
        val |= (uint64(-1) << buf.bitcount());

    vm->retval(val);
}

/*#
@method sizeBits BitBuf
@brief Returns the buffer size, in bits
@return The buffer size, in bits

This function returns or sets the BitBuf size precisely, which can be calculated as
(size() * 8) + X, where X is in [0...7].
*/
FALCON_FUNC BitBuf_sizeBits( ::Falcon::VMachine *vm )
{
    BitBuf& buf = vmGetBuf<BitBuf>(vm);
    vm->retval((int64)buf.size_bits());
}

/*#
@method rposBits BitBuf
@brief Returns the read position, in bits
@return The read position in bits if used as getter, otherwise the buffer itself

This function returns or sets the BitBuf read position precisely, which can be calculated as
(rpos() * 8) + X, where X is in [0...7].
*/
FALCON_FUNC BitBuf_rposBits( ::Falcon::VMachine *vm )
{
    BitBuf& buf = vmGetBuf<BitBuf>(vm);

    if(Item *p0 = vm->param(0))
    {
        buf.rpos_bits((uint32)p0->forceIntegerEx());
        vm->retval(vm->self());
    }
    else
    {
        vm->retval((int64)buf.rpos_bits());
    }
}

/*#
@method wposBits BitBuf
@brief Returns the write position, in bits
@return The write position in bits if used as getter, otherwise the buffer itself

This function returns the BitBuf write position precisely, which can be calculated as
(wpos() * 8) + X, where X is in [0...7].
*/
FALCON_FUNC BitBuf_wposBits( ::Falcon::VMachine *vm )
{
    BitBuf& buf = vmGetBuf<BitBuf>(vm);

    if(Item *p0 = vm->param(0))
    {
        buf.wpos_bits((uint32)p0->forceIntegerEx());
        vm->retval(vm->self());
    }
    else
    {
        vm->retval((int64)buf.wpos_bits());
    }
}

/*#
@method readableBits BitBuf
@brief Returns the amount of bits left that can be read
@return The remaining bits until the end of the BitBuf is reached

This function returns the remaining bits precisely, which can be calculated as
(readable() * 8) + X, where X is in [0...7].
*/
FALCON_FUNC BitBuf_readableBits( ::Falcon::VMachine *vm )
{
    BitBuf& buf = vmGetBuf<BitBuf>(vm);
    vm->retval(int64(buf.size_bits() - buf.rpos_bits()));
}

/*#
@method bitsForInt BitBuf
@brief Static. Returns the amount of bits required to store an integer of the given value
@param n Integer to check
@return The amount of bits required to store an integer of the given value

Calculates how many bits are required to hold the value of the passed integer without losing data.

@note A negative number can be 1 greater then its corresponding positive number, and yield the same result (-8 needs 3 bits, where +8 needs 4, for example)
*/
FALCON_FUNC BitBuf_bits_req( ::Falcon::VMachine *vm )
{
    if(!vm->paramCount())
    {
        throw new ParamError( ErrorParam( e_inv_params, __LINE__ )
            .origin( e_orig_mod ).extra( "I" ) );
    }
    int64 i = vm->param(0)->forceIntegerEx();
    if(i < 0)
        vm->retval(int64(BitBuf::bits_req(uint64(~(i - 1)) - 1))); // make number positive and fix 2-complement off-by-1
    else
        vm->retval(int64(BitBuf::bits_req(uint64(i))));
}

FALCON_FUNC BufferError_init( ::Falcon::VMachine *vm )
{
    CoreObject *obj = vm->self().asObject();
    if(!obj->getUserData())
        obj->setUserData( new BufferError );

    ::Falcon::core::Error_init( vm );
}


}} // namespace Falcon::Ext

/* end of bufext_ext.cpp */