Skip to content

Commit c89db17

Browse files
committed
Move common stream bits to new kio base class.
1 parent 4786651 commit c89db17

File tree

5 files changed

+323
-255
lines changed

5 files changed

+323
-255
lines changed

CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,19 @@ endif()
1818
set (HEADERS
1919
kaitai/kaitaistream.h
2020
kaitai/kaitaistruct.h
21+
kaitai/kio.h
2122
kaitai/kistream.h
2223
)
2324

2425
set (SOURCES
26+
kaitai/kio.cpp
2527
kaitai/kistream.cpp
2628
)
2729

2830
set(STRING_ENCODING_TYPE "ICONV" CACHE STRING "Set the way strings have to be encoded (ICONV|NONE|...)")
2931

3032
add_library (${PROJECT_NAME} SHARED ${HEADERS} ${SOURCES})
31-
set_target_properties(${PROJECT_NAME} PROPERTIES PUBLIC_HEADER "kaitai/kaitaistream.h;kaitai/kaitaistruct.h;kaitai/kistream.h")
33+
set_target_properties(${PROJECT_NAME} PROPERTIES PUBLIC_HEADER "kaitai/kaitaistream.h;kaitai/kaitaistruct.h;kaitai/kio.h;kaitai/kistream.h")
3234

3335
if (ZLIB_FOUND)
3436
target_include_directories(${PROJECT_NAME} PRIVATE ${ZLIB_INCLUDE_DIRS})

