Jackalope / jlib (public) (License: GPLv3 or later) (since 2019-11-18) (hash sha1)
jlib C++ template library
Used to replace std functionality without exception handling.
- data structures
- filesystem routines
- crossplatform threads interface (currently only pthreads implementation)
- thread pool
- crossplatform dynamic memory functions interface (allocate, reallocate, deallocate) with alignment support
- high percision timer routines based on timespec
List of commits:
Subject Hash Author Date (UTC)
io_agent interface and etalon realizations 4464bf88e4da18966ad522709f7490c15d3fd3d0 Your Name 2019-11-21 19:33:31
dynamic array bug fixes a558181cb2c9f3e76e928de8be74684e0c14baa2 Your Name 2019-11-21 19:32:37
deallocate func bug fixed b7b6aa7595db24836e78f892cdce9ffa78b15bf8 Your Name 2019-11-21 19:31:53
added dots =) 5272ca044750a014547db3edcde79e2fe6dbb6ca Your Name 2019-11-21 13:59:21
disabled man generation by doxygen 6dbfdbe48c16b07bd8afc247ae2fa995f56a5332 Your Name 2019-11-21 13:39:46
function commentary improved 791e5df05a5bf6acb18984b5d31260e7f9718466 Your Name 2019-11-21 13:38:54
DynamicArray_sorted instert function bug fix 7677fded3f22300d92a497d787b135a2e7ac988a Your Name 2019-11-20 21:25:15
moved doxygen search path 245fc569f64ae36e7fc8ab93ea954e98696512ed Your Name 2019-11-20 19:02:23
renamed jtl to jlib and namespace jl 343794453e4b4643cb53d01d8fde4a2e75d6bdc1 Your Name 2019-11-20 18:53:58
disabled doxygen sorting e23e48587d14715bc4b2b44ac5d0016525bc1a0d Your Name 2019-11-20 18:45:03
documentation improved by tags 63f7874b0f9d9864a39f408478f56fc5a3c114d2 Your Name 2019-11-20 18:10:30
added doxygen to gitignore 7dff94b8d776d61b9a48b1fbbd8cd6116ec600c0 Your Name 2019-11-20 00:20:22
doxygen documentation 8d1302091cb159975bee74ab8d011d2d21e6ade2 Your Name 2019-11-20 00:13:57
this file no need 571e8c3919e7aef0b7a6d5c1ddccb115d76eb238 Your Name 2019-11-20 00:13:41
fixed forgotten args for call 08bc90ed1322b77548e8693188663ac7c49b5953 Your Name 2019-11-19 20:55:46
dynamic array modifications e072bcf5cb0e9a95f097b6186db845ed5dec0e16 Your Name 2019-11-19 17:42:59
removed CallInfo e75341700184671df5d87b4d09fdbc51f338b9e7 Your Name 2019-11-19 17:42:39
binary search functions df03aebc3f0c64a1406277d98153faf646780707 Your Name 2019-11-19 17:41:11
jtl allocate b6168118b52e446bdf2f8bfe9506783c8ce9be1c Your Name 2019-11-19 08:51:51
added CallMod enums typedefs to cleaner argument view 3ad1e61b19a1522c92a7f5ff6f8d5c08e4f7b13c Your Name 2019-11-18 22:03:37
Commit 4464bf88e4da18966ad522709f7490c15d3fd3d0 - io_agent interface and etalon realizations
Author: Your Name
Author date (UTC): 2019-11-21 19:33
Committer name: Your Name
Committer date (UTC): 2019-11-21 19:33
Parent(s): a558181cb2c9f3e76e928de8be74684e0c14baa2
Signer:
Signing key:
Signing status: N
Tree: 7a901318c2c650447d0f24f4e1d2fc0fae8791d1
File Lines added Lines deleted
CMakeLists.txt 2 2
include/jlib/io_agent.h 75 0
include/jlib/io_agent_memory.h 250 0
include/jlib/io_agent_memory_ro.h 83 0
File CMakeLists.txt changed (mode: 100644) (index 24b0a0d..e2645eb)
1 1 cmake_minimum_required(VERSION 3.5) cmake_minimum_required(VERSION 3.5)
2 2
3 set(JLIB_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE)
4 set(JLIB_SOURCES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src PARENT_SCOPE)
3 set(JLIB_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE)
4 set(JLIB_SOURCES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src PARENT_SCOPE)
File include/jlib/io_agent.h added (mode: 100644) (index 0000000..49c2d1e)
1 /**
2 * @file io_agent.h
3 * @brief IO_Agent interface declaration.
4 */
5
6 #pragma once
7
8 #include <cinttypes>
9
10 namespace jl
11 {
12 /**
13 * @brief IO_Agent interface declaration.
14 *
15 * Interface realizations will act as mediator between user and client.
16 * The point of this interface is that client dont need to know how get to data and where from.
17 *
18 * Example of usage:
19 * @code
20 * template<typename IO_Provider>
21 * [[nodiscard]] bool SomeType::read_some_data_from_something_by_IO_provider(IO_Provider *p_prov)
22 * {
23 * return p_prov->read(this->p_data, this->data_size) == data_size;
24 * }
25 * @endcode
26 *
27 * @see IO_AgentMemoryRO
28 * @see IO_AgentMemory
29 *
30 //TODO @todo make strong template check to insure that only IO_Agent inheritance will be used as template argument
31 */
32 struct IO_Agent
33 {
34 /**
35 * @brief Read data from IO_Agent.
36 *
37 * Position will be automatically moved by returned number of bytes, if -1 not is returned.
38 *
39 * @param[out] p_dst Pointer to memory for reading to with at least size number of bytes.
40 * @param[in] size Size of data to read.
41 *
42 * @return -1 on error or number of bytes written to p_dst.
43 */
44 [[nodiscard]] int64_t read( void *p_dst, uint64_t size);
45
46 /**
47 * @brief Write data to IO_Agent.
48 *
49 * Position will be automatically moved by returned number of bytes, if -1 not is returned.
50 *
51 * @param[in] p_src Pointer to memory for writing from with at least size number of bytes.
52 * @param[in] size Size of data to read.
53 *
54 * @return -1 on error or number of bytes readed from p_src.
55 */
56 [[nodiscard]] int64_t write(const void *p_src, uint64_t size);
57
58 /**
59 * @brief move position for read/write.
60 *
61 * @param[in] relative_offset Positive or negative offset in bytes to move position.
62 *
63 * @return True if position moved, false overwise.
64 */
65 [[nodiscard]] bool position_move(int64_t relative_offset);
66
67
68 /**
69 * @brief Get info if position is at end.
70 *
71 * @return True if position at end, false overwise.
72 */
73 [[nodiscard]] bool is_end() const;
74 };
75 }
File include/jlib/io_agent_memory.h added (mode: 100644) (index 0000000..1dbd007)
1 /**
2 * @file io_agent_memory.h
3 * @brief IO_Agent_Memory realization of IO_Agent interface.
4 */
5
6 #pragma once
7
8 #include "io_agent.h"
9 #include "dynamic_array.h"
10
11 namespace jl
12 {
13 /**
14 * @brief IO_AgentMemory based on IO_Agent interface
15 *
16 * Uses dynamic array of fixed-size memory pools.
17 *
18 * Before using need to call IO_Agent_Memory::init function,
19 * overwise all functions will have an undefined behaviour.
20 *
21 * @tparam ALLOCATION_SIZE Size of single memory pool
22 *
23 * @see IO_Agent
24 * @see IO_AgentMemory::init
25 * @see IO_AgentMemory::destroy
26 * @see IO_AgentMemory::Pos
27 */
28 template<uint64_t ALLOCATION_SIZE = 1024 * 1024>
29 struct IO_AgentMemory : IO_Agent
30 {
31 /**
32 * @brief Initialize IO_AgentMemory with defined state.
33 */
34 void init()
35 {
36 memory.init();
37 pos = end = {};
38 }
39
40 /**
41 * @brief Destroy all memory pools in IO_Agent_Memory
42 */
43 void destroy()
44 {
45 memory.destroy<Call::DEALLOCATE>();
46 init();
47 }
48
49 /**
50 * @brief Read data from agent.
51 *
52 * @see IO_Agent::read
53 */
54 [[nodiscard]] int64_t read(void *dst, uint64_t size)
55 {
56 uint8_t *p_dst = reinterpret_cast<uint8_t*>(dst);
57 int64_t readed = 0;
58
59 while (size > 0)
60 {
61 uint64_t part_read_left = part_read_size_left();
62 if (part_read_left == 0)
63 return readed;
64
65 uint64_t to_write = size;
66 if (to_write > part_read_left)
67 to_write = part_read_left;
68
69 memcpy(p_dst, memory[pos.mem_i] + pos.offset, to_write);
70 p_dst += to_write;
71 readed += to_write;
72 pos.offset += to_write;
73 if (pos.offset >= ALLOCATION_SIZE)
74 {
75 ++pos.mem_i, pos.offset -= ALLOCATION_SIZE;
76 if (pos.mem_i >= memory.count())
77 return readed;
78 }
79
80 size -= to_write;
81 }
82 return readed;
83 }
84
85 /**
86 * @brief Write data to agent.
87 *
88 * @see IO_Agent::write
89 */
90 [[nodiscard]] int64_t write(const void *src, uint64_t size)
91 {
92 int64_t total_size = int64_t(size);
93 uint64_t size_left = this->write_size_left();
94 if (size > size_left)
95 {
96 uint64_t size_to_allocate = size - size_left;
97
98 uint64_t allocate_count = size_to_allocate / ALLOCATION_SIZE
99 + (size_to_allocate % ALLOCATION_SIZE > 0);
100
101 uint64_t start = memory.count();
102 if (not memory.insert_and_call_items<Call::CONSTRUCTOR>(allocate_count))
103 return -1;
104 for (uint64_t i = start; i < memory.count(); ++i)
105 {
106 if (not allocate_bytes(&memory[i], ALLOCATION_SIZE))
107 {
108 for (uint64_t j = start; j < i; ++j)
109 free(memory[j]);
110 return -1;
111 }
112 }
113 }
114
115 const uint8_t *p_src = reinterpret_cast<const uint8_t*>(src);
116
117 while (size > 0)
118 {
119 uint64_t to_write = this->part_write_size_left();
120 if (to_write < size)
121 to_write = size;
122
123 memcpy(memory[pos.mem_i] + pos.offset, p_src, to_write);
124 p_src += to_write;
125 pos.offset += to_write;
126 if (pos.offset >= ALLOCATION_SIZE)
127 ++pos.mem_i, pos.offset -= ALLOCATION_SIZE;
128 size -= to_write;
129 }
130 if (pos > end)
131 end = pos;
132 return total_size;
133 }
134
135 /**
136 * @brief Move position of memory to read/write.
137 *
138 * @see IO_Agent::position_move
139 */
140 [[nodiscard]] bool position_move(int64_t byte_count)
141 {
142 if (byte_count < 0)
143 {
144 uint64_t mem_count = ALLOCATION_SIZE / uint64_t(-byte_count);
145 int64_t new_mem_i = int64_t(pos.mem_i - mem_count);
146 int64_t new_offset = int64_t(pos.offset - (uint64_t(-byte_count) - ALLOCATION_SIZE * mem_count));
147 if (new_offset < 0)
148 {
149 new_mem_i -= 1;
150 new_offset += ALLOCATION_SIZE;
151 }
152 if (new_mem_i < 0)
153 return false;
154
155 pos.mem_i = uint64_t(new_mem_i);
156 pos.offset = uint64_t(new_offset);
157 return true;
158 }
159 else
160 {
161 uint64_t mem_count = ALLOCATION_SIZE / uint64_t(byte_count);
162 uint64_t new_mem_i = pos.mem_i + mem_count;
163 uint64_t new_offset = pos.offset + (uint64_t(byte_count) - ALLOCATION_SIZE * mem_count);
164 if (new_offset >= ALLOCATION_SIZE)
165 {
166 new_mem_i += 1;
167 new_offset -= ALLOCATION_SIZE;
168 }
169 if (new_mem_i >= memory.count())
170 return false;
171
172 pos.mem_i = new_mem_i;
173 pos.offset = new_offset;
174 return true;
175 }
176 }
177
178 /**
179 * @brief Get if position is at end of last memory pool.
180 *
181 * @see IO_Agent::is_end
182 */
183 [[nodiscard]] bool is_end() const
184 {
185 return not (end > pos);
186 }
187
188 protected:
189 [[nodiscard]] uint64_t read_size_left() const
190 {
191 return (end - pos).size();
192 }
193 [[nodiscard]] uint64_t write_size_left() const
194 {
195 return (Pos{memory.count(), 0} - pos).size();
196 }
197
198 [[nodiscard]] uint64_t part_read_size_left() const
199 {
200 if (pos.mem_i == end.mem_i)
201 return end.offset - pos.offset;
202 return ALLOCATION_SIZE - pos.offset;
203 }
204
205 [[nodiscard]] uint64_t part_write_size_left() const
206 {
207 return ALLOCATION_SIZE - pos.offset;
208 }
209
210 [[nodiscard]] uint64_t size() const { return end.size(); }
211
212
213 /**
214 * @brief Position in IO_AgentMemory.
215 *
216 * @see IO_AgentMemory
217 */
218 struct Pos
219 {
220 [[nodiscard]] inline bool operator > (const Pos &o) const
221 {
222 return mem_i > o.mem_i || (mem_i == o.mem_i && offset > o.offset);
223 }
224 [[nodiscard]] inline Pos operator - (const Pos &o) const
225 {
226 Pos res;
227 res.mem_i = mem_i - o.mem_i;
228 if (o.offset > offset)
229 {
230 res.mem_i -= 1;
231 res.offset = ALLOCATION_SIZE - (o.offset - offset);
232 }
233 else res.offset = offset - o.offset;
234 return res;
235 }
236
237 [[nodiscard]] inline uint64_t size() const
238 {
239 return mem_i * ALLOCATION_SIZE + offset;
240 }
241
242 uint64_t mem_i; ///< @brief Index of array of memory pools in IO_AgentMemory.
243 uint64_t offset; ///< @brief Offset of memory pool, pointed by mem_i.
244 };
245
246 DynamicArray<uint8_t*> memory; ///< @brief Array of memory pools.
247 Pos end; ///< @brief Largest position written.
248 Pos pos; ///< @brief Position for reading and writing.
249 };
250 }
File include/jlib/io_agent_memory_ro.h added (mode: 100644) (index 0000000..c6c240c)
1 /**
2 * @file io_agent_memory_ro.h
3 * @brief IO_Agent_MemoryRO realization of IO_Agent interface.
4 */
5
6 #pragma once
7
8 #include "io_agent.h"
9
10 namespace jl
11 {
12 /**
13 * @brief IO_Agent_MemoryRO based on IO_Agent interface
14 *
15 * Uses constant-size raw memory only to read from.
16 *
17 * @see IO_Agent
18 */
19 struct IO_Agent_MemoryRO : IO_Agent
20 {
21 /**
22 * @brief Initialize agent by memory pool.
23 *
24 * @param[in] p_mem Pointer to memory for using as source for reading.
25 * @param[in] mem_size max count of bytes that can be accessed from memory.
26 */
27 void init(const void *p_mem, uint64_t mem_size)
28 {
29 p_memory = reinterpret_cast<const uint8_t*>(p_mem);
30 memory_size = mem_size;
31 position = 0;
32 }
33
34 /**
35 * @brief Read from memory pool.
36 *
37 * @see IO_Agent::read
38 */
39 [[nodiscard]] uint64_t read(void *p_dst, uint64_t size_to_read)
40 {
41 uint64_t memory_size_left = memory_size - position;
42 if (size_to_read > memory_size_left)
43 size_to_read = memory_size_left;
44 for (uint64_t i = 0; i < size_to_read; ++i)
45 reinterpret_cast<uint8_t*>(p_dst)[i] = p_memory[position+i];
46 position += size_to_read;
47 return size_to_read;
48 }
49
50 /**
51 * @brief Move position in memory pool.
52 *
53 * @see IO_Agent::position_move
54 */
55 [[nodiscard]] bool position_move(int64_t offset)
56 {
57 if (offset >= 0) {
58 if (position + uint64_t(offset) > memory_size)
59 return false;
60 }
61 else if (position < uint64_t(-offset))
62 return false;
63 position += uint64_t(offset);
64 return true;
65 }
66
67 /**
68 * @brief Get if position is at end of pool.
69 *
70 * @see IO_Agent::is_end
71 */
72 [[nodiscard]] bool is_end()
73 {
74 return position >= memory_size;
75 }
76
77 const uint8_t *p_memory; ///< @brief Pointer to memory pool.
78 uint64_t memory_size; ///< @brief Size of memory pool in bytes.
79 uint64_t position; ///< @brief Offset from beginning of memory pool for read/write operations.
80
81 [[nodiscard]] int64_t write(const void *src, uint64_t size) = delete;
82 };
83 }
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/Jackalope/jlib

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/Jackalope/jlib

Clone this repository using git:
git clone git://git.rocketgit.com/user/Jackalope/jlib

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main