ail now builds on Linux
[ail.git] / ail / memory.cpp
blob0e3efb43f1a621d5f4c8e6f0f0a345624f4d33e0
1 #include <ail/memory.hpp>
2 #include <ail/string.hpp>
4 #include <boost/foreach.hpp>
6 namespace ail
8 std::size_t const bits_per_byte = 8;
10 bit_reader::bit_reader(std::string const & data, bool high_to_low_order):
11 offset(0),
12 big_endian(true)
14 std::size_t
15 initial_value,
16 limit,
17 direction;
19 if(high_to_low_order)
21 initial_value = bits_per_byte - 1;
22 limit = -1;
23 direction = -1;
25 else
27 initial_value = 0;
28 limit = bits_per_byte;
29 direction = 1;
32 BOOST_FOREACH(char i, data)
34 for(std::size_t bit = initial_value; bit != limit; bit += direction)
35 bit_stream.push_back(static_cast<char>((i >> bit) & 1));
39 ulong bit_reader::read(std::size_t bit_count)
41 std::size_t new_offset = offset + bit_count;
42 if(new_offset > bit_stream.size())
43 throw exception("Reading bit stream data out of bounds");
44 std::string binary_string = bit_stream.substr(offset, bit_count);
45 ulong output = binary_string_to_number(binary_string);
46 offset = new_offset;
47 return output;
50 ulong bit_reader::read_bytes(std::size_t byte_count)
52 return read(bits_per_byte * byte_count);
55 bool bit_reader::read_bool()
57 return read(1) == 1;
60 std::size_t bit_reader::get_offset() const
62 return offset;
65 void bit_reader::set_offset(std::size_t new_offset)
67 if(new_offset > bit_stream.size())
68 throw exception("New bit stream offset is out of bounds");
69 offset = new_offset;
72 std::string bit_reader::string(std::size_t length, std::size_t character_size)
74 std::string output;
75 for(std::size_t i = 0; i < length; i++)
76 output.push_back(static_cast<char>(read(character_size)));
77 return output;
80 ulong read_big_endian(char const * input, std::size_t size, std::size_t offset)
82 unsigned char const * unsigned_input = reinterpret_cast<unsigned char const *>(input + offset);
83 ulong output = 0;
84 if(size)
86 for(unsigned char const * i = unsigned_input, * end = unsigned_input + size; i < end; ++i)
88 output <<= bits_per_byte;
89 output |= *i;
92 return output;
95 ulong read_little_endian(char const * input, std::size_t size, std::size_t offset)
97 unsigned char const * unsigned_input = reinterpret_cast<unsigned char const *>(input + offset);
98 ulong output = 0;
99 if(size)
101 for(unsigned char const * i = unsigned_input + size - 1, * end = unsigned_input; i >= end; --i)
103 output <<= bits_per_byte;
104 output |= static_cast<ulong>(*i);
107 return output;
110 ulong read_big_endian_bits(char const * data, std::size_t bit_count, std::size_t offset)
112 ulong output = 0;
113 for(std::size_t i = 0; i < bit_count; i++)
115 output <<= 1;
116 output |= get_bit(data, offset + i);
118 return output;
121 ulong read_little_endian_bits(char const * data, std::size_t bit_count, std::size_t offset)
123 ulong output = 0;
124 for(std::size_t i = 0; i < bit_count; i++)
125 output |= get_bit(data, offset + i) << i;
126 return output;
129 void write_big_endian(ulong input, char * output, std::size_t size)
131 if(size)
133 for(char * i = output + size - 1; i >= output; --i)
135 *i = (char)input;
136 input >>= bits_per_byte;
141 void write_little_endian(ulong input, char * output, std::size_t size)
143 if(size)
145 for(char * i = output, * end = output + size; i < end; ++i)
147 *i = (char)input;
148 input >>= bits_per_byte;
153 std::string big_endian_string(ulong input, std::size_t size)
155 char * buffer = new char[size];
156 write_big_endian(input, buffer, size);
157 std::string output = std::string(buffer, size);
158 delete buffer;
159 return output;
162 std::string little_endian_string(ulong input, std::size_t size)
164 char * buffer = new char[size];
165 write_little_endian(input, buffer, size);
166 std::string output = std::string(buffer, size);
167 delete buffer;
168 return output;
171 ulong get_bit(char const * data, std::size_t offset)
173 std::size_t byte = offset / bits_per_byte;
174 std::size_t bit = offset % bits_per_byte;
175 return (data[byte] >> bit) & 1;