kaitai/kio.cpp

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
#include <kaitai/kio.h>
2+
3+
#include <iostream>
4+
#include <stdexcept>
5+
6+
kaitai::kio::kio() {
7+
}
8+
9+
kaitai::kio::kio(std::ios* io) {
10+
init(io);
11+
}
12+
13+
void kaitai::kio::init(std::ios* io) {
14+
m_io = io;
15+
exceptions_enable();
16+
}
17+
18+
void kaitai::kio::close() {
19+
// m_io->close();
20+
}
21+
22+
void kaitai::kio::exceptions_enable() const {
23+
m_io->exceptions(
24+
std::ios::eofbit |
25+
std::ios::failbit |
26+
std::ios::badbit
27+
);
28+
}
29+
30+
// ========================================================================
31+
// Byte arrays
32+
// ========================================================================
33+
34+
std::string kaitai::kio::bytes_strip_right(std::string src, char pad_byte) {
35+
std::size_t new_len = src.length();
36+
37+
while (new_len > 0 && src[new_len - 1] == pad_byte)
38+
new_len--;
39+
40+
return src.substr(0, new_len);
41+
}
42+
43+
std::string kaitai::kio::bytes_terminate(std::string src, char term, bool include) {
44+
std::size_t new_len = 0;
45+
std::size_t max_len = src.length();
46+
47+
while (new_len < max_len && src[new_len] != term)
48+
new_len++;
49+
50+
if (include && new_len < max_len)
51+
new_len++;
52+
53+
return src.substr(0, new_len);
54+
}
55+
56+
// ========================================================================
57+
// Byte array processing
58+
// ========================================================================
59+
60+
std::string kaitai::kio::process_xor_one(std::string data, uint8_t key) {
61+
size_t len = data.length();
62+
std::string result(len, ' ');
63+
64+
for (size_t i = 0; i < len; i++)
65+
result[i] = data[i] ^ key;
66+
67+
return result;
68+
}
69+
70+
std::string kaitai::kio::process_xor_many(std::string data, std::string key) {
71+
size_t len = data.length();
72+
size_t kl = key.length();
73+
std::string result(len, ' ');
74+
75+
size_t ki = 0;
76+
for (size_t i = 0; i < len; i++) {
77+
result[i] = data[i] ^ key[ki];
78+
ki++;
79+
if (ki >= kl)
80+
ki = 0;
81+
}
82+
83+
return result;
84+
}
85+
86+
std::string kaitai::kio::process_rotate_left(std::string data, int amount) {
87+
size_t len = data.length();
88+
std::string result(len, ' ');
89+
90+
for (size_t i = 0; i < len; i++) {
91+
uint8_t bits = data[i];
92+
result[i] = (bits << amount) | (bits >> (8 - amount));
93+
}
94+
95+
return result;
96+
}
97+
98+
// ========================================================================
99+
// Misc utility methods
100+
// ========================================================================
101+
102+
int kaitai::kio::mod(int a, int b) {
103+
if (b <= 0)
104+
throw std::invalid_argument("mod: divisor b <= 0");
105+
int r = a % b;
106+
if (r < 0)
107+
r += b;
108+
return r;
109+
}
110+
111+
#include <stdio.h>
112+
std::string kaitai::kio::to_string(int val) {
113+
// if int is 32 bits, "-2147483648" is the longest string representation
114+
// => 11 chars + zero => 12 chars
115+
// if int is 64 bits, "-9223372036854775808" is the longest
116+
// => 20 chars + zero => 21 chars
117+
char buf[25];
118+
int got_len = snprintf(buf, sizeof(buf), "%d", val);
119+
120+
// should never happen, but check nonetheless
121+
if (got_len > sizeof(buf))
122+
throw std::invalid_argument("to_string: integer is longer than string buffer");
123+
124+
return std::string(buf);
125+
}
126+
127+
#include <algorithm>
128+
std::string kaitai::kio::reverse(std::string val) {
129+
std::reverse(val.begin(), val.end());
130+
131+
return val;
132+
}
133+
134+
// ========================================================================
135+
// Other internal methods
136+
// ========================================================================
137+
138+
uint64_t kaitai::kio::get_mask_ones(int n) {
139+
if (n == 64) {
140+
return 0xFFFFFFFFFFFFFFFF;
141+
} else {
142+
return ((uint64_t) 1 << n) - 1;
143+
}
144+
}
145+
146+
#ifndef KS_STR_DEFAULT_ENCODING
147+
#define KS_STR_DEFAULT_ENCODING "UTF-8"
148+
#endif
149+
150+
#ifdef KS_STR_ENCODING_ICONV
151+
152+
#include <iconv.h>
153+
#include <cerrno>
154+
#include <stdexcept>
155+
156+
std::string kaitai::kio::bytes_to_str(std::string src, std::string src_enc) {
157+
iconv_t cd = iconv_open(KS_STR_DEFAULT_ENCODING, src_enc.c_str());
158+
159+
if (cd == (iconv_t) -1) {
160+
if (errno == EINVAL) {
161+
throw std::runtime_error("bytes_to_str: invalid encoding pair conversion requested");
162+
} else {
163+
throw std::runtime_error("bytes_to_str: error opening iconv");
164+
}
165+
}
166+
167+
size_t src_len = src.length();
168+
size_t src_left = src_len;
169+
170+
// Start with a buffer length of double the source length.
171+
size_t dst_len = src_len * 2;
172+
std::string dst(dst_len, ' ');
173+
size_t dst_left = dst_len;
174+
175+
char *src_ptr = &src[0];
176+
char *dst_ptr = &dst[0];
177+
178+
while (true) {
179+
size_t res = iconv(cd, &src_ptr, &src_left, &dst_ptr, &dst_left);
180+
181+
if (res == (size_t) -1) {
182+
if (errno == E2BIG) {
183+
// dst buffer is not enough to accomodate whole string
184+
// enlarge the buffer and try again
185+
size_t dst_used = dst_len - dst_left;
186+
dst_left += dst_len;
187+
dst_len += dst_len;
188+
dst.resize(dst_len);
189+
190+
// dst.resize might have allocated destination buffer in another area
191+
// of memory, thus our previous pointer "dst" will be invalid; re-point
192+
// it using "dst_used".
193+
dst_ptr = &dst[dst_used];
194+
} else {
195+
throw std::runtime_error("bytes_to_str: iconv error");
196+
}
197+
} else {
198+
// conversion successful
199+
dst.resize(dst_len - dst_left);
200+
break;
201+
}
202+
}
203+
204+
if (iconv_close(cd) != 0) {
205+
throw std::runtime_error("bytes_to_str: iconv close error");
206+
}
207+
208+
return dst;
209+
}
210+
#elif defined(KS_STR_ENCODING_NONE)
211+
std::string kaitai::kio::bytes_to_str(std::string src, std::string src_enc) {
212+
return src;
213+
}
214+
#else
215+
#error Need to decide how to handle strings: please define one of: KS_STR_ENCODING_ICONV, KS_STR_ENCODING_NONE
216+
#endif

