* @param maxLength the maximal count of appended chars
* @return <code>*this</code> (chaining)
*/
-ReByteBuffer& ReByteBuffer::appendDump(const char* data, size_t length, int maxLength){
- if (length == size_t(-1)){
+ReByteBuffer& ReByteBuffer::appendDump(const char* data, size_t length,
+ int maxLength) {
+ if (length == size_t(-1)) {
length = strlen(data);
}
if ((int) length > maxLength)
// test if text or binary:
bool isBinary = false;
unsigned char cc;
- for (size_t ii = 0; ii < length; ii++){
- if ( (cc = (unsigned char) data[ii]) > 126
- || (cc < ' ' && cc != '\n' && cc != '\r' && cc != '\t')){
+ for (size_t ii = 0; ii < length; ii++) {
+ if ((cc = (unsigned char) data[ii]) > 126
+ || (cc < ' ' && cc != '\n' && cc != '\r' && cc != '\t')) {
isBinary = true;
break;
}
}
- if (! isBinary)
+ if (!isBinary)
append(data, length);
else
appendHexDump(data, min(length, maxLength / 5)).reduceLength();
* and the length is at least <code>minLength</code> bytes
*/
bool ReByteBuffer::isPrefixOf(const char* source, size_t length,
- bool ignoreCase, int minLength){
+ bool ignoreCase, int minLength) {
if (length == (size_t) -1)
length = strlen(source);
bool rc = length >= m_length && m_length <= length;
ReByteBuffer& append(const ReByteBuffer& source);
ReByteBuffer& append(double, const char* format = "%f");
/** Appends a 8 bit value in an architecture independent way.
- * @param value character to append
+ * @param value integer to append
* @return <code>*this</code> (for chaining)
*/
- inline ReByteBuffer& appendBits8(int value){
+ inline ReByteBuffer& appendBits8(int value) {
setLength(m_length + 1);
m_buffer[m_length - 1] = (char) value;
return *this;
}
/** Appends a 16 bit value in an architecture independent way.
- * @param value character to append
+ * @param value integer to append
* @return <code>*this</code> (for chaining)
*/
- inline ReByteBuffer& appendBits16(int value){
+ inline ReByteBuffer& appendBits16(int value) {
setLength(m_length + 2);
m_buffer[m_length - 2] = char(value >> 8);
m_buffer[m_length - 1] = char(value);
return *this;
}
/** Appends a 24 bit value in an architecture independent way.
- * @param value character to append
+ * @param value integer to append
* @return <code>*this</code> (for chaining)
*/
- inline ReByteBuffer& appendBits24(int value){
+ inline ReByteBuffer& appendBits24(int value) {
setLength(m_length + 3);
m_buffer[m_length - 3] = char(value >> 16);
m_buffer[m_length - 2] = char(value >> 8);
return *this;
}
/** Appends a 24 bit value in an architecture independent way.
- * @param value character to append
+ * @param value integer to append
* @return <code>*this</code> (for chaining)
*/
- inline ReByteBuffer& appendBits32(int value){
+ inline ReByteBuffer& appendBits32(int value) {
setLength(m_length + 4);
m_buffer[m_length - 4] = char(value >> 24);
m_buffer[m_length - 3] = char(value >> 16);
m_buffer[m_length - 1] = char(value);
return *this;
}
- /** Appends a 24 bit value in an architecture independent way.
- * @param value character to append
+ /** Appends a 64 bit value in an architecture independent way.
+ * @param value integer to append
* @return <code>*this</code> (for chaining)
*/
- inline ReByteBuffer& appendBits64(int64_t value){
+ inline ReByteBuffer& appendBits64(int64_t value) {
setLength(m_length + 8);
m_buffer[m_length - 8] = char(value >> 56);
m_buffer[m_length - 7] = char(value >> 48);
m_buffer[m_length - 1] = aChar;
return *this;
}
- /** Appends 2 characters.
- * @param char1 first character to append
- * @param char2 2nd character to append
- * @return <code>*this</code> (for chaining)
- */
- inline ReByteBuffer& appendChar2(char char1, char char2) {
- setLength(m_length + 2);
- m_buffer[m_length - 2] = char1;
- m_buffer[m_length - 1] = char2;
- return *this;
- }
- /** Appends 4 characters.
- * @param char1 first character to append
- * @param char2 2nd character to append
- * @param char3 3rd character to append
- * @param char4 4th character to append
- * @return <code>*this</code> (for chaining)
- */
- inline ReByteBuffer& appendChar(char char1, char char2, char char3, char char4) {
- setLength(m_length + 4);
- m_buffer[m_length - 4] = char1;
- m_buffer[m_length - 3] = char2;
- m_buffer[m_length - 2] = char3;
- m_buffer[m_length - 1] = char4;
- return *this;
- }
- /** Appends 4 characters.
- * @param char1 first character to append
- * @param char2 2nd character to append
- * @param char3 3rd character to append
- * @param char4 4th character to append
- * @return <code>*this</code> (for chaining)
- */
- inline ReByteBuffer& appendChar(char char1, char char2, char char3,
- char char4, char char5, char char6, char char7, char char8) {
- setLength(m_length + 8);
- m_buffer[m_length - 8] = char1;
- m_buffer[m_length - 7] = char2;
- m_buffer[m_length - 6] = char3;
- m_buffer[m_length - 5] = char4;
- m_buffer[m_length - 4] = char5;
- m_buffer[m_length - 3] = char6;
- m_buffer[m_length - 2] = char7;
- m_buffer[m_length - 1] = char8;
- return *this;
- }
/** Appends a character at least one time.
* @param aChar character to append
* @param count number of times to append
}
ReByteBuffer& appendFix(const char* data, size_t length, int maxLength,
int minLength = 0, const char* separator = "*", char padding = ' ');
- ReByteBuffer& appendDump(const char* data, size_t length = -1, int maxLength = 80);
+ ReByteBuffer& appendDump(const char* data, size_t length = -1,
+ int maxLength = 80);
ReByteBuffer& appendHexDump(const char* data, size_t length = -1,
int offset = 0, int bytePerLine = 16, const char* offsetFormat =
"%04x: ", bool withAscii = true, int groupWidth = 1, int gapBehind =
bool insert(size_t ix, const Byte* source, size_t length) {
return splice(ix, 0, source, length);
}
- bool isPrefixOf(const char* source, size_t length = -1, bool ignoreCase = false, int minLength = 0);
+ bool isPrefixOf(const char* source, size_t length = -1, bool ignoreCase =
+ false, int minLength = 0);
/** Returns the last character.
* @return '\0': empty buffer<br>
* otherwise: the last character
/** @brief Destructor.
*/
ReException::~ReException() {
- if (m_message != NULL)
+ if (m_message != NULL) {
free((void*) m_message);
+ m_message = NULL;
+ }
}
ReException::ReException(const ReException& source) :
args.reset(translate(key));
return args;
}
-
+/**
+ * Translate a message.
+ *
+ * @param key the message to translate
+ * @return the translated message
+ */
+const char* i18nTranslate(const char* key) {
+ const char* rc = i18n(key);
+ return rc;
+}
static int m_count;
static ReVarArgs m_varArgs;
};
+extern const char* i18nTranslate(const char* key);
inline const char* i18n(const char* key) {
return ReI18N::tr(key);
}
#elif defined __WIN32__
int maxCount = sec * 50;
int count = 0;
- while(TryEnterCriticalSection(&m_mutex) != 0 && ++count < maxCount){
+ while(TryEnterCriticalSection(&m_mutex) != 0 && ++count < maxCount) {
Sleep(20);
}
rc = count < maxCount;
/**
* Constructor.
*
- * @param length the
+ * @param currentLength the current length of the serialized bytes
+ * @param expectedlength the length needed for the current object
*/
-ReSerializationLengthException::ReSerializationLengthException(int currentLength,
- int expectedlength) :
- ReSerializationException(),
- m_currentLength(currentLength),
- m_expectedLength(expectedlength){
+ReSerializationLengthException::ReSerializationLengthException(
+ int currentLength, int expectedlength) :
+ ReSerializationException(
+ ReByteBuffer(i18n("pack error: length to small: ")).appendInt(
+ currentLength).appendChar('/').appendInt(expectedlength).str()),
+ m_currentLength(currentLength),
+ m_expectedLength(expectedlength) {
+}
+/**
+ * Constructor.
+ *
+ * @param serialId a class specific identifier, inclusive a serialization version
+ */
+ReSerializable::ReSerializable(int serialId) :
+ m_serialId(serialId) {
+}
+/**
+ * Destructor.
+ */
+ReSerializable::~ReSerializable() {
}
#ifndef BASE_RESERIALIZABLE_HPP_
#define BASE_RESERIALIZABLE_HPP_
+extern const char* i18nTranslate(const char* key);
/**
* Base class for all serialization/deserialization errors.
*/
class ReSerializationException: public ReException {
+public:
+ /** Constructor.
+ * @param message description of the error
+ */
+ ReSerializationException(const char* message) :
+ ReException(message) {
+ }
};
/**
* The length is not enough for the deserialization.
*/
-class ReSerializationLengthException : public ReSerializationException {
+class ReSerializationLengthException: public ReSerializationException {
public:
ReSerializationLengthException(int currentLength, int expectedLength);
public:
/**
* Unexpected data found while unpacking.
*/
-class ReSerializeFormatException : public ReSerializationException {
+class ReSerializeFormatException: public ReSerializationException {
+public:
+ /** Constructor.
+ * @param message description of the error
+ */
+ ReSerializeFormatException(const char* message) :
+ ReSerializationException(message) {
+ }
};
/**
* Abstract base class for serializing.
*/
class ReSerializable {
public:
- virtual ~ReSerializable() {
- }
+ ReSerializable(int serialId);
+ virtual ~ReSerializable();
public:
/** Appends a boolean value.
* @param buffer IN/OUT: the buffer with the serialized values
* @param buffer IN/OUT: the buffer with the serialized values
* @param value the value to serialize
*/
- inline void packString8(ReByteBuffer& buffer, ReByteBuffer& value) {
+ inline void packString255(ReByteBuffer& buffer, ReByteBuffer& value) {
buffer.appendBits8(value.length()).append(value);
}
/** Appends a string with a maximal length of 64KiByte to the buffer.
* @param buffer IN/OUT: the buffer with the serialized values
* @param value the value to serialize
*/
- inline void appendString16(ReByteBuffer& buffer, ReByteBuffer& value) {
+ inline void packString64k(ReByteBuffer& buffer, ReByteBuffer& value) {
buffer.appendBits16(value.length()).append(value);
}
/** Appends a string with a maximal length of 4GiByte to the buffer.
* @param buffer IN/OUT: the buffer with the serialized values
* @param value the value to serialize
*/
- inline void appendString32(ReByteBuffer& buffer, ReByteBuffer& value) {
+ inline void packString4t(ReByteBuffer& buffer, ReByteBuffer& value) {
buffer.appendBits32(value.length()).append(value);
}
/** Sets the members of the instance from the byte sequence.
* serialized members
*/
virtual void deserialize(uint8_t*& sequence, size_t& length) = 0;
+ /** Sets the members of the instance from the byte sequence in a buffer.
+ * @param sequence the serialized sequence
+ * @throw ReSerializationLengthException
+ */
+ inline void deserializeBuffer(const ReByteBuffer& sequence) {
+ size_t length = sequence.length();
+ uint8_t* seq = reinterpret_cast<uint8_t*>(sequence.buffer());
+ deserialize(seq, length);
+ if (length != 0)
+ throw ReSerializationLengthException(length, 0);
+ }
/** Appends the class members to the end of the buffer.
*
* @param buffer IN/OUT: the buffer containing the serialized bytes
throw ReSerializationLengthException(length, 1);
char cc = *sequence++;
if (cc != 't' && cc != 'f')
- throw ReSerializeFormatException(i18n("not a boolean value"));
+ throw ReSerializeFormatException(
+ i18nTranslate("not a boolean value"));
value = cc == 't';
length--;
}
* @param length IN/OUT: the length of <code>sequence</code>
* @param value OUT: the value read from the sequence
*/
- inline void unpackInt64(uint8_t*& sequence, size_t& length, int64_t& value) {
+ inline void unpackInt64(uint8_t*& sequence, size_t& length,
+ int64_t& value) {
if (length < 8)
throw ReSerializationLengthException(length, 8);
value = (int64_t(*sequence++) << 56) + (int64_t(*sequence++) << 48)
* @param length IN/OUT: the length of <code>sequence</code>
* @param value OUT: the value read from the sequence
*/
- inline void unpackString255(uint8_t*& sequence, size_t& length, ReByteBuffer& value) {
+ inline void unpackString255(uint8_t*& sequence, size_t& length,
+ ReByteBuffer& value) {
size_t strLen = 0;
if (length == 0 || (strLen = *sequence) > length)
throw ReSerializationLengthException(length, 1 + strLen);
* @param length IN/OUT: the length of <code>sequence</code>
* @param value OUT: the value read from the sequence
*/
- inline void unpackString64k(uint8_t*& sequence, size_t& length, ReByteBuffer& value) {
+ inline void unpackString64k(uint8_t*& sequence, size_t& length,
+ ReByteBuffer& value) {
size_t strLen = 0;
if (length == 0 || (strLen = (sequence[0] << 8) + sequence[1]) > length)
throw ReSerializationLengthException(length, 1 + strLen);
value.set(reinterpret_cast<char*>(sequence), strLen);
- length -= strLen - 1;
+ length -= strLen - 2;
}
/** Reads a string with a max. length of 64KiByte from the serialized byte sequence.
* @param sequence IN/OUT: the byte sequence with the serialized data
* @param length IN/OUT: the length of <code>sequence</code>
* @param value OUT: the value read from the sequence
*/
- inline void unpackString4t(uint8_t*& sequence, size_t& length, ReByteBuffer& value) {
+ inline void unpackString4t(uint8_t*& sequence, size_t& length,
+ ReByteBuffer& value) {
size_t strLen = 0;
- if (length == 0 || (strLen = (sequence[0] << 24) + (sequence[1] << 16)
- + (sequence[2] << 8) + sequence[3]) > length)
+ if (length == 0
+ || (strLen = (sequence[0] << 24) + (sequence[1] << 16)
+ + (sequence[2] << 8) + sequence[3]) > length)
throw ReSerializationLengthException(length, 1 + strLen);
value.set(reinterpret_cast<char*>(sequence), strLen);
- length -= strLen - 1;
+ length -= strLen - 4;
}
+private:
+ int m_serialId;
};
#endif /* BASE_RESERIALIZABLE_HPP_ */
* @param b 2nd value\r
* @return minimum of a and b\r
*/\r
-inline int min(int a, int b){\r
+inline int min(int a, int b) {\r
return a < b ? a : b;\r
}\r
/** Returns the maximum of 2 values.\r
* @param b 2nd value\r
* @return maximum of a and b\r
*/\r
-inline int max(int a, int b){\r
+inline int max(int a, int b) {\r
return a < b ? a : b;\r
}\r
+#include "base/ReException.hpp"\r
#include "base/ReMutex.hpp"\r
#include "base/ReByteBuffer.hpp"\r
#include "base/ReSerializable.hpp"\r
#include "base/ReThread.hpp"\r
#include "base/ReTestUnit.hpp"\r
#include "base/ReCString.hpp"\r
-#include "base/ReException.hpp"\r
#include "base/ReStringUtils.hpp"\r
#include "base/ReDirectory.hpp"\r
#include "base/ReSeqArray.hpp"\r
}
private:
void run() {
+ testAppendBits();
testAppendDump();
testAppendFix();
testEnsureLastChar();
testSplice();
testReplace();
}
- void testIsPrefixOf(){
+ void testAppendBits() {
+ ReByteBuffer buffer;
+ buffer.appendBits8(0x31).appendBits16(0x3233).appendBits24(0x343536);
+ buffer.appendBits32(0x37383941);
+ checkEqu("123456789A", buffer);
+ buffer.set("x", 1).appendBits64(0x4243444546474849LL);
+ checkEqu("xBCDEFGHI", buffer);
+ }
+ void testIsPrefixOf() {
ReByteBuffer buffer;
// predefined length (of source):
// case sensitive, same size
// case sensitive, longer
checkF(buffer.set("aBcd").isPrefixOf("aBcd", 3));
-
// case insensitive, same size
checkT(buffer.set("aBc").isPrefixOf("abc", -1, true));
// case sensitive, shorter
checkT(buffer.set("aBc").isPrefixOf("abcd", -1, true, 2));
checkF(buffer.set("aB").isPrefixOf("abc", -1, true, 3));
}
- void testAppendDump(){
+ void testAppendDump() {
ReByteBuffer buffer;
// true ASCII:
buffer.appendDump("abc");
checkEqu("a\tb\nc\rd", buffer.str());
// binary:
int64_t ii = 0x12345678abcdefll;
- buffer.setLength(0).appendDump(reinterpret_cast<const char*>(&ii), sizeof ii, 40);
- checkEqu("0000: ef cd ab 78 56 34 12 00 | ...xV4.. ",
- buffer.str());
+ buffer.setLength(0).appendDump(reinterpret_cast<const char*>(&ii),
+ sizeof ii, 40);
+ checkEqu(
+ "0000: ef cd ab 78 56 34 12 00 | ...xV4.. ",
+ buffer.str());
}
void testAppendFix() {
ReByteBuffer buffer;
checkEqu(0, buffer.atoi(5, 6));
buffer.set("0x98765432", -1);
- checkEqu(0x98765432, (unsigned ) buffer.atoi());
+ checkEqu(0x98765432U, (unsigned ) buffer.atoi());
buffer.set("0xabcdef01", -1);
- checkEqu(0xabcdef01, (unsigned ) buffer.atoi());
+ checkEqu(0xabcdef01U, (unsigned ) buffer.atoi());
buffer.set("0xABCDEF01", -1);
- checkEqu(0xabcdef01, (unsigned ) buffer.atoi());
+ checkEqu(0xabcdef01U, (unsigned ) buffer.atoi());
buffer.set("0xaFFe01", -1);
- checkEqu(0xaFFe01u, (unsigned ) buffer.atoi());
+ checkEqu(0xaFFe01U, (unsigned ) buffer.atoi());
}
void testEnsureSizeGetLength() {
ReByteBuffer buf1;
--- /dev/null
+/*
+ * cuReSerializable.cpp
+ *
+ * License: Public domain
+ * Do what you want.
+ * No warranties and disclaimer of any damages.
+ * The latest sources: https://github.com/republib
+ */
+#include "base/rebase.hpp"
+
+class ExampleClass: public ReSerializable {
+public:
+ ExampleClass() :
+ ReSerializable(m_serialId),
+ m_int8(0),
+ m_int16(0),
+ m_int32(0),
+ m_bool(false),
+ m_int64(0),
+ m_string255(),
+ m_string64k(),
+ m_string4t() {
+ }
+ ExampleClass(int int8, int int16, int int32, bool boolValue, int64_t int64,
+ const char* string1, const char* string2, const char* string3) :
+ ReSerializable(m_serialId),
+ m_int8(int8),
+ m_int16(int16),
+ m_int32(int32),
+ m_bool(boolValue),
+ m_int64(int64),
+ m_string255(string1),
+ m_string64k(string2),
+ m_string4t(string3) {
+ }
+ virtual void deserialize(uint8_t*& sequence, size_t& length) {
+ int id;
+ unpackInt24(sequence, length, id);
+ unpackInt8(sequence, length, m_int8);
+ unpackInt16(sequence, length, m_int16);
+ unpackInt32(sequence, length, m_int32);
+ unpackBool(sequence, length, m_bool);
+ unpackInt64(sequence, length, m_int64);
+ unpackString255(sequence, length, m_string255);
+ unpackString64k(sequence, length, m_string64k);
+ unpackString4t(sequence, length, m_string4t);
+ }
+ virtual ReByteBuffer& serialize(ReByteBuffer& buffer) {
+ buffer.appendBits24(m_serialId).appendBits8(m_int8);
+ buffer.appendBits16(m_int16).appendBits32(m_int32);
+ packBool(buffer, m_bool);
+ buffer.appendBits64(m_int64);
+ packString255(buffer, m_string255);
+ packString64k(buffer, m_string64k);
+ packString4t(buffer, m_string4t);
+ }
+ const char* toString(ReByteBuffer& buffer) {
+ buffer.setLength(0).append("id: ").appendInt(m_serialId);
+ buffer.append(" i8:").appendInt(m_int8);
+ buffer.append(" i16:").appendInt(m_int16);
+ buffer.append(" i32:").appendInt(m_int32);
+ buffer.append(" b:").appendChar(m_bool ? 't' : 'f');
+ buffer.append(" i64:").appendInt(m_int64);
+ buffer.append(" s255:").append(m_string255);
+ buffer.append(" s64k:").append(m_string64k);
+ buffer.append(" s4t:").append(m_string4t);
+ return buffer.str();
+ }
+private:
+ int m_int8;
+ int m_int16;
+ int m_int32;
+ bool m_bool;
+ int64_t m_int64;
+ ReByteBuffer m_string255;
+ ReByteBuffer m_string64k;
+ ReByteBuffer m_string4t;
+private:
+ static int m_serialId;
+};
+int ExampleClass::m_serialId = 0x123401;
+
+class TestReSerializable: public ReTestUnit {
+ typedef ReByteBuffer::Byte Byte;
+public:
+ TestReSerializable() :
+ ReTestUnit("ReSerializable", __FILE__) {
+ run();
+ }
+private:
+ void run() {
+ testBasic();
+ }
+ void testBasic() {
+ ReByteBuffer buffer;
+ ExampleClass example(250, 64000, 12345678, true, 0x12345678abcdll,
+ "king", "lives", "!");
+ checkEqu(
+ "id: 1192961 i8:250 i16:64000 i32:12345678 b:t i64:20015998348237 s255:king s64k:lives s4t:!",
+ example.toString(buffer));
+ ReByteBuffer serialBuffer;
+ example.serialize(serialBuffer);
+ ExampleClass example2;
+ example.deserializeBuffer(serialBuffer);
+ checkEqu("", example2.toString(buffer));
+ }
+};
+extern void testReSerializable(void);
+
+void testReSerializable(void) {
+ TestReSerializable unit;
+}
+
static bool s_testAll = true;
void testBase() {
- extern void testReSeqArray(void);
- testReSeqArray();
+ extern void testReSerializable(void);
+ testReSerializable();
extern void testReTestUnit();
//testReTestUnit();
testReProgramArgs();
extern void testReLogger(void);
testReLogger();
+ extern void testReSerializable(void);
+ testReSerializable();
}
void testString() {