root/trunk/whisperlib/common/io/num_streaming.cc

Revision 7, 5.3 kB (checked in by whispercastorg, 2 years ago)

version 0.2.0

Line 
1 // Copyright (c) 2009, Whispersoft s.r.l.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Whispersoft s.r.l. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Author: Catalin Popescu & Cosmin Tudorache
31
32 #include <sys/types.h>
33
34 #include "common/io/num_streaming.h"
35
36 namespace io {
37
38 BitArray::BitArray()
39   : data_(NULL), data_size_(0), data_owned_(false),
40     head_(0), head_bit_(0) {
41 }
42 BitArray::~BitArray() {
43   if ( data_owned_ ) {
44     delete data_;
45     data_ = NULL;
46   }
47   data_size_ = 0;
48   data_owned_ = false;
49 }
50
51 void BitArray::Wrap(const void* data, uint32 size) {
52   data_ = static_cast<const uint8*>(data);
53   data_size_ = size;
54   data_owned_ = false;
55   head_ = 0;
56   head_bit_ = 7;
57 }
58 void BitArray::Put(const void* data, uint32 size) {
59   uint8* data_copy = new uint8[size];
60   ::memcpy(data_copy, data, size);
61   delete data_;
62   data_ = data_copy;
63   data_size_ = size;
64   data_owned_ = true;
65   head_ = 0;
66   head_bit_ = 7;
67 }
68
69 void BitArray::Skip(uint32 bit_count) {
70   if ( bit_count <= head_bit_ ) {
71     head_bit_ -= bit_count;
72   } else {
73     uint32 remaining_bit_count = bit_count - head_bit_ - 1;
74     head_bit_ = 7;
75     head_++;
76
77     head_ += (remaining_bit_count / 8);
78     head_bit_ -= (remaining_bit_count % 8);
79   }
80 }
81
82 uint32 BitArray::Size() {
83   CHECK_LE(head_bit_, 7);
84   CHECK_GE(head_bit_, 0);
85   if ( head_ == data_size_ ) {
86     CHECK_EQ(head_bit_, 7);
87     return 0;
88   }
89   CHECK_LT(head_, data_size_);
90   return head_bit_ + 1 + (data_size_ - head_ - 1) * 8;
91 }
92
93 //static
94 void BitArray::BitCopy(const void* void_src, uint32 src_bit_index,
95                        void* void_dst, uint32 dst_bit_index,
96                        uint32 bit_count) {
97   const uint8* src = static_cast<const uint8*>(void_src);
98   uint8* dst = static_cast<uint8*>(void_dst);
99
100   // advance 's' until src_bit_index is < 8
101   src = src + (src_bit_index / 8);
102   src_bit_index = src_bit_index % 8;
103
104   // advance 'd' until dst_bit_index is < 8
105   dst = dst + (dst_bit_index / 8);
106   dst_bit_index = dst_bit_index % 8;
107
108   while ( bit_count != 0 ) {
109     // consider the copy: (the '#' should be copied, the rest of '-' should stay the same)
110     //         7 6 5 4 3 2 1 0
111     //         | | | | | | | |
112     //         V V V V V V V V
113     //  - src [-,-,-,#,#,#,#,-]
114     //  - dst [-,-,-,-,-,-,#,#][#,#,-,-,-,-,-,-]
115     // src_bit_index = 4
116     // dst_bit_index = 1
117     // count: 2 // How many bit do we copy now
118     // src_mask: 00011000 // Use it to extract 'count' bits from src
119     // dst_mask: 00000011 // Negate it and use it to zero 'count' bits in dst
120     // s = *src & src_mask => s = 000##000
121     // shift s to same position as dst_bit_index => s = 000000##
122     // d = *dst & (~dst_mask) => d = ------00
123     // d = d | s => d = ------## // 6 bits from *dst and last 2 bits from *src
124     // *dst = d // 'count' bits copied
125     // src_bit_index -= count // adjust index after copy
126     // dst_bit_index -= count // adjust index after copy
127     // bit_count -= count     // adjust remaining 'bits to copy' after copy
128     //
129     uint32 count = min(min(src_bit_index + 1, dst_bit_index + 1), bit_count);
130
131     uint8 src_mask = (static_cast<uint8>(0xff) >> (7 - src_bit_index)) &
132                      (static_cast<uint8>(0xff) << (src_bit_index + 1 - count));
133     uint8 dst_mask = (static_cast<uint8>(0xff) >> (7 - dst_bit_index)) &
134                      (static_cast<uint8>(0xff) << (dst_bit_index + 1 - count));
135
136     uint8 s = (*src) & src_mask;
137     if ( src_bit_index > dst_bit_index ) {
138       s = s >> (src_bit_index - dst_bit_index);
139     } else {
140       s = s << (dst_bit_index - src_bit_index);
141     }
142     uint8 d = (*dst) & (~dst_mask);
143     d = d | s;
144
145     *dst = d;
146
147     if ( src_bit_index >= count ) {
148       src_bit_index -= count;
149     } else {
150       CHECK_EQ(count, src_bit_index + 1);
151       src_bit_index = 7;
152       src++;
153     }
154     if ( dst_bit_index >= count ) {
155       dst_bit_index -= count;
156     } else {
157       CHECK_EQ(count, dst_bit_index + 1);
158       dst_bit_index = 7;
159       dst++;
160     }
161     CHECK_LE(count, bit_count);
162     bit_count -= count;
163   }
164 }
165 }
Note: See TracBrowser for help on using the browser.