kaitai/kio.h

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
#ifndef KAITAI_KIO_H
2+
#define KAITAI_KIO_H
3+
4+
#include <iostream>
5+
#include <stdint.h>
6+
7+
namespace kaitai {
8+
9+
class kio {
10+
public:
11+
kio(std::ios* io);
12+
13+
void close();
14+
15+
/** @name Byte arrays */
16+
//@{
17+
18+
static std::string bytes_strip_right(std::string src, char pad_byte);
19+
static std::string bytes_terminate(std::string src, char term, bool include);
20+
static std::string bytes_to_str(std::string src, std::string src_enc);
21+
22+
//@}
23+
24+
/** @name Byte array processing */
25+
//@{
26+
27+
/**
28+
* Performs a XOR processing with given data, XORing every byte of input with a single
29+
* given value.
30+
* @param data data to process
31+
* @param key value to XOR with
32+
* @return processed data
33+
*/
34+
static std::string process_xor_one(std::string data, uint8_t key);
35+
36+
/**
37+
* Performs a XOR processing with given data, XORing every byte of input with a key
38+
* array, repeating key array many times, if necessary (i.e. if data array is longer
39+
* than key array).
40+
* @param data data to process
41+
* @param key array of bytes to XOR with
42+
* @return processed data
43+
*/
44+
static std::string process_xor_many(std::string data, std::string key);
45+
46+
/**
47+
* Performs a circular left rotation shift for a given buffer by a given amount of bits,
48+
* using groups of 1 bytes each time. Right circular rotation should be performed
49+
* using this procedure with corrected amount.
50+
* @param data source data to process
51+
* @param amount number of bits to shift by
52+
* @return copy of source array with requested shift applied
53+
*/
54+
static std::string process_rotate_left(std::string data, int amount);
55+
56+
//@}
57+
58+
/**
59+
* Performs modulo operation between two integers: dividend `a`
60+
* and divisor `b`. Divisor `b` is expected to be positive. The
61+
* result is always 0 <= x <= b - 1.
62+
*/
63+
static int mod(int a, int b);
64+
65+
/**
66+
* Converts given integer `val` to a decimal string representation.
67+
* Should be used in place of std::to_string() (which is available only
68+
* since C++11) in older C++ implementations.
69+
*/
70+
static std::string to_string(int val);
71+
72+
/**
73+
* Reverses given string `val`, so that the first character becomes the
74+
* last and the last one becomes the first. This should be used to avoid
75+
* the need of local variables at the caller.
76+
*/
77+
static std::string reverse(std::string val);
78+
79+
protected:
80+
/**
81+
* This constructor allows initialization to be deferred. This is needed
82+
* for when the stream is constructed in the derived class, since it will
83+
* not be able to construct it before constructing kaitai::kio.
84+
*/
85+
kio();
86+
87+
void init(std::ios* io);
88+
89+
static uint64_t get_mask_ones(int n);
90+
91+
void exceptions_enable() const;
92+
93+
private:
94+
std::ios* m_io;
95+
};
96+
97+
}
98+
99+
#endif

0 commit comments

Comments
 (0)