Skip to content

Commit 2c16841

Browse files
committed
Direct copy io_interface files
1 parent 3f5186c commit 2c16841

File tree

9 files changed

+429
-0
lines changed

9 files changed

+429
-0
lines changed

src/ystdlib/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
add_subdirectory(containers)
22
add_subdirectory(error_handling)
3+
add_subdirectory(io_interface)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
cpp_library(
2+
NAME io_interface
3+
NAMESPACE ystdlib
4+
PUBLIC_HEADERS
5+
ErrorCode.hpp
6+
ReaderInterface.hpp
7+
WriterInterface.hpp
8+
PRIVATE_SOURCES
9+
ReaderInterface.cpp
10+
WriterInterface.cpp
11+
TESTS_SOURCES
12+
test/test_ReaderInterface.cpp
13+
test/test_WriterInterface.cpp
14+
)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#ifndef YSTDLIB_IO_INTERFACE_ERRORCODE_HPP
2+
#define YSTDLIB_IO_INTERFACE_ERRORCODE_HPP
3+
4+
namespace ystdlib::io_interface {
5+
typedef enum {
6+
ErrorCode_Success = 0,
7+
ErrorCode_BadParam,
8+
ErrorCode_BadParam_DB_URI,
9+
ErrorCode_Corrupt,
10+
ErrorCode_errno,
11+
ErrorCode_EndOfFile,
12+
ErrorCode_FileExists,
13+
ErrorCode_FileNotFound,
14+
ErrorCode_NoMem,
15+
ErrorCode_NotInit,
16+
ErrorCode_NotReady,
17+
ErrorCode_OutOfBounds,
18+
ErrorCode_TooLong,
19+
ErrorCode_Truncated,
20+
ErrorCode_Unsupported,
21+
ErrorCode_NoAccess,
22+
ErrorCode_Failure,
23+
ErrorCode_Failure_Metadata_Corrupted,
24+
ErrorCode_MetadataCorrupted,
25+
ErrorCode_Failure_DB_Bulk_Write,
26+
ErrorCode_Failure_Network,
27+
} ErrorCode;
28+
} // namespace ystdlib::io_interface
29+
30+
#endif // YSTDLIB_IO_INTERFACE_ERRORCODE_HPP
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
#include "ReaderInterface.hpp"
2+
3+
using std::string;
4+
5+
namespace ystdlib::io_interface {
6+
ErrorCode ReaderInterface::try_read_to_delimiter(
7+
char delim,
8+
bool keep_delimiter,
9+
bool append,
10+
std::string& str
11+
) {
12+
if (false == append) {
13+
str.clear();
14+
}
15+
16+
size_t original_str_length = str.length();
17+
18+
// Read character by character into str, until we find a delimiter
19+
char c;
20+
size_t num_bytes_read;
21+
while (true) {
22+
auto error_code = try_read(&c, 1, num_bytes_read);
23+
if (ErrorCode_Success != error_code) {
24+
if (ErrorCode_EndOfFile == error_code && str.length() > original_str_length) {
25+
return ErrorCode_Success;
26+
}
27+
return error_code;
28+
}
29+
30+
if (delim == c) {
31+
break;
32+
}
33+
34+
str += c;
35+
}
36+
37+
// Add delimiter if necessary
38+
if (keep_delimiter) {
39+
str += delim;
40+
}
41+
42+
return ErrorCode_Success;
43+
}
44+
45+
bool ReaderInterface::read(char* buf, size_t num_bytes_to_read, size_t& num_bytes_read) {
46+
ErrorCode error_code = try_read(buf, num_bytes_to_read, num_bytes_read);
47+
if (ErrorCode_EndOfFile == error_code) {
48+
return false;
49+
}
50+
if (ErrorCode_Success != error_code) {
51+
throw OperationFailed(error_code);
52+
}
53+
return true;
54+
}
55+
56+
bool ReaderInterface::read_to_delimiter(char delim, bool keep_delimiter, bool append, string& str) {
57+
ErrorCode error_code = try_read_to_delimiter(delim, keep_delimiter, append, str);
58+
if (ErrorCode_EndOfFile == error_code) {
59+
return false;
60+
}
61+
if (ErrorCode_Success != error_code) {
62+
throw OperationFailed(error_code);
63+
}
64+
65+
return true;
66+
}
67+
68+
ErrorCode ReaderInterface::try_read_exact_length(char* buf, size_t num_bytes) {
69+
size_t num_bytes_read;
70+
auto error_code = try_read(buf, num_bytes, num_bytes_read);
71+
if (ErrorCode_Success != error_code) {
72+
return error_code;
73+
}
74+
if (num_bytes_read < num_bytes) {
75+
return ErrorCode_Truncated;
76+
}
77+
78+
return ErrorCode_Success;
79+
}
80+
81+
bool ReaderInterface::read_exact_length(char* buf, size_t num_bytes, bool eof_possible) {
82+
ErrorCode error_code = try_read_exact_length(buf, num_bytes);
83+
if (eof_possible && ErrorCode_EndOfFile == error_code) {
84+
return false;
85+
}
86+
if (ErrorCode_Success != error_code) {
87+
throw OperationFailed(error_code);
88+
}
89+
return true;
90+
}
91+
92+
ErrorCode ReaderInterface::try_read_string(size_t const str_length, string& str) {
93+
// Resize string to fit str_length
94+
str.resize(str_length);
95+
96+
return try_read_exact_length(&str[0], str_length);
97+
}
98+
99+
bool ReaderInterface::read_string(size_t const str_length, string& str, bool eof_possible) {
100+
ErrorCode error_code = try_read_string(str_length, str);
101+
if (eof_possible && ErrorCode_EndOfFile == error_code) {
102+
return false;
103+
}
104+
if (ErrorCode_Success != error_code) {
105+
throw OperationFailed(error_code);
106+
}
107+
return true;
108+
}
109+
110+
void ReaderInterface::seek_from_begin(size_t pos) {
111+
ErrorCode error_code = try_seek_from_begin(pos);
112+
if (ErrorCode_Success != error_code) {
113+
throw OperationFailed(error_code);
114+
}
115+
}
116+
117+
size_t ReaderInterface::get_pos() {
118+
size_t pos;
119+
ErrorCode error_code = try_get_pos(pos);
120+
if (ErrorCode_Success != error_code) {
121+
throw OperationFailed(error_code);
122+
}
123+
124+
return pos;
125+
}
126+
} // namespace ystdlib::io_interface
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
#ifndef YSTDLIB_IO_INTERFACE_READERINTERFACE_HPP
2+
#define YSTDLIB_IO_INTERFACE_READERINTERFACE_HPP
3+
4+
#include <cstddef>
5+
#include <string>
6+
7+
#include "ErrorCode.hpp"
8+
9+
namespace ystdlib::io_interface {
10+
class ReaderInterface {
11+
public:
12+
// Types
13+
class OperationFailed : public std::exception {
14+
public:
15+
OperationFailed(ErrorCode error_code) {}
16+
};
17+
18+
// Destructor
19+
virtual ~ReaderInterface() = default;
20+
21+
// Methods
22+
virtual ErrorCode try_read(char* buf, size_t num_bytes_to_read, size_t& num_bytes_read) = 0;
23+
virtual ErrorCode try_seek_from_begin(size_t pos) = 0;
24+
virtual ErrorCode try_get_pos(size_t& pos) = 0;
25+
26+
/**
27+
* Tries to read up to the next delimiter and stores it in the given string.
28+
* NOTE: Implementations should override this if they can achieve better performance.
29+
* @param delim The delimiter to stop at
30+
* @param keep_delimiter Whether to include the delimiter in the output string or not
31+
* @param append Whether to append to the given string or replace its contents
32+
* @param str The string read
33+
* @return ErrorCode_Success on success
34+
* @return Same as ReaderInterface::try_read otherwise
35+
*/
36+
virtual ErrorCode
37+
try_read_to_delimiter(char delim, bool keep_delimiter, bool append, std::string& str);
38+
39+
/**
40+
* Reads up to a given number of bytes
41+
* @param buf
42+
* @param num_bytes_to_read The number of bytes to try and read
43+
* @param num_bytes_read The actual number of bytes read
44+
* @return false on EOF
45+
* @return true otherwise
46+
*/
47+
bool read(char* buf, size_t num_bytes_to_read, size_t& num_bytes_read);
48+
49+
/**
50+
* Reads up to the next delimiter and stores it in the given string
51+
* @param delim The delimiter to stop at
52+
* @param keep_delimiter Whether to include the delimiter in the output string or not
53+
* @param append Whether to append to the given string or replace its contents
54+
* @param str The string read
55+
* @return false on EOF
56+
* @return true on success
57+
*/
58+
bool read_to_delimiter(char delim, bool keep_delimiter, bool append, std::string& str);
59+
60+
/**
61+
* Tries to read a number of bytes
62+
* @param buf
63+
* @param num_bytes Number of bytes to read
64+
* @return Same as the underlying medium's try_read method
65+
* @return ErrorCode_Truncated if 0 < # bytes read < num_bytes
66+
*/
67+
ErrorCode try_read_exact_length(char* buf, size_t num_bytes);
68+
/**
69+
* Reads a number of bytes
70+
* @param buf
71+
* @param num_bytes Number of bytes to read
72+
* @param eof_possible If EOF should be possible (without reading any bytes)
73+
* @return false if EOF is possible and EOF was hit
74+
* @return true on success
75+
*/
76+
bool read_exact_length(char* buf, size_t num_bytes, bool eof_possible);
77+
78+
/**
79+
* Tries to read a numeric value from a file
80+
* @param value The read value
81+
* @return Same as FileReader::try_read_exact_length's return values
82+
*/
83+
template <typename ValueType>
84+
ErrorCode try_read_numeric_value(ValueType& value);
85+
/**
86+
* Reads a numeric value
87+
* @param value The read value
88+
* @param eof_possible If EOF should be possible (without reading any bytes)
89+
* @return false if EOF is possible and EOF was hit
90+
* @return true on success
91+
*/
92+
template <typename ValueType>
93+
bool read_numeric_value(ValueType& value, bool eof_possible);
94+
95+
/**
96+
* Tries to read a string
97+
* @param str_length
98+
* @param str The string read
99+
* @return Same as ReaderInterface::try_read_exact_length
100+
*/
101+
ErrorCode try_read_string(size_t str_length, std::string& str);
102+
/**
103+
* Reads a string
104+
* @param str_length
105+
* @param str The string read
106+
* @param eof_possible If EOF should be possible (without reading any bytes)
107+
* @return false if EOF is possible and EOF was hit
108+
* @return true on success
109+
*/
110+
bool read_string(size_t str_length, std::string& str, bool eof_possible);
111+
112+
/**
113+
* Seeks from the beginning to the given position
114+
* @param pos
115+
*/
116+
void seek_from_begin(size_t pos);
117+
118+
/**
119+
* Gets the current position of the read head
120+
* @return Position of the read head
121+
*/
122+
size_t get_pos();
123+
};
124+
125+
template <typename ValueType>
126+
ErrorCode ReaderInterface::try_read_numeric_value(ValueType& value) {
127+
ErrorCode error_code = try_read_exact_length(reinterpret_cast<char*>(&value), sizeof(value));
128+
if (ErrorCode_Success != error_code) {
129+
return error_code;
130+
}
131+
return ErrorCode_Success;
132+
}
133+
134+
template <typename ValueType>
135+
bool ReaderInterface::read_numeric_value(ValueType& value, bool eof_possible) {
136+
ErrorCode error_code = try_read_numeric_value(value);
137+
if (ErrorCode_EndOfFile == error_code && eof_possible) {
138+
return false;
139+
}
140+
if (ErrorCode_Success != error_code) {
141+
throw OperationFailed(error_code);
142+
}
143+
return true;
144+
}
145+
} // namespace ystdlib::io_interface
146+
147+
#endif // YSTDLIB_IO_INTERFACE_READERINTERFACE_HPP
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#include "WriterInterface.hpp"
2+
3+
namespace ystdlib::io_interface {
4+
void WriterInterface::write_char(char c) {
5+
write(&c, 1);
6+
}
7+
8+
void WriterInterface::write_string(std::string const& str) {
9+
write(str.c_str(), str.length());
10+
}
11+
12+
void WriterInterface::seek_from_begin(size_t pos) {
13+
auto error_code = try_seek_from_begin(pos);
14+
if (ErrorCode_Success != error_code) {
15+
throw OperationFailed(error_code);
16+
}
17+
}
18+
19+
void WriterInterface::seek_from_current(off_t offset) {
20+
auto error_code = try_seek_from_current(offset);
21+
if (ErrorCode_Success != error_code) {
22+
throw OperationFailed(error_code);
23+
}
24+
}
25+
26+
size_t WriterInterface::get_pos() const {
27+
size_t pos;
28+
ErrorCode error_code = try_get_pos(pos);
29+
if (ErrorCode_Success != error_code) {
30+
throw OperationFailed(error_code);
31+
}
32+
33+
return pos;
34+
}
35+
} // namespace ystdlib::io_interface

0 commit comments

Comments
 (0)