From: hama Date: Wed, 29 Jul 2015 22:29:21 +0000 (+0200) Subject: Refactoring: ReByteArray, dirtool improvements X-Git-Url: https://gitweb.hamatoma.de/?a=commitdiff_plain;h=7e9d42f3c146e9ffe558870e86b634342b9d6204;p=crepublib Refactoring: ReByteArray, dirtool improvements * dirtool: ** --editor argument ** if --dry: no creation of subdirs ** --delete: empty string allowed --- diff --git a/base/ReAppenders.cpp b/base/ReAppenders.cpp index 90fed67..f0c730e 100644 --- a/base/ReAppenders.cpp +++ b/base/ReAppenders.cpp @@ -1,6 +1,6 @@ /* * ReAppenders.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -33,8 +33,8 @@ ReMemoryAppender::~ReMemoryAppender() { * @param append truethe buffer will not truncated before storage * @return buffer (for chaining) */ -ReByteBuffer& ReMemoryAppender::join(ReByteBuffer& buffer, bool append) { - ReByteBuffer current; +ReByteArray& ReMemoryAppender::join(ReByteArray& buffer, bool append) { + ReByteArray current; if (!append) buffer.setLength(0); for (int ix = count() - 1; ix >= 0; ix--) { @@ -81,7 +81,7 @@ ReSlaveAppender::~ReSlaveAppender() { * @param message the logging message to store */ void ReSlaveAppender::say(ReLogger* logger, const char* message) { - ReByteBuffer buffer(logger->standardPrefix(m_charPrefix)); + ReByteArray buffer(logger->standardPrefix(m_charPrefix)); buffer.append(message == NULL ? logger->asCString() : message); m_masterLogger->say(logger->currentMode(), 0, buffer.str()); } diff --git a/base/ReAppenders.hpp b/base/ReAppenders.hpp index fcab1f7..c2674a4 100644 --- a/base/ReAppenders.hpp +++ b/base/ReAppenders.hpp @@ -1,6 +1,6 @@ /* * ReAppenders.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -23,7 +23,7 @@ public: ReMemoryAppender(int maxLines); ~ReMemoryAppender(); public: - ReByteBuffer& join(ReByteBuffer& buffer, bool append = false); + ReByteArray& join(ReByteArray& buffer, bool append = false); virtual void say(ReLogger* logger, const char* message); protected: int m_maxLines; diff --git a/base/ReBaseUtils.cpp b/base/ReBaseUtils.cpp index 64e9861..e933e58 100644 --- a/base/ReBaseUtils.cpp +++ b/base/ReBaseUtils.cpp @@ -1,6 +1,6 @@ /* * ReBaseUtils.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. diff --git a/base/ReBaseUtils.hpp b/base/ReBaseUtils.hpp index cde959e..d0185b6 100644 --- a/base/ReBaseUtils.hpp +++ b/base/ReBaseUtils.hpp @@ -1,6 +1,6 @@ /* * ReBaseUtils.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. diff --git a/base/ReByteArray.cpp b/base/ReByteArray.cpp new file mode 100644 index 0000000..590eb2f --- /dev/null +++ b/base/ReByteArray.cpp @@ -0,0 +1,930 @@ +/* + * ReByteArray.cpp + * + * License: Public Domain + * You can use and modify this file without any restriction. + * Do what you want. + * No warranties and disclaimer of any damages. + * You also can use this license: http://www.wtfpl.net + * The latest sources: https://github.com/republib + */ + +#include "base/rebase.hpp" + +#ifdef __linux__ +extern void* memcpy(void* dest, const void* src, size_t n); +extern void* memmove(void* dest, const void* src, size_t n); +extern int _memcmp (const void* s1, const void* s2, size_t n); +extern int _snprintf(char* s, size_t maxlen, const char* format, ...); +#endif + +/** @brief Constructor. + * + * @param delta If a new storage must be allocated the size + * is incremented by at least this count of bytes + */ +ReByteArray::ReByteArray(size_t delta) : + // m_primaryBuffer + m_delta(delta), + m_buffer(m_primaryBuffer), + m_length(0), + m_capacity(sizeof m_primaryBuffer - 1), + m_reallocation(0) { + m_buffer[0] = '\0'; +} +/** @brief Constructor. + * + * @param source the instance to copy (C string) + */ +ReByteArray::ReByteArray(const char* source) : + // m_primaryBuffer + m_delta(PRIMARY_BUFFER_SIZE), + m_buffer(m_primaryBuffer), + m_length(0), + m_capacity(sizeof m_primaryBuffer), + m_reallocation(0) { + m_buffer[0] = '\0'; + if (source != NULL) + append(source); +} + +/** @brief Constructor. + * + * @param source The byte sequence to copy + * @param sourceLength length of source + */ +ReByteArray::ReByteArray(const Byte* source, size_t sourceLength) : + // m_primaryBuffer + m_delta(PRIMARY_BUFFER_SIZE), + m_buffer(m_primaryBuffer), + m_length(0), + m_capacity(sizeof m_primaryBuffer - 1), + m_reallocation(0) { + m_buffer[0] = '\0'; + append(source, sourceLength); +} + +/** @brief Destructor. + * + */ +ReByteArray::~ReByteArray() { + if (m_buffer != m_primaryBuffer) + delete[] m_buffer; + m_buffer = NULL; + m_capacity = 0; + m_length = 0; +} +/** @brief Copy constructor. + * + * @param source the instance to copy + */ +ReByteArray::ReByteArray(const ReByteArray& source) : + // m_primaryBuffer + m_delta(source.delta()), + m_buffer(m_primaryBuffer), + m_length(0), + m_capacity(sizeof m_primaryBuffer), + m_reallocation(0) { + append(source.buffer(), source.length()); +} + +/** @brief The assignment operator. + * + * @param source the instance to copy + * + * @return the instance itself + */ +ReByteArray& ReByteArray::operator =(const ReByteArray& source) { + m_delta = source.delta(); + set(source.buffer(), source.length()); + return *this; +} + +/** @brief Appends a byte sequence at the end of the buffer. + * + * If the space is not enough it will be allocated. + * + *
Example:
+ * ReByteBuffer buf;
+ * assert(4 == buf.append("abc", 3).append("x").getLength());
+ * 
+ * + * @param source the sequence to append + * @param length the length of the sequence + * + * @return *this (for chaining) + */ +ReByteArray& ReByteArray::append(const Byte* source, size_t length) { + if (source != NULL) { + if (length == (size_t) -1) + length = strlen(source); + ensureSize(m_length + length); + memcpy((void*) (m_buffer + m_length), source, length); + m_length += length; + m_buffer[m_length] = '\0'; + } + return *this; +} +/** @brief Appends the content of another ReByteBuffer instance at the end of the buffer. + * + * If the space is not enough it will be allocated. + * + *
Example:
+ * ReByteBuffer name; name.append("mydoc");
+ * ReByteBuffer ext; ext.append(".txt");
+ * name.append(ext);
+ * assert("mydoc.txt", name.getBuffer());
+ * 
+ * + * @return *this (for chaining) + */ +ReByteArray& ReByteArray::append(const ReByteArray& source) { + return append(source.str(), source.length()); +} + +/** @brief Appends a floaating point number at the end of the buffer. + * + * If the space is not enough it will be allocated. + * + *
Example:
+ * ReByteBuffer buf; buf.append("amount: ").append(377 / 100.0, "%5.2f");
+ * assert("amount:   3.77", buf.str());
+ * 
+ * + * @return *this (for chaining) + */ +ReByteArray& ReByteArray::append(double value, const char* format) { + char buffer[256]; + + _snprintf(buffer, sizeof buffer, format, value); + append(buffer, -1); + return *this; +} + +/** + * Appends a string with minimal/maximal length. + * + * If the length is greater than the maximal length the string will be cutted + * (in the middle) and a separator will set at the cut. + * + *
Example:
+ * buffer.appendFix("sammy2", -1, 5, 5, "*").appendFix("x", 1, 99, -3);
+ * 
+ * Buffer contains: "sa*y2  x"
+ * 
+ * + * @param data data to append + * @param length length of data. -1: strlen(data) + * @param maxLength the stored length is at most this value + * @param minLength if the length is smaller padding characters will be added
+ * < 0: padding is done at the top + * @param separator NULL or the string used at the separaration point + * @param padding character used for padding (see minLength) + * @return *this (for chaining) + */ +ReByteArray& ReByteArray::appendFix(const char* data, size_t length, + int maxLength, int minLength, const char* separator, char padding) { + if (length == (size_t) -1) + length = strlen(data); + if ((int) length < abs(minLength)) { + ensureSize(m_length + abs(minLength)); + if (minLength < 0) + appendChar(padding, -minLength - length); + append(data, length); + if (minLength > 0) + appendChar(padding, minLength - length); + } else if ((int) length > maxLength) { + ensureSize(m_length + maxLength); + int sepLength = separator == NULL ? 0 : strlen(separator); + int lengthPart1 = (maxLength - sepLength + 1) / 2; + int lengthPart2 = maxLength - sepLength - lengthPart1; + append(data, lengthPart1); + if (sepLength > 0) + append(separator, sepLength); + append(data + length - lengthPart2, lengthPart2); + } else { + append(data, length); + } + return *this; +} + +/** + * Appends data as string or as binary (hexdump). + * + * If data contains non ASCII char the data will be treated as binary. + * + * @param data the data to append + * @param length -1 (strlen()) or the length of data + * @param maxLength the maximal count of appended chars + * @return *this (chaining) + */ +ReByteArray& ReByteArray::appendDump(const char* data, size_t length, + int maxLength) { + if (length == size_t(-1)) { + length = strlen(data); + } + if ((int) length > maxLength) + 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')) { + isBinary = true; + break; + } + } + if (!isBinary) + append(data, length); + else + appendHexDump(data, min(length, maxLength / 5)).reduceLength(); + return *this; +} +/** + * Appends a hexadecimal dump of a memory array. + * + *
Example:
+ * buffer.appendHex("01234567890abcde", -1, 0x10, 16, "%0x8x", 1, -1, " | ");
+ * 
+ * Buffer contains:
+ * 00000010  30 31 32 33 34 35 36 37  38 39 30 61 62 63 64 65 | 01234567890abcde
+ * 
+ * + * @param data data to dump + * @param length length of data. -1: strlen(data) + * @param offset a format which is used to append a preceeding position + * of source. NULL: no offset is appended + * @param bytesPerLine number of bytes in one line. If length is greater more + * lines are appended + * @param offsetFormat NULL or the sprintf format of the offset, e.g. "0x04x " + * @param withAscii true: the data is interpreted as ASCII too + * @param groupWidth behind groupWidth hex bytes a ' ' is appended + * @param gapBehind behind gapBehind hex bytes a ' ' is appended
+ * -1: bytePerLine / 2 + * @param separator NULL or a string between hex area and ASCII area + * @return *this (for chaining) + */ +ReByteArray& ReByteArray::appendHexDump(const char* data, size_t length, + int offset, int bytesPerLine, const char* offsetFormat, bool withAscii, + int groupWidth, int gapBehind, const char* separator) { + if (length == (size_t) -1) + length = strlen(data); + if (gapBehind < 0) + gapBehind = bytesPerLine / 2; + ensureSize(32); + int offsetLength = 0; + if (offsetFormat != NULL) { + _snprintf(m_buffer, 31, offsetFormat, offset + length); + offsetLength = strlen(m_buffer); + } + ensureSize( + (length + bytesPerLine - 1) / bytesPerLine + * (4 + offsetLength + + (gapBehind <= 0 ? 0 : bytesPerLine / gapBehind + 1) + + (separator == NULL ? 0 : strlen(separator)) + 1)); + while (length > 0) { + if (offsetFormat != NULL) + appendInt(offset, offsetFormat); + int ix; + for (ix = 0; ix < bytesPerLine; ix++) { + if (ix < (int) length) + appendInt((unsigned char) data[ix], "%02x"); + else + append(" "); + if (ix < bytesPerLine - 1 + && (groupWidth == 1 || ix % groupWidth == groupWidth - 1)) + appendChar(' '); + if (ix < bytesPerLine - 1 && gapBehind > 0 + && (gapBehind == 1 || ix % gapBehind == gapBehind - 1)) + appendChar(' '); + } + if (withAscii) { + if (separator != NULL) + append(separator, -1); + char cc; + for (ix = 0; ix < bytesPerLine; ix++) { + if (ix < (int) length) + appendInt((cc = data[ix]) < ' ' || cc > 127 ? '.' : cc, + "%c"); + else + append(" "); + if (ix < bytesPerLine - 1 && gapBehind > 0 + && (gapBehind == 1 || ix % gapBehind == gapBehind - 1)) + append(" ", 1); + } + appendChar('\n'); + length = + length <= (size_t) bytesPerLine ? 0 : length - bytesPerLine; + data += bytesPerLine; + offset += bytesPerLine; + } + } + return *this; +} + +/** @brief Appends an integer as string at the end of the buffer. + * + * If the space is not enough it will be allocated. + * + *
Example:
+ * ReByteBuffer buf; buf.appendInt(33, "%-4d");
+ * assert(strcmp("33  ", buf.str()) == 0);
+ * 
+ * + * @param number the number to append + * @param format the format of the number used by sprintf() + * + * @return *this (for chaining) + */ +ReByteArray& ReByteArray::appendInt(int number, const char* format) { + char buffer[128]; + + _snprintf(buffer, sizeof buffer, format, number); + append(buffer, -1); + return *this; +} + +/** @brief Appends an integer as string at the end of the buffer. + * + * If the space is not enough it will be allocated. + * + *
Example:
+ * ReByteBuffer buf; buf.appendInt(33U, "%x");
+ * assert(strcmp("21  ", buf.str()) == 0);
+ * 
+ * + * @param number the number to append + * @param format the format of the number used by sprintf() + * + * @return *this (for chaining) + */ +ReByteArray& ReByteArray::appendInt(unsigned int number, const char* format) { + char buffer[128]; + + _snprintf(buffer, sizeof buffer, format, number); + append(buffer, -1); + return *this; +} + +/** @brief Appends an integer as string at the end of the buffer. + * + * If the space is not enough it will be allocated. + * + *
Example:
+ * ReByteBuffer buf; buf.appendInt(12345678901ll, "%12d");
+ * assert(strcmp(" 12345678901", buf.str()) == 0);
+ * 
+ * + * @param number the number to append + * @param format the format of the number used by sprintf() + * + * @return *this (for chaining) + */ +ReByteArray& ReByteArray::appendInt(int64_t number, const char* format) { + char buffer[256]; + + _snprintf(buffer, sizeof buffer, format, number); + append(buffer, -1); + return *this; +} + +/** @brief Appends an integer as string at the end of the buffer. + * + * If the space is not enough it will be allocated. + * + *
Example:
+ * ReByteBuffer buf; buf.appendInt((uint64_t) 0x12345678901ll, "%12x");
+ * assert(strcmp(" 12345678901", buf.str()) == 0);
+ * 
+ * + * @param number the number to append + * @param format the format of the number used by sprintf() + * + * @return *this (for chaining) + */ +ReByteArray& ReByteArray::appendInt(uint64_t number, const char* format) { + char buffer[256]; + + _snprintf(buffer, sizeof buffer, format, number); + append(buffer, -1); + return *this; +} + +/** @brief Appends a time (given in milli seconds) as 'dd:HH:MM.mmm'. + * + * @param time the time (duration) in msec + * @param minLength > 5: seconds will be 2 digits (preceeding '0' if needed)
+ * > 6: at least MM:SS.sss
+ * > 9: at least HH:MM:SS.sss
+ * > 12: at least dd:HH:MM:SS.sss
+ * @return buffer (for chaining) + */ +ReByteArray& ReByteArray::appendMilliSec(int time, int minLength) { + int days = time / (24 * 3600 * 1000LL); + time %= 24 * 3600 * 1000; + int expectedLength = days > 0 ? 12 : 0; + int hours = time / (3600 * 1000); + time %= 3600 * 1000; + if (hours > 0 && expectedLength == 0) + expectedLength = 9; + int minutes = time / (60 * 1000); + time %= 60 * 1000; + if (minutes > 0 && expectedLength == 0) + expectedLength = 5; + int minimum = minLength > expectedLength ? minLength : expectedLength; + int sec = time / 1000; + int msec = time % 1000; + static const char* stdFormat = "%02d"; + if (days > 0 || minimum > 12) + appendInt(days).append(":"); + if (hours > 0 || minimum > 9) + appendInt(hours, stdFormat).append(":"); + if (minutes > 0 || minimum > 6) + appendInt(minutes, stdFormat).append(":"); + appendInt(sec, sec > 10 || minimum > 5 ? stdFormat : "%d").append("."); + appendInt(msec, "%03d"); + return *this; +} + +/** @brief Appends a time (given in milli seconds) as 'dd:HH:MM.mmm'. + * + * @param time the time (duration) in msec + * @param minLength > 3: seconds will be 2 digits (preceeding '0' if needed)
+ * > 4: at least MM:SS.sss
+ * > 7: at least HH:MM:SS.sss
+ * > 10: at least dd:HH:MM:SS
+ * @return buffer (for chaining) + */ +ReByteArray& ReByteArray::appendTime(int time, int minLength) { + int days = time / (24 * 3600); + time %= 24 * 3600; + int expectedLength = days > 0 ? 10 : 0; + int hours = time / 3600; + time %= 3600; + if (hours > 0 && expectedLength == 0) + expectedLength = 7; + int minutes = time / 60; + time %= 60; + if (minutes > 0 && expectedLength == 0) + expectedLength = 3; + int minimum = minLength > expectedLength ? minLength : expectedLength; + int sec = time; + static const char* stdFormat = "%02d"; + if (days > 0 || minimum > 10) + appendInt(days).append(":"); + if (hours > 0 || minimum > 7) + appendInt(hours, stdFormat).append(":"); + if (minutes > 0 || minimum > 4) + appendInt(minutes, stdFormat).append(":"); + appendInt(sec, sec > 10 || minimum > 3 ? stdFormat : "%d"); + return *this; +} + +/** Converts a subsequence into an integer. + * + * The number may be a decimal or a hexadecimal number. Hex numbers start with 0x. + *
Example:
+ * ReByteBuffer buf;
+ * buf.set("abc123", 6);
+ * assert(12 == buf.atoi(3, 3 + 2));
+ * 
+ * + * @param start the first index to convert + * @param end -1: all found digits will be converted + * Otherwise: the maximal number of digits to convert + */ +int ReByteArray::atoi(size_t start, int end) const { + int rc = 0; + if (start < m_length) { + if (end < 0) + end = m_length; + char cc; + if (m_buffer[start] == '0' && tolower(m_buffer[start + 1]) == 'x') { + // Hexadecimal number: + start += 2; + while (start < (size_t) end && (cc = m_buffer[start++]) >= '0' + && isxdigit(cc)) + rc = rc * 16 + (cc <= '9' ? cc - '0' : toupper(cc) - 'A' + 10); + } else { + // Decimal number: + while (start < (size_t) end && (cc = m_buffer[start++]) >= '0' + && cc <= '9') + rc = rc * 10 + cc - '0'; + } + } + return rc; +} + +/** + * Counts the occurrencies of a given byte sequence. + * + * @param toCount the byte sequence to count + * @param lengthOfToCount -1: length is strlen(toCount)
+ * otherwise: length of toCount + */ +int ReByteArray::count(const char* toCount, size_t lengthToCount) { + int rc = 0; + size_t start = 0; + if (lengthToCount == (size_t) -1) + lengthToCount = strlen(toCount); + while ((start = indexOf(toCount, lengthToCount, start)) != (size_t) -1) { + rc++; + start += lengthToCount; + } + return rc; +} + +/** + * Tests whether the buffer ends with a given a byte sequence. + * + * @param tail the byte sequence to test + * @param tailLength -1: strlen(tail)
+ * otherwise: the length of tail + * @param ignoreCase true: the comparison is case insensitive
+ * false: the comparison is case sensitive
+ * @return true: the buffer ends with tail
+ * false: otherwise + */ +bool ReByteArray::endsWith(const Byte* tail, size_t tailLength, + bool ignoreCase) const { + bool rc = tail != NULL; + if (rc) { + if (tailLength == (size_t) -1) + tailLength = strlen(tail); + rc = indexOf(tail, tailLength, m_length - tailLength, m_length, + ignoreCase) >= 0; + } + return rc; +} + +/** @brief Ensures that there is enough space. + * + * If not it will be allocated and the old value will be copied. + * + * A new allocation will be use at least m_delta bytes. + * The allocated space is incremented by one because of the ending '\\0'. + * + * @param size the size will be at least this value + */ +void ReByteArray::ensureSize(size_t size) { + if (m_capacity < size) { + int delta = + m_delta > 0 ? m_delta : + (int) m_capacity < -m_delta / 2 ? (int) 2 * m_capacity : -m_delta; + if (int(size - m_capacity) < delta) + size = m_capacity + delta; + // Think for the ending '\0': + Byte* buffer = new Byte[size + 1]; + assert(buffer != NULL); + if (m_length > 0) + memcpy(buffer, m_buffer, m_length); + buffer[m_length] = '\0'; + if (m_buffer != m_primaryBuffer) + delete[] m_buffer; + m_buffer = buffer; + m_capacity = size; + m_reallocation++; + } +} +/** + * @brief Fills a part of the buffer with a given character. + * + * @param filler the byte which is used as filler + * @param start the first index to fill. 0 <= start < m_length + * @param end the index behind the last filled position. May be behind m_length + * @return the instance itself (vor chaining) + */ +ReByteArray& ReByteArray::fill(Byte filler, int start, int end) { + if (end == -1) + end = m_length; + if (start >= 0 && start < end) { + if (end > (int) m_length) + setLength(end); + memset(m_buffer + start, filler, end - start); + } + return *this; +} + +/** @brief Checks for the index of the first different byte. + * + * @param source source to inspect + * @param length -1 or the length of source + * @param start the first index to inspect + * @param ignoreCase true: the comparison is case insensitive + * @return -1: both byte sequences are equal
+ * otherwise: the index of the first difference + */ +int ReByteArray::firstDifference(const Byte* source, size_t length, int start, + bool ignoreCase) { + int rc = -1; + if (start < 0) + rc = 0; + else if (start < (int) m_length) { + if (length == (size_t) -1) + length = strlen(source); + int count = length > m_length - start ? m_length - start : length; + const Byte* ptr = m_buffer + start; + for (int ix = 0; rc < 0 && ix < count; ix++) { + if ((!ignoreCase && *ptr++ != *source++) + || (ignoreCase && (tolower(*ptr++) != tolower(*source++)))) + rc = start + ix; + } + if (rc < 0 && length > m_length - start) + rc = start + count; + } + return rc; +} + +/** @brief Searches for a byte sequence in the internal buffer. + * + * Finds the first occurrence of a byte sequence in a given range. + * + *
Example:
+ * ReByteBuffer buf;
+ * buf.set("12abc123", 8);
+ * assert(5 == buf.indexOf("12", -1, 3));
+ * 
+ * + * @param toFind the sequence to find + * @param toFindLength Length of toFind, + * If -1 the strlen(toFind) will be taken + * @param start the search respects the indices in the range [start, end[ + * @param end -1: no upper limit to search
+ * otherwise: the first index above the search range + * @param ignoreCase true: case insensitive search
+ * true: case sensitive search + * @return -1: the sequence could not be found. + * Otherwise: the index of toFind in the internal buffer + */ +int ReByteArray::indexOf(const Byte* toFind, size_t toFindLength, int start, + int end, bool ignoreCase) const { + if (toFindLength == (size_t) -1) + toFindLength = strlen(toFind); + int rc = -1; + if (end < 0 || end > (int) m_length) + end = m_length; + if (start >= 0 && start <= int(m_length - toFindLength) + && end >= (int) toFindLength && end <= (int) m_length) { + while (rc < 0 && start <= int(end - toFindLength)) { + if (ignoreCase ? + _memicmp((void*) toFind, (void*) (m_buffer + start), + toFindLength) == 0 : + _memcmp(toFind, m_buffer + start, toFindLength) == 0) + rc = start; + else + start++; + } + } + return rc; +} +/** + * Tests whether the instance is a prefix of a given string. + * + * @param source the string to inspect + * @param length the length of the string
+ * -1: strlen(source) + * @param ignoreCase true: the test is case insensitive + * @param minLength the substring (instance) must have at least this length + * for a positive test + * @return truethe instance is a prefix of the source + * and the length is at least minLength bytes + */ +bool ReByteArray::isPrefixOf(const char* source, size_t length, + bool ignoreCase, int minLength) { + if (length == (size_t) -1) + length = strlen(source); + bool rc = length >= m_length && m_length <= length; + if (rc) + rc = equals(source, m_length, ignoreCase); + return rc; +} + +/** @brief Searches revers for a byte sequence in the internal buffer. + * + * Finds the last occurrence of a byte sequence in a given range. + * + *
Example:
+ * ReByteBuffer buf;
+ * buf.set("12abc123", 8);
+ * assert(5 == buf.rindexOf("12", -1, 3));
+ * 
+ * + * @param toFind the sequence to find + * @param toFindLength length of toFind. + * If -1 the strlen(toFind) will be taken + * @param start the search respects the indices in the range [start, end[ + * @param end -1: no upper limit to search
+ * otherwise: the first index above the search range + * @param ignoreCase true: case insensitive search
+ * true: case sensitive search + * @return -1: the sequence could not be found. + * Otherwise: the index of toFind in the internal buffer + */ +int ReByteArray::rindexOf(const Byte* toFind, size_t toFindLength, int start, + int end, bool ignoreCase) const { + if (toFindLength == (size_t) -1) + toFindLength = strlen(toFind); + int rc = -1; + if (end < 0 || end > (int) m_length) + end = m_length; + if (start >= 0 && start <= int(m_length - toFindLength) + && end >= (int) toFindLength && end <= (int) m_length) { + int current = end - toFindLength; + while (current >= start) { + if (ignoreCase ? + _strnicmp(toFind, m_buffer + current, toFindLength) != 0 : + _memcmp(toFind, m_buffer + current, toFindLength) != 0) + current--; + else { + rc = current; + break; + } + } + } + return rc; +} +/** @brief Replaces all occurrences of toFind with replacement. + * + * A single replacement can be done with splice(). + * + *
Example:
+ * ReByteBuffer buf;
+ * buf.set("12abc123", 8);
+ * buf.replaceAll("12", -1, "XYZ", -1);
+ * assert(strcmp("XYZabcXYZ3", buf.str()) == 0);
+ * 
+ * + * @param toFind the substring which will be replaced + * @param toFindLength the length of toFind. -1: strlen() will be used + * @param replacement the replacement + * @param replacementLength the length of replacement. -1: strlen() will be used + * @param start the first index to inspect + */ +ReByteArray& ReByteArray::replaceAll(const Byte* toFind, size_t toFindLength, + const Byte* replacement, size_t replacementLength, int start) { + if (toFindLength == size_t(-1)) + toFindLength = strlen(toFind); + if (replacementLength == size_t(-1)) + replacementLength = strlen(replacement); + + while ((start = indexOf(toFind, toFindLength, start)) != -1) { + splice(start, toFindLength, replacement, replacementLength); + start += replacementLength; + } + return *this; +} + +/** @brief Sets the increment used to increase the capacity. + * + * @param delta > 0: reservation allocates at least this amount of bytes
+ * 0: delta is set to a default value
+ * < 0: the current capacity will be doubled until - delta + */ +void ReByteArray::setDelta(int delta) { + m_delta = delta == 0 ? PRIMARY_BUFFER_SIZE : delta; +} + +/** @brief Sets the length to a given value. + * + * The new length is greater than the current size the buffer will reallocated. + * + *
Example:
+ * ReByteBuffer buf;
+ * buf.set("123", 3);
+ * buf.setLength(5);
+ * assert(strcmp("123", buf.str()) == 0);
+ * assert(5 == buf.getLength());
+ * 
+ * + * @param length the new length + * + * @return *this (for chaining) + */ +ReByteArray& ReByteArray::setLength(size_t length) { + ensureSize(length); + m_length = length; + m_buffer[length] = '\0'; + return *this; +} +/** @brief Sets the length to a given value and fills the new allocated part of the buffer with a given value. + * + * The new length is greater than the current size the buffer will reallocated. + * + *
Example:
+ * ReByteBuffer buf;
+ * buf.set("123", 3);
+ * buf.setLengthAndFill(5, 'X');
+ * assert(strcmp("123XX", buf.str()) == 0);
+ * 
+ * + * @param length the new length + * @param filler if the new length is greater than the current length the space + * will be filled with this value + * @return *this (for chaining) + */ +ReByteArray& ReByteArray::setLengthAndFillOut(size_t length, Byte filler) { + ensureSize(length); + if (length > m_length) + memset(m_buffer + m_length, filler, length - m_length); + m_length = length; + m_buffer[length] = '\0'; + return *this; +} +/** @brief Cuts a sequence from the internal buffer and inserts another. + * + * This function implies a pure insertion and pure deletion of a subsequence. + * + *
Example:
+ * ReByteBuffer buf;
+ * buf.set("12345", 5);
+ * buf.splice(2, 2, "XYZ", 3);
+ * assert(strcmp("12XYZ5", buf.str()) == 0);
+ * 
+ * + * @param ix the index where the cut/insertion takes place + * @param replacedLength the number of deleted bytes. If 0 a pure insertion will be done + * @param source the sequence to insert. May be NULL (for pure deletion) + * @param length the length of the inserted sequence
+ * 0: a pure deletion will be done
+ * -1: strlen(source) will be taken + * + * @return true: Success. false: ix out of range + */ +bool ReByteArray::splice(size_t ix, size_t replacedLength, + const ReByteArray::Byte* source, size_t length) { + bool rc; + if (ix < 0 || ix > m_length) + rc = false; + else { + rc = true; + + if (source == NULL) + length = 0; + if (length == (size_t) -1) + length = strlen(source); + if (ix + replacedLength > m_length) + replacedLength = m_length - ix; + + ensureSize(m_length + length - replacedLength); + + Byte* start = m_buffer + ix; + Byte* tail = start + replacedLength; + size_t lengthTail = m_length - ix - replacedLength; + + if (length <= replacedLength) { + // The sequence will not be longer: + if (length > 0) + memcpy(start, source, length); + if (length < replacedLength) { + memmove(start + length, tail, lengthTail); + } + } else { + // The sequence will be longer: + memmove(start + length, tail, lengthTail); + memcpy(start, source, length); + } + m_length += length - replacedLength; + m_buffer[m_length] = '\0'; + } + return rc; +} +/** + * Tests whether the buffer starts with a given a byte sequence. + * + * @param head the byte sequence to test + * @param headLength -1: strlen(tail)
+ * otherwise: the length of tail + * @param ignoreCase true: the comparison is case insensitive
+ * false: the comparison is case sensitive
+ * @return true: the buffer starts with head
+ * false: otherwise + */ +bool ReByteArray::startsWith(const Byte* head, size_t headLength, + const bool ignoreCase) const { + bool rc = head != NULL; + if (rc) { + if (headLength == (size_t) -1) + headLength = strlen(head); + rc = indexOf(head, headLength, 0, headLength, ignoreCase) == 0; + } + return rc; +} + +/** + * Appends the status data of the instance onto the buffer. + * + * @param buffer OUT: the space for the data report + * @param prefix NULL or a prefix of the output + * @return buffer.str() (for chaining) + */ +const char* ReByteArray::status(ReByteArray& buffer, + const char* prefix) const { + if (prefix != NULL) + buffer.append(prefix); + buffer.append("capacity:").appendInt(m_capacity).append(" length: ") + .appendInt(m_length).append(" realloc: ").appendInt(m_reallocation) + .append("\n"); + return buffer.str(); +} + diff --git a/base/ReByteArray.hpp b/base/ReByteArray.hpp new file mode 100644 index 0000000..40310d0 --- /dev/null +++ b/base/ReByteArray.hpp @@ -0,0 +1,425 @@ +/* + * ReByteArray.hpp + * + * License: Public Domain + * You can use and modify this file without any restriction. + * Do what you want. + * No warranties and disclaimer of any damages. + * You also can use this license: http://www.wtfpl.net + * The latest sources: https://github.com/republib + */ + +#ifndef REBYTEBUFFER_H_ +#define REBYTEBUFFER_H_ + +#define PRIMARY_BUFFER_SIZE 513 +/** @brief An efficient dynamic memory buffer. + * + * Implements a very efficient dynamic byte sequence. + *

+ * Note:
+ * It is guaranteed that the sequence is terminated by a '\\0' like C strings. + * This end marker is outside the visible buffer.
+ * Technically:
+ * ReByteBuffer buf; assert(buf.getBuffer()[buf.getLength()] == '\\0'); + *

+ *

This class can be used as a poor man's string class. + *

+ *

Very effizient: + *

    + *
  • Every instance contains an array (512 Bytes), + * which is used if not more space is needed. + * In many cases there is no need of heap allocation (new or malloc().
  • + *
  • Many of the methods are written as inlines.
  • + *
+ *

+ */ +class ReByteArray { +public: + typedef char Byte; +public: + ReByteArray(size_t delta = PRIMARY_BUFFER_SIZE); + ReByteArray(const char* source); + ReByteArray(const Byte* source, size_t sourceLength); + virtual ~ReByteArray(); + ReByteArray(const ReByteArray& source); + ReByteArray& operator =(const ReByteArray& source); +public: + ReByteArray& append(const Byte* source, size_t length = -1); + ReByteArray& append(const ReByteArray& source); + ReByteArray& append(double, const char* format = "%f"); + /** Appends a 8 bit value in an architecture independent way. + * @param value integer to append + * @return *this (for chaining) + */ + inline ReByteArray& 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 integer to append + * @return *this (for chaining) + */ + inline ReByteArray& 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 integer to append + * @return *this (for chaining) + */ + inline ReByteArray& appendBits24(int value) { + setLength(m_length + 3); + m_buffer[m_length - 3] = char(value >> 16); + 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 integer to append + * @return *this (for chaining) + */ + inline ReByteArray& 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 - 2] = char(value >> 8); + m_buffer[m_length - 1] = char(value); + return *this; + } + /** Appends a 64 bit value in an architecture independent way. + * @param value integer to append + * @return *this (for chaining) + */ + inline ReByteArray& 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 - 6] = char(value >> 40); + m_buffer[m_length - 5] = char(value >> 32); + m_buffer[m_length - 4] = char(value >> 24); + m_buffer[m_length - 3] = char(value >> 16); + m_buffer[m_length - 2] = char(value >> 8); + m_buffer[m_length - 1] = char(value); + return *this; + } + /** Appends a character. + * @param aChar character to append + * @return *this (for chaining) + */ + inline ReByteArray& appendChar(char aChar) { + setLength(m_length + 1); + m_buffer[m_length - 1] = aChar; + return *this; + } + /** Appends a character at least one time. + * @param aChar character to append + * @param count number of times to append + * @return *this (for chaining) + */ + inline ReByteArray& appendChar(char aChar, int count) { + if (count > 0) { + size_t oldLength = m_length; + setLength(m_length + count); + memset(m_buffer + oldLength, aChar, count); + } + return *this; + } + ReByteArray& appendFix(const char* data, size_t length, int maxLength, + int minLength = 0, const char* separator = "*", char padding = ' '); + ReByteArray& appendDump(const char* data, size_t length = -1, + int maxLength = 80); + ReByteArray& 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 = + -1, const char* separator = " | "); + ReByteArray& appendInt(int number, const char* format = "%d"); + ReByteArray& appendInt(unsigned int number, const char* format = "%d"); + ReByteArray& appendInt(int64_t number, const char* format = "%lld"); + ReByteArray& appendInt(uint64_t number, const char* format = "%lld"); + ReByteArray& appendMilliSec(int time, int minLength = 5); + ReByteArray& appendTime(int time, int minLength = 1); + /** @brief Returns the n-th byte of the internal buffer. + * @param index The index of the wanted byte. + * @return 0: Wrong index. Otherwise: The byte from the wanted position. + */ + inline Byte at(size_t index) const { + return index >= m_length ? 0 : m_buffer[index]; + } + int atoi(size_t start = 0, int end = -1) const; + /** @brief Returns the buffer (permitting modifying). + * @return The internal used buffer. + */ + inline Byte* buffer() const { + return m_buffer; + } + /**@brief Returns the current size of the internal buffer. + * @return The current size of the internal buffer. + */ + inline size_t capacity() const { + return m_capacity; + } + /**@brief Sets the length to 0. + * @return the instance (for chaining) + */ + ReByteArray& clear(){ + m_length = 0; + m_buffer[0] = '\0'; + return *this; + } + /** @brief Returns a immutable C string. + * @return a pointer to the buffer content + */ + const char* constData() const{ + return reinterpret_cast(m_buffer); + } + /**@brief Returns the minimum allocation unit. + * @return The minimum of bytes to allocate. + */ + inline size_t delta() const { + return m_delta; + } + /** @brief Tests whether a given character is part of the content. + * @param cc character to test + * @return true: part is a part of the content + */ + inline bool contains(char cc) const { + return indexOf(cc) >= 0; + } + /** @brief Tests whether a c string is part of the content. + * @param part array to test + * @return true: part is a part of the content + */ + inline bool contains(const char* part) const{ + return indexOf(part, -1) >= 0; + } + /** @brief Tests whether a byte array is part of the instance's content. + * @param part array to test + * @return true: part is a part of the content + */ + inline bool contains(const ReByteArray& part) const{ + return indexOf(part.constData(), part.length()) >= 0; + } + int count(const char* toCount, size_t lengthToCount = -1); + /** @brief Returns whether the byte array is empty. + * @return true: the byte array is empty (the length is 0) + */ + inline bool empty() const { + return m_length == 0; + } + bool endsWith(const Byte* tail, size_t tailLength = -1, bool ignoreCase = + false) const; + /** @brief Test whether a given character is the end of the instance's content. + * @param tail the array to test + * @param ignoreCase true: the comparison is case insensitive + * @return true: tail is found at the end + */ + inline + bool endsWith(char tail, bool ignoreCase = false) const{ + return m_length > 0 && tolower(tail) == tolower(m_buffer[m_length-1]); + } + /** @brief Test whether a given byte array is the end of the instance's content. + * @param tail the array to test + * @param ignoreCase true: the comparison is case insensitive + * @return true: tail is found at the end + */ + inline + bool endsWith(const ReByteArray& tail, bool ignoreCase = false) const{ + return endsWith((const Byte*) tail.str(), (size_t) tail.length(), ignoreCase); + } + void ensureSize(size_t size); + /** After the call the last character is the given. + * @param aChar the character which will be the last + * @return *this (for chaining) + */ + inline + ReByteArray& ensureLastChar(char aChar) { + if (lastChar() != aChar) + appendChar(aChar); + return *this; + } + /** @brief Tests whether another instance is equal to this instance. + * @param data string to compare + * @param length length of data. If -1: strlen(data) + * @param ignoreCase true: case insensitive comparison + * @return true: the buffer's contents are equal + */ + inline + bool equals(const char* data, size_t length = (size_t) -1, + bool ignoreCase = false) const { + if (length == (size_t) -1) + length = strlen(data); + bool rc = length == m_length + && ((!ignoreCase && _memcmp(data, m_buffer, length) == 0) + || (ignoreCase && _strnicmp(data, m_buffer, length) == 0)); + return rc; + } + /** @brief Tests whether another instance is equal to this instance. + * @param buffer the buffer to compare + * @param ignoreCase true: case insensitive comparison + * @return true: the buffer's contents are equal + */ + inline + bool equals(const ReByteArray& buffer, bool ignoreCase = false) const { + bool rc = buffer.length() == m_length + && ((!ignoreCase && _memcmp(buffer.str(), m_buffer, m_length) == 0) + || (ignoreCase + && _strnicmp(buffer.str(), m_buffer, m_length) == 0)); + return rc; + } + ReByteArray& fill(Byte filler = 0, int start = 0, int end = -1); + int firstDifference(const Byte* source, size_t length, int start = 0, + bool ignoreCase = false); + /** @brief Finds the index of the first occurrence of a given byte. + * @param toFind This byte will be searched. + * @param start The first index for searching. + * @return -1: not found. Otherwise: The index of the first occurrence. + */ + inline + int indexOf(Byte toFind, int start = 0) const { + while ((size_t) start < m_length) + if (m_buffer[start++] == toFind) + return start - 1; + return -1; + } + int indexOf(const Byte* toFind, size_t toFindLength, int start = 0, + int end = -1, bool ignoreCase = false) const; + /** @brief Inserts a byte sequence. + * @param ix The position in the internal buffer for the insertion. + * @param source The sequence to insert. + * @param length The length of the inserted sequence. + * + * @return true: Success. false: ix out of range. + */ + inline + 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); + /** Returns the last character. + * @return '\0': empty buffer
+ * otherwise: the last character + */ + inline + char lastChar() const { + return m_length == 0 ? '\0' : m_buffer[m_length - 1]; + } + /**@brief Returns the length of the buffer (the count of used bytes). + * @return The count of the allocated bytes in the internal buffer. + */ + inline size_t length() const { + return m_length; + } + /** Sets the length to a lower value. + * @param decrement the count to reduce the length + * @return The count of the allocated bytes in the internal buffer. + */ + inline ReByteArray& reduceLength(int decrement = 1) { + if (decrement > 0 && m_length > 0) { + if (decrement > (int) m_length) + decrement = m_length; + setLength(m_length - decrement); + } + return *this; + } + /** @brief Cuts a sequence from the internal buffer. + * + * @param ix The index where the cut/insertion takes place. + * @param deletedLength The number of deleted bytes. + * This value may be larger than the existing bytes. + * + * @return true: Success. false: ix out of range. + */ + inline + bool remove(size_t ix, size_t deletedLength) { + return splice(ix, deletedLength, NULL, 0); + } + /** Replaces a given character by another. + * @param toFind the character which will be replaced + * @param replacement the replacement character + * @param start only characters behind this index will be replaced + * @return *this (for chaining) + */ + inline + ReByteArray& replace(char toFind, char replacement, int start = 0){ + return replaceAll(reinterpret_cast(&toFind), 1, + reinterpret_cast(&replacement), 1, start); + } + ReByteArray& replaceAll(const Byte* toFind, size_t toFindLength, + const Byte* replacement, size_t replacementLength, int start = 0); + /** Removes an unwanted character at the end. + * @param aChar character to remove + * @return *this (for chaining) + */ + inline ReByteArray& removeLastChar(char aChar) { + if (m_length > 0 && m_buffer[m_length - 1] == aChar) + setLength(m_length - 1); + return *this; + } + /** @brief Finds the index of the last occurrence of a given byte (reverse index of). + * @param toFind This byte will be searched. + * @param start The first index for searching. If < 0: relative to the end. + * @return -1: not found. Otherwise: The index of the last occurrence. + */ + inline + int rindexOf(Byte toFind, int start = -1) const { + if (start < 0) + start = m_length + start; + while (start >= 0) + if (m_buffer[start--] == toFind) + return start + 1; + return -1; + } + int rindexOf(const Byte* toFind, size_t toFindLength, int start = 0, + int end = -1, bool ignoreCase = false) const; + /** @brief Sets the content of the buffer by copying a byte sequence. + * @param source The byte sequence to copy. + * @param length The length of source. + * @return *this (for chaining). + */ + inline ReByteArray& set(const Byte* source, size_t length) { + return setLength(0).append(source, length); + } + /** @brief Sets the content of the buffer by copying a byte sequence. + * @param source the source to copy. + * @return *this (for chaining). + */ + inline ReByteArray& set(const ReByteArray& source) { + return setLength(0).append(source); + } + void setDelta(int delta); + ReByteArray& setLength(size_t length); + ReByteArray& setLengthAndFillOut(size_t length, Byte filler = 0); + bool splice(size_t ix, size_t replacedLength, const Byte* source, + size_t length); + bool startsWith(const Byte* head, size_t headLength = -1, + const bool ignoreCase = false) const; + const char* status(ReByteArray& buffer, const char* prefix = NULL) const; + /** @brief Returns the buffer content as C string. + * This is exactly the same result as from getBuffer(). + * @return The internal used buffer. + */ + inline + const char* str() const { + return (const char*) m_buffer; + } +protected: + //@ If the needed space is small enough this buffer will be used. + char m_primaryBuffer[PRIMARY_BUFFER_SIZE]; + // The minimum difference between old and new size after a new allocation. + int m_delta; + //@ The internal buffer. Points to m_primaryBuffer if the space is small enough. + char* m_buffer; + //@ The used bytes in m_buffer. + size_t m_length; + //@ The size of m_buffer. + size_t m_capacity; + //@ number of reallocation in ensureSize() + int m_reallocation; +}; + +#endif /* REBYTEBUFFER_H_ */ diff --git a/base/ReByteBuffer.cpp b/base/ReByteBuffer.cpp deleted file mode 100644 index 01a7f55..0000000 --- a/base/ReByteBuffer.cpp +++ /dev/null @@ -1,930 +0,0 @@ -/* - * ReByteBuffer.cpp - * - * License: Public Domain - * You can use and modify this file without any restriction. - * Do what you want. - * No warranties and disclaimer of any damages. - * You also can use this license: http://www.wtfpl.net - * The latest sources: https://github.com/republib - */ - -#include "base/rebase.hpp" - -#ifdef __linux__ -extern void* memcpy(void* dest, const void* src, size_t n); -extern void* memmove(void* dest, const void* src, size_t n); -extern int _memcmp (const void* s1, const void* s2, size_t n); -extern int _snprintf(char* s, size_t maxlen, const char* format, ...); -#endif - -/** @brief Constructor. - * - * @param delta If a new storage must be allocated the size - * is incremented by at least this count of bytes - */ -ReByteBuffer::ReByteBuffer(size_t delta) : - m_delta(delta), - // m_primaryBuffer - m_buffer(m_primaryBuffer), - m_length(0), - m_capacity(sizeof m_primaryBuffer - 1), - m_reallocation(0) { - m_buffer[0] = '\0'; -} -/** @brief Constructor. - * - * @param source the instance to copy (C string) - */ -ReByteBuffer::ReByteBuffer(const char* source) : - m_delta(PRIMARY_BUFFER_SIZE), - // m_primaryBuffer - m_buffer(m_primaryBuffer), - m_length(0), - m_capacity(sizeof m_primaryBuffer), - m_reallocation(0) { - m_buffer[0] = '\0'; - if (source != NULL) - append(source); -} - -/** @brief Constructor. - * - * @param source The byte sequence to copy - * @param sourceLength length of source - */ -ReByteBuffer::ReByteBuffer(const Byte* source, size_t sourceLength) : - m_delta(PRIMARY_BUFFER_SIZE), - // m_primaryBuffer - m_buffer(m_primaryBuffer), - m_length(0), - m_capacity(sizeof m_primaryBuffer - 1), - m_reallocation(0) { - m_buffer[0] = '\0'; - append(source, sourceLength); -} - -/** @brief Destructor. - * - */ -ReByteBuffer::~ReByteBuffer() { - if (m_buffer != m_primaryBuffer) - delete[] m_buffer; - m_buffer = NULL; - m_capacity = 0; - m_length = 0; -} -/** @brief Copy constructor. - * - * @param source the instance to copy - */ -ReByteBuffer::ReByteBuffer(const ReByteBuffer& source) : - m_delta(source.delta()), - // m_primaryBuffer - m_buffer(m_primaryBuffer), - m_length(0), - m_capacity(sizeof m_primaryBuffer), - m_reallocation(0) { - append(source.buffer(), source.length()); -} - -/** @brief The assignment operator. - * - * @param source the instance to copy - * - * @return the instance itself - */ -ReByteBuffer& ReByteBuffer::operator =(const ReByteBuffer& source) { - m_delta = source.delta(); - set(source.buffer(), source.length()); - return *this; -} - -/** @brief Appends a byte sequence at the end of the buffer. - * - * If the space is not enough it will be allocated. - * - *
Example:
- * ReByteBuffer buf;
- * assert(4 == buf.append("abc", 3).append("x").getLength());
- * 
- * - * @param source the sequence to append - * @param length the length of the sequence - * - * @return *this (for chaining) - */ -ReByteBuffer& ReByteBuffer::append(const Byte* source, size_t length) { - if (source != NULL) { - if (length == (size_t) -1) - length = strlen(source); - ensureSize(m_length + length); - memcpy((void*) (m_buffer + m_length), source, length); - m_length += length; - m_buffer[m_length] = '\0'; - } - return *this; -} -/** @brief Appends the content of another ReByteBuffer instance at the end of the buffer. - * - * If the space is not enough it will be allocated. - * - *
Example:
- * ReByteBuffer name; name.append("mydoc");
- * ReByteBuffer ext; ext.append(".txt");
- * name.append(ext);
- * assert("mydoc.txt", name.getBuffer());
- * 
- * - * @return *this (for chaining) - */ -ReByteBuffer& ReByteBuffer::append(const ReByteBuffer& source) { - return append(source.str(), source.length()); -} - -/** @brief Appends a floaating point number at the end of the buffer. - * - * If the space is not enough it will be allocated. - * - *
Example:
- * ReByteBuffer buf; buf.append("amount: ").append(377 / 100.0, "%5.2f");
- * assert("amount:   3.77", buf.str());
- * 
- * - * @return *this (for chaining) - */ -ReByteBuffer& ReByteBuffer::append(double value, const char* format) { - char buffer[256]; - - _snprintf(buffer, sizeof buffer, format, value); - append(buffer, -1); - return *this; -} - -/** - * Appends a string with minimal/maximal length. - * - * If the length is greater than the maximal length the string will be cutted - * (in the middle) and a separator will set at the cut. - * - *
Example:
- * buffer.appendFix("sammy2", -1, 5, 5, "*").appendFix("x", 1, 99, -3);
- * 
- * Buffer contains: "sa*y2  x"
- * 
- * - * @param data data to append - * @param length length of data. -1: strlen(data) - * @param maxLength the stored length is at most this value - * @param minLength if the length is smaller padding characters will be added
- * < 0: padding is done at the top - * @param separator NULL or the string used at the separaration point - * @param padding character used for padding (see minLength) - * @return *this (for chaining) - */ -ReByteBuffer& ReByteBuffer::appendFix(const char* data, size_t length, - int maxLength, int minLength, const char* separator, char padding) { - if (length == (size_t) -1) - length = strlen(data); - if ((int) length < abs(minLength)) { - ensureSize(m_length + abs(minLength)); - if (minLength < 0) - appendChar(padding, -minLength - length); - append(data, length); - if (minLength > 0) - appendChar(padding, minLength - length); - } else if ((int) length > maxLength) { - ensureSize(m_length + maxLength); - int sepLength = separator == NULL ? 0 : strlen(separator); - int lengthPart1 = (maxLength - sepLength + 1) / 2; - int lengthPart2 = maxLength - sepLength - lengthPart1; - append(data, lengthPart1); - if (sepLength > 0) - append(separator, sepLength); - append(data + length - lengthPart2, lengthPart2); - } else { - append(data, length); - } - return *this; -} - -/** - * Appends data as string or as binary (hexdump). - * - * If data contains non ASCII char the data will be treated as binary. - * - * @param data the data to append - * @param length -1 (strlen()) or the length of data - * @param maxLength the maximal count of appended chars - * @return *this (chaining) - */ -ReByteBuffer& ReByteBuffer::appendDump(const char* data, size_t length, - int maxLength) { - if (length == size_t(-1)) { - length = strlen(data); - } - if ((int) length > maxLength) - 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')) { - isBinary = true; - break; - } - } - if (!isBinary) - append(data, length); - else - appendHexDump(data, min(length, maxLength / 5)).reduceLength(); - return *this; -} -/** - * Appends a hexadecimal dump of a memory array. - * - *
Example:
- * buffer.appendHex("01234567890abcde", -1, 0x10, 16, "%0x8x", 1, -1, " | ");
- * 
- * Buffer contains:
- * 00000010  30 31 32 33 34 35 36 37  38 39 30 61 62 63 64 65 | 01234567890abcde
- * 
- * - * @param data data to dump - * @param length length of data. -1: strlen(data) - * @param offset a format which is used to append a preceeding position - * of source. NULL: no offset is appended - * @param bytesPerLine number of bytes in one line. If length is greater more - * lines are appended - * @param offsetFormat NULL or the sprintf format of the offset, e.g. "0x04x " - * @param withAscii true: the data is interpreted as ASCII too - * @param groupWidth behind groupWidth hex bytes a ' ' is appended - * @param gapBehind behind gapBehind hex bytes a ' ' is appended
- * -1: bytePerLine / 2 - * @param separator NULL or a string between hex area and ASCII area - * @return *this (for chaining) - */ -ReByteBuffer& ReByteBuffer::appendHexDump(const char* data, size_t length, - int offset, int bytesPerLine, const char* offsetFormat, bool withAscii, - int groupWidth, int gapBehind, const char* separator) { - if (length == (size_t) -1) - length = strlen(data); - if (gapBehind < 0) - gapBehind = bytesPerLine / 2; - ensureSize(32); - int offsetLength = 0; - if (offsetFormat != NULL) { - _snprintf(m_buffer, 31, offsetFormat, offset + length); - offsetLength = strlen(m_buffer); - } - ensureSize( - (length + bytesPerLine - 1) / bytesPerLine - * (4 + offsetLength - + (gapBehind <= 0 ? 0 : bytesPerLine / gapBehind + 1) - + (separator == NULL ? 0 : strlen(separator)) + 1)); - while (length > 0) { - if (offsetFormat != NULL) - appendInt(offset, offsetFormat); - int ix; - for (ix = 0; ix < bytesPerLine; ix++) { - if (ix < (int) length) - appendInt((unsigned char) data[ix], "%02x"); - else - append(" "); - if (ix < bytesPerLine - 1 - && (groupWidth == 1 || ix % groupWidth == groupWidth - 1)) - appendChar(' '); - if (ix < bytesPerLine - 1 && gapBehind > 0 - && (gapBehind == 1 || ix % gapBehind == gapBehind - 1)) - appendChar(' '); - } - if (withAscii) { - if (separator != NULL) - append(separator, -1); - char cc; - for (ix = 0; ix < bytesPerLine; ix++) { - if (ix < (int) length) - appendInt((cc = data[ix]) < ' ' || cc > 127 ? '.' : cc, - "%c"); - else - append(" "); - if (ix < bytesPerLine - 1 && gapBehind > 0 - && (gapBehind == 1 || ix % gapBehind == gapBehind - 1)) - append(" ", 1); - } - appendChar('\n'); - length = - length <= (size_t) bytesPerLine ? 0 : length - bytesPerLine; - data += bytesPerLine; - offset += bytesPerLine; - } - } - return *this; -} - -/** @brief Appends an integer as string at the end of the buffer. - * - * If the space is not enough it will be allocated. - * - *
Example:
- * ReByteBuffer buf; buf.appendInt(33, "%-4d");
- * assert(strcmp("33  ", buf.str()) == 0);
- * 
- * - * @param number the number to append - * @param format the format of the number used by sprintf() - * - * @return *this (for chaining) - */ -ReByteBuffer& ReByteBuffer::appendInt(int number, const char* format) { - char buffer[128]; - - _snprintf(buffer, sizeof buffer, format, number); - append(buffer, -1); - return *this; -} - -/** @brief Appends an integer as string at the end of the buffer. - * - * If the space is not enough it will be allocated. - * - *
Example:
- * ReByteBuffer buf; buf.appendInt(33U, "%x");
- * assert(strcmp("21  ", buf.str()) == 0);
- * 
- * - * @param number the number to append - * @param format the format of the number used by sprintf() - * - * @return *this (for chaining) - */ -ReByteBuffer& ReByteBuffer::appendInt(unsigned int number, const char* format) { - char buffer[128]; - - _snprintf(buffer, sizeof buffer, format, number); - append(buffer, -1); - return *this; -} - -/** @brief Appends an integer as string at the end of the buffer. - * - * If the space is not enough it will be allocated. - * - *
Example:
- * ReByteBuffer buf; buf.appendInt(12345678901ll, "%12d");
- * assert(strcmp(" 12345678901", buf.str()) == 0);
- * 
- * - * @param number the number to append - * @param format the format of the number used by sprintf() - * - * @return *this (for chaining) - */ -ReByteBuffer& ReByteBuffer::appendInt(int64_t number, const char* format) { - char buffer[256]; - - _snprintf(buffer, sizeof buffer, format, number); - append(buffer, -1); - return *this; -} - -/** @brief Appends an integer as string at the end of the buffer. - * - * If the space is not enough it will be allocated. - * - *
Example:
- * ReByteBuffer buf; buf.appendInt((uint64_t) 0x12345678901ll, "%12x");
- * assert(strcmp(" 12345678901", buf.str()) == 0);
- * 
- * - * @param number the number to append - * @param format the format of the number used by sprintf() - * - * @return *this (for chaining) - */ -ReByteBuffer& ReByteBuffer::appendInt(uint64_t number, const char* format) { - char buffer[256]; - - _snprintf(buffer, sizeof buffer, format, number); - append(buffer, -1); - return *this; -} - -/** @brief Appends a time (given in milli seconds) as 'dd:HH:MM.mmm'. - * - * @param time the time (duration) in msec - * @param minLength > 5: seconds will be 2 digits (preceeding '0' if needed)
- * > 6: at least MM:SS.sss
- * > 9: at least HH:MM:SS.sss
- * > 12: at least dd:HH:MM:SS.sss
- * @return buffer (for chaining) - */ -ReByteBuffer& ReByteBuffer::appendMilliSec(int time, int minLength) { - int days = time / (24 * 3600 * 1000LL); - time %= 24 * 3600 * 1000; - int expectedLength = days > 0 ? 12 : 0; - int hours = time / (3600 * 1000); - time %= 3600 * 1000; - if (hours > 0 && expectedLength == 0) - expectedLength = 9; - int minutes = time / (60 * 1000); - time %= 60 * 1000; - if (minutes > 0 && expectedLength == 0) - expectedLength = 5; - int minimum = minLength > expectedLength ? minLength : expectedLength; - int sec = time / 1000; - int msec = time % 1000; - static const char* stdFormat = "%02d"; - if (days > 0 || minimum > 12) - appendInt(days).append(":"); - if (hours > 0 || minimum > 9) - appendInt(hours, stdFormat).append(":"); - if (minutes > 0 || minimum > 6) - appendInt(minutes, stdFormat).append(":"); - appendInt(sec, sec > 10 || minimum > 5 ? stdFormat : "%d").append("."); - appendInt(msec, "%03d"); - return *this; -} - -/** @brief Appends a time (given in milli seconds) as 'dd:HH:MM.mmm'. - * - * @param time the time (duration) in msec - * @param minLength > 3: seconds will be 2 digits (preceeding '0' if needed)
- * > 4: at least MM:SS.sss
- * > 7: at least HH:MM:SS.sss
- * > 10: at least dd:HH:MM:SS
- * @return buffer (for chaining) - */ -ReByteBuffer& ReByteBuffer::appendTime(int time, int minLength) { - int days = time / (24 * 3600); - time %= 24 * 3600; - int expectedLength = days > 0 ? 10 : 0; - int hours = time / 3600; - time %= 3600; - if (hours > 0 && expectedLength == 0) - expectedLength = 7; - int minutes = time / 60; - time %= 60; - if (minutes > 0 && expectedLength == 0) - expectedLength = 3; - int minimum = minLength > expectedLength ? minLength : expectedLength; - int sec = time; - static const char* stdFormat = "%02d"; - if (days > 0 || minimum > 10) - appendInt(days).append(":"); - if (hours > 0 || minimum > 7) - appendInt(hours, stdFormat).append(":"); - if (minutes > 0 || minimum > 4) - appendInt(minutes, stdFormat).append(":"); - appendInt(sec, sec > 10 || minimum > 3 ? stdFormat : "%d"); - return *this; -} - -/** Converts a subsequence into an integer. - * - * The number may be a decimal or a hexadecimal number. Hex numbers start with 0x. - *
Example:
- * ReByteBuffer buf;
- * buf.set("abc123", 6);
- * assert(12 == buf.atoi(3, 3 + 2));
- * 
- * - * @param start the first index to convert - * @param end -1: all found digits will be converted - * Otherwise: the maximal number of digits to convert - */ -int ReByteBuffer::atoi(size_t start, int end) const { - int rc = 0; - if (start < m_length) { - if (end < 0) - end = m_length; - char cc; - if (m_buffer[start] == '0' && tolower(m_buffer[start + 1]) == 'x') { - // Hexadecimal number: - start += 2; - while (start < (size_t) end && (cc = m_buffer[start++]) >= '0' - && isxdigit(cc)) - rc = rc * 16 + (cc <= '9' ? cc - '0' : toupper(cc) - 'A' + 10); - } else { - // Decimal number: - while (start < (size_t) end && (cc = m_buffer[start++]) >= '0' - && cc <= '9') - rc = rc * 10 + cc - '0'; - } - } - return rc; -} - -/** - * Counts the occurrencies of a given byte sequence. - * - * @param toCount the byte sequence to count - * @param lengthOfToCount -1: length is strlen(toCount)
- * otherwise: length of toCount - */ -int ReByteBuffer::count(const char* toCount, size_t lengthToCount) { - int rc = 0; - size_t start = 0; - if (lengthToCount == (size_t) -1) - lengthToCount = strlen(toCount); - while ((start = indexOf(toCount, lengthToCount, start)) != (size_t) -1) { - rc++; - start += lengthToCount; - } - return rc; -} - -/** - * Tests whether the buffer ends with a given a byte sequence. - * - * @param tail the byte sequence to test - * @param tailLength -1: strlen(tail)
- * otherwise: the length of tail - * @param ignoreCase true: the comparison is case insensitive
- * false: the comparison is case sensitive
- * @return true: the buffer ends with tail
- * false: otherwise - */ -bool ReByteBuffer::endsWith(const Byte* tail, size_t tailLength, - bool ignoreCase) const { - bool rc = tail != NULL; - if (rc) { - if (tailLength == (size_t) -1) - tailLength = strlen(tail); - rc = indexOf(tail, tailLength, m_length - tailLength, m_length, - ignoreCase) >= 0; - } - return rc; -} - -/** @brief Ensures that there is enough space. - * - * If not it will be allocated and the old value will be copied. - * - * A new allocation will be use at least m_delta bytes. - * The allocated space is incremented by one because of the ending '\\0'. - * - * @param size the size will be at least this value - */ -void ReByteBuffer::ensureSize(size_t size) { - if (m_capacity < size) { - int delta = - m_delta > 0 ? m_delta : - (int) m_capacity < -m_delta / 2 ? (int) 2 * m_capacity : -m_delta; - if (int(size - m_capacity) < delta) - size = m_capacity + delta; - // Think for the ending '\0': - Byte* buffer = new Byte[size + 1]; - assert(buffer != NULL); - if (m_length > 0) - memcpy(buffer, m_buffer, m_length); - buffer[m_length] = '\0'; - if (m_buffer != m_primaryBuffer) - delete[] m_buffer; - m_buffer = buffer; - m_capacity = size; - m_reallocation++; - } -} -/** - * @brief Fills a part of the buffer with a given character. - * - * @param filler the byte which is used as filler - * @param start the first index to fill. 0 <= start < m_length - * @param end the index behind the last filled position. May be behind m_length - * @return the instance itself (vor chaining) - */ -ReByteBuffer& ReByteBuffer::fill(Byte filler, int start, int end) { - if (end == -1) - end = m_length; - if (start >= 0 && start < end) { - if (end > (int) m_length) - setLength(end); - memset(m_buffer + start, filler, end - start); - } - return *this; -} - -/** @brief Checks for the index of the first different byte. - * - * @param source source to inspect - * @param length -1 or the length of source - * @param start the first index to inspect - * @param ignoreCase true: the comparison is case insensitive - * @return -1: both byte sequences are equal
- * otherwise: the index of the first difference - */ -int ReByteBuffer::firstDifference(const Byte* source, size_t length, int start, - bool ignoreCase) { - int rc = -1; - if (start < 0) - rc = 0; - else if (start < (int) m_length) { - if (length == (size_t) -1) - length = strlen(source); - int count = length > m_length - start ? m_length - start : length; - const Byte* ptr = m_buffer + start; - for (int ix = 0; rc < 0 && ix < count; ix++) { - if ((!ignoreCase && *ptr++ != *source++) - || (ignoreCase && (tolower(*ptr++) != tolower(*source++)))) - rc = start + ix; - } - if (rc < 0 && length > m_length - start) - rc = start + count; - } - return rc; -} - -/** @brief Searches for a byte sequence in the internal buffer. - * - * Finds the first occurrence of a byte sequence in a given range. - * - *
Example:
- * ReByteBuffer buf;
- * buf.set("12abc123", 8);
- * assert(5 == buf.indexOf("12", -1, 3));
- * 
- * - * @param toFind the sequence to find - * @param toFindLength Length of toFind, - * If -1 the strlen(toFind) will be taken - * @param start the search respects the indices in the range [start, end[ - * @param end -1: no upper limit to search
- * otherwise: the first index above the search range - * @param ignoreCase true: case insensitive search
- * true: case sensitive search - * @return -1: the sequence could not be found. - * Otherwise: the index of toFind in the internal buffer - */ -int ReByteBuffer::indexOf(const Byte* toFind, size_t toFindLength, int start, - int end, bool ignoreCase) const { - if (toFindLength == (size_t) -1) - toFindLength = strlen(toFind); - int rc = -1; - if (end < 0 || end > (int) m_length) - end = m_length; - if (start >= 0 && start <= int(m_length - toFindLength) - && end >= (int) toFindLength && end <= (int) m_length) { - while (rc < 0 && start <= int(end - toFindLength)) { - if (ignoreCase ? - _memicmp((void*) toFind, (void*) (m_buffer + start), - toFindLength) == 0 : - _memcmp(toFind, m_buffer + start, toFindLength) == 0) - rc = start; - else - start++; - } - } - return rc; -} -/** - * Tests whether the instance is a prefix of a given string. - * - * @param source the string to inspect - * @param length the length of the string
- * -1: strlen(source) - * @param ignoreCase true: the test is case insensitive - * @param minLength the substring (instance) must have at least this length - * for a positive test - * @return truethe instance is a prefix of the source - * and the length is at least minLength bytes - */ -bool ReByteBuffer::isPrefixOf(const char* source, size_t length, - bool ignoreCase, int minLength) { - if (length == (size_t) -1) - length = strlen(source); - bool rc = length >= m_length && m_length <= length; - if (rc) - rc = equals(source, m_length, ignoreCase); - return rc; -} - -/** @brief Searches revers for a byte sequence in the internal buffer. - * - * Finds the last occurrence of a byte sequence in a given range. - * - *
Example:
- * ReByteBuffer buf;
- * buf.set("12abc123", 8);
- * assert(5 == buf.rindexOf("12", -1, 3));
- * 
- * - * @param toFind the sequence to find - * @param toFindLength length of toFind. - * If -1 the strlen(toFind) will be taken - * @param start the search respects the indices in the range [start, end[ - * @param end -1: no upper limit to search
- * otherwise: the first index above the search range - * @param ignoreCase true: case insensitive search
- * true: case sensitive search - * @return -1: the sequence could not be found. - * Otherwise: the index of toFind in the internal buffer - */ -int ReByteBuffer::rindexOf(const Byte* toFind, size_t toFindLength, int start, - int end, bool ignoreCase) const { - if (toFindLength == (size_t) -1) - toFindLength = strlen(toFind); - int rc = -1; - if (end < 0 || end > (int) m_length) - end = m_length; - if (start >= 0 && start <= int(m_length - toFindLength) - && end >= (int) toFindLength && end <= (int) m_length) { - int current = end - toFindLength; - while (current >= start) { - if (ignoreCase ? - _strnicmp(toFind, m_buffer + current, toFindLength) != 0 : - _memcmp(toFind, m_buffer + current, toFindLength) != 0) - current--; - else { - rc = current; - break; - } - } - } - return rc; -} -/** @brief Replaces all occurrences of toFind with replacement. - * - * A single replacement can be done with splice(). - * - *
Example:
- * ReByteBuffer buf;
- * buf.set("12abc123", 8);
- * buf.replaceAll("12", -1, "XYZ", -1);
- * assert(strcmp("XYZabcXYZ3", buf.str()) == 0);
- * 
- * - * @param toFind the substring which will be replaced - * @param toFindLength the length of toFind. -1: strlen() will be used - * @param replacement the replacement - * @param replacementLength the length of replacement. -1: strlen() will be used - * @param start the first index to inspect - */ -ReByteBuffer& ReByteBuffer::replaceAll(const Byte* toFind, size_t toFindLength, - const Byte* replacement, size_t replacementLength, int start) { - if (toFindLength == size_t(-1)) - toFindLength = strlen(toFind); - if (replacementLength == size_t(-1)) - replacementLength = strlen(replacement); - - while ((start = indexOf(toFind, toFindLength, start)) != -1) { - splice(start, toFindLength, replacement, replacementLength); - start += replacementLength; - } - return *this; -} - -/** @brief Sets the increment used to increase the capacity. - * - * @param delta > 0: reservation allocates at least this amount of bytes
- * 0: delta is set to a default value
- * < 0: the current capacity will be doubled until - delta - */ -void ReByteBuffer::setDelta(int delta) { - m_delta = delta == 0 ? PRIMARY_BUFFER_SIZE : delta; -} - -/** @brief Sets the length to a given value. - * - * The new length is greater than the current size the buffer will reallocated. - * - *
Example:
- * ReByteBuffer buf;
- * buf.set("123", 3);
- * buf.setLength(5);
- * assert(strcmp("123", buf.str()) == 0);
- * assert(5 == buf.getLength());
- * 
- * - * @param length the new length - * - * @return *this (for chaining) - */ -ReByteBuffer& ReByteBuffer::setLength(size_t length) { - ensureSize(length); - m_length = length; - m_buffer[length] = '\0'; - return *this; -} -/** @brief Sets the length to a given value and fills the new allocated part of the buffer with a given value. - * - * The new length is greater than the current size the buffer will reallocated. - * - *
Example:
- * ReByteBuffer buf;
- * buf.set("123", 3);
- * buf.setLengthAndFill(5, 'X');
- * assert(strcmp("123XX", buf.str()) == 0);
- * 
- * - * @param length the new length - * @param filler if the new length is greater than the current length the space - * will be filled with this value - * @return *this (for chaining) - */ -ReByteBuffer& ReByteBuffer::setLengthAndFillOut(size_t length, Byte filler) { - ensureSize(length); - if (length > m_length) - memset(m_buffer + m_length, filler, length - m_length); - m_length = length; - m_buffer[length] = '\0'; - return *this; -} -/** @brief Cuts a sequence from the internal buffer and inserts another. - * - * This function implies a pure insertion and pure deletion of a subsequence. - * - *
Example:
- * ReByteBuffer buf;
- * buf.set("12345", 5);
- * buf.splice(2, 2, "XYZ", 3);
- * assert(strcmp("12XYZ5", buf.str()) == 0);
- * 
- * - * @param ix the index where the cut/insertion takes place - * @param replacedLength the number of deleted bytes. If 0 a pure insertion will be done - * @param source the sequence to insert. May be NULL (for pure deletion) - * @param length the length of the inserted sequence
- * 0: a pure deletion will be done
- * -1: strlen(source) will be taken - * - * @return true: Success. false: ix out of range - */ -bool ReByteBuffer::splice(size_t ix, size_t replacedLength, - const ReByteBuffer::Byte* source, size_t length) { - bool rc; - if (ix < 0 || ix > m_length) - rc = false; - else { - rc = true; - - if (source == NULL) - length = 0; - if (length == (size_t) -1) - length = strlen(source); - if (ix + replacedLength > m_length) - replacedLength = m_length - ix; - - ensureSize(m_length + length - replacedLength); - - Byte* start = m_buffer + ix; - Byte* tail = start + replacedLength; - size_t lengthTail = m_length - ix - replacedLength; - - if (length <= replacedLength) { - // The sequence will not be longer: - if (length > 0) - memcpy(start, source, length); - if (length < replacedLength) { - memmove(start + length, tail, lengthTail); - } - } else { - // The sequence will be longer: - memmove(start + length, tail, lengthTail); - memcpy(start, source, length); - } - m_length += length - replacedLength; - m_buffer[m_length] = '\0'; - } - return rc; -} -/** - * Tests whether the buffer starts with a given a byte sequence. - * - * @param head the byte sequence to test - * @param headLength -1: strlen(tail)
- * otherwise: the length of tail - * @param ignoreCase true: the comparison is case insensitive
- * false: the comparison is case sensitive
- * @return true: the buffer starts with head
- * false: otherwise - */ -bool ReByteBuffer::startsWith(const Byte* head, size_t headLength, - const bool ignoreCase) const { - bool rc = head != NULL; - if (rc) { - if (headLength == (size_t) -1) - headLength = strlen(head); - rc = indexOf(head, headLength, 0, headLength, ignoreCase) == 0; - } - return rc; -} - -/** - * Appends the status data of the instance onto the buffer. - * - * @param buffer OUT: the space for the data report - * @param prefix NULL or a prefix of the output - * @return buffer.str() (for chaining) - */ -const char* ReByteBuffer::status(ReByteBuffer& buffer, - const char* prefix) const { - if (prefix != NULL) - buffer.append(prefix); - buffer.append("capacity:").appendInt(m_capacity).append(" length: ") - .appendInt(m_length).append(" realloc: ").appendInt(m_reallocation) - .append("\n"); - return buffer.str(); -} - diff --git a/base/ReByteBuffer.hpp b/base/ReByteBuffer.hpp deleted file mode 100644 index eba2d42..0000000 --- a/base/ReByteBuffer.hpp +++ /dev/null @@ -1,354 +0,0 @@ -/* - * ReByteBuffer.hpp - * - * License: Public Domain - * You can use and modify this file without any restriction. - * Do what you want. - * No warranties and disclaimer of any damages. - * You also can use this license: http://www.wtfpl.net - * The latest sources: https://github.com/republib - */ - -#ifndef REBYTEBUFFER_H_ -#define REBYTEBUFFER_H_ - -#define PRIMARY_BUFFER_SIZE 513 -/** @brief An efficient dynamic memory buffer. - * - * Implements a very efficient dynamic byte sequence. - *

- * Note:
- * It is guaranteed that the sequence is terminated by a '\\0' like C strings. - * This end marker is outside the visible buffer.
- * Technically:
- * ReByteBuffer buf; assert(buf.getBuffer()[buf.getLength()] == '\\0'); - *

- *

This class can be used as a poor man's string class. - *

- *

Very effizient: - *

    - *
  • Every instance contains an array (512 Bytes), - * which is used if not more space is needed. - * In many cases there is no need of heap allocation (new or malloc().
  • - *
  • Many of the methods are written as inlines.
  • - *
- *

- */ -class ReByteBuffer { -public: - typedef char Byte; -public: - ReByteBuffer(size_t delta = PRIMARY_BUFFER_SIZE); - ReByteBuffer(const char* source); - ReByteBuffer(const Byte* source, size_t sourceLength); - virtual ~ReByteBuffer(); - ReByteBuffer(const ReByteBuffer& source); - ReByteBuffer& operator =(const ReByteBuffer& source); -public: - ReByteBuffer& append(const Byte* source, size_t length = -1); - ReByteBuffer& append(const ReByteBuffer& source); - ReByteBuffer& append(double, const char* format = "%f"); - /** Appends a 8 bit value in an architecture independent way. - * @param value integer to append - * @return *this (for chaining) - */ - 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 integer to append - * @return *this (for chaining) - */ - 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 integer to append - * @return *this (for chaining) - */ - 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); - m_buffer[m_length - 1] = char(value); - return *this; - } - /** Appends a 24 bit value in an architecture independent way. - * @param value integer to append - * @return *this (for chaining) - */ - 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 - 2] = char(value >> 8); - m_buffer[m_length - 1] = char(value); - return *this; - } - /** Appends a 64 bit value in an architecture independent way. - * @param value integer to append - * @return *this (for chaining) - */ - 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 - 6] = char(value >> 40); - m_buffer[m_length - 5] = char(value >> 32); - m_buffer[m_length - 4] = char(value >> 24); - m_buffer[m_length - 3] = char(value >> 16); - m_buffer[m_length - 2] = char(value >> 8); - m_buffer[m_length - 1] = char(value); - return *this; - } - /** Appends a character. - * @param aChar character to append - * @return *this (for chaining) - */ - inline ReByteBuffer& appendChar(char aChar) { - setLength(m_length + 1); - m_buffer[m_length - 1] = aChar; - return *this; - } - /** Appends a character at least one time. - * @param aChar character to append - * @param count number of times to append - * @return *this (for chaining) - */ - inline ReByteBuffer& appendChar(char aChar, int count) { - if (count > 0) { - size_t oldLength = m_length; - setLength(m_length + count); - memset(m_buffer + oldLength, aChar, count); - } - return *this; - } - 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& 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 = - -1, const char* separator = " | "); - ReByteBuffer& appendInt(int number, const char* format = "%d"); - ReByteBuffer& appendInt(unsigned int number, const char* format = "%d"); - ReByteBuffer& appendInt(int64_t number, const char* format = "%lld"); - ReByteBuffer& appendInt(uint64_t number, const char* format = "%lld"); - ReByteBuffer& appendMilliSec(int time, int minLength = 5); - ReByteBuffer& appendTime(int time, int minLength = 1); - /** @brief Returns the n-th byte of the internal buffer. - * @param index The index of the wanted byte. - * @return 0: Wrong index. Otherwise: The byte from the wanted position. - */ - inline Byte at(size_t index) const { - return index >= m_length ? 0 : m_buffer[index]; - } - int atoi(size_t start = 0, int end = -1) const; - /** @brief Returns the buffer (permitting modifying). - * @return The internal used buffer. - */ - inline Byte* buffer() const { - return m_buffer; - } - /**@brief Returns the current size of the internal buffer. - * @return The current size of the internal buffer. - */ - inline size_t capacity() const { - return m_capacity; - } - int count(const char* toCount, size_t lengthToCount = -1); - /**@brief Returns the minimum allocation unit. - * @return The minimum of bytes to allocate. - */ - inline size_t delta() const { - return m_delta; - } - bool endsWith(const Byte* tail, size_t tailLength = -1, bool ignoreCase = - false) const; - void ensureSize(size_t size); - /** After the call the last character is the given. - * @param aChar the character which will be the last - * @return *this (for chaining) - */ - inline ReByteBuffer& ensureLastChar(char aChar) { - if (lastChar() != aChar) - appendChar(aChar); - return *this; - } - /** @brief Tests whether another instance is equal to this instance. - * @param data string to compare - * @param length length of data. If -1: strlen(data) - * @param ignoreCase true: case insensitive comparison - * @return true: the buffer's contents are equal - */ - inline - bool equals(const char* data, size_t length, - bool ignoreCase = false) const { - if (length == (size_t) -1) - length = strlen(data); - bool rc = length == m_length - && ((!ignoreCase && _memcmp(data, m_buffer, length) == 0) - || (ignoreCase && _strnicmp(data, m_buffer, length) == 0)); - return rc; - } - /** @brief Tests whether another instance is equal to this instance. - * @param buffer the buffer to compare - * @param ignoreCase true: case insensitive comparison - * @return true: the buffer's contents are equal - */ - inline - bool equals(const ReByteBuffer& buffer, bool ignoreCase = false) const { - bool rc = buffer.length() == m_length - && ((!ignoreCase && _memcmp(buffer.str(), m_buffer, m_length) == 0) - || (ignoreCase - && _strnicmp(buffer.str(), m_buffer, m_length) == 0)); - return rc; - } - ReByteBuffer& fill(Byte filler = 0, int start = 0, int end = -1); - int firstDifference(const Byte* source, size_t length, int start = 0, - bool ignoreCase = false); - /** @brief Finds the index of the first occurrence of a given byte. - * @param toFind This byte will be searched. - * @param start The first index for searching. - * @return -1: not found. Otherwise: The index of the first occurrence. - */ - inline - int indexOf(Byte toFind, int start = 0) const { - while ((size_t) start < m_length) - if (m_buffer[start++] == toFind) - return start - 1; - return -1; - } - int indexOf(const Byte* toFind, size_t toFindLength, int start = 0, - int end = -1, bool ignoreCase = false) const; - /** @brief Inserts a byte sequence. - * @param ix The position in the internal buffer for the insertion. - * @param source The sequence to insert. - * @param length The length of the inserted sequence. - * - * @return true: Success. false: ix out of range. - */ - inline - 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); - /** Returns the last character. - * @return '\0': empty buffer
- * otherwise: the last character - */ - inline - char lastChar() const { - return m_length == 0 ? '\0' : m_buffer[m_length - 1]; - } - /**@brief Returns the length of the buffer (the count of used bytes). - * @return The count of the allocated bytes in the internal buffer. - */ - inline size_t length() const { - return m_length; - } - /** Sets the length to a lower value. - * @param decrement the count to reduce the length - * @return The count of the allocated bytes in the internal buffer. - */ - inline ReByteBuffer& reduceLength(int decrement = 1) { - if (decrement > 0 && m_length > 0) { - if (decrement > (int) m_length) - decrement = m_length; - setLength(m_length - decrement); - } - return *this; - } - /** @brief Cuts a sequence from the internal buffer. - * - * @param ix The index where the cut/insertion takes place. - * @param deletedLength The number of deleted bytes. - * This value may be larger than the existing bytes. - * - * @return true: Success. false: ix out of range. - */ - inline - bool remove(size_t ix, size_t deletedLength) { - return splice(ix, deletedLength, NULL, 0); - } - ReByteBuffer& replaceAll(const Byte* toFind, size_t toFindLength, - const Byte* replacement, size_t replacementLength, int start = 0); - /** Removes an unwanted character at the end. - * @param aChar character to remove - * @return *this (for chaining) - */ - inline ReByteBuffer& removeLastChar(char aChar) { - if (m_length > 0 && m_buffer[m_length - 1] == aChar) - setLength(m_length - 1); - return *this; - } - /** @brief Finds the index of the last occurrence of a given byte (reverse index of). - * @param toFind This byte will be searched. - * @param start The first index for searching. If < 0: relative to the end. - * @return -1: not found. Otherwise: The index of the last occurrence. - */ - inline - int rindexOf(Byte toFind, int start = -1) const { - if (start < 0) - start = m_length + start; - while (start >= 0) - if (m_buffer[start--] == toFind) - return start + 1; - return -1; - } - int rindexOf(const Byte* toFind, size_t toFindLength, int start = 0, - int end = -1, bool ignoreCase = false) const; - /** @brief Sets the content of the buffer by copying a byte sequence. - * @param source The byte sequence to copy. - * @param length The length of source. - * @return *this (for chaining). - */ - inline ReByteBuffer& set(const Byte* source, size_t length) { - return setLength(0).append(source, length); - } - /** @brief Sets the content of the buffer by copying a byte sequence. - * @param source the source to copy. - * @return *this (for chaining). - */ - inline ReByteBuffer& set(const ReByteBuffer& source) { - return setLength(0).append(source); - } - void setDelta(int delta); - ReByteBuffer& setLength(size_t length); - ReByteBuffer& setLengthAndFillOut(size_t length, Byte filler = 0); - bool splice(size_t ix, size_t replacedLength, const Byte* source, - size_t length); - bool startsWith(const Byte* head, size_t headLength = -1, - const bool ignoreCase = false) const; - const char* status(ReByteBuffer& buffer, const char* prefix = NULL) const; - /** @brief Returns the buffer content as C string. - * This is exactly the same result as from getBuffer(). - * @return The internal used buffer. - */ - inline - const char* str() const { - return (const char*) m_buffer; - } -protected: - // The minimum difference between old and new size after a new allocation. - int m_delta; - //@ If the needed space is small enough this buffer will be used. - char m_primaryBuffer[PRIMARY_BUFFER_SIZE]; - //@ The internal buffer. Points to m_primaryBuffer if the space is small enough. - char* m_buffer; - //@ The used bytes in m_buffer. - size_t m_length; - //@ The size of m_buffer. - size_t m_capacity; - //@ number of reallocation in ensureSize() - int m_reallocation; -}; - -#endif /* REBYTEBUFFER_H_ */ diff --git a/base/ReCString.cpp b/base/ReCString.cpp index 8bb4b5b..d4aec83 100644 --- a/base/ReCString.cpp +++ b/base/ReCString.cpp @@ -1,6 +1,6 @@ /* * ReCString.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. diff --git a/base/ReCString.hpp b/base/ReCString.hpp index d413c86..56f6f52 100644 --- a/base/ReCString.hpp +++ b/base/ReCString.hpp @@ -1,6 +1,6 @@ /* * ReCString.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. diff --git a/base/ReClassId.cpp b/base/ReClassId.cpp index 32f4b50..edf9576 100644 --- a/base/ReClassId.cpp +++ b/base/ReClassId.cpp @@ -1,6 +1,6 @@ /* * ReClassId.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -10,7 +10,7 @@ */ #include "base/rebase.hpp" -static ReByteBuffer s_unknownClassname; +static ReByteArray s_unknownClassname; const char* classIdToString(ReClassId classId) { const char* rc = "?"; diff --git a/base/ReClassId.hpp b/base/ReClassId.hpp index 3777581..5934c71 100644 --- a/base/ReClassId.hpp +++ b/base/ReClassId.hpp @@ -1,6 +1,6 @@ /* * ReClassId.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. diff --git a/base/ReConfigFile.cpp b/base/ReConfigFile.cpp index 4400c22..7d0abf2 100644 --- a/base/ReConfigFile.cpp +++ b/base/ReConfigFile.cpp @@ -1,6 +1,6 @@ /* * ReConfigFile.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -52,7 +52,7 @@ void ReConfigFile::readFile(const char* filename) { FILE* fp = fopen(filename, "r"); char line[4096]; char* equal; - ReByteBuffer buffer; + ReByteArray buffer; if (fp != NULL) { int lineNo = 0; @@ -85,7 +85,7 @@ void ReConfigFile::readFile(const char* filename) { * @return The wanted integer or the default value. */ int ReConfigFile::getInteger(const char* key, int defaultVal) { - ReByteBuffer value; + ReByteArray value; getString(key, value, NULL); int rc = defaultVal; if (!isdigit(value.at(0))) @@ -102,7 +102,7 @@ int ReConfigFile::getInteger(const char* key, int defaultVal) { * @param buffer Out: The buffer for the result string. * @param defaultVal If the key could not found this value will be returned. May be NULL. */ -void ReConfigFile::getString(const char* key, ReByteBuffer& buffer, +void ReConfigFile::getString(const char* key, ReByteArray& buffer, const char* defaultVal) { if (!get(key, -1, buffer)) { if (defaultVal == NULL) @@ -119,7 +119,7 @@ void ReConfigFile::getString(const char* key, ReByteBuffer& buffer, * @return The wanted boolean or the default value. */ bool ReConfigFile::getBool(const char* key, bool defaultVal) { - ReByteBuffer value; + ReByteArray value; getString(key, value, NULL); bool rc = defaultVal; if (ReStringUtils::isInList(value.str(), i18n(m_falseValues))) diff --git a/base/ReConfigFile.hpp b/base/ReConfigFile.hpp index 6f075e2..7737118 100644 --- a/base/ReConfigFile.hpp +++ b/base/ReConfigFile.hpp @@ -1,6 +1,6 @@ /* * ReConfigFile.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -27,7 +27,7 @@ private: public: void readFile(const char* filename); int getInteger(const char* key, int defaultVal = 0); - void getString(const char* key, ReByteBuffer& buffer, + void getString(const char* key, ReByteArray& buffer, const char* defaultVal = NULL); bool getBool(const char* key, bool defaultVal = false); /** @brief Returns whether the instance is in a valid state. @@ -37,7 +37,7 @@ public: return m_valid; } protected: - ReByteBuffer m_filename; + ReByteArray m_filename; bool m_valid; }; diff --git a/base/ReDirectory.cpp b/base/ReDirectory.cpp index 4288b6e..5b666c9 100644 --- a/base/ReDirectory.cpp +++ b/base/ReDirectory.cpp @@ -1,6 +1,6 @@ /* * ReDirectory.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -11,11 +11,16 @@ #include "base/rebase.hpp" +/// pattern for "all files", used in findFirst(): +const char* ReDirectory::ALL_FILES = ""; + /** @brief Constructor. */ ReDirectory::ReDirectory() : m_path(), m_pattern(), + m_currentFull(), + m_stat(), #if defined __linux__ m_dir(NULL), m_entry(NULL), @@ -79,10 +84,11 @@ void ReDirectory::close() { /** @brief Returns the name of the current file found by the last findFirst() * or findNext(). * - * @return NULL: No current file exists. Otherwise: The name of the current file. + * @return NULL: No current file exists
+ * Otherwise: The name of the current file (without path) * */ -const char* ReDirectory::currentFile() { +const char* ReDirectory::currentNode() { #if defined __linux__ const char* rc = m_entry == NULL ? NULL : m_entry->d_name; #elif defined __WIN32__ @@ -91,6 +97,44 @@ const char* ReDirectory::currentFile() { return rc; } +/** + * Returns the file status info of the current file. + * + * @param the status info given by lstat() + */ +struct stat& ReDirectory::currentLStat(){ + if (m_stat.st_gid == -1 && filetimeIsUndefined(m_stat.st_mtim)){ + lstat(currentFull().str(), &m_stat); + } + return m_stat; +} + +/** + * Returns whether the current file is a directory. + * + * @return true: the current file is a directory + */ +bool ReDirectory::currentIsDir(){ +#if defined __linux__ + return S_ISDIR(currentLStat().st_mode); +#elif defined __WIN32__ + return +#endif +} + +/** + * Returns whether the current file is a directory. + * + * @return true: the current file is a directory + */ +ReFileTime_t ReDirectory::currentModified(){ +#if defined __linux__ + return currentLStat().st_mtim; +#elif defined __WIN32__ + return +#endif +} + /** * Deletes a directory tree. * @@ -101,18 +145,17 @@ const char* ReDirectory::currentFile() { void ReDirectory::deleteTree(const char* base, bool deleteBaseToo) { if (true) { ReDirectory dir(base); - if (dir.findFirst("*", false)) { - ReByteBuffer full; + if (dir.findFirst(ALL_FILES, false)) { do { struct stat info; - const char* node = dir.currentFile(); + const char* node = dir.currentNode(); if ((!(node[0] == '.' && (node[1] == '\0' || (node[1] == '.' && node[2] == '\0')))) - && stat(dir.fullpath(full).str(), &info) == 0) { + && stat(dir.currentFull().str(), &info) == 0) { if (S_ISDIR(info.st_mode)) - deleteTree(full.str(), true); + deleteTree(dir.currentFull().str(), true); else - _unlink(full.str()); + _unlink(dir.currentFull().str()); } } while (dir.findNext()); } @@ -123,6 +166,27 @@ void ReDirectory::deleteTree(const char* base, bool deleteBaseToo) { } } +/** + * Returns the filetime of a given file. + * + * @param filename filename with path + * @param modified OUT: the modification date. May be NULL + * @param created OUT: the modification date. May be NULL + * @param accessed OUT: the modification date. May be NULL + */ +bool ReDirectory::filetime(const char* filename, ReFileTime_t* modified, + ReFileTime_t* created, ReFileTime_t* accessed){ +#if defined __linux__ + struct stat info; + bool rc = stat(filename, &info) == 0; + if (rc){ + if (modified != NULL) + ; + } +#elif defined __WIN32__ +#endif + return rc; +} /** @brief Returns the name of the directory. * * @return The name of the directory. @@ -133,8 +197,9 @@ const char* ReDirectory::getDir(void) const { /** @brief Find the first file with a given filename pattern. * - * @param pattern A filename pattern. - * @param isRegExpr true: The pattern contains regular expressions. false: The pattern contains wildcards. + * @param pattern A filename pattern. If "": delivery of all files + * @param isRegExpr true: The pattern contains regular expressions.
+ * false: The pattern contains wildcards. * * @return true: A file has been found. false: The directory contains no file with the given pattern. */ @@ -163,7 +228,7 @@ bool ReDirectory::findFirst(const char* pattern, bool isRegExpr) { rc = findNext(); } #elif defined __WIN32__ - ReByteBuffer full(m_path); + ReByteArray full(m_path); full.append(OS_SEPARATOR, -1).append(pattern, -1); m_handle = FindFirstFileA(full.str(), &m_data); rc = m_handle != INVALID_HANDLE_VALUE; @@ -178,6 +243,9 @@ bool ReDirectory::findFirst(const char* pattern, bool isRegExpr) { */ bool ReDirectory::findNext() { bool rc = false; + m_currentFull.clear(); + m_stat.st_gid = -1; + setFiletimeUndef(m_stat.st_mtim); if (m_valid) { #if defined __linux__ while (!rc && (m_entry = readdir(m_dir)) != NULL) { @@ -187,7 +255,9 @@ bool ReDirectory::findNext() { sizeof match / sizeof match[0], match, 0); if (rc2 == 0) rc = true; - } else { + } else if (m_pattern.empty()) + rc = true; + else { if (fnmatch(m_pattern.str(), m_entry->d_name, 0) == 0) rc = true; } @@ -207,10 +277,10 @@ bool ReDirectory::findNext() { * * @param false: No file found. true: A file was found. */ -bool ReDirectory::findYoungest(ReByteBuffer& filename) { +bool ReDirectory::findYoungest(ReByteArray& filename) { bool rc = false; filename.setLength(0); - ReByteBuffer fullname; + ReByteArray fullname; #if defined __linux__ if (m_entry != NULL) { @@ -261,7 +331,7 @@ bool ReDirectory::findYoungest(ReByteBuffer& filename) { * * @return path (for chaining). */ -ReByteBuffer& ReDirectory::fullpath(ReByteBuffer& path, const char* name) { +ReByteArray& ReDirectory::fullpath(ReByteArray& path, const char* name) { path.setLength(0); if (name != NULL) { path.set(m_path.str(), m_path.length()); @@ -304,7 +374,7 @@ void ReDirectory::setDir(const char* path) { m_valid = m_dir != NULL; #elif defined __WIN32__ struct stat info; - ReByteBuffer thePath(m_path); + ReByteArray thePath(m_path); thePath.removeLastChar(OS_SEPARATOR_CHAR); m_valid = stat(thePath.str(), &info) == 0 && S_ISDIR(info.st_mode); #endif diff --git a/base/ReDirectory.hpp b/base/ReDirectory.hpp index 265167e..6a19272 100644 --- a/base/ReDirectory.hpp +++ b/base/ReDirectory.hpp @@ -1,6 +1,6 @@ /* * ReDirectory.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -9,8 +9,8 @@ * The latest sources: https://github.com/republib */ -#ifndef REFILEFINDER_H_ -#define REFILEFINDER_H_ +#ifndef REDIRECTORY_H_ +#define REDIRECTORY_H_ /** ReDirectory searches files using pattern matching and/or file date. */ class ReDirectory { @@ -20,21 +20,38 @@ public: ~ReDirectory(); public: void close(); - const char* currentFile(); + /** @brief Returns the filename of the current file with path. + * @return the full filename with path + */ + const ReByteArray& currentFull(){ + if (m_currentFull.empty()) + m_currentFull.set(m_path).append(currentNode()); + return m_currentFull; + } + const char* currentNode(); + bool currentIsDir(); + struct stat& currentLStat(); + ReFileTime_t currentModified(); bool findFirst(const char* pattern, bool isRegExpr); bool findNext(); - bool findYoungest(ReByteBuffer& filename); - ReByteBuffer& fullpath(ReByteBuffer& path, const char* name = NULL); + bool findYoungest(ReByteArray& filename); + ReByteArray& fullpath(ReByteArray& path, const char* name = NULL); const char* getDir(void) const; bool isValid(); void setDir(const char* path); void setRegExprFlags(int flags); public: static void deleteTree(const char* base, bool deleteBaseToo = false); + static bool filetime(const char* filename, ReFileTime_t* modified, + ReFileTime_t* created = NULL, ReFileTime_t* accessed = NULL); +public: + static const char* ALL_FILES; private: //@ The name of the current directory. Always ends with slash! - ReByteBuffer m_path; - ReByteBuffer m_pattern; + ReByteArray m_path; + ReByteArray m_pattern; + struct stat m_stat; + ReByteArray m_currentFull; #if defined __linux__ DIR* m_dir; struct dirent* m_entry; @@ -50,4 +67,93 @@ private: //@ true: The directory is ok. false: The directory is undefined. bool m_valid; }; -#endif /* REFILEFINDER_H_ */ + +/** Returns whether a filetime is undefined. + * @param time the filetime to test + * @return true: the given filetime is undefined + */ +inline bool filetimeIsUndefined(const ReFileTime_t& time) { +#if defined __linux__ + return time.tv_sec == 0 && time.tv_nsec == 0; +#elif defined __WIN32__ + return time.dwHighDateTime == 0 && time.dwLowDateTime == 0; +#endif +} +/** Sets the filetime to undefined. + * @param time the filetime to clear + */ +inline void setFiletimeUndef(ReFileTime_t& time) { +#if defined __linux__ + time.tv_sec = time.tv_nsec = 0; +#elif defined __WIN32__ + time.dwHighDateTime = time.dwLowDateTime = 0; +#endif +} +/** Returns whether a filetime is equal than another. + * @param op1 first operand + * @param op2 second operand + * @return true: op1 == op2 + */ +inline bool operator ==(const ReFileTime_t& op1, const ReFileTime_t& op2){ +#if defined __linux__ + return op1.tv_sec == op2.tv_sec && op1.tv_nsec == op2.tv_nsec; +#else + return time1.dwHighDateTime == time2.dwHighDateTime + && time1.dwLowDateTime == time2.dwLowDateTime; +#endif +} +/** Returns whether a filetime is equal than another. + * @param op1 first operand + * @param op2 second operand + * @return true: op1 == op2 + */ +inline bool operator !=(const ReFileTime_t& op1, const ReFileTime_t& op2){ + return ! (op1 == op2); +} +/** Returns whether a filetime is greater (younger) than another. + * @param op1 first operand + * @param op2 second operand + * @return true: op1 > op2 + */ +inline bool operator >(const ReFileTime_t& op1, const ReFileTime_t& op2){ +#if defined __linux__ + return op1.tv_sec > op2.tv_sec || op1.tv_sec == op2.tv_sec && op1.tv_nsec > op2.tv_nsec; +#else + return time1.dwHighDateTime > time2.dwHighDateTime + || (time1.dwHighDateTime == time2.dwHighDateTime + && time1.dwLowDateTime > time2.dwLowDateTime); +#endif +} +/** Returns whether a filetime is greater (younger) or equal than another. + * @param op1 first operand + * @param op2 second operand + * @return true: op1 > op2 + */ +inline bool operator >=(const ReFileTime_t& op1, const ReFileTime_t& op2){ +#if defined __linux__ + return op1.tv_sec > op2.tv_sec || op1.tv_sec == op2.tv_sec && op1.tv_nsec >= op2.tv_nsec; +#else + return time1.dwHighDateTime > time2.dwHighDateTime + || (time1.dwHighDateTime == time2.dwHighDateTime + && time1.dwLowDateTime >= time2.dwLowDateTime); +#endif +} +/** Returns whether a filetime is lower (younger) than another. + * @param op1 first operand + * @param op2 second operand + * @return true: op1 > op2 + */ +inline bool operator <(const ReFileTime_t& op1, const ReFileTime_t& op2){ + return ! (op1 >= op2); +} +/** Returns whether a filetime is lower (older) or equal than another. + * @param op1 first operand + * @param op2 second operand + * @return true: op1 > op2 + */ +inline bool operator <=(const ReFileTime_t& op1, const ReFileTime_t& op2){ + return op1 == op2 || op1 < op2; +} + + +#endif /* REDIRECTORY_H_ */ diff --git a/base/ReException.cpp b/base/ReException.cpp index 3d95941..73929e4 100644 --- a/base/ReException.cpp +++ b/base/ReException.cpp @@ -1,6 +1,6 @@ /* * ReException.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -130,5 +130,5 @@ ReBoundsException::ReBoundsException(const char* name, int index, int bound, */ ReNotImplementedException::ReNotImplementedException(const char* description) : ReException( - ReByteBuffer(i18n("not implemented: ")).append(description).str()) { + ReByteArray(i18n("not implemented: ")).append(description).str()) { } diff --git a/base/ReException.hpp b/base/ReException.hpp index 4f9122b..b4b650a 100644 --- a/base/ReException.hpp +++ b/base/ReException.hpp @@ -1,6 +1,6 @@ /* * ReException.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. diff --git a/base/ReHashList.cpp b/base/ReHashList.cpp index 5afb527..ae09af5 100644 --- a/base/ReHashList.cpp +++ b/base/ReHashList.cpp @@ -1,6 +1,6 @@ /* * ReHashList.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -71,7 +71,7 @@ void ReHashList::dump(FILE* stream, const char* prefix) const { if (prefix != NULL) fprintf(stream, "%s\n", prefix); ReArrayPosition position; - ReByteBuffer key, value; + ReByteArray key, value; while (next(position, &key, &value)) { fprintf(stream, "%s : [%3d] %s\n", key.str(), (int) value.length(), value.str()); @@ -99,7 +99,7 @@ int ReHashList::find(const Byte* key, size_t length) const { * @return false: The key was not found. true: The key was found. */ bool ReHashList::get(const Byte* key, size_t keyLength, - ReByteBuffer& value) const { + ReByteArray& value) const { ReSeqArray::Index index; ReSeqArray::Tag tag; bool rc = m_keys.binarySearch(key, keyLength, index, &tag); @@ -115,7 +115,7 @@ bool ReHashList::get(const Byte* key, size_t keyLength, * * @return false: The key was not found. true: The key was found. */ -bool ReHashList::get(const ReByteBuffer& key, ReByteBuffer& value) const { +bool ReHashList::get(const ReByteArray& key, ReByteArray& value) const { bool rc = get(key.str(), key.length(), value); return rc; } @@ -130,11 +130,11 @@ bool ReHashList::get(const ReByteBuffer& key, ReByteBuffer& value) const { * * @param true: An item was found. false: No more items. */ -bool ReHashList::next(ReArrayPosition& position, ReByteBuffer* key, - ReByteBuffer* value) const { +bool ReHashList::next(ReArrayPosition& position, ReByteArray* key, + ReByteArray* value) const { bool rc = position.m_position + 1 < m_keys.count(); if (rc) { - ReByteBuffer dummy; + ReByteArray dummy; ReSeqArray::Tag tag; if (key == NULL) key = &dummy; @@ -190,7 +190,7 @@ void ReHashList::put(const char* key, const char* value) { * @param key The key. * @param value The value. */ -void ReHashList::put(const ReByteBuffer& key, const ReByteBuffer& value) { +void ReHashList::put(const ReByteArray& key, const ReByteArray& value) { put(key.str(), key.length(), value.str(), value.length()); } @@ -230,7 +230,7 @@ void ReHashList::setSizes(int sizeOfKeyString, int sizeOfValueString) { * @param prefix NULL or a prefix of the output * @return buffer.str() (for chaining) */ -const char* ReHashList::status(ReByteBuffer& buffer, const char* prefix) const { +const char* ReHashList::status(ReByteArray& buffer, const char* prefix) const { if (prefix != NULL) buffer.append(prefix).append("\n", 1); m_keys.status(buffer, "keys: "); diff --git a/base/ReHashList.hpp b/base/ReHashList.hpp index 6daf572..4b8f322 100644 --- a/base/ReHashList.hpp +++ b/base/ReHashList.hpp @@ -1,6 +1,6 @@ /* * ReHashList.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -39,17 +39,17 @@ public: public: void clear(); void dump(FILE* stream, const char* prefix = NULL) const; - bool get(const Byte* key, size_t keyLength, ReByteBuffer& value) const; - bool get(const ReByteBuffer& key, ReByteBuffer& value) const; - bool next(ReArrayPosition& position, ReByteBuffer* key, - ReByteBuffer* val) const; + bool get(const Byte* key, size_t keyLength, ReByteArray& value) const; + bool get(const ReByteArray& key, ReByteArray& value) const; + bool next(ReArrayPosition& position, ReByteArray* key, + ReByteArray* val) const; void put(const Byte* key, size_t keyLength, const Byte* value, size_t valueLength); void put(const char* key, const char* value); - void put(const ReByteBuffer& key, const ReByteBuffer& value); + void put(const ReByteArray& key, const ReByteArray& value); void setCapacity(int maxKeys, int keySpace, int contentSpace); void setSizes(int sizeOfKeyString, int sizeOfValueString); - const char* status(ReByteBuffer& buffer, const char* prefix = NULL) const; + const char* status(ReByteArray& buffer, const char* prefix = NULL) const; protected: int find(const Byte* key, size_t length) const; diff --git a/base/ReI18N.cpp b/base/ReI18N.cpp index 6736ebc..c724182 100644 --- a/base/ReI18N.cpp +++ b/base/ReI18N.cpp @@ -1,6 +1,6 @@ /* * ReI18N.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. diff --git a/base/ReI18N.hpp b/base/ReI18N.hpp index cc5d788..e0418eb 100644 --- a/base/ReI18N.hpp +++ b/base/ReI18N.hpp @@ -1,6 +1,6 @@ /* * ReI18N.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. diff --git a/base/ReLogger.cpp b/base/ReLogger.cpp index 011ff44..d1d083f 100644 --- a/base/ReLogger.cpp +++ b/base/ReLogger.cpp @@ -1,6 +1,6 @@ /* * ReLogger.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -180,10 +180,10 @@ void ReFileAppender::setConfig(const char* pattern, int maxFiles, int maxSize) { strcat(m_filePattern + len, first + 1); } - ReByteBuffer fn, protocol, path, name, ext; + ReByteArray fn, protocol, path, name, ext; ReStringUtils::splitPath(m_filePattern, &protocol, &path, &name, &ext); ReStringUtils::joinPath(fn, &protocol, &path, NULL, NULL); - if (fn.length() == 0) + if (fn.empty()) fn.set(".", 1); ReDirectory dir(fn.str()); if (!dir.isValid()) { @@ -209,7 +209,7 @@ void ReFileAppender::setConfig(const char* pattern, int maxFiles, int maxSize) { m_currentFileNo = fn.atoi(ix, 4); } struct stat info; - ReByteBuffer fullname; + ReByteArray fullname; dir.fullpath(fullname, fn.str()); #ifdef __WIN32__ #define lstat stat diff --git a/base/ReLogger.hpp b/base/ReLogger.hpp index 95bfb7b..f13014d 100644 --- a/base/ReLogger.hpp +++ b/base/ReLogger.hpp @@ -1,6 +1,6 @@ /* * ReLogger.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. diff --git a/base/ReMutex.cpp b/base/ReMutex.cpp index 6c0b135..2bed0f3 100644 --- a/base/ReMutex.cpp +++ b/base/ReMutex.cpp @@ -1,6 +1,6 @@ /* * ReMutex.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. diff --git a/base/ReMutex.hpp b/base/ReMutex.hpp index fe5f79f..66edb8e 100644 --- a/base/ReMutex.hpp +++ b/base/ReMutex.hpp @@ -1,6 +1,6 @@ /* * ReMutex.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. diff --git a/base/ReProgramArgs.cpp b/base/ReProgramArgs.cpp index c1d78cb..bbd6516 100644 --- a/base/ReProgramArgs.cpp +++ b/base/ReProgramArgs.cpp @@ -1,6 +1,6 @@ /* * ReProgramArgs.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -53,7 +53,7 @@ ReProgramArgs::ReProgramArgs(const char* usageList[], const char* examples[]) : m_program(NULL), m_lastError() { m_properties.setCapacity(64, 64 * 8, 64 * 1024); - ReByteBuffer line; + ReByteArray line; for (const char** argv = usageList; *argv != NULL; argv++) { line.set(*argv); line.removeLastChar('\n'); @@ -64,7 +64,7 @@ ReProgramArgs::ReProgramArgs(const char* usageList[], const char* examples[]) : if (strncmp(*argv, "$0", 2) != 0) m_examples.append(*argv); else { - ReByteBuffer line; + ReByteArray line; line.append(m_program, -1); m_examples.append(line.str() + 2); } @@ -94,7 +94,7 @@ ReProgramArgs::ReProgramArgs(const char* usageString, const char* examples) : if (strstr(examples, "$0") == NULL) m_examples.split(examples, '\n'); else { - ReByteBuffer line; + ReByteArray line; line.append(examples, -1); line.replaceAll("$0", 2, m_program, -1); m_examples.split(line.str(), '\n'); @@ -133,9 +133,9 @@ void ReProgramArgs::setUsage(const char* usage[]) { void ReProgramArgs::addProperties(const char*name, const char* description, char shortOpt, const char* longOpt, DataType dataType, const char* defaultValue, size_t lengthValue) { - ReByteBuffer properties; - ReByteBuffer descr(description, -1); - ReByteBuffer replacement("\n", 1); + ReByteArray properties; + ReByteArray descr(description, -1); + ReByteArray replacement("\n", 1); replacement.append(PREFIX_LINE_OPTION); descr.replaceAll("\n", 1, replacement.str(), replacement.length()); properties.append(descr).appendChar('\1'); @@ -186,7 +186,7 @@ void ReProgramArgs::addBool(const char* name, const char* description, */ void ReProgramArgs::addInt(const char* name, const char* description, char shortOpt, const char* longOpt, int defaultVal) { - ReByteBuffer number; + ReByteArray number; number.appendInt(defaultVal); addProperties(name, description, shortOpt, longOpt, DT_INT, number.str(), number.length()); @@ -219,7 +219,7 @@ void ReProgramArgs::addString(const char* name, const char* description, */ void ReProgramArgs::analyseLong(const char* opt) { ReStringList properties(512, 1024, 2, 2); - ReByteBuffer name; + ReByteArray name; search('\0', opt, name, properties); const char* nameStr = name.str(); @@ -292,7 +292,7 @@ bool ReProgramArgs::analyseShort(const char* opt, const char* nextArg) { bool rc = false; ReStringList properties(512, 1024, 2, 2); bool again; - ReByteBuffer name; + ReByteArray name; do { again = false; @@ -376,7 +376,7 @@ int ReProgramArgs::argCount() const { */ bool ReProgramArgs::getBool(const char* name) { ReStringList properties(512, 1024, 2, 2); - ReByteBuffer buffer; + ReByteArray buffer; ReVarArgs args; if (!m_properties.get(name, -1, buffer)) throw ReOptionException(this, i18n("$1 is not an option name"), name); @@ -402,7 +402,7 @@ bool ReProgramArgs::getBool(const char* name) { */ int ReProgramArgs::getInt(const char* name) { ReStringList properties(512, 1024, 2, 2); - ReByteBuffer buffer; + ReByteArray buffer; ReVarArgs args; if (!m_properties.get(name, -1, buffer)) throw ReOptionException(this, i18n("$1 is not an option name"), name); @@ -426,7 +426,7 @@ int ReProgramArgs::getInt(const char* name) { * * @throws ReOptionException Unknown name or wrong type. */ -const char* ReProgramArgs::getString(const char* name, ReByteBuffer& buffer) { +const char* ReProgramArgs::getString(const char* name, ReByteArray& buffer) { ReStringList properties(512, 1024, 2, 2); ReVarArgs args; if (!m_properties.get(name, strlen(name), buffer)) @@ -461,10 +461,10 @@ void ReProgramArgs::help(const char* message, bool issueLastError, if (m_properties.next(position, NULL, NULL)) { lines.append(i18n(":")); } - ReByteBuffer name; - ReByteBuffer prop; - ReByteBuffer line; - ReByteBuffer param; + ReByteArray name; + ReByteArray prop; + ReByteArray line; + ReByteArray param; while (m_properties.next(position, &name, &prop)) { ReStringList properties(512, 1024, 2, 2); @@ -586,9 +586,9 @@ const char* ReProgramArgs::programName() const { * @throws ReOptionException Unknown option. */ void ReProgramArgs::search(char shortName, const char* longName, - ReByteBuffer& name, ReStringList& list) { + ReByteArray& name, ReStringList& list) { ReArrayPosition position; - ReByteBuffer properties; + ReByteArray properties; bool found = false; size_t lengthLongName = 0; if (longName != NULL) { @@ -650,7 +650,7 @@ void ReProgramArgs::setValue(const char* name, const char* value, default: break; } - ReByteBuffer buffer; + ReByteArray buffer; // First character says: defined. buffer.appendChar(' ').append(value, -1); m_values.put(name, buffer.str()); diff --git a/base/ReProgramArgs.hpp b/base/ReProgramArgs.hpp index 0252e45..9025c3e 100644 --- a/base/ReProgramArgs.hpp +++ b/base/ReProgramArgs.hpp @@ -1,6 +1,6 @@ /* * ReProgramArgs.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -66,7 +66,7 @@ public: const char* arg(size_t index) const; bool getBool(const char* name); int getInt(const char* name); - const char* getString(const char* name, ReByteBuffer& buffer); + const char* getString(const char* name, ReByteArray& buffer); void help(const char* message, bool issueLastError, ReStringList& lines) const; void help(const char* message, bool issueLastError, FILE* stream) const; @@ -80,7 +80,7 @@ private: size_t lengthValue); void analyseLong(const char* opt); bool analyseShort(const char* opt, const char* nextArg); - void search(char shortName, const char* longName, ReByteBuffer& name, + void search(char shortName, const char* longName, ReByteArray& name, ReStringList& list); void setValue(const char* name, const char* value, const char* dataType); protected: @@ -91,7 +91,7 @@ protected: const char** m_args; int m_argCount; const char* m_program; - ReByteBuffer m_lastError; + ReByteArray m_lastError; }; #endif /* REPROGRAMARGS_H_ */ diff --git a/base/ReSeqArray.cpp b/base/ReSeqArray.cpp index 36ba798..40834fc 100644 --- a/base/ReSeqArray.cpp +++ b/base/ReSeqArray.cpp @@ -1,6 +1,6 @@ /* * ReSeqArray.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -248,7 +248,7 @@ int ReSeqArray::compare(Index index1, Index index2) { * @param prefix NULL or a introduction */ void ReSeqArray::dump(FILE* fp, const char* prefix) const { - ReByteBuffer buffer; + ReByteArray buffer; Tag tag; if (prefix != NULL) fprintf(fp, "%s\n", prefix); @@ -303,7 +303,7 @@ ReSeqArray::Index ReSeqArray::find(const Byte* toFind, size_t length, * @param true: The index is ok, the sequence is in the output buffer. * false: No copy has been done. */ -bool ReSeqArray::get(Index index, ReByteBuffer& value, Tag* tag) const { +bool ReSeqArray::get(Index index, ReByteArray& value, Tag* tag) const { bool rc = false; if (index < count()) { const Sequence* seq = getInfo(index); @@ -739,7 +739,7 @@ void ReSeqArray::sort() { * @param prefix NULL or a prefix of the output * @return buffer.str() (for chaining) */ -const char* ReSeqArray::status(ReByteBuffer& buffer, const char* prefix) const { +const char* ReSeqArray::status(ReByteArray& buffer, const char* prefix) const { if (prefix != NULL) buffer.append(prefix); buffer.append("age: ").appendInt(m_age).append("\n"); diff --git a/base/ReSeqArray.hpp b/base/ReSeqArray.hpp index 6a9b8a9..831a0e8 100644 --- a/base/ReSeqArray.hpp +++ b/base/ReSeqArray.hpp @@ -1,6 +1,6 @@ /* * ReSeqArray.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -54,7 +54,7 @@ public: } void dump(FILE* fp, const char* prefix) const; Index find(const Byte* toFind, size_t length = -1, Tag* tag = NULL) const; - bool get(Index index, ReByteBuffer& value, Tag* tag = NULL) const; + bool get(Index index, ReByteArray& value, Tag* tag = NULL) const; /** Returns whether the comparisons inside the list are case insensitive. * @return true the comparisons inside the list are case insensitive */ @@ -77,7 +77,7 @@ public: void setSorted(bool onNotOff); void setIgnoreCase(bool onNotOff); void sort(); - const char* status(ReByteBuffer& buffer, const char* prefix = NULL) const; + const char* status(ReByteArray& buffer, const char* prefix = NULL) const; protected: /** @brief Returns a pointer of the content buffer. * @return A pointer of the first byte of the content buffer. @@ -99,9 +99,9 @@ protected: void shiftDown(int from, int to); protected: //@ Contains the sequences itself. - ReByteBuffer m_content; + ReByteArray m_content; //@ Contains an array of Sequences. - ReByteBuffer m_list; + ReByteArray m_list; //@ If strings have been replaced/deleted the space in m_content is still allocated. //@ This is the sum of lost space. size_t m_lost; diff --git a/base/ReSerializable.cpp b/base/ReSerializable.cpp index 6ffd960..59404c1 100644 --- a/base/ReSerializable.cpp +++ b/base/ReSerializable.cpp @@ -1,6 +1,6 @@ /* * ReSerializable.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -22,7 +22,7 @@ class ReSerialable; ReSerializationException::ReSerializationException(const char* message, ReSerializable* instance) : ReException( - ReByteBuffer(message, -1).appendChar(' ').append( + ReByteArray(message, -1).appendChar(' ').append( instance->parentClassName()).str()) { } /** @@ -35,7 +35,7 @@ ReSerializationException::ReSerializationException(const char* message, ReSerializationLengthException::ReSerializationLengthException( int currentLength, int expectedLength, ReSerializable* instance) : ReSerializationException( - ReByteBuffer(i18n("pack error: length to small: ")).appendInt( + ReByteArray(i18n("pack error: length to small: ")).appendInt( currentLength).appendChar('/').appendInt(expectedLength).str(), instance), m_currentLength(currentLength), @@ -52,7 +52,7 @@ ReSerializationLengthException::ReSerializationLengthException( ReSerializeStringLengthException::ReSerializeStringLengthException( int currentLength, int maxLength, ReSerializable* instance) : ReSerializationException( - ReByteBuffer(i18nTranslate("string length too large: ")).appendInt( + ReByteArray(i18nTranslate("string length too large: ")).appendInt( currentLength).appendChar('/').appendInt(maxLength).str(), instance), m_currentLength(currentLength), @@ -81,7 +81,7 @@ ReSerializable::~ReSerializable() { * @param time the filetime to serialize * */ -void ReSerializable::packFileTime(ReByteBuffer& sequence, +void ReSerializable::packFileTime(ReByteArray& sequence, const ReFileTime_t& time) { uint64_t value; #if defined __linux__ diff --git a/base/ReSerializable.hpp b/base/ReSerializable.hpp index a3ce56d..dbee416 100644 --- a/base/ReSerializable.hpp +++ b/base/ReSerializable.hpp @@ -1,6 +1,6 @@ /* * ReSerializable.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -83,7 +83,7 @@ public: * @param sequence the serialized sequence * @throw ReSerializationLengthException */ - inline void deserializeBuffer(const ReByteBuffer& sequence) { + inline void deserializeBuffer(const ReByteArray& sequence) { size_t length = sequence.length(); const uint8_t* seq = reinterpret_cast(sequence.str()); deserialize(seq, length); @@ -94,15 +94,15 @@ public: * @param sequence IN/OUT: the sequence with the serialized values * @param value the value to serialize */ - inline void packBool(ReByteBuffer& sequence, bool value) { + inline void packBool(ReByteArray& sequence, bool value) { sequence.appendChar(value ? 't' : 'f'); } - void packFileTime(ReByteBuffer& sequence, const ReFileTime_t& time); + void packFileTime(ReByteArray& sequence, const ReFileTime_t& time); /** Appends a string with a maximal length of 255 to the sequence. * @param sequence IN/OUT: the sequence with the serialized values * @param value the value to serialize */ - inline void packString255(ReByteBuffer& sequence, ReByteBuffer& value) { + inline void packString255(ReByteArray& sequence, ReByteArray& value) { if (value.length() > 255) throw ReSerializeStringLengthException(value.length(), 255, this); sequence.appendBits8(value.length()).append(value); @@ -111,7 +111,7 @@ public: * @param sequence IN/OUT: the sequence with the serialized values * @param value the value to serialize */ - inline void packString255(ReByteBuffer& sequence, const char* value, + inline void packString255(ReByteArray& sequence, const char* value, size_t length = -1) { if (length == (size_t) -1) length = strlen(value); @@ -123,7 +123,7 @@ public: * @param sequence IN/OUT: the sequence with the serialized values * @param value the value to serialize */ - inline void packString64k(ReByteBuffer& sequence, ReByteBuffer& value) { + inline void packString64k(ReByteArray& sequence, ReByteArray& value) { if (value.length() > 0xffff) throw ReSerializeStringLengthException(value.length(), 0xffff, this); @@ -135,7 +135,7 @@ public: * @param length length of value
* -1: strlen(value) */ - inline void packString64k(ReByteBuffer& sequence, const char* value, + inline void packString64k(ReByteArray& sequence, const char* value, size_t length = -1) { if (length == (size_t) -1) length = strlen(value); @@ -147,7 +147,7 @@ public: * @param sequence IN/OUT: the sequence with the serialized values * @param value the value to serialize */ - inline void packString4t(ReByteBuffer& sequence, ReByteBuffer& value) { + inline void packString4t(ReByteArray& sequence, ReByteArray& value) { sequence.appendBits32(value.length()).append(value); } /** Appends a string with a maximal length of 4 TiByte to the sequence. @@ -156,7 +156,7 @@ public: * @param length length of value
* -1: strlen(value) */ - inline void packString4t(ReByteBuffer& sequence, const char* value, + inline void packString4t(ReByteArray& sequence, const char* value, size_t length = -1) { if (length == (size_t) -1) length = strlen(value); @@ -179,7 +179,7 @@ public: * @param sequence IN/OUT: the sequence containing the serialized bytes * @return the sequence (for chaining) */ - virtual ReByteBuffer& serialize(ReByteBuffer& sequence) = 0; + virtual ReByteArray& serialize(ReByteArray& sequence) = 0; /** Reads a 8 bit integer from the serialized byte sequence. * @param sequence IN/OUT: the byte sequence with the serialized data * @param length IN/OUT: the length of sequence @@ -268,7 +268,7 @@ public: * @param value OUT: the value read from the sequence */ inline void unpackString255(const uint8_t*& sequence, size_t& length, - ReByteBuffer& value) { + ReByteArray& value) { size_t strLen = 0; if (length < 1 || (strLen = *sequence) > length) throw ReSerializationLengthException(length, 1 + strLen, this); @@ -283,7 +283,7 @@ public: * @param value OUT: the value read from the sequence */ inline void unpackString64k(const uint8_t*& sequence, size_t& length, - ReByteBuffer& value) { + ReByteArray& value) { size_t strLen = 0; if (length < 2 || (strLen = (sequence[0] << 8) + sequence[1]) > length) throw ReSerializationLengthException(length, 2 + strLen, this); @@ -298,7 +298,7 @@ public: * @param value OUT: the value read from the sequence */ inline void unpackString4t(const uint8_t*& sequence, size_t& length, - ReByteBuffer& value) { + ReByteArray& value) { size_t strLen = 0; if (length < 4 || (strLen = (sequence[0] << 24) + (sequence[1] << 16) diff --git a/base/ReStringList.cpp b/base/ReStringList.cpp index 4f4a8ae..e191a0e 100644 --- a/base/ReStringList.cpp +++ b/base/ReStringList.cpp @@ -1,6 +1,6 @@ /* * ReStringList.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -43,7 +43,7 @@ ReStringList& ReStringList::append(const char* source, Tag tagOf) { * @param tag a number which will stored with the string. Not interpreted by the instance * @return the instance itself (for chaining) */ -ReStringList& ReStringList::append(const ReByteBuffer& source, Tag tag) { +ReStringList& ReStringList::append(const ReByteArray& source, Tag tag) { add(-1, source.str(), source.length() + 1, tag); return *this; } @@ -141,7 +141,7 @@ void ReStringList::replaceString(Index index, const char* source) { * @param tag the new tag */ void ReStringList::replaceTag(Index index, Tag tag) { - ReByteBuffer buffer; + ReByteArray buffer; if (get(index, buffer)) set(index, buffer.str(), buffer.length(), tag); } @@ -172,7 +172,7 @@ const char* ReStringList::strOf(Index index) const { */ ReSeqArray::Tag ReStringList::tagOf(Index index) const { Tag rc = -1; - ReByteBuffer buffer; + ReByteArray buffer; if (!get(index, buffer, &rc)) { rc = -1; } @@ -204,7 +204,7 @@ size_t ReStringList::sizeOf(Index index) const { */ size_t ReStringList::strLengthOf(Index index) const { size_t rc = 0; - ReByteBuffer buffer; + ReByteArray buffer; if (get(index, buffer)) rc = buffer.length() - 1; return rc; @@ -215,7 +215,7 @@ size_t ReStringList::strLengthOf(Index index) const { */ size_t ReStringList::sumOfSizes() const { size_t rc = 0; - ReByteBuffer buffer; + ReByteArray buffer; for (int ii = count() - 1; ii >= 0; ii--) { get(ii, buffer); rc += buffer.length(); @@ -301,7 +301,7 @@ void ReStringList::split(const char* list, char separator, bool append) { clear(); const char* end = list == NULL ? NULL : strchr(list, separator); const char* end2; - ReByteBuffer item; + ReByteArray item; while (end != NULL) { if (separator == '\n' && end != list && end[-1] == '\r') end2 = end - 1; @@ -326,7 +326,7 @@ void ReStringList::split(const char* list, char separator, bool append) { * @param result OUT: the result buffer * @return buffer (for chaining) */ -ReByteBuffer& ReStringList::join(const char* separator, ReByteBuffer& result, +ReByteArray& ReStringList::join(const char* separator, ReByteArray& result, bool append) const { size_t theCount = count(); if (!append) diff --git a/base/ReStringList.hpp b/base/ReStringList.hpp index 8c261ae..84d3da6 100644 --- a/base/ReStringList.hpp +++ b/base/ReStringList.hpp @@ -1,6 +1,6 @@ /* * ReStringList.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -41,14 +41,14 @@ public: virtual ~ReStringList(); public: ReStringList& append(const char* source, Tag tag = 0); - ReStringList& append(const ReByteBuffer& source, Tag tag = 0); + ReStringList& append(const ReByteArray& source, Tag tag = 0); ReStringList& append(const ReStringList& source); bool equal(const ReStringList& toCompare) const; int firstDiff(const ReStringList& toCompare) const; Index indexOf(const char* toFind, bool ignoreCase = false, Index start = 0) const; void insert(Index index, const char* source, Tag tag = 0); - ReByteBuffer& join(const char* separator, ReByteBuffer& result, + ReByteArray& join(const char* separator, ReByteArray& result, bool append = false) const; Index nextStartingWith(Index index, const char* prefix, bool ignoreCase = false); diff --git a/base/ReStringUtils.cpp b/base/ReStringUtils.cpp index 9621f53..75c09a4 100644 --- a/base/ReStringUtils.cpp +++ b/base/ReStringUtils.cpp @@ -1,6 +1,6 @@ /* * ReStringUtils.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -68,9 +68,9 @@ bool ReStringUtils::isInList(const char* phrase, const char* list, * * @result fullpath. (for chaining). */ -ReByteBuffer& ReStringUtils::joinPath(ReByteBuffer& fullpath, - ReByteBuffer* protocol, ReByteBuffer* path, ReByteBuffer* name, - ReByteBuffer* ext) { +ReByteArray& ReStringUtils::joinPath(ReByteArray& fullpath, + ReByteArray* protocol, ReByteArray* path, ReByteArray* name, + ReByteArray* ext) { fullpath.setLength(0); if (protocol != NULL) fullpath.append(*protocol); @@ -100,7 +100,7 @@ ReByteBuffer& ReStringUtils::joinPath(ReByteBuffer& fullpath, * * @result fullpath. (for chaining). */ -ReByteBuffer& ReStringUtils::joinPath(ReByteBuffer& fullpath, +ReByteArray& ReStringUtils::joinPath(ReByteArray& fullpath, const char* protocol, const char* path, const char* name, const char* ext) { fullpath.setLength(0); if (protocol != NULL) @@ -165,8 +165,8 @@ int ReStringUtils::lengthOfUnsigned(const char* text, int length, * @param name Out: The name part of the filename. May be NULL. * @param ext Out: The extension. May be NULL. */ -void ReStringUtils::splitPath(const char* fullname, ReByteBuffer* protocol, - ReByteBuffer* path, ReByteBuffer* name, ReByteBuffer* ext) { +void ReStringUtils::splitPath(const char* fullname, ReByteArray* protocol, + ReByteArray* path, ReByteArray* name, ReByteArray* ext) { const char currentSlash = strchr(fullname, '/') != NULL ? '/' : OS_SEPARATOR_CHAR; const char* start = strchr(fullname, ':'); diff --git a/base/ReStringUtils.hpp b/base/ReStringUtils.hpp index 6b6f476..b50ce4c 100644 --- a/base/ReStringUtils.hpp +++ b/base/ReStringUtils.hpp @@ -1,6 +1,6 @@ /* * ReStringUtils.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -23,14 +23,14 @@ public: public: static bool isInList(const char* phrase, const char* list, bool ignoreCase = true, char separator = AUTO_SEPARATOR); - static ReByteBuffer& joinPath(ReByteBuffer& result, ReByteBuffer* protocol, - ReByteBuffer* path, ReByteBuffer* name, ReByteBuffer* ext); - static ReByteBuffer& joinPath(ReByteBuffer& result, const char* protocol, + static ReByteArray& joinPath(ReByteArray& result, ReByteArray* protocol, + ReByteArray* path, ReByteArray* name, ReByteArray* ext); + static ReByteArray& joinPath(ReByteArray& result, const char* protocol, const char* path, const char* name, const char* ext); static int lengthOfUnsigned(const char* text, int length = -1, unsigned int* value = NULL); - static void splitPath(const char* fullname, ReByteBuffer* protocol, - ReByteBuffer* path, ReByteBuffer* name, ReByteBuffer* ext); + static void splitPath(const char* fullname, ReByteArray* protocol, + ReByteArray* path, ReByteArray* name, ReByteArray* ext); static int strnicmp(const char* string1, const char* string2, size_t length); }; diff --git a/base/ReTestUnit.cpp b/base/ReTestUnit.cpp index 261d301..e4a8763 100644 --- a/base/ReTestUnit.cpp +++ b/base/ReTestUnit.cpp @@ -1,6 +1,6 @@ /* * ReTestUnit.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -10,7 +10,7 @@ */ #include "base/rebase.hpp" -ReByteBuffer ReTestUnit::m_tempDir; +ReByteArray ReTestUnit::m_tempDir; /** @brief Constructor. * @@ -63,29 +63,23 @@ void ReTestUnit::assertFalse(bool condition, int lineNo) { logF(true, i18n("%s-%d: not false!"), m_sourceFile.str(), lineNo); } } -/** @brief Checks a pointer expression. A not null value will be logged. - * - * @param pointer this expression will be tested - * if not null an error messsage will be issued - * @param lineNo the line number of the test (for the error message) - */ -void ReTestUnit::assertNull(void* pointer, int lineNo) { - if (pointer != NULL) { - logF(true, "%s-%d: is not null %llx", m_sourceFile.str(), lineNo, - (int64_t) pointer); - } -} -/** @brief Checks a pointer expression. A null value will be logged. + +/** @brief Checks whether a directory exists. If not this will be logged. * - * @param pointer this expression will be tested - * if null an error messsage will be issued + * @param dir the name of the directory * @param lineNo the line number of the test (for the error message) */ -void ReTestUnit::assertNotNull(void* pointer, int lineNo) { - if (pointer == NULL) { - logF(true, i18n("%s-%d: is null"), m_sourceFile.str(), lineNo); +void ReTestUnit::assertDirExists(const char* dir, int lineNo) { + struct stat info; + if (stat(dir, &info) != 0) { + logF(true, i18n("%s-%d: Directory does not exist: %s"), + m_sourceFile.str(), lineNo, dir); + } else if (!S_ISDIR(info.st_mode)) { + logF(true, i18n("%s-%d: File exists but this is not a directory: %s"), + m_sourceFile.str(), lineNo, dir); } } + /** @brief Compares two integer values. If not equal this will be logged. * * @param expected the expected value @@ -98,6 +92,7 @@ void ReTestUnit::assertEqual(int expected, int current, int lineNo) { m_sourceFile.str(), lineNo, expected, expected, current, current); } } + /** @brief Compares two integer values. If not equal this will be logged. * * @param expected the expected value @@ -147,7 +142,7 @@ void ReTestUnit::assertEqual(const char* expected, const char* current, * @param current the current value * @param lineNo the line number of the test (for the error message) */ -void ReTestUnit::assertEqual(const char* expected, const ReByteBuffer& current, +void ReTestUnit::assertEqual(const char* expected, const ReByteArray& current, int lineNo) { assertEqual(expected, current.str(), lineNo); } @@ -157,8 +152,8 @@ void ReTestUnit::assertEqual(const char* expected, const ReByteBuffer& current, * @param current the current value * @param lineNo the line number of the test (for the error message) */ -void ReTestUnit::assertEqual(const ReByteBuffer& expected, - const ReByteBuffer& current, int lineNo) { +void ReTestUnit::assertEqual(const ReByteArray& expected, + const ReByteArray& current, int lineNo) { assertEqual(expected.str(), current.str(), lineNo); } /** @brief Compares two string values. If not equal this will be logged. @@ -178,21 +173,6 @@ void ReTestUnit::assertEqualIgnoreCase(const char* expected, } } -/** @brief Checks whether a file exists. If not this will be logged. - * - * @param name the filename - * @param lineNo the line number of the test (for the error message) - */ -void ReTestUnit::assertFileExists(const char* name, int lineNo) { - struct stat info; - if (stat(name, &info) != 0) { - logF(true, i18n("%s-%d: File does not exist: %s"), m_sourceFile.str(), - lineNo, name); - } else if (S_ISDIR(info.st_mode)) { - logF(true, i18n("%s-%d: File does exist but this is a directory: %s"), - m_sourceFile.str(), lineNo, name); - } -} /** @brief Checks whether two files have the same content. If not this will be logged. * * @param name1 name of the first file @@ -201,14 +181,14 @@ void ReTestUnit::assertFileExists(const char* name, int lineNo) { */ void ReTestUnit::assertEqualFiles(const char* name1, const char* name2, int lineNo) { - ReByteBuffer buffer; + ReByteArray buffer; ReStringList list1; ReStringList list2; list1.readFromFile(name1); list2.readFromFile(name2); int ix = list1.firstDiff(list2); if (ix >= 0) { - ReByteBuffer line1(list1.strOf(ix), list1.strLengthOf(ix)); + ReByteArray line1(list1.strOf(ix), list1.strLengthOf(ix)); int ixLine = line1.firstDifference(list2.strOf(ix), list2.strLengthOf(ix)); logF(true, i18n("%s-%d: Files differ in line %d-%d\n%s\n%s\n%s"), @@ -219,13 +199,55 @@ void ReTestUnit::assertEqualFiles(const char* name1, const char* name2, } + +/** @brief Checks whether a file exists. If not this will be logged. + * + * @param name the filename + * @param lineNo the line number of the test (for the error message) + */ +void ReTestUnit::assertFileExists(const char* name, int lineNo) { + struct stat info; + if (stat(name, &info) != 0) { + logF(true, i18n("%s-%d: File does not exist: %s"), m_sourceFile.str(), + lineNo, name); + } else if (S_ISDIR(info.st_mode)) { + logF(true, i18n("%s-%d: File does exist but this is a directory: %s"), + m_sourceFile.str(), lineNo, name); + } +} + +/** @brief Checks a pointer expression. A null value will be logged. + * + * @param pointer this expression will be tested + * if null an error messsage will be issued + * @param lineNo the line number of the test (for the error message) + */ +void ReTestUnit::assertNotNull(void* pointer, int lineNo) { + if (pointer == NULL) { + logF(true, i18n("%s-%d: is null"), m_sourceFile.str(), lineNo); + } +} + +/** @brief Checks a pointer expression. A not null value will be logged. + * + * @param pointer this expression will be tested + * if not null an error messsage will be issued + * @param lineNo the line number of the test (for the error message) + */ +void ReTestUnit::assertNull(void* pointer, int lineNo) { + if (pointer != NULL) { + logF(true, "%s-%d: is not null %llx", m_sourceFile.str(), lineNo, + (int64_t) pointer); + } +} + /** @brief Returns the full path of a file in the test directory. * * @param node the node (filename without path) * @param buffer OUT: the filename will be constructed in this buffer * @return buffer.str(): the full filename */ -const char* ReTestUnit::buildFilename(const char* node, ReByteBuffer& buffer) { +const char* ReTestUnit::buildFilename(const char* node, ReByteArray& buffer) { createTestDir(); buffer.setLength(0).append(m_tempDir).append(node); return buffer.str(); @@ -246,11 +268,36 @@ const char* ReTestUnit::colMarker(int col) { return m_buffer.str(); } +/** @brief Creates a file and fills it with an given content. + * + * @param filename the name of the file + * @param content the content of the file. If NULL the file will be empty + */ +void ReTestUnit::createDir(const char* filename) { + _mkdir(filename, ALLPERMS); +} + +/** @brief Creates a file and fills it with an given content. + * + * @param filename the name of the file + * @param content the content of the file. If NULL the file will be empty + */ +void ReTestUnit::createFile(const char* filename, const char* content) { + FILE* fp = fopen(filename, "w"); + if (fp == NULL) { + int error = getLastOSError(); + logF(true, "createFile(%d): %s", error, filename); + } else if (content != NULL) { + fwrite(content, strlen(content), 1, fp); + fclose(fp); + } +} + /** @brief Creates an empty temporary directory. * the name can be retrieved by getTestDir(). */ void ReTestUnit::createTestDir() { - if (m_tempDir.length() == 0) { + if (m_tempDir.empty()) { if (getenv("TMP") != NULL) { m_tempDir = getenv("TMP"); } else if (getenv("TEMP")) { @@ -273,83 +320,6 @@ void ReTestUnit::createTestDir() { } } -/** - * @brief Calculates the time since a given start. - * - *
int64_t start = test.timer();
- * ...
- * int duration = test.milliSecSince(start);
- * 
- * - * @return a time usable for for runtime measurement - */ -int ReTestUnit::milliSecSince(int64_t start) { - return ReBaseUtils::milliSecSince(start); -} - -/** - * @brief Returns a time value usable for runtime measurement. - * - * Note: The value is platform dependent. Use with milliSecSince(). - *
int64_t start = test.timer();
- * ...
- * int duration = test.milliSecSince(start);
- * 
- * @return a time usable for for runtime measurement - */ -int64_t ReTestUnit::timer() { - return ReBaseUtils::timer(); -} - -/** @brief Returns the temporary directory. - * - * @return the name of a temporary directory - */ -const char* ReTestUnit::testDir() { - createTestDir(); - return m_tempDir.str(); -} - -/** @brief Creates a file and fills it with an given content. - * - * @param filename the name of the file - * @param content the content of the file. If NULL the file will be empty - */ -void ReTestUnit::createFile(const char* filename, const char* content) { - FILE* fp = fopen(filename, "w"); - if (fp == NULL) { - int error = getLastOSError(); - logF(true, "createFile(%d): %s", error, filename); - } else if (content != NULL) { - fwrite(content, strlen(content), 1, fp); - fclose(fp); - } -} -/** @brief Creates a file and fills it with an given content. - * - * @param filename the name of the file - * @param content the content of the file. If NULL the file will be empty - */ -void ReTestUnit::createDir(const char* filename) { - _mkdir(filename, ALLPERMS); -} - -/** @brief Checks whether a directory exists. If not this will be logged. - * - * @param dir the name of the directory - * @param lineNo the line number of the test (for the error message) - */ -void ReTestUnit::assertDirExists(const char* dir, int lineNo) { - struct stat info; - if (stat(dir, &info) != 0) { - logF(true, i18n("%s-%d: Directory does not exist: %s"), - m_sourceFile.str(), lineNo, dir); - } else if (!S_ISDIR(info.st_mode)) { - logF(true, i18n("%s-%d: File exists but this is not a directory: %s"), - m_sourceFile.str(), lineNo, dir); - } -} - /** @brief Logs a message. * * It can be used to inform the user about coming (error-) messages @@ -384,3 +354,88 @@ bool ReTestUnit::logF(bool isError, const char* format, ...) { va_end(args); return log(isError, buffer); } + +/** + * @brief Calculates the time since a given start. + * + *
int64_t start = test.timer();
+ * ...
+ * int duration = test.milliSecSince(start);
+ * 
+ * + * @return a time usable for for runtime measurement + */ +int ReTestUnit::milliSecSince(int64_t start) { + return ReBaseUtils::milliSecSince(start); +} + +/** @brief Returns the temporary directory. + * + * @return the name of a temporary directory + */ +const char* ReTestUnit::testDir() { + createTestDir(); + return m_tempDir.str(); +} + +/** + * Tests a file against a given content with wildcards. + * + * @param filename name of the file to test + * @param content expected content: each line can contain one or more '*'s + * used as wildcards (any count of any character) + */ +void ReTestUnit::testFileContentWithWildcards(ReByteArray& filename, const char* content) { + ReStringList current; + current.readFromFile(filename.str()); + ReStringList expected; + expected.split(content, '\n'); + if (expected.count() != current.count()) + checkEqu(expected.count(), current.count()); + ReByteArray line; + ReStringList cols; + for (size_t ix = 0; ix < current.count(); ix++) { + line.setLength(0).append(current.strOf(ix), -1); + cols.split(expected.strOf(ix), '*'); + const char* col1 = cols.strOf(0); + if (!line.startsWith(col1)) + checkEqu(col1, line); + int count = cols.count(); + if (count > 1){ + const char* col2; + if (count > 2){ + int startIx = cols.strLengthOf(0) + 1; + int lastIndex = line.length() - cols.strLengthOf(count - 1); + for (int ix = 1; ix < count - 1; ix++){ + col2 = cols.strOf(ix); + + int found = line.indexOf(col2, cols.strLengthOf(ix), startIx); + if (found < 0 || found >= lastIndex){ + checkEqu(col2, line.str() + startIx); + break; + } + startIx = found + cols.strLengthOf(ix); + } + } + col2 = cols.strOf(count - 1); + if (!line.endsWith(col2)) { + checkEqu(col2, line); + } + } + } +} + +/** + * @brief Returns a time value usable for runtime measurement. + * + * Note: The value is platform dependent. Use with milliSecSince(). + *
int64_t start = test.timer();
+ * ...
+ * int duration = test.milliSecSince(start);
+ * 
+ * @return a time usable for for runtime measurement + */ +int64_t ReTestUnit::timer() { + return ReBaseUtils::timer(); +} + diff --git a/base/ReTestUnit.hpp b/base/ReTestUnit.hpp index cc23271..63c4c54 100644 --- a/base/ReTestUnit.hpp +++ b/base/ReTestUnit.hpp @@ -1,6 +1,6 @@ /* * ReTestUnit.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -28,9 +28,9 @@ public: void assertEqual(int expected, int current, int lineNo); void assertEqual(unsigned int expected, unsigned int current, int lineNo); void assertEqual(const char* expected, const char* current, int lineNo); - void assertEqual(const char* expected, const ReByteBuffer& current, + void assertEqual(const char* expected, const ReByteArray& current, int lineNo); - void assertEqual(const ReByteBuffer& expected, const ReByteBuffer& current, + void assertEqual(const ReByteArray& expected, const ReByteArray& current, int lineNo); void assertEqualIgnoreCase(const char* expected, const char* current, int lineNo); @@ -40,26 +40,27 @@ public: void assertNotNull(void* pointer, int lineNo); void assertNull(void* pointer, int lineNo); void assertTrue(bool conditon, int lineNo); - const char* buildFilename(const char* node, ReByteBuffer& buffer); + const char* buildFilename(const char* node, ReByteArray& buffer); void createDir(const char* filename); void createFile(const char* filename, const char* content); const char* colMarker(int col); - const char* testDir(); virtual bool log(bool isError, const char* message); virtual bool logF(bool isError, const char* format, ...); int milliSecSince(int64_t start); + const char* testDir(); + void testFileContentWithWildcards(ReByteArray& filename, const char* content); int64_t timer(); private: void createTestDir(); protected: int m_errorCount; - ReByteBuffer m_name; - ReByteBuffer m_sourceFile; - ReByteBuffer m_buffer; + ReByteArray m_name; + ReByteArray m_sourceFile; + ReByteArray m_buffer; ReMemoryAppender* m_memoryAppender; ReLogger m_silentLogger; protected: - static ReByteBuffer m_tempDir; + static ReByteArray m_tempDir; }; #define checkT(cond) assertTrue(cond, __LINE__) #define checkF(cond) assertFalse(cond, __LINE__) diff --git a/base/ReThread.cpp b/base/ReThread.cpp index 3ded469..1e8333c 100644 --- a/base/ReThread.cpp +++ b/base/ReThread.cpp @@ -1,6 +1,6 @@ /* * ReThread.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. diff --git a/base/ReThread.hpp b/base/ReThread.hpp index 6980db8..5570d50 100644 --- a/base/ReThread.hpp +++ b/base/ReThread.hpp @@ -1,6 +1,6 @@ /* * ReThread.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. diff --git a/base/ReVarArgs.cpp b/base/ReVarArgs.cpp index 516cdc4..bd76269 100644 --- a/base/ReVarArgs.cpp +++ b/base/ReVarArgs.cpp @@ -1,6 +1,6 @@ /* * ReVarArgs.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -23,7 +23,7 @@ int const ReVarArgs::STD_SPACE = 20; char const ReVarArgs::PLACE_HOLDER_MARK = '$'; -typedef ReByteBuffer::Byte Byte; +typedef ReByteArray::Byte Byte; /** @brief Constructor. */ ReVarArgs::ReVarArgs(void) : @@ -248,7 +248,7 @@ ReVarArgs& ReVarArgs::arg(const char* value, int minWidth, int maxWidth, if (length >= minWidth) { store(value, maxWidth); } else { - ReByteBuffer buffer; + ReByteArray buffer; buffer.setLengthAndFillOut(minWidth, ' '); if (alignRight) memcpy(buffer.buffer() + minWidth - length, value, length); diff --git a/base/ReVarArgs.hpp b/base/ReVarArgs.hpp index b0b60f9..0b111c0 100644 --- a/base/ReVarArgs.hpp +++ b/base/ReVarArgs.hpp @@ -1,6 +1,6 @@ /* * ReVarArgs.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -60,7 +60,7 @@ public: * @param maxWidth maximum width of the string * @param alignRight true: padding is done at the start */ - inline ReVarArgs& arg(const ReByteBuffer& value, int minWidth = 0, + inline ReVarArgs& arg(const ReByteArray& value, int minWidth = 0, int maxWidth = 1024, bool alignRight = false) { return arg(value.str(), minWidth, maxWidth, alignRight); } @@ -75,9 +75,9 @@ protected: int m_maxArgNo; //@ Stores the format. When the first call of asCharPtr() //@ the expanded string will be stored here. - ReByteBuffer m_format; + ReByteArray m_format; //@ Stores the argument strings including the trailing '\0'. - ReByteBuffer m_argBuffer; + ReByteArray m_argBuffer; //@ Stores the positions (indexes) of the arguments in m_argBuffer. int m_args[100]; //@ true: The compound string is constructed (with expanded placeholders). false: Otherwise. diff --git a/base/baselocations.hpp b/base/baselocations.hpp index afa526a..dca1361 100644 --- a/base/baselocations.hpp +++ b/base/baselocations.hpp @@ -1,6 +1,6 @@ /* * baselocations.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. diff --git a/base/rebase.hpp b/base/rebase.hpp index 1003c16..8bc8c07 100644 --- a/base/rebase.hpp +++ b/base/rebase.hpp @@ -1,6 +1,6 @@ /* * rebase.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -10,6 +10,7 @@ */ #ifndef REBASE_HPP_ #define REBASE_HPP_ + #define min() #define max() #include @@ -133,7 +134,7 @@ inline int max(int a, int b) { #include "base/ReClassId.hpp" #include "base/ReException.hpp" #include "base/ReMutex.hpp" -#include "base/ReByteBuffer.hpp" +#include "base/ReByteArray.hpp" #include "base/ReSerializable.hpp" #include "base/ReVarArgs.hpp" #include "base/ReLogger.hpp" diff --git a/base/restring.hpp b/base/restring.hpp index 83e2d08..25dc650 100644 --- a/base/restring.hpp +++ b/base/restring.hpp @@ -1,6 +1,6 @@ /* * restring.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. diff --git a/cunit/basetest.cpp b/cunit/basetest.cpp index ffc13d5..bea5b62 100644 --- a/cunit/basetest.cpp +++ b/cunit/basetest.cpp @@ -1,6 +1,6 @@ /* * basetest.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. diff --git a/cunit/cuReByteArray.cpp b/cunit/cuReByteArray.cpp new file mode 100644 index 0000000..a0aa7ed --- /dev/null +++ b/cunit/cuReByteArray.cpp @@ -0,0 +1,725 @@ +/* + * cuReByteArray.cpp + * + * License: Public Domain + * You can use and modify this file without any restriction. + * Do what you want. + * No warranties and disclaimer of any damages. + * You also can use this license: http://www.wtfpl.net + * The latest sources: https://github.com/republib + */ +#include "base/rebase.hpp" +class TestReByteBuffer: public ReTestUnit { + typedef ReByteArray::Byte Byte; +public: + TestReByteBuffer() : + ReTestUnit("ReByteBuffer", __FILE__) { + run(); + } +private: + void run() { + testAppendBits(); + testAppendDump(); + testAppendFix(); + testEnsureLastChar(); + testLastChar(); + testReduceLength(); + testRemoveLastChar(); + testAppendChar(); + testAppendFloat(); + testAppendInt64(); + testEnsureSize2(); + testHexDump(); + testFill(); + testAppendMilliSec(); + testSetDelta(); + testFirstDiff(); + testCount(); + testEnsureSizeGetLength(); + testIndexOf(); + testRIndexOf(); + testStartsWidth(); + testEndsWidth(); + testOpAssignCopyConstructor(); + testAt(); + testBasic(); + testAtoi(); + testIndexOfCharRIndexOfChar(); + testRIndexOf(); + testInsert(); + testRemove(); + testSplice(); + testReplace(); + } + void testAppendBits() { + ReByteArray 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() { + ReByteArray buffer; + // predefined length (of source): + // case sensitive, same size + checkT(buffer.set("aBc").isPrefixOf("aBc")); + // case sensitive, shorter + checkT(buffer.set("aB").isPrefixOf("aBc")); + checkF(buffer.set("ab").isPrefixOf("aBc")); + // case sensitive, longer + checkF(buffer.set("aBcd").isPrefixOf("aBc")); + + // given length (of source): + // case sensitive, same size + checkT(buffer.set("aBc").isPrefixOf("aBcd", 3)); + // case sensitive, shorter + checkT(buffer.set("aB").isPrefixOf("aBcd", 3)); + checkF(buffer.set("ab").isPrefixOf("aBcd", 3)); + // 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("aB").isPrefixOf("abc", -1, true)); + // case sensitive, longer + checkF(buffer.set("aBcd").isPrefixOf("abc", -1, true)); + + // minSize: + checkT(buffer.set("aBc").isPrefixOf("abcd", -1, true, 2)); + checkF(buffer.set("aB").isPrefixOf("abc", -1, true, 3)); + } + void testAppendDump() { + ReByteArray buffer; + // true ASCII: + buffer.appendDump("abc"); + checkEqu("abc", buffer.str()); + buffer.setLength(0).appendDump("abcdefg", -1, 4); + checkEqu("abcd", buffer.str()); + buffer.setLength(0).appendDump("a\tb\nc\rd"); + checkEqu("a\tb\nc\rd", buffer.str()); + // binary: + int64_t ii = 0x12345678abcdefll; + buffer.setLength(0).appendDump(reinterpret_cast(&ii), + sizeof ii, 40); + checkEqu( + "0000: ef cd ab 78 56 34 12 00 | ...xV4.. ", + buffer.str()); + } + void testAppendFix() { + ReByteArray buffer; + // maxLength exceeded + // odd maxlength: + buffer.appendFix("123456", -1, 5); + checkEqu("12*56", buffer); + // given separator, even maxLength + buffer.appendFix("abcdefg", -1, 4, 4, "."); + checkEqu("12*56ab.g", buffer); + // given separator with more than one char / no separator + buffer.appendFix("ABCDEF", -1, 5, 5, "...").appendFix("xyz", -1, 2, 0, + NULL); + checkEqu("12*56ab.gA...Fxz", buffer); + + buffer = "x"; + // minlength not reached: + // data length given, minLength == length + buffer.appendFix("123", 2U, 99, 2, NULL, ':'); + checkEqu("x12", buffer); + // positive minLength + buffer.appendFix("abc", -1, 99, 4, NULL, ':'); + checkEqu("x12abc:", buffer); + // negative minLength + buffer.appendFix("AB", -1, 99, -4, NULL, '.'); + checkEqu("x12abc:..AB", buffer); + + buffer = "y"; + // minLength and maxLength not reached: + // minLength equal, maxLength equal: + buffer.appendFix("1234", 4, 4, 4); + checkEqu("y1234", buffer); + // minLength smaller, maxLength larger: + buffer.appendFix("a", 1, 2, 1); + checkEqu("y1234a", buffer); + + } + void testEnsureLastChar() { + ReByteArray buffer("1/"); + buffer.ensureLastChar('/'); + checkEqu(2U, buffer.length()); + checkEqu('/', buffer.lastChar()); + buffer.ensureLastChar('x'); + checkEqu(3U, buffer.length()); + checkEqu('x', buffer.lastChar()); + } + void testLastChar() { + ReByteArray buffer("12345"); + checkEqu('5', buffer.lastChar()); + buffer.setLength(0); + checkEqu('\0', buffer.lastChar()); + } + void testReduceLength() { + ReByteArray buffer("12345"); + buffer.reduceLength(); + checkEqu(4U, buffer.length()); + checkEqu("1234", buffer); + buffer.reduceLength(2); + checkEqu(2U, buffer.length()); + checkEqu("12", buffer); + buffer.reduceLength(0).reduceLength(-1); + checkEqu(2U, buffer.length()); + checkEqu("12", buffer); + buffer.reduceLength(99); + checkEqu(0U, buffer.length()); + } + void testRemoveLastChar() { + ReByteArray buffer("123"); + buffer.removeLastChar('x').removeLastChar('3'); + checkEqu(2U, buffer.length()); + checkEqu("12", buffer); + } + void testAppendChar() { + ReByteArray buffer; + buffer.appendChar('1'); + checkEqu(1U, buffer.length()); + checkEqu("1", buffer); + buffer.appendChar('2'); + checkEqu(2U, buffer.length()); + checkEqu("12", buffer); + + buffer.appendChar('x', 1); + checkEqu(3U, buffer.length()); + checkEqu("12x", buffer); + + buffer.appendChar('y', 3); + checkEqu(6U, buffer.length()); + checkEqu("12xyyy", buffer); + + buffer.appendChar('x', 0); + checkEqu(6U, buffer.length()); + checkEqu("12xyyy", buffer); + + buffer.appendChar('x', -1); + checkEqu(6U, buffer.length()); + checkEqu("12xyyy", buffer); + + } + void testAppendFloat() { + ReByteArray buffer; + + buffer.append(125 / 100.0); + checkEqu("1.250000", buffer); + buffer.append(0.333, "%.2f"); + checkEqu("1.2500000.33", buffer); + } + void testAppendInt64() { + ReByteArray buffer; + buffer.appendInt((int64_t) 12345678901ll); + checkEqu("12345678901", buffer); + buffer.appendInt((uint64_t) 0x123456789ll, "%llx"); + checkEqu("12345678901123456789", buffer); + + } + void testEnsureSize2() { + ReByteArray buffer; + buffer.setLength(PRIMARY_BUFFER_SIZE - 1); + buffer.fill('x', PRIMARY_BUFFER_SIZE - 1); + checkEqu(PRIMARY_BUFFER_SIZE - 1, (int ) buffer.capacity()); + buffer.ensureSize(PRIMARY_BUFFER_SIZE); + checkEqu(PRIMARY_BUFFER_SIZE*2 - 1, (int ) buffer.capacity()); + } + void testHexDump() { + ReByteArray buf; + /* appendHexDump(const char* data, size_t length, int offset = 0, int bytePerLine = 16, + const char* offsetFormat = "%04x ", bool withAscii = true, + int groupWidth = 1, int gapBehind = -1, const char* separator = " | "); + */ + buf.appendHexDump("abcdefghijklmnopq"); + checkEqu( + "0000: 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 | abcdefgh ijklmnop\n" + "0010: 71 | q \n", + buf); + buf.setLength(0).appendHexDump("abcdefghijklmnopq", 16); + checkEqu( + "0000: 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 | abcdefgh ijklmnop\n", + buf); + buf.setLength(0).appendHexDump("\t\nü23456789x123456", -1, 20, 8, + "%3d: ", true, 4, 0, NULL); + checkEqu(" 20: 090ac3bc 32333435....2345\n" + " 28: 36373839 783132336789x123\n" + " 36: 343536 456 \n", buf); + buf.setLength(0).appendHexDump("abcdefghijk", -1, 0, 8, "%3d: ", true, + 2, 4); + checkEqu(" 0: 6162 6364 6566 6768 | abcd efgh\n" + " 8: 696a 6b | ijk \n", buf); + } + void testFill() { + ReByteArray buf; + buf.fill('=', 0, 3); + checkEqu("===", buf); + buf.fill('x', 1, 2); + checkEqu("=x=", buf); + } + void testAppendMilliSec() { + ReByteArray buf; + checkEqu("5.123", buf.appendMilliSec(5123)); + checkEqu("32:45.789", + buf.setLength(0).appendMilliSec(32 * 60 * 1000 + 45789)); + checkEqu("17:04:06.976", + buf.setLength(0).appendMilliSec( + 17 * 3600 * 1000 + 4 * 60 * 1000 + 6976)); + } + void testSetDelta() { + ReByteArray buf("abcd"); + int maxDelta = 512 * (1 << 10); + buf.setDelta(-maxDelta); + int count = 0; + while (buf.capacity() < (size_t) maxDelta) { + buf.ensureSize(buf.capacity() + 2); + count++; + } + checkT(count <= 10 + 1); + } + void testFirstDiff() { + ReByteArray buf("abcd"); + // firstDifference(const Byte* source, size_t length, int start, bool ignoreCase) + // ignoreCase == false: + // start == 0, length == -1, same length: + checkEqu(-1, buf.firstDifference("abcd", -1)); + checkEqu(0, buf.firstDifference("xbcd", -1)); + checkEqu(1, buf.firstDifference("aBcd", -1)); + // start == 2, length == -1, same length: + checkEqu(-1, buf.firstDifference("cd", -1, 2)); + checkEqu(2, buf.firstDifference("xd", -1, 2)); + checkEqu(3, buf.firstDifference("cD", -1, 2)); + // start == 0, length > 0, same length: + checkEqu(-1, buf.firstDifference("axcd", 1)); + checkEqu(0, buf.firstDifference("xbcd", 2)); + checkEqu(1, buf.firstDifference("aBcd", 2)); + // start == 2, length > 0, same length: + checkEqu(-1, buf.firstDifference("cdx", 1, 2)); + checkEqu(2, buf.firstDifference("xd", 1, 2)); + checkEqu(3, buf.firstDifference("cD", 2, 2)); + + // ignoreCase == true: + // start == 0, length == -1, same length: + checkEqu(-1, buf.firstDifference("Abcd", -1, 0, true)); + checkEqu(0, buf.firstDifference("xbcd", -1, 0, true)); + checkEqu(-1, buf.firstDifference("aBcd", -1, 0, true)); + checkEqu(1, buf.firstDifference("aXcd", -1, 0, true)); + // start == 2, length == -1, same length: + checkEqu(-1, buf.firstDifference("cd", -1, 2, true)); + checkEqu(2, buf.firstDifference("xd", -1, 2, true)); + checkEqu(-1, buf.firstDifference("cD", -1, 2, true)); + checkEqu(3, buf.firstDifference("CX", -1, 2, true)); + // start == 0, length > 0, same length: + checkEqu(-1, buf.firstDifference("Axcd", 1, 0, true)); + checkEqu(0, buf.firstDifference("xbcd", 2, 0, true)); + checkEqu(-1, buf.firstDifference("AXcd", 1, 0, true)); + // start == 2, length > 0, same length: + checkEqu(-1, buf.firstDifference("cDx", 1, 2, true)); + checkEqu(2, buf.firstDifference("xd", 1, 2, true)); + checkEqu(-1, buf.firstDifference("cD", 1, 2, true)); + checkEqu(3, buf.firstDifference("cX", 2, 2, true)); + + // larger length: + checkEqu(4, buf.firstDifference("abcde", -1, 0, false)); + checkEqu(4, buf.firstDifference("cde", -1, 2, false)); + // wrong indexe: + checkEqu(0, buf.firstDifference("cdx", 1, -1, true)); + checkEqu(0, buf.firstDifference("cdx", 1, -1, false)); + } + void testCount() { + ReByteArray buffer("aabbaabb"); + checkEqu(4, buffer.count("a")); + checkEqu(4, buffer.count("b")); + checkEqu(2, buffer.count("ab")); + checkEqu(1, buffer.count("aabbaabb")); + } + void testStartsWidth() { + // . . . . . . . . . 01234567 + ReByteArray buffer("aabbaabb"); + // case sensitive + checkT(buffer.startsWith("aabbaabb", -1, false)); + checkT(buffer.startsWith("aabbaabb", 8, false)); + checkT(buffer.startsWith("a", -1, false)); + checkT(buffer.startsWith("aab", -1, false)); + checkT(buffer.startsWith("ax", 1, false)); + + // case insensitive + checkT(buffer.startsWith("AabbaabB", -1, true)); + checkT(buffer.startsWith("aabbaabB", 8, true)); + checkT(buffer.startsWith("A", -1, true)); + checkT(buffer.startsWith("aAb", -1, true)); + checkT(buffer.startsWith("Aax", 2, true)); + checkT(buffer.startsWith("aab", -1, false)); + + // not matching: + checkF(buffer.startsWith("b", 1, false)); + checkF(buffer.startsWith("ab", 2, false)); + checkF(buffer.startsWith("A", 1, false)); + checkF(buffer.startsWith("Ab", 2, false)); + + // binary: + buffer.buffer()[1] = '\0'; + ReByteArray buffer2("aab"); + ReByteArray buffer3("aax"); + buffer2.buffer()[1] = '\0'; + buffer3.buffer()[1] = '\0'; + checkT(buffer.startsWith(buffer2.str(), 3, false)); + checkF(buffer.startsWith(buffer3.str(), 3, false)); + buffer2.buffer()[0] = 'A'; + buffer3.buffer()[0] = 'A'; + checkT(buffer.startsWith(buffer2.str(), 3, true)); + checkF(buffer.startsWith(buffer3.str(), 3, true)); + } + + void testEndsWidth() { + // . . . . . . . . . 01234567 + ReByteArray buffer("aabbaabb"); + // case sensitive + checkT(buffer.endsWith("b", -1, false)); + checkT(buffer.endsWith("abb", -1, false)); + checkT(buffer.endsWith("bx", 1, false)); + + // case insensitive + checkT(buffer.endsWith("B", -1, true)); + checkT(buffer.endsWith("aBb", -1, true)); + checkT(buffer.endsWith("Bbx", 2, true)); + checkT(buffer.endsWith("Abb", -1, true)); + + // not matching: + checkF(buffer.endsWith("a", -1, false)); + checkF(buffer.endsWith("a", 1, false)); + checkF(buffer.endsWith("ab", 2, false)); + checkF(buffer.endsWith("B", 1, false)); + checkF(buffer.endsWith("Ab", 2, false)); + + // binary: + buffer.buffer()[6] = '\0'; + ReByteArray buffer2("abb"); + buffer2.buffer()[1] = '\0'; + checkT(buffer.endsWith(buffer2.str(), 3, false)); + buffer2.buffer()[0] = 'A'; + checkT(buffer.endsWith(buffer2.str(), 3, true)); + } + + void testIndexOf() { + // . . . . . . . . . 01234567 + ReByteArray buffer("aabbaabb"); + // const Byte* toFind, size_t toFindLength, int start,int end, bool ignoreCase + checkEqu(0, buffer.indexOf("aa", -1, 0, -1, false)); + int ix; + for (ix = 1; ix <= 4; ix++) + checkEqu(4, buffer.indexOf("aa", 2, ix, -1, false)); + checkEqu(4, buffer.indexOf("aa", 2, 1, 6, false)); + checkEqu(-1, buffer.indexOf("aa", 2, 1, 5, false)); + checkEqu(1, buffer.indexOf("ab", 2, 0, -1, false)); + checkEqu(-1, buffer.indexOf("Aa", 2, 0, -1, false)); + + checkEqu(0, buffer.indexOf("aA", 2, 0, -1, true)); + for (ix = 1; ix <= 4; ix++) + checkEqu(4, buffer.indexOf("Aa", 2, ix, -1, true)); + checkEqu(4, buffer.indexOf("aA", 2, 1, 6, true)); + checkEqu(-1, buffer.indexOf("Aa", 2, 1, 5, true)); + checkEqu(1, buffer.indexOf("aB", 2, 0, -1, true)); + } + void testRIndexOf() { + // . . . . . . . . . 01234567 + ReByteArray buffer("aabbaabb"); + // const Byte* toFind, size_t toFindLength, int start,int end, bool ignoreCase + checkEqu(4, buffer.rindexOf("aa", -1, 0, -1, false)); + int ix; + for (ix = 9; ix >= 6; ix--) + checkEqu(4, buffer.rindexOf("aa", 2, 0, ix, false)); + checkEqu(0, buffer.rindexOf("aa", 2, 0, 5, false)); + checkEqu(-1, buffer.rindexOf("aa", 2, 1, 3, false)); + checkEqu(1, buffer.rindexOf("ab", 2, 0, 5, false)); + checkEqu(1, buffer.rindexOf("ab", 2, 1, 5, false)); + checkEqu(-1, buffer.rindexOf("Aa", 2, 0, -1, false)); + + for (ix = 9; ix >= 6; ix--) + checkEqu(4, buffer.rindexOf("Aa", 2, 0, ix, true)); + checkEqu(0, buffer.rindexOf("aA", 2, 0, 5, true)); + checkEqu(-1, buffer.rindexOf("Aa", 2, 1, 3, true)); + checkEqu(1, buffer.rindexOf("aB", 2, 0, 5, true)); + checkEqu(1, buffer.rindexOf("Ab", 2, 1, 5, true)); + checkEqu(4, buffer.rindexOf("Aa", 2, 0, -1, true)); + } + void testBasic() { + ReByteArray buffer(10); + + buffer.append((Byte*) "123", 3); + checkEqu("123", buffer.buffer()); + checkEqu("123", buffer); + checkEqu(3u, buffer.length()); + buffer.append((Byte*) "ab", 2); + checkEqu("123ab", buffer.buffer()); + checkEqu(5u, buffer.length()); + + buffer.setLengthAndFillOut(8, 'x'); + checkEqu("123abxxx", buffer.buffer()); + checkEqu(8u, buffer.length()); + buffer.setLength(3); + checkEqu("123", buffer.buffer()); + checkEqu(3u, buffer.length()); + + buffer.setLengthAndFillOut(PRIMARY_BUFFER_SIZE - 1, 'y'); + buffer.setLengthAndFillOut(PRIMARY_BUFFER_SIZE, 'z'); + checkEqu("yyz", buffer.buffer() + PRIMARY_BUFFER_SIZE - 3); + checkEqu(PRIMARY_BUFFER_SIZE + 10 - 1, (int ) buffer.capacity()); + + ReByteArray buffer2; + buffer2.set("xyz", -1); + buffer.set("abc", -1); + checkEqu("abc", buffer.buffer()); + checkEqu(3u, buffer.length()); + buffer.append(buffer2); + checkEqu("abcxyz", buffer.buffer()); + checkEqu("abcxyz", buffer); + checkEqu(6u, buffer.length()); + + buffer.setLength(0); + buffer.appendInt(-1); + checkEqu("-1", buffer); + checkEqu(2u, buffer.length()); + + buffer.appendInt(9, "%03d"); + checkEqu("-1009", buffer); + checkEqu(5u, buffer.length()); + + buffer.setLength(0).appendInt((unsigned int) 123); + checkEqu("123", buffer); + buffer.appendInt((unsigned int) 0x87654321, "%x"); + checkEqu("12387654321", buffer); + + } + void testOpAssignCopyConstructor() { + ReByteArray buf1; + buf1.set("abc", 3); + ReByteArray buf3; + { + ReByteArray buf2(buf1); + checkEqu("abc", buf2); + buf3 = buf2; + buf2.append("123", 3); + } + checkEqu("abc", buf3); + checkEqu("abc", buf1); + } + void testAt() { + ReByteArray buf1; + buf1.set("abc", 3); + for (size_t ii = 0; ii < buf1.length(); ii++) { + checkEqu(int('a' + ii), (int ) buf1.at(ii)); + } + checkEqu(0, buf1.at(-1)); + checkEqu(0, buf1.at(3)); + checkEqu(0, buf1.at(4)); + } + void testAtoi() { + ReByteArray buffer; + buffer.set("y1234", -1); + + checkEqu(1, buffer.atoi(1, 2)); + checkEqu(12, buffer.atoi(1, 3)); + checkEqu(123, buffer.atoi(1, 4)); + checkEqu(1234, buffer.atoi(1, 5)); + checkEqu(1234, buffer.atoi(1, 6)); + checkEqu(0, buffer.atoi(0, 6)); + + buffer.set("456y", -1); + + checkEqu(4, buffer.atoi(0, 1)); + checkEqu(45, buffer.atoi(0, 2)); + checkEqu(456, buffer.atoi(0, 3)); + checkEqu(456, buffer.atoi(0, 4)); + checkEqu(0, buffer.atoi(4, 6)); + + buffer.set("987654321", -1); + checkEqu(987654321, buffer.atoi()); + + buffer.set("187654302ab", -1); + checkEqu(187654302, buffer.atoi()); + + buffer.set("y0x1234", -1); + + checkEqu(0x1, buffer.atoi(1, 4)); + checkEqu(0x12, buffer.atoi(1, 5)); + checkEqu(0x123, buffer.atoi(1, 6)); + checkEqu(0x1234, buffer.atoi(1, 7)); + checkEqu(0x1234, buffer.atoi(1, 8)); + checkEqu(0, buffer.atoi(0, 8)); + checkEqu(0, buffer.atoi(2, 8)); + + buffer.set("0x456y", -1); + + checkEqu(0x4, buffer.atoi(0, 3)); + checkEqu(0x45, buffer.atoi(0, 4)); + checkEqu(0x456, buffer.atoi(0, 6)); + checkEqu(0x456, buffer.atoi(0, 7)); + checkEqu(0, buffer.atoi(5, 6)); + + buffer.set("0x98765432", -1); + checkEqu(0x98765432U, (unsigned ) buffer.atoi()); + + buffer.set("0xabcdef01", -1); + checkEqu(0xabcdef01U, (unsigned ) buffer.atoi()); + buffer.set("0xABCDEF01", -1); + checkEqu(0xabcdef01U, (unsigned ) buffer.atoi()); + buffer.set("0xaFFe01", -1); + checkEqu(0xaFFe01U, (unsigned ) buffer.atoi()); + } + void testEnsureSizeGetLength() { + ReByteArray buf1; + buf1.ensureSize(2000); + checkEqu(2000u, buf1.capacity()); + buf1.set("0123456789", 10); + checkEqu(10u, buf1.length()); + + buf1.setLength(5); + checkEqu("01234", buf1); + checkEqu(5u, buf1.length()); + + buf1.setLengthAndFillOut(8, 'X'); + checkEqu("01234XXX", buf1); + checkEqu(8u, buf1.length()); + checkEqu(2000u, buf1.capacity()); + } + + void testIndexOfCharRIndexOfChar() { + ReByteArray buffer; + buffer.set("123123", -1); + checkEqu(0, buffer.indexOf('1')); + checkEqu(1, buffer.indexOf('2')); + checkEqu(3, buffer.indexOf('1', 1)); + checkEqu(2, buffer.indexOf('3', 2)); + checkEqu(5, buffer.indexOf('3', 3)); + checkEqu(-1, buffer.indexOf('4')); + checkEqu(-1, buffer.indexOf('1', 4)); + + checkEqu(3, buffer.rindexOf('1')); + checkEqu(4, buffer.rindexOf('2')); + checkEqu(3, buffer.rindexOf('1', -2)); + checkEqu(3, buffer.rindexOf('1', -3)); + checkEqu(0, buffer.rindexOf('1', -4)); + + checkEqu(4, buffer.rindexOf('2', 4)); + checkEqu(1, buffer.rindexOf('2', 3)); + + checkEqu(4, buffer.rindexOf('2', -2)); + checkEqu(1, buffer.rindexOf('2', -3)); + + checkEqu(0, buffer.rindexOf('1', 0)); + + checkEqu(-1, buffer.rindexOf('4')); + checkEqu(-1, buffer.rindexOf('2', 0)); + + checkEqu(1, buffer.indexOf("23", 2, 0)); + checkEqu(1, buffer.indexOf("23", -1, 0)); + checkEqu(1, buffer.indexOf("23x", 2, 0)); + checkEqu(4, buffer.indexOf("23", 2, 2)); + checkEqu(4, buffer.indexOf("23", -1, 2)); + + checkEqu(-1, buffer.indexOf("234", -1, 0)); + checkEqu(-1, buffer.indexOf("23", -1, 5)); + } + void testInsert() { + ReByteArray buf1; + checkT(buf1.insert(0, "123", 2)); + checkEqu("12", buf1); + checkEqu(2u, buf1.length()); + + checkT(buf1.insert(0, "abc", 1)); + checkEqu("a12", buf1); + checkEqu(3u, buf1.length()); + + checkT(buf1.insert(1, "x", 1)); + checkEqu("ax12", buf1); + checkEqu(4u, buf1.length()); + + checkT(buf1.insert(4, "yz", 2)); + checkEqu("ax12yz", buf1); + checkEqu(6u, buf1.length()); + + checkF(buf1.insert(-1, "-", 1)); + checkF(buf1.insert(8, "/", 1)); + + } + void testRemove() { + ReByteArray buf1; + buf1.set("1234567890", 10); + checkT(buf1.remove(0, 2)); + checkEqu("34567890", buf1); + checkEqu(8u, buf1.length()); + + checkF(buf1.remove(-1, 2)); + checkEqu("34567890", buf1); + checkEqu(8u, buf1.length()); + + checkF(buf1.remove(9, 2)); + checkEqu("34567890", buf1); + checkEqu(8u, buf1.length()); + + checkT(buf1.remove(7, 2)); + checkEqu("3456789", buf1); + checkEqu(7u, buf1.length()); + + checkT(buf1.remove(5, 2)); + checkEqu("34567", buf1); + checkEqu(5u, buf1.length()); + + checkT(buf1.remove(0, 99)); + checkEqu("", buf1); + checkEqu(0u, buf1.length()); + } + void testReplace() { + ReByteArray buffer; + + buffer.set("1234", 4); + buffer.replaceAll("12", 2, "abc", 3); + checkEqu("abc34", buffer); + + buffer.replaceAll("c34", 2, "uv", 3); + checkEqu("abuv", buffer); + + buffer.set("$$x$$", -1); + buffer.replaceAll("$", 1, "XX", 2); + checkEqu("XXXXxXXXX", buffer); + } + void testSplice() { + ReByteArray buffer; + + buffer.append((Byte*) "12.ab", 5); + checkT(buffer.splice(0, 0, "xy", 2)); + checkEqu("xy12.ab", buffer.buffer()); + buffer.splice(2, 2, NULL, 0); + checkEqu("xy.ab", buffer.buffer()); + buffer.splice(0, 2, "w", 1); + checkEqu("w.ab", buffer.buffer()); + + buffer.setLength(0); + buffer.append((Byte*) "123", 3); + buffer.insert(1, "ab", 2); + checkEqu("1ab23", buffer.buffer()); + checkEqu(5u, buffer.length()); + buffer.remove(0, 1); + checkEqu("ab23", buffer.buffer()); + checkEqu(4u, buffer.length()); + buffer.remove(3, 55); + checkEqu("ab2", buffer.buffer()); + checkEqu(3u, buffer.length()); + buffer.remove(2, 2); + checkEqu("ab", buffer.buffer()); + checkEqu(2u, buffer.length()); + buffer.remove(1, 1); + checkEqu("a", buffer.buffer()); + checkEqu(1u, buffer.length()); + } +}; +extern void testReByteBuffer(void); + +void testReByteBuffer(void) { + TestReByteBuffer unit; +} + diff --git a/cunit/cuReByteBuffer.cpp b/cunit/cuReByteBuffer.cpp deleted file mode 100644 index cec85c1..0000000 --- a/cunit/cuReByteBuffer.cpp +++ /dev/null @@ -1,725 +0,0 @@ -/* - * cuReByteBuffer.cpp - * - * License: Public Domain - * You can use and modify this file without any restriction. - * Do what you want. - * No warranties and disclaimer of any damages. - * You also can use this license: http://www.wtfpl.net - * The latest sources: https://github.com/republib - */ -#include "base/rebase.hpp" -class TestReByteBuffer: public ReTestUnit { - typedef ReByteBuffer::Byte Byte; -public: - TestReByteBuffer() : - ReTestUnit("ReByteBuffer", __FILE__) { - run(); - } -private: - void run() { - testAppendBits(); - testAppendDump(); - testAppendFix(); - testEnsureLastChar(); - testLastChar(); - testReduceLength(); - testRemoveLastChar(); - testAppendChar(); - testAppendFloat(); - testAppendInt64(); - testEnsureSize2(); - testHexDump(); - testFill(); - testAppendMilliSec(); - testSetDelta(); - testFirstDiff(); - testCount(); - testEnsureSizeGetLength(); - testIndexOf(); - testRIndexOf(); - testStartsWidth(); - testEndsWidth(); - testOpAssignCopyConstructor(); - testAt(); - testBasic(); - testAtoi(); - testIndexOfCharRIndexOfChar(); - testRIndexOf(); - testInsert(); - testRemove(); - testSplice(); - testReplace(); - } - 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 - checkT(buffer.set("aBc").isPrefixOf("aBc")); - // case sensitive, shorter - checkT(buffer.set("aB").isPrefixOf("aBc")); - checkF(buffer.set("ab").isPrefixOf("aBc")); - // case sensitive, longer - checkF(buffer.set("aBcd").isPrefixOf("aBc")); - - // given length (of source): - // case sensitive, same size - checkT(buffer.set("aBc").isPrefixOf("aBcd", 3)); - // case sensitive, shorter - checkT(buffer.set("aB").isPrefixOf("aBcd", 3)); - checkF(buffer.set("ab").isPrefixOf("aBcd", 3)); - // 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("aB").isPrefixOf("abc", -1, true)); - // case sensitive, longer - checkF(buffer.set("aBcd").isPrefixOf("abc", -1, true)); - - // minSize: - checkT(buffer.set("aBc").isPrefixOf("abcd", -1, true, 2)); - checkF(buffer.set("aB").isPrefixOf("abc", -1, true, 3)); - } - void testAppendDump() { - ReByteBuffer buffer; - // true ASCII: - buffer.appendDump("abc"); - checkEqu("abc", buffer.str()); - buffer.setLength(0).appendDump("abcdefg", -1, 4); - checkEqu("abcd", buffer.str()); - buffer.setLength(0).appendDump("a\tb\nc\rd"); - checkEqu("a\tb\nc\rd", buffer.str()); - // binary: - int64_t ii = 0x12345678abcdefll; - buffer.setLength(0).appendDump(reinterpret_cast(&ii), - sizeof ii, 40); - checkEqu( - "0000: ef cd ab 78 56 34 12 00 | ...xV4.. ", - buffer.str()); - } - void testAppendFix() { - ReByteBuffer buffer; - // maxLength exceeded - // odd maxlength: - buffer.appendFix("123456", -1, 5); - checkEqu("12*56", buffer); - // given separator, even maxLength - buffer.appendFix("abcdefg", -1, 4, 4, "."); - checkEqu("12*56ab.g", buffer); - // given separator with more than one char / no separator - buffer.appendFix("ABCDEF", -1, 5, 5, "...").appendFix("xyz", -1, 2, 0, - NULL); - checkEqu("12*56ab.gA...Fxz", buffer); - - buffer = "x"; - // minlength not reached: - // data length given, minLength == length - buffer.appendFix("123", 2U, 99, 2, NULL, ':'); - checkEqu("x12", buffer); - // positive minLength - buffer.appendFix("abc", -1, 99, 4, NULL, ':'); - checkEqu("x12abc:", buffer); - // negative minLength - buffer.appendFix("AB", -1, 99, -4, NULL, '.'); - checkEqu("x12abc:..AB", buffer); - - buffer = "y"; - // minLength and maxLength not reached: - // minLength equal, maxLength equal: - buffer.appendFix("1234", 4, 4, 4); - checkEqu("y1234", buffer); - // minLength smaller, maxLength larger: - buffer.appendFix("a", 1, 2, 1); - checkEqu("y1234a", buffer); - - } - void testEnsureLastChar() { - ReByteBuffer buffer("1/"); - buffer.ensureLastChar('/'); - checkEqu(2U, buffer.length()); - checkEqu('/', buffer.lastChar()); - buffer.ensureLastChar('x'); - checkEqu(3U, buffer.length()); - checkEqu('x', buffer.lastChar()); - } - void testLastChar() { - ReByteBuffer buffer("12345"); - checkEqu('5', buffer.lastChar()); - buffer.setLength(0); - checkEqu('\0', buffer.lastChar()); - } - void testReduceLength() { - ReByteBuffer buffer("12345"); - buffer.reduceLength(); - checkEqu(4U, buffer.length()); - checkEqu("1234", buffer); - buffer.reduceLength(2); - checkEqu(2U, buffer.length()); - checkEqu("12", buffer); - buffer.reduceLength(0).reduceLength(-1); - checkEqu(2U, buffer.length()); - checkEqu("12", buffer); - buffer.reduceLength(99); - checkEqu(0U, buffer.length()); - } - void testRemoveLastChar() { - ReByteBuffer buffer("123"); - buffer.removeLastChar('x').removeLastChar('3'); - checkEqu(2U, buffer.length()); - checkEqu("12", buffer); - } - void testAppendChar() { - ReByteBuffer buffer; - buffer.appendChar('1'); - checkEqu(1U, buffer.length()); - checkEqu("1", buffer); - buffer.appendChar('2'); - checkEqu(2U, buffer.length()); - checkEqu("12", buffer); - - buffer.appendChar('x', 1); - checkEqu(3U, buffer.length()); - checkEqu("12x", buffer); - - buffer.appendChar('y', 3); - checkEqu(6U, buffer.length()); - checkEqu("12xyyy", buffer); - - buffer.appendChar('x', 0); - checkEqu(6U, buffer.length()); - checkEqu("12xyyy", buffer); - - buffer.appendChar('x', -1); - checkEqu(6U, buffer.length()); - checkEqu("12xyyy", buffer); - - } - void testAppendFloat() { - ReByteBuffer buffer; - - buffer.append(125 / 100.0); - checkEqu("1.250000", buffer); - buffer.append(0.333, "%.2f"); - checkEqu("1.2500000.33", buffer); - } - void testAppendInt64() { - ReByteBuffer buffer; - buffer.appendInt((int64_t) 12345678901ll); - checkEqu("12345678901", buffer); - buffer.appendInt((uint64_t) 0x123456789ll, "%llx"); - checkEqu("12345678901123456789", buffer); - - } - void testEnsureSize2() { - ReByteBuffer buffer; - buffer.setLength(PRIMARY_BUFFER_SIZE - 1); - buffer.fill('x', PRIMARY_BUFFER_SIZE - 1); - checkEqu(PRIMARY_BUFFER_SIZE - 1, (int ) buffer.capacity()); - buffer.ensureSize(PRIMARY_BUFFER_SIZE); - checkEqu(PRIMARY_BUFFER_SIZE*2 - 1, (int ) buffer.capacity()); - } - void testHexDump() { - ReByteBuffer buf; - /* appendHexDump(const char* data, size_t length, int offset = 0, int bytePerLine = 16, - const char* offsetFormat = "%04x ", bool withAscii = true, - int groupWidth = 1, int gapBehind = -1, const char* separator = " | "); - */ - buf.appendHexDump("abcdefghijklmnopq"); - checkEqu( - "0000: 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 | abcdefgh ijklmnop\n" - "0010: 71 | q \n", - buf); - buf.setLength(0).appendHexDump("abcdefghijklmnopq", 16); - checkEqu( - "0000: 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 | abcdefgh ijklmnop\n", - buf); - buf.setLength(0).appendHexDump("\t\nü23456789x123456", -1, 20, 8, - "%3d: ", true, 4, 0, NULL); - checkEqu(" 20: 090ac3bc 32333435....2345\n" - " 28: 36373839 783132336789x123\n" - " 36: 343536 456 \n", buf); - buf.setLength(0).appendHexDump("abcdefghijk", -1, 0, 8, "%3d: ", true, - 2, 4); - checkEqu(" 0: 6162 6364 6566 6768 | abcd efgh\n" - " 8: 696a 6b | ijk \n", buf); - } - void testFill() { - ReByteBuffer buf; - buf.fill('=', 0, 3); - checkEqu("===", buf); - buf.fill('x', 1, 2); - checkEqu("=x=", buf); - } - void testAppendMilliSec() { - ReByteBuffer buf; - checkEqu("5.123", buf.appendMilliSec(5123)); - checkEqu("32:45.789", - buf.setLength(0).appendMilliSec(32 * 60 * 1000 + 45789)); - checkEqu("17:04:06.976", - buf.setLength(0).appendMilliSec( - 17 * 3600 * 1000 + 4 * 60 * 1000 + 6976)); - } - void testSetDelta() { - ReByteBuffer buf("abcd"); - int maxDelta = 512 * (1 << 10); - buf.setDelta(-maxDelta); - int count = 0; - while (buf.capacity() < (size_t) maxDelta) { - buf.ensureSize(buf.capacity() + 2); - count++; - } - checkT(count <= 10 + 1); - } - void testFirstDiff() { - ReByteBuffer buf("abcd"); - // firstDifference(const Byte* source, size_t length, int start, bool ignoreCase) - // ignoreCase == false: - // start == 0, length == -1, same length: - checkEqu(-1, buf.firstDifference("abcd", -1)); - checkEqu(0, buf.firstDifference("xbcd", -1)); - checkEqu(1, buf.firstDifference("aBcd", -1)); - // start == 2, length == -1, same length: - checkEqu(-1, buf.firstDifference("cd", -1, 2)); - checkEqu(2, buf.firstDifference("xd", -1, 2)); - checkEqu(3, buf.firstDifference("cD", -1, 2)); - // start == 0, length > 0, same length: - checkEqu(-1, buf.firstDifference("axcd", 1)); - checkEqu(0, buf.firstDifference("xbcd", 2)); - checkEqu(1, buf.firstDifference("aBcd", 2)); - // start == 2, length > 0, same length: - checkEqu(-1, buf.firstDifference("cdx", 1, 2)); - checkEqu(2, buf.firstDifference("xd", 1, 2)); - checkEqu(3, buf.firstDifference("cD", 2, 2)); - - // ignoreCase == true: - // start == 0, length == -1, same length: - checkEqu(-1, buf.firstDifference("Abcd", -1, 0, true)); - checkEqu(0, buf.firstDifference("xbcd", -1, 0, true)); - checkEqu(-1, buf.firstDifference("aBcd", -1, 0, true)); - checkEqu(1, buf.firstDifference("aXcd", -1, 0, true)); - // start == 2, length == -1, same length: - checkEqu(-1, buf.firstDifference("cd", -1, 2, true)); - checkEqu(2, buf.firstDifference("xd", -1, 2, true)); - checkEqu(-1, buf.firstDifference("cD", -1, 2, true)); - checkEqu(3, buf.firstDifference("CX", -1, 2, true)); - // start == 0, length > 0, same length: - checkEqu(-1, buf.firstDifference("Axcd", 1, 0, true)); - checkEqu(0, buf.firstDifference("xbcd", 2, 0, true)); - checkEqu(-1, buf.firstDifference("AXcd", 1, 0, true)); - // start == 2, length > 0, same length: - checkEqu(-1, buf.firstDifference("cDx", 1, 2, true)); - checkEqu(2, buf.firstDifference("xd", 1, 2, true)); - checkEqu(-1, buf.firstDifference("cD", 1, 2, true)); - checkEqu(3, buf.firstDifference("cX", 2, 2, true)); - - // larger length: - checkEqu(4, buf.firstDifference("abcde", -1, 0, false)); - checkEqu(4, buf.firstDifference("cde", -1, 2, false)); - // wrong indexe: - checkEqu(0, buf.firstDifference("cdx", 1, -1, true)); - checkEqu(0, buf.firstDifference("cdx", 1, -1, false)); - } - void testCount() { - ReByteBuffer buffer("aabbaabb"); - checkEqu(4, buffer.count("a")); - checkEqu(4, buffer.count("b")); - checkEqu(2, buffer.count("ab")); - checkEqu(1, buffer.count("aabbaabb")); - } - void testStartsWidth() { - // . . . . . . . . . 01234567 - ReByteBuffer buffer("aabbaabb"); - // case sensitive - checkT(buffer.startsWith("aabbaabb", -1, false)); - checkT(buffer.startsWith("aabbaabb", 8, false)); - checkT(buffer.startsWith("a", -1, false)); - checkT(buffer.startsWith("aab", -1, false)); - checkT(buffer.startsWith("ax", 1, false)); - - // case insensitive - checkT(buffer.startsWith("AabbaabB", -1, true)); - checkT(buffer.startsWith("aabbaabB", 8, true)); - checkT(buffer.startsWith("A", -1, true)); - checkT(buffer.startsWith("aAb", -1, true)); - checkT(buffer.startsWith("Aax", 2, true)); - checkT(buffer.startsWith("aab", -1, false)); - - // not matching: - checkF(buffer.startsWith("b", 1, false)); - checkF(buffer.startsWith("ab", 2, false)); - checkF(buffer.startsWith("A", 1, false)); - checkF(buffer.startsWith("Ab", 2, false)); - - // binary: - buffer.buffer()[1] = '\0'; - ReByteBuffer buffer2("aab"); - ReByteBuffer buffer3("aax"); - buffer2.buffer()[1] = '\0'; - buffer3.buffer()[1] = '\0'; - checkT(buffer.startsWith(buffer2.str(), 3, false)); - checkF(buffer.startsWith(buffer3.str(), 3, false)); - buffer2.buffer()[0] = 'A'; - buffer3.buffer()[0] = 'A'; - checkT(buffer.startsWith(buffer2.str(), 3, true)); - checkF(buffer.startsWith(buffer3.str(), 3, true)); - } - - void testEndsWidth() { - // . . . . . . . . . 01234567 - ReByteBuffer buffer("aabbaabb"); - // case sensitive - checkT(buffer.endsWith("b", -1, false)); - checkT(buffer.endsWith("abb", -1, false)); - checkT(buffer.endsWith("bx", 1, false)); - - // case insensitive - checkT(buffer.endsWith("B", -1, true)); - checkT(buffer.endsWith("aBb", -1, true)); - checkT(buffer.endsWith("Bbx", 2, true)); - checkT(buffer.endsWith("Abb", -1, true)); - - // not matching: - checkF(buffer.endsWith("a", -1, false)); - checkF(buffer.endsWith("a", 1, false)); - checkF(buffer.endsWith("ab", 2, false)); - checkF(buffer.endsWith("B", 1, false)); - checkF(buffer.endsWith("Ab", 2, false)); - - // binary: - buffer.buffer()[6] = '\0'; - ReByteBuffer buffer2("abb"); - buffer2.buffer()[1] = '\0'; - checkT(buffer.endsWith(buffer2.str(), 3, false)); - buffer2.buffer()[0] = 'A'; - checkT(buffer.endsWith(buffer2.str(), 3, true)); - } - - void testIndexOf() { - // . . . . . . . . . 01234567 - ReByteBuffer buffer("aabbaabb"); - // const Byte* toFind, size_t toFindLength, int start,int end, bool ignoreCase - checkEqu(0, buffer.indexOf("aa", -1, 0, -1, false)); - int ix; - for (ix = 1; ix <= 4; ix++) - checkEqu(4, buffer.indexOf("aa", 2, ix, -1, false)); - checkEqu(4, buffer.indexOf("aa", 2, 1, 6, false)); - checkEqu(-1, buffer.indexOf("aa", 2, 1, 5, false)); - checkEqu(1, buffer.indexOf("ab", 2, 0, -1, false)); - checkEqu(-1, buffer.indexOf("Aa", 2, 0, -1, false)); - - checkEqu(0, buffer.indexOf("aA", 2, 0, -1, true)); - for (ix = 1; ix <= 4; ix++) - checkEqu(4, buffer.indexOf("Aa", 2, ix, -1, true)); - checkEqu(4, buffer.indexOf("aA", 2, 1, 6, true)); - checkEqu(-1, buffer.indexOf("Aa", 2, 1, 5, true)); - checkEqu(1, buffer.indexOf("aB", 2, 0, -1, true)); - } - void testRIndexOf() { - // . . . . . . . . . 01234567 - ReByteBuffer buffer("aabbaabb"); - // const Byte* toFind, size_t toFindLength, int start,int end, bool ignoreCase - checkEqu(4, buffer.rindexOf("aa", -1, 0, -1, false)); - int ix; - for (ix = 9; ix >= 6; ix--) - checkEqu(4, buffer.rindexOf("aa", 2, 0, ix, false)); - checkEqu(0, buffer.rindexOf("aa", 2, 0, 5, false)); - checkEqu(-1, buffer.rindexOf("aa", 2, 1, 3, false)); - checkEqu(1, buffer.rindexOf("ab", 2, 0, 5, false)); - checkEqu(1, buffer.rindexOf("ab", 2, 1, 5, false)); - checkEqu(-1, buffer.rindexOf("Aa", 2, 0, -1, false)); - - for (ix = 9; ix >= 6; ix--) - checkEqu(4, buffer.rindexOf("Aa", 2, 0, ix, true)); - checkEqu(0, buffer.rindexOf("aA", 2, 0, 5, true)); - checkEqu(-1, buffer.rindexOf("Aa", 2, 1, 3, true)); - checkEqu(1, buffer.rindexOf("aB", 2, 0, 5, true)); - checkEqu(1, buffer.rindexOf("Ab", 2, 1, 5, true)); - checkEqu(4, buffer.rindexOf("Aa", 2, 0, -1, true)); - } - void testBasic() { - ReByteBuffer buffer(10); - - buffer.append((Byte*) "123", 3); - checkEqu("123", buffer.buffer()); - checkEqu("123", buffer); - checkEqu(3u, buffer.length()); - buffer.append((Byte*) "ab", 2); - checkEqu("123ab", buffer.buffer()); - checkEqu(5u, buffer.length()); - - buffer.setLengthAndFillOut(8, 'x'); - checkEqu("123abxxx", buffer.buffer()); - checkEqu(8u, buffer.length()); - buffer.setLength(3); - checkEqu("123", buffer.buffer()); - checkEqu(3u, buffer.length()); - - buffer.setLengthAndFillOut(PRIMARY_BUFFER_SIZE - 1, 'y'); - buffer.setLengthAndFillOut(PRIMARY_BUFFER_SIZE, 'z'); - checkEqu("yyz", buffer.buffer() + PRIMARY_BUFFER_SIZE - 3); - checkEqu(PRIMARY_BUFFER_SIZE + 10 - 1, (int ) buffer.capacity()); - - ReByteBuffer buffer2; - buffer2.set("xyz", -1); - buffer.set("abc", -1); - checkEqu("abc", buffer.buffer()); - checkEqu(3u, buffer.length()); - buffer.append(buffer2); - checkEqu("abcxyz", buffer.buffer()); - checkEqu("abcxyz", buffer); - checkEqu(6u, buffer.length()); - - buffer.setLength(0); - buffer.appendInt(-1); - checkEqu("-1", buffer); - checkEqu(2u, buffer.length()); - - buffer.appendInt(9, "%03d"); - checkEqu("-1009", buffer); - checkEqu(5u, buffer.length()); - - buffer.setLength(0).appendInt((unsigned int) 123); - checkEqu("123", buffer); - buffer.appendInt((unsigned int) 0x87654321, "%x"); - checkEqu("12387654321", buffer); - - } - void testOpAssignCopyConstructor() { - ReByteBuffer buf1; - buf1.set("abc", 3); - ReByteBuffer buf3; - { - ReByteBuffer buf2(buf1); - checkEqu("abc", buf2); - buf3 = buf2; - buf2.append("123", 3); - } - checkEqu("abc", buf3); - checkEqu("abc", buf1); - } - void testAt() { - ReByteBuffer buf1; - buf1.set("abc", 3); - for (size_t ii = 0; ii < buf1.length(); ii++) { - checkEqu(int('a' + ii), (int ) buf1.at(ii)); - } - checkEqu(0, buf1.at(-1)); - checkEqu(0, buf1.at(3)); - checkEqu(0, buf1.at(4)); - } - void testAtoi() { - ReByteBuffer buffer; - buffer.set("y1234", -1); - - checkEqu(1, buffer.atoi(1, 2)); - checkEqu(12, buffer.atoi(1, 3)); - checkEqu(123, buffer.atoi(1, 4)); - checkEqu(1234, buffer.atoi(1, 5)); - checkEqu(1234, buffer.atoi(1, 6)); - checkEqu(0, buffer.atoi(0, 6)); - - buffer.set("456y", -1); - - checkEqu(4, buffer.atoi(0, 1)); - checkEqu(45, buffer.atoi(0, 2)); - checkEqu(456, buffer.atoi(0, 3)); - checkEqu(456, buffer.atoi(0, 4)); - checkEqu(0, buffer.atoi(4, 6)); - - buffer.set("987654321", -1); - checkEqu(987654321, buffer.atoi()); - - buffer.set("187654302ab", -1); - checkEqu(187654302, buffer.atoi()); - - buffer.set("y0x1234", -1); - - checkEqu(0x1, buffer.atoi(1, 4)); - checkEqu(0x12, buffer.atoi(1, 5)); - checkEqu(0x123, buffer.atoi(1, 6)); - checkEqu(0x1234, buffer.atoi(1, 7)); - checkEqu(0x1234, buffer.atoi(1, 8)); - checkEqu(0, buffer.atoi(0, 8)); - checkEqu(0, buffer.atoi(2, 8)); - - buffer.set("0x456y", -1); - - checkEqu(0x4, buffer.atoi(0, 3)); - checkEqu(0x45, buffer.atoi(0, 4)); - checkEqu(0x456, buffer.atoi(0, 6)); - checkEqu(0x456, buffer.atoi(0, 7)); - checkEqu(0, buffer.atoi(5, 6)); - - buffer.set("0x98765432", -1); - checkEqu(0x98765432U, (unsigned ) buffer.atoi()); - - buffer.set("0xabcdef01", -1); - checkEqu(0xabcdef01U, (unsigned ) buffer.atoi()); - buffer.set("0xABCDEF01", -1); - checkEqu(0xabcdef01U, (unsigned ) buffer.atoi()); - buffer.set("0xaFFe01", -1); - checkEqu(0xaFFe01U, (unsigned ) buffer.atoi()); - } - void testEnsureSizeGetLength() { - ReByteBuffer buf1; - buf1.ensureSize(2000); - checkEqu(2000u, buf1.capacity()); - buf1.set("0123456789", 10); - checkEqu(10u, buf1.length()); - - buf1.setLength(5); - checkEqu("01234", buf1); - checkEqu(5u, buf1.length()); - - buf1.setLengthAndFillOut(8, 'X'); - checkEqu("01234XXX", buf1); - checkEqu(8u, buf1.length()); - checkEqu(2000u, buf1.capacity()); - } - - void testIndexOfCharRIndexOfChar() { - ReByteBuffer buffer; - buffer.set("123123", -1); - checkEqu(0, buffer.indexOf('1')); - checkEqu(1, buffer.indexOf('2')); - checkEqu(3, buffer.indexOf('1', 1)); - checkEqu(2, buffer.indexOf('3', 2)); - checkEqu(5, buffer.indexOf('3', 3)); - checkEqu(-1, buffer.indexOf('4')); - checkEqu(-1, buffer.indexOf('1', 4)); - - checkEqu(3, buffer.rindexOf('1')); - checkEqu(4, buffer.rindexOf('2')); - checkEqu(3, buffer.rindexOf('1', -2)); - checkEqu(3, buffer.rindexOf('1', -3)); - checkEqu(0, buffer.rindexOf('1', -4)); - - checkEqu(4, buffer.rindexOf('2', 4)); - checkEqu(1, buffer.rindexOf('2', 3)); - - checkEqu(4, buffer.rindexOf('2', -2)); - checkEqu(1, buffer.rindexOf('2', -3)); - - checkEqu(0, buffer.rindexOf('1', 0)); - - checkEqu(-1, buffer.rindexOf('4')); - checkEqu(-1, buffer.rindexOf('2', 0)); - - checkEqu(1, buffer.indexOf("23", 2, 0)); - checkEqu(1, buffer.indexOf("23", -1, 0)); - checkEqu(1, buffer.indexOf("23x", 2, 0)); - checkEqu(4, buffer.indexOf("23", 2, 2)); - checkEqu(4, buffer.indexOf("23", -1, 2)); - - checkEqu(-1, buffer.indexOf("234", -1, 0)); - checkEqu(-1, buffer.indexOf("23", -1, 5)); - } - void testInsert() { - ReByteBuffer buf1; - checkT(buf1.insert(0, "123", 2)); - checkEqu("12", buf1); - checkEqu(2u, buf1.length()); - - checkT(buf1.insert(0, "abc", 1)); - checkEqu("a12", buf1); - checkEqu(3u, buf1.length()); - - checkT(buf1.insert(1, "x", 1)); - checkEqu("ax12", buf1); - checkEqu(4u, buf1.length()); - - checkT(buf1.insert(4, "yz", 2)); - checkEqu("ax12yz", buf1); - checkEqu(6u, buf1.length()); - - checkF(buf1.insert(-1, "-", 1)); - checkF(buf1.insert(8, "/", 1)); - - } - void testRemove() { - ReByteBuffer buf1; - buf1.set("1234567890", 10); - checkT(buf1.remove(0, 2)); - checkEqu("34567890", buf1); - checkEqu(8u, buf1.length()); - - checkF(buf1.remove(-1, 2)); - checkEqu("34567890", buf1); - checkEqu(8u, buf1.length()); - - checkF(buf1.remove(9, 2)); - checkEqu("34567890", buf1); - checkEqu(8u, buf1.length()); - - checkT(buf1.remove(7, 2)); - checkEqu("3456789", buf1); - checkEqu(7u, buf1.length()); - - checkT(buf1.remove(5, 2)); - checkEqu("34567", buf1); - checkEqu(5u, buf1.length()); - - checkT(buf1.remove(0, 99)); - checkEqu("", buf1); - checkEqu(0u, buf1.length()); - } - void testReplace() { - ReByteBuffer buffer; - - buffer.set("1234", 4); - buffer.replaceAll("12", 2, "abc", 3); - checkEqu("abc34", buffer); - - buffer.replaceAll("c34", 2, "uv", 3); - checkEqu("abuv", buffer); - - buffer.set("$$x$$", -1); - buffer.replaceAll("$", 1, "XX", 2); - checkEqu("XXXXxXXXX", buffer); - } - void testSplice() { - ReByteBuffer buffer; - - buffer.append((Byte*) "12.ab", 5); - checkT(buffer.splice(0, 0, "xy", 2)); - checkEqu("xy12.ab", buffer.buffer()); - buffer.splice(2, 2, NULL, 0); - checkEqu("xy.ab", buffer.buffer()); - buffer.splice(0, 2, "w", 1); - checkEqu("w.ab", buffer.buffer()); - - buffer.setLength(0); - buffer.append((Byte*) "123", 3); - buffer.insert(1, "ab", 2); - checkEqu("1ab23", buffer.buffer()); - checkEqu(5u, buffer.length()); - buffer.remove(0, 1); - checkEqu("ab23", buffer.buffer()); - checkEqu(4u, buffer.length()); - buffer.remove(3, 55); - checkEqu("ab2", buffer.buffer()); - checkEqu(3u, buffer.length()); - buffer.remove(2, 2); - checkEqu("ab", buffer.buffer()); - checkEqu(2u, buffer.length()); - buffer.remove(1, 1); - checkEqu("a", buffer.buffer()); - checkEqu(1u, buffer.length()); - } -}; -extern void testReByteBuffer(void); - -void testReByteBuffer(void) { - TestReByteBuffer unit; -} - diff --git a/cunit/cuReCString.cpp b/cunit/cuReCString.cpp index 6785988..7b535ee 100644 --- a/cunit/cuReCString.cpp +++ b/cunit/cuReCString.cpp @@ -1,6 +1,6 @@ /* * cuReCString.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. diff --git a/cunit/cuReDirTools.cpp b/cunit/cuReDirTools.cpp index 3408da6..d373a7a 100644 --- a/cunit/cuReDirTools.cpp +++ b/cunit/cuReDirTools.cpp @@ -1,6 +1,6 @@ /* * cuReDirTools.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -48,16 +48,17 @@ public: ReDirectory::deleteTree(m_base.str(), true); } private: - ReByteBuffer m_base; - ReByteBuffer m_buffer; + ReByteArray m_base; + ReByteArray m_buffer; bool m_testAll; ReLogger* m_logger; private: void run() { - testRandom(); - testDelete(); - testChecksumBuild(); + testToolSync(); if (m_testAll) { + testRandom(); + testDelete(); + testChecksumBuild(); testDirOptions(); checkSetFilterFromProgramArgs(); testList2(); @@ -66,7 +67,6 @@ private: testDirStatistic(); testCopyFile(); testList(); - testToolSync(); testBatch(); testChecksumBuild(); testDelete(); @@ -80,9 +80,9 @@ private: } void testDelete() { rebuildTree(); - ReByteBuffer nameCurrent; + ReByteArray nameCurrent; buildFilename("current", nameCurrent); - ReByteBuffer optOutput("--output-file="); + ReByteArray optOutput("--output-file="); optOutput.append(nameCurrent); const char* argv[] = { "delete", "-p;x*.txt", optOutput.str(), m_base .str(), NULL }; @@ -110,7 +110,7 @@ private: mayNotExist(s_allFiles); } void mustExist(const char** names) { - ReByteBuffer name; + ReByteArray name; struct stat info; for (int ix = 0; names[ix] != NULL; ix++) { const char* arg = names[ix]; @@ -128,7 +128,7 @@ private: } } void mayNotExist(const char** names) { - ReByteBuffer name; + ReByteArray name; struct stat info; for (int ix = 0; names[ix] != NULL; ix++) { const char* arg = names[ix]; @@ -159,7 +159,7 @@ private: return m_buffer.str(); } void makeFile(const char* relPath) { - ReByteBuffer path(m_base); + ReByteArray path(m_base); path.append(relPath); path.replaceAll("/", 1, OS_SEPARATOR, -1); createFile(path.str(), relPath); @@ -183,16 +183,16 @@ private: } void testChecksumBuild() { rebuildTree(); - ReByteBuffer nameCurrent; + ReByteArray nameCurrent; buildFilename("current", nameCurrent); - ReByteBuffer optOutput("--output-file="); + ReByteArray optOutput("--output-file="); optOutput.append(nameCurrent); const char* argv[] = { "dt", "checksum", "-P;*;-cache", "-tr", "-p;*.txt", "-s4711", "-arpd64", "-cBuild", optOutput.str(), m_base .str(), NULL }; ReDirTools tools; tools.main(-1, (char**) argv); - // checkFile(nameCurrent, ""); + // testFileContentWithWildcards(nameCurrent, ""); const char* argv2[] = { "dt", "checksum", "-P;*;-cache", "-tr", "-p;*.txt", "-s4711", "-arpd64", "-cCompare", optOutput.str(), m_base.str(), NULL }; @@ -213,11 +213,11 @@ private: void testCopyFile() { rebuildTree(); #if defined __linux__ - ReByteBuffer src(m_base); + ReByteArray src(m_base); src.append("dir1/dir1_2/dir1_2_1/x1.txt"); - ReByteBuffer trg(testDir()); + ReByteArray trg(testDir()); trg.append("copy_x1.txt"); - ReByteBuffer buffer; + ReByteArray buffer; buffer.ensureSize(5); ReDirSync::copyFile(src.str(), NULL, trg.str(), buffer, ReLogger::globalLogger()); @@ -307,8 +307,8 @@ private: } void checkOneFile(const char* node, const char* parent, const ReHashList& hash) { - ReByteBuffer path, expected; - checkT(hash.get(ReByteBuffer(node), path)); + ReByteArray path, expected; + checkT(hash.get(ReByteArray(node), path)); expected.set(parent, -1); if (!expected.endsWith(OS_SEPARATOR)) expected.append(OS_SEPARATOR); @@ -320,14 +320,14 @@ private: ReTraverser traverser(m_base.str()); RePatternList patterns; // exclude */cache/* - ReByteBuffer buffer(";*;-cache"); + ReByteArray buffer(";*;-cache"); patterns.set(buffer.str()); traverser.setDirPattern(&patterns); int level = 0; ReDirStatus_t* entry; ReHashList hash; while ((entry = traverser.rawNextFile(level)) != NULL) { - hash.put(ReByteBuffer(entry->node(), -1), entry->m_path); + hash.put(ReByteArray(entry->node(), -1), entry->m_path); logF(false, "%d: %-12s %2d %s", level, entry->node(), int(entry->fileSize()), entry->m_path.str()); } @@ -342,8 +342,8 @@ private: rebuildTree(); ReDirStatistic stat(m_logger); const ReStringList& list = stat.calculate(m_base.str(), 1); - ReByteBuffer buffer; - ReByteBuffer expected; + ReByteArray buffer; + ReByteArray expected; log(false, list.join("\n", buffer).str()); checkEqu(3u, list.count()); // "1 t:\temp\winfried\2\retestunit\dir1\n" @@ -375,48 +375,18 @@ private: checkT(buffer.startsWith(" 0.000087 MB 5 6\t")); expected.set(m_base.str(), m_base.length()); } - /** - * Tests a file with a given context. - * - * @param filename name of the file to test - * @param content expected content: each line must contain a '*', - * separating the start of line and the end of line - */ - void checkFile(ReByteBuffer& filename, const char* content) { - ReStringList current; - current.readFromFile(filename.str()); - ReStringList expected; - expected.split(content, '\n'); - checkEqu(expected.count(), current.count()); - ReByteBuffer line; - ReStringList cols; - for (size_t ix = 0; ix < current.count(); ix++) { - line.setLength(0).append(current.strOf(ix), -1); -#if defined __WIN32__ - line.replaceAll("/", 1, OS_SEPARATOR, 1); -#endif - cols.split(expected.strOf(ix), '*'); - const char* col1 = cols.strOf(0); - if (!line.startsWith(col1)) - checkEqu(col1, line); - const char* col2 = cols.strOf(1); - if (!line.endsWith(col2)) { - checkEqu(col2, line); - } - } - } void testTouch() { rebuildTree(); - ReByteBuffer nameCurrent; + ReByteArray nameCurrent; buildFilename("current", nameCurrent); - ReByteBuffer optOutput("--output-file="); + ReByteArray optOutput("--output-file="); optOutput.append(nameCurrent); ReDirTools tools; const char* argv[] = { "dt", "touch", "-P;*;-cache", "-tr", "-p;*.txt", "-m2015.03.28/10:21:31", optOutput.str(), m_base.str(), NULL }; tools.main(8, (char**) argv); - checkFile(nameCurrent, + testFileContentWithWildcards(nameCurrent, "2015.03.28 10:21:31 *dirtool/1.txt\n" "2015.03.28 10:21:31 *dirtool/dir1/dir1_2/dir1_2_1/x1.txt\n" "2015.03.28 10:21:31 *dirtool/dir1/dir1_2/dir1_2_1/x2.txt\n" @@ -427,7 +397,7 @@ private: "-h", optOutput.str(), m_base.str(), NULL }; tools.main(8, (char**) argv2); - checkFile(nameCurrent, + testFileContentWithWildcards(nameCurrent, " 0.000005 2015.03.28 10:21:31 *dirtool/1.txt\n" " 0.000027 2015.03.28 10:21:31 *dirtool/dir1/dir1_2/dir1_2_1/x1.txt\n" " 0.000027 2015.03.28 10:21:31 *dirtool/dir1/dir1_2/dir1_2_1/x2.txt\n" @@ -437,9 +407,9 @@ private: } void testBatch() { rebuildTree(); - ReByteBuffer nameCurrent; + ReByteArray nameCurrent; buildFilename("current", nameCurrent); - ReByteBuffer optOutput("--output-file="); + ReByteArray optOutput("--output-file="); optOutput.append(nameCurrent); ReDirTools tools; const char* argv[] = { "dt", "batch", "-P;*;-cache", "-td", @@ -467,7 +437,7 @@ private: "rem === filtered: 0 file(s) 0.000000 MByte 6 dirs(s) *sec\n" "rem === total: 4 file(s) 0.000067 MByte 6 dirs(s) * sec"; #endif - checkFile(nameCurrent, content); + testFileContentWithWildcards(nameCurrent, content); } void testToolStatistic() { rebuildTree(); @@ -476,18 +446,72 @@ private: tools.main(5, (char**) argv); } void testToolSync() { + struct stat info; rebuildTree(); + ReByteArray nameCurrent; + buildFilename("current", nameCurrent); + ReByteArray optOutput("--output-file="); + optOutput.append(nameCurrent); ReDirTools tools; - ReByteBuffer source(m_base); + ReByteArray source(m_base); source.append("dir1"); - ReByteBuffer target(testDir()); + ReByteArray target(testDir()); target.ensureLastChar(OS_SEPARATOR_CHAR); target.append("synctest", -1); _mkdir(target.str(), ALLPERMS); - const char* argv[] = { "dt", "sync", "-P;*;-cache", "-p;*.txt", source + ReDirectory::deleteTree(target.str(), false); + const char* argv[] = { "dt", "sync", "-P;*;-cache", "-p;*.txt", "-v3", optOutput.str(), source .str(), target.str() }; - tools.main(6, (char**) argv); + tools.main(8, (char**) argv); + target.appendChar(OS_SEPARATOR_CHAR); + for(const char** pFile = s_allFiles; *pFile != NULL; pFile++){ + ReByteArray fullTarget(target); + fullTarget.append(*pFile); + if (fullTarget.endsWith(".txt") || ! fullTarget.contains("cache") >= 0){ + checkT(stat(fullTarget.str(), &info)); + } else { + checkF(stat(fullTarget.str(), &info)); + } + } + static const char* content = + "+dir1_2/dir1_2_1/x1.txt\n" + "+dir1_2/dir1_2_1/x2.txt\n" + "+cache/cache.txt\n" + "-/tmp/retestunit/synctest/dir1/cache/cache.txt\n" + "=== copied: * sec 3 file(s) 0.000074 MByte (* MB/sec).\n" + "=== tree: 5 dir(s) 3 file(s) 0.000074 MByte"; + ReByteArray content2(content); + content2.replace('/', OS_SEPARATOR_CHAR); + testFileContentWithWildcards(nameCurrent, content2.str()); + } + void testToolSync2() { + rebuildTree(); + ReDirTools tools; + ReByteArray source(m_base); + source.append("dir1"); + ReByteArray target(testDir()); + target.ensureLastChar(OS_SEPARATOR_CHAR); + target.append("synctest", -1); + _mkdir(target.str(), ALLPERMS); + const char* argv[] = { "dt", "sync", "--delete=1h", "-p;*.txt", source + .str(), target.str() }; + //tools.main(6, (char**) argv); } + /* + " 1.txt", // + "*dir1", // + "*dir2", // + "*dir1/cache", // + "*dir1/dir1_1", // + "*dir1/dir1_2", // + "*dir1/dir1_2/dir1_2_1", // + " dir1/dir1_2/dir1_2_1/x1.txt", // + " dir1/dir1_2/dir1_2_1/x2.txt", // + " dir2/2.x", // + " dir1/cache/cache.txt", // + NULL }; + + */ }; extern void testReDirTools(void); diff --git a/cunit/cuReDirectory.cpp b/cunit/cuReDirectory.cpp index 677a3f8..2c0dbf4 100644 --- a/cunit/cuReDirectory.cpp +++ b/cunit/cuReDirectory.cpp @@ -1,6 +1,6 @@ /* * cuReDirectory.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -13,18 +13,70 @@ class TestReDirectory: public ReTestUnit { public: TestReDirectory() : - ReTestUnit("ReFileFinder", __FILE__) { + ReTestUnit("TestReDirectory", __FILE__) { run(); } private: void run() { - ReByteBuffer dir; + testFileTime(); + testBase(); + } + void checkOrder(ReFileTime_t& time1, ReFileTime_t& time2, ReFileTime_t& time3){ + checkT(time1 < time2); + checkF(time1 == time2); + checkT(time1 != time2); + checkF(time1 > time2); + checkF(time1 >= time2); + + checkF(time2 < time3); + checkT(time2 == time3); + checkF(time2 != time3); + checkF(time2 > time3); + checkT(time2 >= time3); + + } + void testFileTime(){ + // time1 < time2 == time3 + ReFileTime_t time1; + ReFileTime_t time2; + ReFileTime_t time3; + +#ifdef __linux__ + time1.tv_sec = 1234; + time1.tv_nsec = 56789; + time2.tv_sec = time1.tv_sec + 1; + time2.tv_nsec = time1.tv_nsec - 1; +#elif defined __WIN32__ + time1.dwHighDateTime = 1234; + time1.dwLowDateTime = 56789; + time2.dwHighDateTime = time1.dwHighDateTime + 1; + time2.dwLowDateTime = time1.dwLowDateTime - 1; +#endif + time3 = time2; + checkOrder(time1, time2, time3); + +#ifdef __linux__ + time2.tv_sec = time1.tv_sec; + time2.tv_nsec = time1.tv_nsec + 1; +#elif defined __WIN32__ + time2.dwHighDateTime = time1.dwHighDateTime; + time2.dwLowDateTime = time1.dwLowDateTime + 1; +#endif + time3 = time2; + checkOrder(time1, time2, time3); + + checkF(filetimeIsUndefined(time1)); + setFiletimeUndef(time1); + checkT(filetimeIsUndefined(time1)); + } + void testBase(){ + ReByteArray dir; dir.set(testDir(), -1); - ReByteBuffer file1 = dir; + ReByteArray file1 = dir; file1.append("abc.1.txt", -1); createFile(file1.str(), "abc1"); - ReByteBuffer file2 = dir; + ReByteArray file2 = dir; file2.append("abc.2.txt", -1); createFile(file2.str(), "abc2"); @@ -32,16 +84,16 @@ private: checkT(finder.isValid()); checkT(finder.findFirst("abc.*.txt", false)); - checkEqu("abc.1.txt", finder.currentFile()); + checkEqu("abc.1.txt", finder.currentNode()); checkT(finder.findNext()); - checkEqu("abc.2.txt", finder.currentFile()); + checkEqu("abc.2.txt", finder.currentNode()); checkF(finder.findNext()); checkF(finder.findFirst("abx.*.txt", false)); #ifdef __linux__ checkT(finder.findFirst("abc[.][0-9][.]txt", true)); - checkEqu("abc.1.txt", finder.currentFile()); + checkEqu("abc.1.txt", finder.currentNode()); checkT(finder.findNext()); - checkEqu("abc.2.txt", finder.currentFile()); + checkEqu("abc.2.txt", finder.currentNode()); checkF(finder.findNext()); checkF(finder.findFirst("abx[.][0-9][.]txt", true)); #endif diff --git a/cunit/cuReException.cpp b/cunit/cuReException.cpp index 9909d22..086f317 100644 --- a/cunit/cuReException.cpp +++ b/cunit/cuReException.cpp @@ -1,6 +1,6 @@ /* * cuReException.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. diff --git a/cunit/cuReHashList.cpp b/cunit/cuReHashList.cpp index 5c2d47e..d799b63 100644 --- a/cunit/cuReHashList.cpp +++ b/cunit/cuReHashList.cpp @@ -1,6 +1,6 @@ /* * cuReHashList.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -33,7 +33,7 @@ private: ReSeqArray list; list.setCapacity(maxKeys, maxKeys * maxLength); list.setSizes(4, maxKeys <= 0xffff ? 2 : 3); - ReByteBuffer key, value; + ReByteArray key, value; int64_t start = timer(); int ix; int collisions = 0; @@ -64,7 +64,7 @@ private: } void testBasic() { ReHashList hash; - ReByteBuffer key, value; + ReByteArray key, value; hash.put("abc", "123"); checkT(hash.get("abc", -1, value)); @@ -100,7 +100,7 @@ private: int flagsKey = 0; int flagsVal = 0; ReArrayPosition pos; - ReByteBuffer key, value; + ReByteArray key, value; while (hash.next(pos, &key, &value)) { int x = atol(key.buffer()); int y = atol(value.buffer()); diff --git a/cunit/cuReI18N.cpp b/cunit/cuReI18N.cpp index 84bf6bb..6469c25 100644 --- a/cunit/cuReI18N.cpp +++ b/cunit/cuReI18N.cpp @@ -1,6 +1,6 @@ /* * cuReI18N.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. diff --git a/cunit/cuReLogger.cpp b/cunit/cuReLogger.cpp index 11df992..5f824d9 100644 --- a/cunit/cuReLogger.cpp +++ b/cunit/cuReLogger.cpp @@ -1,6 +1,6 @@ /* * cuReLogger.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -45,7 +45,7 @@ private: appender.say(NULL, "x1"); appender.say(NULL, "x2"); appender.say(NULL, "x3"); - ReByteBuffer line; + ReByteArray line; checkEqu(3U, appender.count()); checkT(appender.get(2, line)); checkT(line.indexOf("x1", 2) >= 0); @@ -61,7 +61,7 @@ private: checkT(line.indexOf("x3", 2) >= 0); checkT(appender.get(0, line)); checkT(line.indexOf("x4", 2) >= 0); - ReByteBuffer all; + ReByteArray all; checkEqu(3, appender.join(all).count("\n")); } void testSlaveAppender() { @@ -79,7 +79,7 @@ private: slave1.say(LOG_INFO | CAT_TEST, 9999, "slave1"); slave2.say(LOG_INFO | CAT_TEST, 9999, "slave2"); - ReByteBuffer line; + ReByteArray line; memoryAppender.get(0, line); checkT(line.indexOf('%') >= 0); checkT(line.indexOf("slave2", -1) >= 0); diff --git a/cunit/cuReMD5.cpp b/cunit/cuReMD5.cpp index db02725..cad4397 100644 --- a/cunit/cuReMD5.cpp +++ b/cunit/cuReMD5.cpp @@ -1,6 +1,6 @@ /* * cuReMD5.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -39,14 +39,14 @@ private: md5.update((const uint8_t*) "", 0); checkEqu("d41d8cd98f00b204e9800998ecf8427e", md5.hexDigest()); } - int testOneLong(ReByteBuffer& text, int seed2 = 0) { + int testOneLong(ReByteArray& text, int seed2 = 0) { ReMD5 md5; int rc = 0; ReShiftRandom random; random.setSeed(text.length() + seed2); md5.update((uint8_t*) text.str(), text.length()); - ReByteBuffer digest(md5.hexDigest()); + ReByteArray digest(md5.hexDigest()); md5.reset(); int max2 = text.length() / 20; if (max2 < 1) @@ -63,7 +63,7 @@ private: return rc; } void testLong() { - ReByteBuffer text( + ReByteArray text( "01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVEXYZ0123456789001234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVEXYZ01234567890\n"); for (int ii = 178 - 69 + 1; ii > 0; ii--) { text.setLength(ii); @@ -71,7 +71,7 @@ private: } } void testBig() { - ReByteBuffer text; + ReByteArray text; ReShiftRandom random; int64_t start = timer(); int count = 1000; @@ -84,11 +84,11 @@ private: } printf("count: %d updates: %d avg length: %d duration: %s\n", count, parts, sumLength / count, - ReByteBuffer("").appendMilliSec(milliSecSince(start)).str()); + ReByteArray("").appendMilliSec(milliSecSince(start)).str()); } void testSpeed() { int max = 1024 * 1024 * 50; - ReByteBuffer buffer; + ReByteArray buffer; buffer.ensureSize(max); buffer.setLength(max - 1); buffer.fill('x', max - 1); @@ -111,7 +111,7 @@ private: #endif max / 1024.0 / 1024, passes, max / 1024.0 / 1024 * 1000 * passes / duration, - ReByteBuffer("").appendMilliSec(duration).str()); + ReByteArray("").appendMilliSec(duration).str()); } }; extern void testReMD5(void); diff --git a/cunit/cuReMatcher.cpp b/cunit/cuReMatcher.cpp index e021e6d..ef3f37e 100644 --- a/cunit/cuReMatcher.cpp +++ b/cunit/cuReMatcher.cpp @@ -1,6 +1,6 @@ /* * cuReMatcher.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. diff --git a/cunit/cuReProgramArgs.cpp b/cunit/cuReProgramArgs.cpp index d92946d..287f398 100644 --- a/cunit/cuReProgramArgs.cpp +++ b/cunit/cuReProgramArgs.cpp @@ -1,6 +1,6 @@ /* * cuReProgramArgs.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -89,7 +89,7 @@ private: checkF(args.getBool("boolarg")); checkEqu(9, args.getInt("intarg")); - ReByteBuffer buffer; + ReByteArray buffer; checkEqu("empty", args.getString("estringarg", buffer)); checkEqu("abc", args.getString("stringarg", buffer)); @@ -112,13 +112,13 @@ private: checkEqu("arg1", args.arg(0)); checkEqu("arg2", args.arg(1)); checkEqu(2, args.argCount()); - ReByteBuffer fn; + ReByteArray fn; FILE* fp = fopen(buildFilename("help.tmp.txt", fn), "w"); checkF(fp == NULL); if (fp != NULL) { args.help("Not really an error!", false, fp); fclose(fp); - ReByteBuffer fnExpected; + ReByteArray fnExpected; buildFilename("help.exp.txt", fnExpected); createExpectedShortHelp(fnExpected.str()); checkFileEqu(fnExpected.str(), fn.str()); @@ -191,7 +191,7 @@ private: args.addString("estringarg3", "This 3thrd string may be empty", 'V', "estring3", true, "undef3"); - ReByteBuffer buffer; + ReByteArray buffer; const char* vector[] = { "testprog", "--boolval", "--boolval2=true", "--boolval3=f", "--boolval4=0", "--intval=3", "--string=x y", "--estring=", "--estring2=not empty", "arg1", "arg2" }; @@ -209,13 +209,13 @@ private: checkEqu("arg1", args.arg(0)); checkEqu("arg2", args.arg(1)); checkEqu(2, args.argCount()); - ReByteBuffer fn; + ReByteArray fn; FILE* fp = fopen(buildFilename("help.tmp.txt", fn), "w"); checkT(fp != NULL); if (fp) { args.help(NULL, false, fp); fclose(fp); - ReByteBuffer fnExpected; + ReByteArray fnExpected; createExpectedLongHelp(buildFilename("help.exp.txt", fnExpected)); checkFileEqu(fnExpected.str(), fn.str()); } diff --git a/cunit/cuReRPD64.cpp b/cunit/cuReRPD64.cpp index 57eee08..3cc81c7 100644 --- a/cunit/cuReRPD64.cpp +++ b/cunit/cuReRPD64.cpp @@ -1,6 +1,6 @@ /* * cuReRPD64.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -39,14 +39,14 @@ private: RPD64.update((const uint8_t*) "", 0); checkEqu("3c7b4e20d8ee3cf7716c2dacdddd9e30", RPD64.hexDigest()); } - int testOneLong(ReByteBuffer& text, int seed2 = 0) { + int testOneLong(ReByteArray& text, int seed2 = 0) { ReRPD64 RPD64; int rc = 0; ReShiftRandom random; random.setSeed(text.length() + seed2); RPD64.update((uint8_t*) text.str(), text.length()); - ReByteBuffer digest(RPD64.hexDigest()); + ReByteArray digest(RPD64.hexDigest()); RPD64.reset(); int max2 = text.length() / 20; if (max2 < 1) @@ -63,7 +63,7 @@ private: return rc; } void testLong() { - ReByteBuffer text( + ReByteArray text( "01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVEXYZ0123456789001234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVEXYZ01234567890\n"); for (int ii = 178 - 69 + 1; ii > 0; ii--) { text.setLength(ii); @@ -71,7 +71,7 @@ private: } } void testBig() { - ReByteBuffer text; + ReByteArray text; ReShiftRandom random; int64_t start = timer(); int count = 1000; @@ -84,11 +84,11 @@ private: } printf("count: %d updates: %d avg length: %d duration: %s\n", count, parts, sumLength / count, - ReByteBuffer("").appendMilliSec(milliSecSince(start)).str()); + ReByteArray("").appendMilliSec(milliSecSince(start)).str()); } void testSpeed() { int max = 1024 * 1024 * 50; - ReByteBuffer buffer; + ReByteArray buffer; buffer.ensureSize(max); buffer.setLength(max - 1); buffer.fill('x', max - 1); @@ -111,7 +111,7 @@ private: #endif max / 1024.0 / 1024, passes, max / 1024.0 / 1024 * 1000 * passes / duration, - ReByteBuffer("").appendMilliSec(duration).str()); + ReByteArray("").appendMilliSec(duration).str()); } }; extern void testReRPD64(void); diff --git a/cunit/cuReRandomizer.cpp b/cunit/cuReRandomizer.cpp index 4d18971..f099365 100644 --- a/cunit/cuReRandomizer.cpp +++ b/cunit/cuReRandomizer.cpp @@ -1,6 +1,6 @@ /* * cuReRandomizer.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. diff --git a/cunit/cuReSeqArray.cpp b/cunit/cuReSeqArray.cpp index 52e2824..5d0505b 100644 --- a/cunit/cuReSeqArray.cpp +++ b/cunit/cuReSeqArray.cpp @@ -1,6 +1,6 @@ /* * cuReSeqArray.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -29,7 +29,7 @@ private: } void checkElement(ReSeqArray& list, ReSeqArray::Index index, const char* value, ReSeqArray::Tag expectedTag) { - ReByteBuffer buffer; + ReByteArray buffer; ReSeqArray::Tag tag; checkT(list.get(index, buffer, &tag)); checkIEqu(value, buffer.str()); @@ -38,7 +38,7 @@ private: void testBinSearch() { ReSeqArray list; list.setIgnoreCase(true); - ReByteBuffer value, expectedValue; + ReByteArray value, expectedValue; list.add(-1, "abc", -1, 300); list.add(-1, "abc", -1, 350); list.add(-1, "abce", -1, 100); @@ -72,7 +72,7 @@ private: void testBinSearch2() { ReSeqArray list; ReSeqArray::Index index; - ReByteBuffer value; + ReByteArray value; list.setSorted(true); value = "ab"; for (int count = 2; count < 16; count++) { @@ -105,7 +105,7 @@ private: void testSorted() { ReSeqArray list; list.setIgnoreCase(true); - ReByteBuffer value, expectedValue; + ReByteArray value, expectedValue; list.add(-1, "bcd", -1, 200); list.add(-1, "abcd", -1, 100); list.add(-1, "abc", -1, 300); @@ -135,7 +135,7 @@ private: void testIgnoreCase() { ReSeqArray list; list.setIgnoreCase(true); - ReByteBuffer value, expectedValue; + ReByteArray value, expectedValue; list.add(-1, "bcd", -1, 200); list.add(0, "abc", -1, 100); // list.dump(stdout); @@ -144,7 +144,7 @@ private: } void testAdd() { ReSeqArray list; - ReByteBuffer value, expectedValue; + ReByteArray value, expectedValue; ReSeqArray::Tag tag = 0; ReSeqArray::Tag expectedTag = 0; size_t maxIx = 64; @@ -171,7 +171,7 @@ private: } void testFind() { ReSeqArray list; - ReByteBuffer value, expectedValue; + ReByteArray value, expectedValue; ReSeqArray::Tag tag = 0; ReSeqArray::Tag expectedTag = 0; size_t maxIx = 13; @@ -200,7 +200,7 @@ private: } void testBase() { ReSeqArray list; - ReByteBuffer value; + ReByteArray value; ReSeqArray::Tag tag = 0; list.setSizes(8, 4); list.add(-1, "xxx", -1, ReSeqArray::Tag(1l) << 31); @@ -251,7 +251,7 @@ private: } void testRemove() { ReSeqArray list; - ReByteBuffer value; + ReByteArray value; ReSeqArray::Tag tag = 0; list.add(-1, "abc", -1, 100); diff --git a/cunit/cuReSerializable.cpp b/cunit/cuReSerializable.cpp index f7de4e4..3fa4567 100644 --- a/cunit/cuReSerializable.cpp +++ b/cunit/cuReSerializable.cpp @@ -1,6 +1,6 @@ /* * cuReSerializable.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -49,7 +49,7 @@ public: unpackString64k(sequence, length, m_string64k); unpackString4t(sequence, length, m_string4t); } - virtual ReByteBuffer& serialize(ReByteBuffer& buffer) { + virtual ReByteArray& serialize(ReByteArray& buffer) { buffer.appendBits24(m_serialId).appendBits8(m_int8); buffer.appendBits16(m_int16).appendBits32(m_int32); packBool(buffer, m_bool); @@ -59,7 +59,7 @@ public: packString4t(buffer, m_string4t); return buffer; } - const char* toString(ReByteBuffer& buffer) { + const char* toString(ReByteArray& buffer) { buffer.setLength(0).append("id: ").appendInt(m_serialId); buffer.append(" i8:").appendInt(m_int8, "%x"); buffer.append(" i16:").appendInt(m_int16, "%x"); @@ -77,16 +77,16 @@ private: int m_int32; bool m_bool; int64_t m_int64; - ReByteBuffer m_string255; - ReByteBuffer m_string64k; - ReByteBuffer m_string4t; + ReByteArray m_string255; + ReByteArray m_string64k; + ReByteArray m_string4t; private: static int m_serialId; }; int ExampleClass::m_serialId = 0x123401; class TestReSerializable: public ReTestUnit { - typedef ReByteBuffer::Byte Byte; + typedef ReByteArray::Byte Byte; public: TestReSerializable() : ReTestUnit("ReSerializable", __FILE__) { @@ -97,13 +97,13 @@ private: testBasic(); } void testBasic() { - ReByteBuffer buffer; + ReByteArray buffer; ExampleClass example(250, 64000, 12345678, true, 0x12345678abcdll, "king", "lives", "!"); checkEqu( "id: 1192961 i8:fa i16:fa00 i32:bc614e b:t i64:12345678abcd s255:king s64k:lives s4t:!", example.toString(buffer)); - ReByteBuffer serialBuffer; + ReByteArray serialBuffer; example.serialize(serialBuffer); ExampleClass example2; example2.deserializeBuffer(serialBuffer); diff --git a/cunit/cuReStringList.cpp b/cunit/cuReStringList.cpp index bec68c4..56bdf1b 100644 --- a/cunit/cuReStringList.cpp +++ b/cunit/cuReStringList.cpp @@ -1,6 +1,6 @@ /* * cuReStringList.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -27,7 +27,7 @@ private: } void testAppendByteBuffer() { ReStringList list; - ReByteBuffer line; + ReByteArray line; line.set("Hi", -1); list.append(line, 99); line.append("!", -1); @@ -140,7 +140,7 @@ private: checkEqu("4", list.strOf(3)); checkEqu("", list.strOf(4)); checkEqu("99", list.strOf(5)); - ReByteBuffer value("x"); + ReByteArray value("x"); list.join(";", value); checkEqu(str, value); @@ -151,7 +151,7 @@ private: } void testFile() { if (true) { - ReByteBuffer file; + ReByteArray file; buildFilename("abc.csv", file); ReStringList list; @@ -183,7 +183,7 @@ private: void testBase() { if (true) { ReStringList list; - ReByteBuffer value; + ReByteArray value; list.append("123", 100); checkEqu(0U, list.indexOf("123")); diff --git a/cunit/cuReStringUtils.cpp b/cunit/cuReStringUtils.cpp index 05227db..a186819 100644 --- a/cunit/cuReStringUtils.cpp +++ b/cunit/cuReStringUtils.cpp @@ -1,6 +1,6 @@ /* * cuReStringUtils.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -77,7 +77,7 @@ private: } void testSplitPath() { - ReByteBuffer fullname, protocol, path, name, ext; + ReByteArray fullname, protocol, path, name, ext; const char* fn = "file:/etc/samba/smb.cnf"; ReStringUtils::splitPath(fn, &protocol, &path, &name, &ext); diff --git a/cunit/cuReTCP.cpp b/cunit/cuReTCP.cpp index 162cb1d..d246f15 100644 --- a/cunit/cuReTCP.cpp +++ b/cunit/cuReTCP.cpp @@ -1,6 +1,6 @@ /* * cuReTCP.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -34,7 +34,7 @@ public: ReTCPClient client(theLogger); client.connect("localhost", s_port); client.send("echo", "Hello world"); - ReByteBuffer command, data; + ReByteArray command, data; client.receive(command, data); if (!command.equals("Echo ")) { theLogger->sayF(LOG_ERROR | CAT_TEST, location, @@ -61,7 +61,7 @@ public: direction).end(); ReTCPClient client(logger); if (client.connect("localhost", s_port)) { - ReByteBuffer data, command, answer; + ReByteArray data, command, answer; int size = 1024 * 1024 * 10; const char* request; if (upload) { @@ -86,7 +86,7 @@ public: int miByte = count * (size / (1024 * 1024)); _snprintf(msg, sizeof msg, "%s: %d MiByte in %s/%d sec: %.3f (%.3f) MiByte/sec", direction, - miByte, ReByteBuffer("").appendMilliSec((int) duration).str(), + miByte, ReByteArray("").appendMilliSec((int) duration).str(), duration2, miByte * 1000.0 / (double) duration, miByte / (double) duration2); logger->say(LOG_INFO | CAT_LIB, location, msg); diff --git a/cunit/cuReTest.cpp b/cunit/cuReTest.cpp index 3596035..e9dfbbf 100644 --- a/cunit/cuReTest.cpp +++ b/cunit/cuReTest.cpp @@ -1,6 +1,6 @@ /* * cuReTest.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -25,7 +25,7 @@ private: testEquFiles(); } void testFileNameInTestDir() { - ReByteBuffer fn; + ReByteArray fn; const char* name = buildFilename("xyz.txt", fn); checkEqu(name, fn.str()); checkT(fn.endsWith("xyz.txt")); @@ -70,9 +70,9 @@ private: checkEqu("^", colMarker(0)); } void testEquFiles() { - ReByteBuffer fn1; + ReByteArray fn1; buildFilename("x1.txt", fn1); - ReByteBuffer fn2; + ReByteArray fn2; buildFilename("x2.txt", fn2); createFile(fn1.str(), "123\nline 2"); createFile(fn2.str(), "123\nline 2"); diff --git a/cunit/cuReTraverser.cpp b/cunit/cuReTraverser.cpp index 90cc05c..379b751 100644 --- a/cunit/cuReTraverser.cpp +++ b/cunit/cuReTraverser.cpp @@ -1,6 +1,6 @@ /* * cuReTraverser.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -27,8 +27,8 @@ public: ReDirectory::deleteTree(m_base.str(), true); } private: - ReByteBuffer m_base; - ReByteBuffer m_buffer; + ReByteArray m_base; + ReByteArray m_buffer; ReLogger* m_logger; private: const char* makeDir(const char* relPath) { @@ -43,7 +43,7 @@ private: return m_buffer.str(); } void makeFile(const char* relPath) { - ReByteBuffer path(m_base); + ReByteArray path(m_base); path.append("/").append(relPath); path.replaceAll("/", 1, OS_SEPARATOR, -1); createFile(path.str(), relPath); @@ -82,11 +82,11 @@ private: } void testCopyFile() { #if defined __linux__ - ReByteBuffer src(m_base); + ReByteArray src(m_base); src.append("dir1/dir1_2/dir1_2_1/x1.txt"); - ReByteBuffer trg(testDir()); + ReByteArray trg(testDir()); trg.append("copy_x1.txt"); - ReByteBuffer buffer; + ReByteArray buffer; buffer.ensureSize(5); ReDirSync::copyFile(src.str(), NULL, trg.str(), buffer, ReLogger::globalLogger()); @@ -105,8 +105,8 @@ private: void checkOneFile(const char* node, const char* parent, const ReHashList& hash) { - ReByteBuffer path, expected; - checkT(hash.get(ReByteBuffer(node), path)); + ReByteArray path, expected; + checkT(hash.get(ReByteArray(node), path)); expected.set(parent, -1); if (!expected.endsWith(OS_SEPARATOR)) expected.append(OS_SEPARATOR); @@ -117,7 +117,7 @@ private: ReTraverser traverser(m_base.str()); RePatternList patterns; // exclude */cache/* - ReByteBuffer buffer(";*;-cache"); + ReByteArray buffer(";*;-cache"); patterns.set(buffer.str()); traverser.setDirPattern(&patterns); int level = 0; @@ -127,7 +127,7 @@ private: int state = 0; while ((entry = traverser.rawNextFile(level)) != NULL) { const char* node = entry->node(); - hashPath.put(ReByteBuffer(node, -1), entry->m_path); + hashPath.put(ReByteArray(node, -1), entry->m_path); if (traverser.hasChangedPath(state)) listChanged.add(-1, node); logF(false, "%d: %-12s %2d %s", level, node, int(entry->fileSize()), diff --git a/cunit/cuReVarArgs.cpp b/cunit/cuReVarArgs.cpp index 283e1ac..50e41ea 100644 --- a/cunit/cuReVarArgs.cpp +++ b/cunit/cuReVarArgs.cpp @@ -1,6 +1,6 @@ /* * cuReVarArgs.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. diff --git a/cunit/cuReconfig.cpp b/cunit/cuReconfig.cpp index d2e9768..7b9a5f7 100644 --- a/cunit/cuReconfig.cpp +++ b/cunit/cuReconfig.cpp @@ -1,6 +1,6 @@ /* * cuReconfig.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -22,7 +22,7 @@ private: testBasic(); } void testBasic() { - ReByteBuffer fn; + ReByteArray fn; buildFilename("reconfigfile.cfg", fn); createFile(fn.str(), "#x.int=a\nx.int=1\nx.bool=true\nx.str=abc\nx.bool2=0\nstring=abc\n"); @@ -39,7 +39,7 @@ private: checkF(config.getBool("x.bool2", true)); checkF(config.getBool("x.bool2", false)); - ReByteBuffer buffer; + ReByteArray buffer; config.getString("string", buffer, "x"); checkEqu("abc", buffer); config.getString("string1", buffer, "x"); diff --git a/cunit/testall.cpp b/cunit/testall.cpp index 342b823..0b17811 100644 --- a/cunit/testall.cpp +++ b/cunit/testall.cpp @@ -1,6 +1,6 @@ /* * testall.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -14,7 +14,7 @@ #include "net/renet.hpp" #endif -static bool s_testAll = true; +static bool s_testAll = false; void testBase() { extern void testReSerializable(void); @@ -89,12 +89,12 @@ void testMath() { } void testAll() { try { + testOs(); testBase(); testNet(); if (s_testAll) { testString(); testMath(); - testOs(); //testNet(); testBase(); } diff --git a/dirtool.cpp b/dirtool.cpp index 43fb5f5..807f131 100644 --- a/dirtool.cpp +++ b/dirtool.cpp @@ -1,6 +1,6 @@ /* * dirtool.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. diff --git a/math/ReMD5.cpp b/math/ReMD5.cpp index fe33a49..a98c7f4 100644 --- a/math/ReMD5.cpp +++ b/math/ReMD5.cpp @@ -1,6 +1,6 @@ /* * ReMD5.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -8,513 +8,513 @@ * You also can use this license: http://www.wtfpl.net * The latest sources: https://github.com/republib */ - -#include "base/rebase.hpp" -#include "math/remath.hpp" - -const int ReMD5::m_s[RE_DIGEST_CHUNK_SIZE] = { 7, 12, 17, 22, 7, 12, 17, 22, 7, - 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, - 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, - 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 }; -// for x in [1..64] : int(2**32 * sin(x)) -const uint32_t ReMD5::m_K[RE_DIGEST_CHUNK_SIZE] = { 0xd76aa478, 0xe8c7b756, - 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, - 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, - 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, - 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, - 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, - 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, - 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, - 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, 0xf4292244, 0x432aff97, - 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, - 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, - 0x2ad7d2bb, 0xeb86d391 }; - -/** - * Constructor. - * - * @param digest the buffer for the binary checksum - * @param digestSize the length of digest - * @param waiting a buffer for a chunk. Must have space for at least 2*chunksize bytes - * NULL: an intrinsic buffer will be used - * @param chunkSize the length of one full input block - */ -ReDigest::ReDigest(uint8_t* digest, size_t digestSize, uint8_t* waiting, - size_t chunkSize) : - m_digest(digest), - m_digestSize(digestSize), - // m_waitingBuffer[RE_DIGEST_CHUNK_SIZE]; - m_waiting(waiting != NULL ? waiting : m_waitingBuffer), - m_lengthWaiting(0), - m_chunkSize(chunkSize), - m_length(0), - m_finalized(false), - m_salt(0) { -} -/** - * Destructor. - */ -ReDigest::~ReDigest() { -} -/** - * Returns the binary digest value. - * - * @return the binary digest (16 byte array) - */ -const uint8_t* ReDigest::digest() { - if (!m_finalized) { - finalize(); - } - return m_digest; -} - -/** - * Returns the binary digest value. - * - * @return the binary digest (16 byte array) - */ -const ReByteBuffer& ReDigest::hexDigest() { - if (m_hexDigest.length() == 0) { - digest(); - for (size_t ix = 0; ix < m_digestSize; ix++) { - m_hexDigest.appendInt(m_digest[ix], "%02x"); - } - } - return m_hexDigest; -} - -/** - * Processes a 64 byte block. - * - * @param block a block which should be added to the digest - * @param blockLength the length of block - */ -void ReDigest::update(const uint8_t* block, int blockLength) { - if (blockLength == -1) - blockLength = strlen((const char*) block); - // process the "waiting" input (incomplete chunk): - m_length += blockLength; - if (m_lengthWaiting > 0) { - int rest = m_chunkSize - m_lengthWaiting; - if (rest > blockLength) - rest = blockLength; - memcpy(m_waiting + m_lengthWaiting, block, rest); - blockLength -= rest; - block += rest; - m_lengthWaiting += rest; - // Is the chunk complete? - if (m_lengthWaiting == m_chunkSize) { - processChunk(m_waiting); - m_lengthWaiting = 0; - } - } - // process full 512 bit chunks (64 byte blocks): - for (int ix = blockLength / m_chunkSize; ix > 0; ix--) { - processChunk(block); - block += m_chunkSize; - } - blockLength %= m_chunkSize; - if (blockLength != 0) { - assert(m_lengthWaiting == 0); - memcpy(m_waiting, block, blockLength); - m_lengthWaiting = blockLength; - } -} - -/** - * Sets the salt of the checksum algorithm. - * - * Important: set the salt before you make the first update()! - * - * The salt makes that the checksum of the same input is (extremly) different - * to another salt. - * - * @param salt the salt to set - */ -void ReDigest::setSalt(uint64_t salt) { - m_salt = salt; -} -/** - * Constructor. - */ -ReMD5::ReMD5() : - ReDigest(m_digest, sizeof m_digest), - m_a0(0x67452301), - m_b0(0xefcdab89), - m_c0(0x98badcfe), - m_d0(0x10325476) { -} - -/** - * Destructor. - */ -ReMD5::~ReMD5() { -} - -/** - * Finalizes the digest. - * - * Handles the rest block (< 64 byte) and append a special tail: a "1" bit - * and the length of the total input length (in bits). - * - * @param block the rest input (incomplete chunk) - * @param blockLength the length of the block: 0..63 - */ -void ReMD5::finalize() { - uint8_t* block = m_waiting; - int blockLength = m_lengthWaiting; - // append "1" bit to message - // Notice: the input bytes are considered as bits strings, - // where the first bit is the most significant bit of the byte. - block[blockLength++] = 0x80; - //Pre-processing: padding with zeros - //append "0" bit until message length in bits ≡ 448 (mod 512) - // fill the rest of the chunk with '\0'. - // the last 8 bytes is set to the length in bits (length in bytes * 8) - int restLength = (m_length + 1) % RE_DIGEST_CHUNK_SIZE; - // 0 -> 56, 1 -> 55, 2 -> 54, ... 55 -> 1, 56 -> 0, - // 57 -> 63, 58 -> 62, ... 63 -> 57 - int zeros = restLength <= 56 ? 56 - restLength : 120 - restLength; - memset(block + blockLength, 0, zeros); - blockLength += zeros; - //append original length in bits mod (2 pow 64) to message - uint64_t lengthBits = 8LL * m_length + m_salt; -#if defined __LITTLE_ENDIAN__ - memcpy(block + blockLength, &lengthBits, 8); - blockLength += 8; -#else - block[blockLength++] = lengthBits; - lengthBits >>= 8; - block[blockLength++] = lengthBits; - lengthBits >>= 8; - block[blockLength++] = lengthBits; - lengthBits >>= 8; - block[blockLength++] = lengthBits; - lengthBits >>= 8; - block[blockLength++] = lengthBits; - lengthBits >>= 8; - block[blockLength++] = lengthBits; - lengthBits >>= 8; - block[blockLength++] = lengthBits; - lengthBits >>= 8; - block[blockLength++] = lengthBits; -#endif - processChunk(block); - if (blockLength > RE_DIGEST_CHUNK_SIZE) - processChunk(block + RE_DIGEST_CHUNK_SIZE); -#if defined __LITTLE_ENDIAN__ - memcpy(m_digest, &m_a0, 4); - memcpy(m_digest + 4, &m_b0, 4); - memcpy(m_digest + 8, &m_c0, 4); - memcpy(m_digest + 12, &m_d0, 4); -#else + +#include "base/rebase.hpp" +#include "math/remath.hpp" + +const int ReMD5::m_s[RE_DIGEST_CHUNK_SIZE] = { 7, 12, 17, 22, 7, 12, 17, 22, 7, + 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, + 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, + 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 }; +// for x in [1..64] : int(2**32 * sin(x)) +const uint32_t ReMD5::m_K[RE_DIGEST_CHUNK_SIZE] = { 0xd76aa478, 0xe8c7b756, + 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, + 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, + 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, + 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, + 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, 0xf4292244, 0x432aff97, + 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, + 0x2ad7d2bb, 0xeb86d391 }; + +/** + * Constructor. + * + * @param digest the buffer for the binary checksum + * @param digestSize the length of digest + * @param waiting a buffer for a chunk. Must have space for at least 2*chunksize bytes + * NULL: an intrinsic buffer will be used + * @param chunkSize the length of one full input block + */ +ReDigest::ReDigest(uint8_t* digest, size_t digestSize, uint8_t* waiting, + size_t chunkSize) : + m_digest(digest), + m_digestSize(digestSize), + // m_waitingBuffer[RE_DIGEST_CHUNK_SIZE]; + m_waiting(waiting != NULL ? waiting : m_waitingBuffer), + m_lengthWaiting(0), + m_chunkSize(chunkSize), + m_length(0), + m_finalized(false), + m_salt(0) { +} +/** + * Destructor. + */ +ReDigest::~ReDigest() { +} +/** + * Returns the binary digest value. + * + * @return the binary digest (16 byte array) + */ +const uint8_t* ReDigest::digest() { + if (!m_finalized) { + finalize(); + } + return m_digest; +} + +/** + * Returns the binary digest value. + * + * @return the binary digest (16 byte array) + */ +const ReByteArray& ReDigest::hexDigest() { + if (m_hexDigest.empty()) { + digest(); + for (size_t ix = 0; ix < m_digestSize; ix++) { + m_hexDigest.appendInt(m_digest[ix], "%02x"); + } + } + return m_hexDigest; +} + +/** + * Processes a 64 byte block. + * + * @param block a block which should be added to the digest + * @param blockLength the length of block + */ +void ReDigest::update(const uint8_t* block, int blockLength) { + if (blockLength == -1) + blockLength = strlen((const char*) block); + // process the "waiting" input (incomplete chunk): + m_length += blockLength; + if (m_lengthWaiting > 0) { + int rest = m_chunkSize - m_lengthWaiting; + if (rest > blockLength) + rest = blockLength; + memcpy(m_waiting + m_lengthWaiting, block, rest); + blockLength -= rest; + block += rest; + m_lengthWaiting += rest; + // Is the chunk complete? + if (m_lengthWaiting == m_chunkSize) { + processChunk(m_waiting); + m_lengthWaiting = 0; + } + } + // process full 512 bit chunks (64 byte blocks): + for (int ix = blockLength / m_chunkSize; ix > 0; ix--) { + processChunk(block); + block += m_chunkSize; + } + blockLength %= m_chunkSize; + if (blockLength != 0) { + assert(m_lengthWaiting == 0); + memcpy(m_waiting, block, blockLength); + m_lengthWaiting = blockLength; + } +} + +/** + * Sets the salt of the checksum algorithm. + * + * Important: set the salt before you make the first update()! + * + * The salt makes that the checksum of the same input is (extremly) different + * to another salt. + * + * @param salt the salt to set + */ +void ReDigest::setSalt(uint64_t salt) { + m_salt = salt; +} +/** + * Constructor. + */ +ReMD5::ReMD5() : + ReDigest(m_digest, sizeof m_digest), + m_a0(0x67452301), + m_b0(0xefcdab89), + m_c0(0x98badcfe), + m_d0(0x10325476) { +} + +/** + * Destructor. + */ +ReMD5::~ReMD5() { +} + +/** + * Finalizes the digest. + * + * Handles the rest block (< 64 byte) and append a special tail: a "1" bit + * and the length of the total input length (in bits). + * + * @param block the rest input (incomplete chunk) + * @param blockLength the length of the block: 0..63 + */ +void ReMD5::finalize() { + uint8_t* block = m_waiting; + int blockLength = m_lengthWaiting; + // append "1" bit to message + // Notice: the input bytes are considered as bits strings, + // where the first bit is the most significant bit of the byte. + block[blockLength++] = 0x80; + //Pre-processing: padding with zeros + //append "0" bit until message length in bits ≡ 448 (mod 512) + // fill the rest of the chunk with '\0'. + // the last 8 bytes is set to the length in bits (length in bytes * 8) + int restLength = (m_length + 1) % RE_DIGEST_CHUNK_SIZE; + // 0 -> 56, 1 -> 55, 2 -> 54, ... 55 -> 1, 56 -> 0, + // 57 -> 63, 58 -> 62, ... 63 -> 57 + int zeros = restLength <= 56 ? 56 - restLength : 120 - restLength; + memset(block + blockLength, 0, zeros); + blockLength += zeros; + //append original length in bits mod (2 pow 64) to message + uint64_t lengthBits = 8LL * m_length + m_salt; +#if defined __LITTLE_ENDIAN__ + memcpy(block + blockLength, &lengthBits, 8); + blockLength += 8; +#else + block[blockLength++] = lengthBits; + lengthBits >>= 8; + block[blockLength++] = lengthBits; + lengthBits >>= 8; + block[blockLength++] = lengthBits; + lengthBits >>= 8; + block[blockLength++] = lengthBits; + lengthBits >>= 8; + block[blockLength++] = lengthBits; + lengthBits >>= 8; + block[blockLength++] = lengthBits; + lengthBits >>= 8; + block[blockLength++] = lengthBits; + lengthBits >>= 8; + block[blockLength++] = lengthBits; +#endif + processChunk(block); + if (blockLength > RE_DIGEST_CHUNK_SIZE) + processChunk(block + RE_DIGEST_CHUNK_SIZE); +#if defined __LITTLE_ENDIAN__ + memcpy(m_digest, &m_a0, 4); + memcpy(m_digest + 4, &m_b0, 4); + memcpy(m_digest + 8, &m_c0, 4); + memcpy(m_digest + 12, &m_d0, 4); +#else #define oneWord(word, ix) m_digest[ix] = word; word >>= 8; \ m_digest[ix + 1] = word; word >>= 8; m_digest[ix + 2] = word; word >>= 8; \ - m_digest[ix + 3] = word - oneWord(m_a0, 0); - oneWord(m_b0, 4); - oneWord(m_c0, 8); - oneWord(m_d0, 12); -#endif -} - -/** - * Processes a 512 bit block ("chunk"). - * - * This method is a direct programming of the algorithm described in wikipedia. - */ -void ReMD5::processChunk2(const uint8_t block[RE_DIGEST_CHUNK_SIZE]) { - uint32_t M[16]; - // break chunk into sixteen 32-bit words M[j], 0 ≤ j ≤ 15 - for (int ix = 0; ix < 16; ix++) { - uint32_t x = block[3]; - for (int jj = 2; jj >= 0; jj--) { - x = (x << 8) + block[jj]; - } - M[ix] = x; - block += 4; - } - //Initialize hash value for this chunk: - uint32_t A = m_a0; - uint32_t B = m_b0; - uint32_t C = m_c0; - uint32_t D = m_d0; - //Main loop: - - int F, g; -//#define TRACE_MD5 -#if defined TRACE_MD5 - printf("neu: (%s)\n", block); -#endif - for (int i = 0; i < RE_DIGEST_CHUNK_SIZE; i++) { -#if defined TRACE_MD5 - if (i < 8) - printf("%2d: A: %08x B: %08x C: %08x D%08x\n", i, A, B, C, D); -#endif - if (i < 16) { -# define F1(B, C, D) ((B & C) | (~ B & D)) - // F := (B and C) or ((not B) and D) - F = F1(B, C, D); - g = i; - } else if (i < 32) { - // F := (D and B) or (C and (not D)) - // g := (5×i + 1) mod 16 -# define F2(B, C, D) ((D & B) | (C & ~ D)) - F = F2(B, C, D); - g = (5 * i + 1) % 16; - } else if (i < 48) { - // F := B xor C xor D - // g := (3×i + 5) mod 16 -# define F3(B, C, D) ((B ^ C) ^ D) - F = F3(B, C, D); - g = (3 * i + 5) % 16; - } else { - // F := C xor (B or (not D)) -# define F4(B, C, D) (C ^ (B | ~ D)) - // g := (7×i) mod 16 - F = F4(B, C, D); - g = (7 * i) % 16; - } -#if defined TRACE_MD5 - if (i < 8) - printf(" K[%2d]: %08x M[%2d]: %08x shift: %02d\n", - i, m_K[i], g, M[g], m_s[i]); -#endif - uint32_t dTemp = D; - D = C; - C = B; - // B := B + leftrotate((A + F + K[i] + M[g]), s[i]) - uint32_t x = (A + F + m_K[i] + M[g]); - int shift = m_s[i]; - B += (x << shift) | (x >> (32 - shift)); - A = dTemp; - } - //Add this chunk's hash to result so far: - m_a0 += A; - m_b0 += B; - m_c0 += C; - m_d0 += D; -} -/** ---------------------- - */ -#if defined OPTIMIZER_WORKS_GREAT -inline void rotate_left_and_add(uint32_t& rc, uint32_t data, int shift, uint32_t term) { - rc = ((data << shift) | (data >> (32-shift))) + term; -} -//#define TRACE_MD5 -#if defined TRACE_MD5 -static int s_ix = 0; -#endif -inline void X1(uint32_t &var, uint32_t x, uint32_t y, uint32_t z, - uint32_t data, uint32_t aConst, uint32_t shift) { -#if defined TRACE_MD5 - printf("%2d: A: %08x B: %08x C: %08x D%08x\n", s_ix++ % 16, var, x, y, z); - printf(" K[%2d]: %08x M[?]: %08x shift: %02d\n", - s_ix - 1, aConst, data, shift); -#endif - rotate_left_and_add(var, var + F1(x, y, z) + data + aConst, shift, x); -} -inline void X2(uint32_t& var, uint32_t x, uint32_t y, uint32_t z, - uint32_t data, uint32_t aConst, uint32_t shift) { -#if defined TRACE_MD5 - printf("%2d: A: %08x B: %08x C: %08x D%08x\n", s_ix++ % 16, var, x, y, z); - printf(" K[%2d]: %08x M[?]: %08x shift: %02d\n", - s_ix - 1, aConst, data, shift); -#endif - rotate_left_and_add(var, var + F2(x, y, z) + data + aConst, shift, x); -} - -inline void X3(uint32_t& var, uint32_t x, uint32_t y, uint32_t z, - uint32_t data, uint32_t aConst, uint32_t shift) { -#if defined TRACE_MD5 - printf("%2d: A: %08x B: %08x C: %08x D%08x\n", s_ix++ % 16, var, x, y, z); - printf(" K[%2d]: %08x M[?]: %08x shift: %02d\n", - s_ix - 1, aConst, data, shift); -#endif - rotate_left_and_add(var, var + F3(x, y, z) + data + aConst, shift, x); -} - -inline void X4(uint32_t& var, uint32_t x, uint32_t y, uint32_t z, - uint32_t data, uint32_t aConst, uint32_t shift) { -#if defined TRACE_MD5 - printf("%2d: A: %08x B: %08x C: %08x D%08x\n", s_ix++ % 16, var, x, y, z); - printf(" K[%2d]: %08x M[?]: %08x shift: %02d\n", - s_ix - 1, aConst, data, shift); -#endif - rotate_left_and_add(var, var + F4(x, y, z) + data + aConst, shift, x); -} -#else + m_digest[ix + 3] = word + oneWord(m_a0, 0); + oneWord(m_b0, 4); + oneWord(m_c0, 8); + oneWord(m_d0, 12); +#endif +} + +/** + * Processes a 512 bit block ("chunk"). + * + * This method is a direct programming of the algorithm described in wikipedia. + */ +void ReMD5::processChunk2(const uint8_t block[RE_DIGEST_CHUNK_SIZE]) { + uint32_t M[16]; + // break chunk into sixteen 32-bit words M[j], 0 ≤ j ≤ 15 + for (int ix = 0; ix < 16; ix++) { + uint32_t x = block[3]; + for (int jj = 2; jj >= 0; jj--) { + x = (x << 8) + block[jj]; + } + M[ix] = x; + block += 4; + } + //Initialize hash value for this chunk: + uint32_t A = m_a0; + uint32_t B = m_b0; + uint32_t C = m_c0; + uint32_t D = m_d0; + //Main loop: + + int F, g; +//#define TRACE_MD5 +#if defined TRACE_MD5 + printf("neu: (%s)\n", block); +#endif + for (int i = 0; i < RE_DIGEST_CHUNK_SIZE; i++) { +#if defined TRACE_MD5 + if (i < 8) + printf("%2d: A: %08x B: %08x C: %08x D%08x\n", i, A, B, C, D); +#endif + if (i < 16) { +# define F1(B, C, D) ((B & C) | (~ B & D)) + // F := (B and C) or ((not B) and D) + F = F1(B, C, D); + g = i; + } else if (i < 32) { + // F := (D and B) or (C and (not D)) + // g := (5×i + 1) mod 16 +# define F2(B, C, D) ((D & B) | (C & ~ D)) + F = F2(B, C, D); + g = (5 * i + 1) % 16; + } else if (i < 48) { + // F := B xor C xor D + // g := (3×i + 5) mod 16 +# define F3(B, C, D) ((B ^ C) ^ D) + F = F3(B, C, D); + g = (3 * i + 5) % 16; + } else { + // F := C xor (B or (not D)) +# define F4(B, C, D) (C ^ (B | ~ D)) + // g := (7×i) mod 16 + F = F4(B, C, D); + g = (7 * i) % 16; + } +#if defined TRACE_MD5 + if (i < 8) + printf(" K[%2d]: %08x M[%2d]: %08x shift: %02d\n", + i, m_K[i], g, M[g], m_s[i]); +#endif + uint32_t dTemp = D; + D = C; + C = B; + // B := B + leftrotate((A + F + K[i] + M[g]), s[i]) + uint32_t x = (A + F + m_K[i] + M[g]); + int shift = m_s[i]; + B += (x << shift) | (x >> (32 - shift)); + A = dTemp; + } + //Add this chunk's hash to result so far: + m_a0 += A; + m_b0 += B; + m_c0 += C; + m_d0 += D; +} +/** ---------------------- + */ +#if defined OPTIMIZER_WORKS_GREAT +inline void rotate_left_and_add(uint32_t& rc, uint32_t data, int shift, uint32_t term) { + rc = ((data << shift) | (data >> (32-shift))) + term; +} +//#define TRACE_MD5 +#if defined TRACE_MD5 +static int s_ix = 0; +#endif +inline void X1(uint32_t &var, uint32_t x, uint32_t y, uint32_t z, + uint32_t data, uint32_t aConst, uint32_t shift) { +#if defined TRACE_MD5 + printf("%2d: A: %08x B: %08x C: %08x D%08x\n", s_ix++ % 16, var, x, y, z); + printf(" K[%2d]: %08x M[?]: %08x shift: %02d\n", + s_ix - 1, aConst, data, shift); +#endif + rotate_left_and_add(var, var + F1(x, y, z) + data + aConst, shift, x); +} +inline void X2(uint32_t& var, uint32_t x, uint32_t y, uint32_t z, + uint32_t data, uint32_t aConst, uint32_t shift) { +#if defined TRACE_MD5 + printf("%2d: A: %08x B: %08x C: %08x D%08x\n", s_ix++ % 16, var, x, y, z); + printf(" K[%2d]: %08x M[?]: %08x shift: %02d\n", + s_ix - 1, aConst, data, shift); +#endif + rotate_left_and_add(var, var + F2(x, y, z) + data + aConst, shift, x); +} + +inline void X3(uint32_t& var, uint32_t x, uint32_t y, uint32_t z, + uint32_t data, uint32_t aConst, uint32_t shift) { +#if defined TRACE_MD5 + printf("%2d: A: %08x B: %08x C: %08x D%08x\n", s_ix++ % 16, var, x, y, z); + printf(" K[%2d]: %08x M[?]: %08x shift: %02d\n", + s_ix - 1, aConst, data, shift); +#endif + rotate_left_and_add(var, var + F3(x, y, z) + data + aConst, shift, x); +} + +inline void X4(uint32_t& var, uint32_t x, uint32_t y, uint32_t z, + uint32_t data, uint32_t aConst, uint32_t shift) { +#if defined TRACE_MD5 + printf("%2d: A: %08x B: %08x C: %08x D%08x\n", s_ix++ % 16, var, x, y, z); + printf(" K[%2d]: %08x M[?]: %08x shift: %02d\n", + s_ix - 1, aConst, data, shift); +#endif + rotate_left_and_add(var, var + F4(x, y, z) + data + aConst, shift, x); +} +#else #define rotate_left_and_add(var, data, shift, term) { \ uint32_t val = data; \ var = ((val << shift) | (val >> (32-shift))) + term; \ -} +} #define X1(var, x, y, z, data, aConst, shift) \ - rotate_left_and_add(var, var + F1(x, y, z) + data + aConst, shift, x) + rotate_left_and_add(var, var + F1(x, y, z) + data + aConst, shift, x) #define X2(var, x, y, z, data, aConst, shift) \ - rotate_left_and_add(var, var + F2(x, y, z) + data + aConst, shift, x) + rotate_left_and_add(var, var + F2(x, y, z) + data + aConst, shift, x) #define X3(var, x, y, z, data, aConst, shift) \ - rotate_left_and_add(var, var + F3(x, y, z) + data + aConst, shift, x) + rotate_left_and_add(var, var + F3(x, y, z) + data + aConst, shift, x) #define X4(var, x, y, z, data, aConst, shift) \ - rotate_left_and_add(var, var + F4(x, y, z) + data + aConst, shift, x) -#endif /* OPTIMIZER_WORKS_GREAT */ - -/** - * Processes a 512 bit block ("chunk"). - * - * This is a optimized version, derived from the method above. - * We unroll the loop, this brings speed with factor 2. - *
- * B := B + leftrotate((A + F + K[i] + M[g]), s[i])
- *	D := C;
- *	C := B;
- *  B := B + leftrotate((A + F + K[i] + M[g]), s[i])
- *  A := D(old)
- * (D, C, B, A) = (C, B, B + leftrotate((A + F + K[i] + M[g]), s[i]), D)
- * ==> (A, B, C, D) = (D, B + leftrotate((A + F + K[i] + M[g]), s[i]), B, A)
- * The unrolled loop:
- * i = g = 0;
- * (A, B, C, D) = (D, B + leftrotate((A +  F1(B, C, D) + K[0] + M[0]), s[0]), B, A)
- * only one var must be calculated, the other 3 are exchanged only.
- * i = g = 1;
- * (A, B, C, D) = (D, B + leftrotate((A +  F1(B, C, D) + K[1] + M[1]), s[1]), B, A)
- * i = g = 2;
- * (A, B, C, D) = (D, B + leftrotate((A +  F1(B, C, D) + K[2] + M[2]), s[2]), B, A)
- * i = g = 3;
- * (A, B, C, D) = (D, B + leftrotate((A +  F1(B, C, D) + K[3] + M[3]), s[3]), B, A)
- * in each of the 4 statements another variable (of A, B, C and D) will be calculated
- * so we do not exchange in each step, we calculate in the end position
- * we define a function to do this:
- * void X1(uint32_t &var, uint32_t x, uint32_t y, uint32_t z, uint32_t data, uint32_t shift, uint32_t aConst){
- *	 var = rotate_left(var+ F1(x, y, z) + data + aConst, shift) + x;
- * }
- * Note: the input parameter of X1 must respect the exchange:
- * A -> D -> C -> B ...
- * X1(A, B, C, D,  M[0], K[0], s[0]);
- * X1(D, A, B, C,  M[1], K[1], s[1]);
- * X1(C, D, A, B,  M[2], K[2], s[2]);
- * X1(B, C, D, A,  M[3], K[3], s[3]);
- * ...
- * 
- */ -void ReMD5::processChunk(const uint8_t block[RE_DIGEST_CHUNK_SIZE]) { - uint32_t M[16]; - // break chunk into sixteen 32-bit words M[j], 0 ≤ j ≤ 15 -#ifdef __LITTLE_ENDIAN__ - for (int ix = 0; ix < 16; ix++) { - //memcpy(&M[ix], block + ix * 4, 4); - M[ix] = *(uint32_t*) (block + ix * 4); - } -#elif defined __BIG_ENDIAN__ - for (int ix = 0; ix < 16; ix++) { - uint32_t x = block[3]; - for (int jj = 2; jj >= 0; jj--) { - x = (x << 8) + block[jj]; - } - M[ix] = x; - block += 4; - } -#else -# error "missing __LITTLE_ENDIAN__ or __BIG_ENDIAN__" -#endif - //Initialize hash value for this chunk: - uint32_t A = m_a0; - uint32_t B = m_b0; - uint32_t C = m_c0; - uint32_t D = m_d0; -#if defined NeverAndNeverAndNeverAgain - // Derivation of the optimization: - -#endif - /* Round 1 */ - X1(A, B, C, D, M[0], 0xd76aa478, 7); - X1(D, A, B, C, M[1], 0xe8c7b756, 12); - X1(C, D, A, B, M[2], 0x242070db, 17); - X1(B, C, D, A, M[3], 0xc1bdceee, 22); - X1(A, B, C, D, M[4], 0xf57c0faf, 7); - X1(D, A, B, C, M[5], 0x4787c62a, 12); - X1(C, D, A, B, M[6], 0xa8304613, 17); - X1(B, C, D, A, M[7], 0xfd469501, 22); - X1(A, B, C, D, M[8], 0x698098d8, 7); - X1(D, A, B, C, M[9], 0x8b44f7af, 12); - X1(C, D, A, B, M[10], 0xffff5bb1, 17); - X1(B, C, D, A, M[11], 0x895cd7be, 22); - X1(A, B, C, D, M[12], 0x6b901122, 7); - X1(D, A, B, C, M[13], 0xfd987193, 12); - X1(C, D, A, B, M[14], 0xa679438e, 17); - X1(B, C, D, A, M[15], 0x49b40821, 22); - - /* Round 2 */ - X2(A, B, C, D, M[1], 0xf61e2562, 5); - X2(D, A, B, C, M[6], 0xc040b340, 9); - X2(C, D, A, B, M[11], 0x265e5a51, 14); - X2(B, C, D, A, M[0], 0xe9b6c7aa, 20); - X2(A, B, C, D, M[5], 0xd62f105d, 5); - X2(D, A, B, C, M[10], 0x02441453, 9); - X2(C, D, A, B, M[15], 0xd8a1e681, 14); - X2(B, C, D, A, M[4], 0xe7d3fbc8, 20); - X2(A, B, C, D, M[9], 0x21e1cde6, 5); - X2(D, A, B, C, M[14], 0xc33707d6, 9); - X2(C, D, A, B, M[3], 0xf4d50d87, 14); - X2(B, C, D, A, M[8], 0x455a14ed, 20); - X2(A, B, C, D, M[13], 0xa9e3e905, 5); - X2(D, A, B, C, M[2], 0xfcefa3f8, 9); - X2(C, D, A, B, M[7], 0x676f02d9, 14); - X2(B, C, D, A, M[12], 0x8d2a4c8a, 20); - - /* Round 3 */ - X3(A, B, C, D, M[5], 0xfffa3942, 4); - X3(D, A, B, C, M[8], 0x8771f681, 11); - X3(C, D, A, B, M[11], 0x6d9d6122, 16); - X3(B, C, D, A, M[14], 0xfde5380c, 23); - X3(A, B, C, D, M[1], 0xa4beea44, 4); - X3(D, A, B, C, M[4], 0x4bdecfa9, 11); - X3(C, D, A, B, M[7], 0xf6bb4b60, 16); - X3(B, C, D, A, M[10], 0xbebfbc70, 23); - X3(A, B, C, D, M[13], 0x289b7ec6, 4); - X3(D, A, B, C, M[0], 0xeaa127fa, 11); - X3(C, D, A, B, M[3], 0xd4ef3085, 16); - X3(B, C, D, A, M[6], 0x04881d05, 23); - X3(A, B, C, D, M[9], 0xd9d4d039, 4); - X3(D, A, B, C, M[12], 0xe6db99e5, 11); - X3(C, D, A, B, M[15], 0x1fa27cf8, 16); - X3(B, C, D, A, M[2], 0xc4ac5665, 23); - - /* Round 4 */ - X4(A, B, C, D, M[0], 0xf4292244, 6); - X4(D, A, B, C, M[7], 0x432aff97, 10); - X4(C, D, A, B, M[14], 0xab9423a7, 15); - X4(B, C, D, A, M[5], 0xfc93a039, 21); - X4(A, B, C, D, M[12], 0x655b59c3, 6); - X4(D, A, B, C, M[3], 0x8f0ccc92, 10); - X4(C, D, A, B, M[10], 0xffeff47d, 15); - X4(B, C, D, A, M[1], 0x85845dd1, 21); - X4(A, B, C, D, M[8], 0x6fa87e4f, 6); - X4(D, A, B, C, M[15], 0xfe2ce6e0, 10); - X4(C, D, A, B, M[6], 0xa3014314, 15); - X4(B, C, D, A, M[13], 0x4e0811a1, 21); - X4(A, B, C, D, M[4], 0xf7537e82, 6); - X4(D, A, B, C, M[11], 0xbd3af235, 10); - X4(C, D, A, B, M[2], 0x2ad7d2bb, 15); - X4(B, C, D, A, M[9], 0xeb86d391, 21); - - //Add this chunk's hash to result so far: - m_a0 += A; - m_b0 += B; - m_c0 += C; - m_d0 += D; -} -/** - * Prepares the instance for a new checksum. - */ -void ReMD5::reset() { - m_a0 = 0x67452301; - m_b0 = 0xefcdab89; - m_c0 = 0x98badcfe; - m_d0 = 0x10325476; - memset(m_digest, 0, sizeof m_digest); - memset(m_waiting, 0, m_chunkSize); - m_lengthWaiting = 0; - m_length = 0; - m_hexDigest.setLength(0); - m_finalized = false; -} + rotate_left_and_add(var, var + F4(x, y, z) + data + aConst, shift, x) +#endif /* OPTIMIZER_WORKS_GREAT */ + +/** + * Processes a 512 bit block ("chunk"). + * + * This is a optimized version, derived from the method above. + * We unroll the loop, this brings speed with factor 2. + *
+ * B := B + leftrotate((A + F + K[i] + M[g]), s[i])
+ *	D := C;
+ *	C := B;
+ *  B := B + leftrotate((A + F + K[i] + M[g]), s[i])
+ *  A := D(old)
+ * (D, C, B, A) = (C, B, B + leftrotate((A + F + K[i] + M[g]), s[i]), D)
+ * ==> (A, B, C, D) = (D, B + leftrotate((A + F + K[i] + M[g]), s[i]), B, A)
+ * The unrolled loop:
+ * i = g = 0;
+ * (A, B, C, D) = (D, B + leftrotate((A +  F1(B, C, D) + K[0] + M[0]), s[0]), B, A)
+ * only one var must be calculated, the other 3 are exchanged only.
+ * i = g = 1;
+ * (A, B, C, D) = (D, B + leftrotate((A +  F1(B, C, D) + K[1] + M[1]), s[1]), B, A)
+ * i = g = 2;
+ * (A, B, C, D) = (D, B + leftrotate((A +  F1(B, C, D) + K[2] + M[2]), s[2]), B, A)
+ * i = g = 3;
+ * (A, B, C, D) = (D, B + leftrotate((A +  F1(B, C, D) + K[3] + M[3]), s[3]), B, A)
+ * in each of the 4 statements another variable (of A, B, C and D) will be calculated
+ * so we do not exchange in each step, we calculate in the end position
+ * we define a function to do this:
+ * void X1(uint32_t &var, uint32_t x, uint32_t y, uint32_t z, uint32_t data, uint32_t shift, uint32_t aConst){
+ *	 var = rotate_left(var+ F1(x, y, z) + data + aConst, shift) + x;
+ * }
+ * Note: the input parameter of X1 must respect the exchange:
+ * A -> D -> C -> B ...
+ * X1(A, B, C, D,  M[0], K[0], s[0]);
+ * X1(D, A, B, C,  M[1], K[1], s[1]);
+ * X1(C, D, A, B,  M[2], K[2], s[2]);
+ * X1(B, C, D, A,  M[3], K[3], s[3]);
+ * ...
+ * 
+ */ +void ReMD5::processChunk(const uint8_t block[RE_DIGEST_CHUNK_SIZE]) { + uint32_t M[16]; + // break chunk into sixteen 32-bit words M[j], 0 ≤ j ≤ 15 +#ifdef __LITTLE_ENDIAN__ + for (int ix = 0; ix < 16; ix++) { + //memcpy(&M[ix], block + ix * 4, 4); + M[ix] = *(uint32_t*) (block + ix * 4); + } +#elif defined __BIG_ENDIAN__ + for (int ix = 0; ix < 16; ix++) { + uint32_t x = block[3]; + for (int jj = 2; jj >= 0; jj--) { + x = (x << 8) + block[jj]; + } + M[ix] = x; + block += 4; + } +#else +# error "missing __LITTLE_ENDIAN__ or __BIG_ENDIAN__" +#endif + //Initialize hash value for this chunk: + uint32_t A = m_a0; + uint32_t B = m_b0; + uint32_t C = m_c0; + uint32_t D = m_d0; +#if defined NeverAndNeverAndNeverAgain + // Derivation of the optimization: + +#endif + /* Round 1 */ + X1(A, B, C, D, M[0], 0xd76aa478, 7); + X1(D, A, B, C, M[1], 0xe8c7b756, 12); + X1(C, D, A, B, M[2], 0x242070db, 17); + X1(B, C, D, A, M[3], 0xc1bdceee, 22); + X1(A, B, C, D, M[4], 0xf57c0faf, 7); + X1(D, A, B, C, M[5], 0x4787c62a, 12); + X1(C, D, A, B, M[6], 0xa8304613, 17); + X1(B, C, D, A, M[7], 0xfd469501, 22); + X1(A, B, C, D, M[8], 0x698098d8, 7); + X1(D, A, B, C, M[9], 0x8b44f7af, 12); + X1(C, D, A, B, M[10], 0xffff5bb1, 17); + X1(B, C, D, A, M[11], 0x895cd7be, 22); + X1(A, B, C, D, M[12], 0x6b901122, 7); + X1(D, A, B, C, M[13], 0xfd987193, 12); + X1(C, D, A, B, M[14], 0xa679438e, 17); + X1(B, C, D, A, M[15], 0x49b40821, 22); + + /* Round 2 */ + X2(A, B, C, D, M[1], 0xf61e2562, 5); + X2(D, A, B, C, M[6], 0xc040b340, 9); + X2(C, D, A, B, M[11], 0x265e5a51, 14); + X2(B, C, D, A, M[0], 0xe9b6c7aa, 20); + X2(A, B, C, D, M[5], 0xd62f105d, 5); + X2(D, A, B, C, M[10], 0x02441453, 9); + X2(C, D, A, B, M[15], 0xd8a1e681, 14); + X2(B, C, D, A, M[4], 0xe7d3fbc8, 20); + X2(A, B, C, D, M[9], 0x21e1cde6, 5); + X2(D, A, B, C, M[14], 0xc33707d6, 9); + X2(C, D, A, B, M[3], 0xf4d50d87, 14); + X2(B, C, D, A, M[8], 0x455a14ed, 20); + X2(A, B, C, D, M[13], 0xa9e3e905, 5); + X2(D, A, B, C, M[2], 0xfcefa3f8, 9); + X2(C, D, A, B, M[7], 0x676f02d9, 14); + X2(B, C, D, A, M[12], 0x8d2a4c8a, 20); + + /* Round 3 */ + X3(A, B, C, D, M[5], 0xfffa3942, 4); + X3(D, A, B, C, M[8], 0x8771f681, 11); + X3(C, D, A, B, M[11], 0x6d9d6122, 16); + X3(B, C, D, A, M[14], 0xfde5380c, 23); + X3(A, B, C, D, M[1], 0xa4beea44, 4); + X3(D, A, B, C, M[4], 0x4bdecfa9, 11); + X3(C, D, A, B, M[7], 0xf6bb4b60, 16); + X3(B, C, D, A, M[10], 0xbebfbc70, 23); + X3(A, B, C, D, M[13], 0x289b7ec6, 4); + X3(D, A, B, C, M[0], 0xeaa127fa, 11); + X3(C, D, A, B, M[3], 0xd4ef3085, 16); + X3(B, C, D, A, M[6], 0x04881d05, 23); + X3(A, B, C, D, M[9], 0xd9d4d039, 4); + X3(D, A, B, C, M[12], 0xe6db99e5, 11); + X3(C, D, A, B, M[15], 0x1fa27cf8, 16); + X3(B, C, D, A, M[2], 0xc4ac5665, 23); + + /* Round 4 */ + X4(A, B, C, D, M[0], 0xf4292244, 6); + X4(D, A, B, C, M[7], 0x432aff97, 10); + X4(C, D, A, B, M[14], 0xab9423a7, 15); + X4(B, C, D, A, M[5], 0xfc93a039, 21); + X4(A, B, C, D, M[12], 0x655b59c3, 6); + X4(D, A, B, C, M[3], 0x8f0ccc92, 10); + X4(C, D, A, B, M[10], 0xffeff47d, 15); + X4(B, C, D, A, M[1], 0x85845dd1, 21); + X4(A, B, C, D, M[8], 0x6fa87e4f, 6); + X4(D, A, B, C, M[15], 0xfe2ce6e0, 10); + X4(C, D, A, B, M[6], 0xa3014314, 15); + X4(B, C, D, A, M[13], 0x4e0811a1, 21); + X4(A, B, C, D, M[4], 0xf7537e82, 6); + X4(D, A, B, C, M[11], 0xbd3af235, 10); + X4(C, D, A, B, M[2], 0x2ad7d2bb, 15); + X4(B, C, D, A, M[9], 0xeb86d391, 21); + + //Add this chunk's hash to result so far: + m_a0 += A; + m_b0 += B; + m_c0 += C; + m_d0 += D; +} +/** + * Prepares the instance for a new checksum. + */ +void ReMD5::reset() { + m_a0 = 0x67452301; + m_b0 = 0xefcdab89; + m_c0 = 0x98badcfe; + m_d0 = 0x10325476; + memset(m_digest, 0, sizeof m_digest); + memset(m_waiting, 0, m_chunkSize); + m_lengthWaiting = 0; + m_length = 0; + m_hexDigest.setLength(0); + m_finalized = false; +} diff --git a/math/ReMD5.hpp b/math/ReMD5.hpp index 3be9883..c4ea834 100644 --- a/math/ReMD5.hpp +++ b/math/ReMD5.hpp @@ -1,6 +1,6 @@ /* * ReMD5.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -22,12 +22,12 @@ public: virtual ~ReDigest(); public: const uint8_t* digest(); - const ReByteBuffer& hexDigest(); + const ReByteArray& hexDigest(); virtual void update(const uint8_t* block, int blockLength); /** Updates the digest with data of any length. * @param block the data to process */ - inline void update(const ReByteBuffer& block) { + inline void update(const ReByteArray& block) { update(reinterpret_cast(block.str()), (int) block.length()); } @@ -39,7 +39,7 @@ protected: protected: uint8_t* m_digest; size_t m_digestSize; - ReByteBuffer m_hexDigest; + ReByteArray m_hexDigest; // normally only the first chunk is used (64 byte), but while finalization // a 2nd chunk may be needed. uint8_t m_waitingBuffer[2 * RE_DIGEST_CHUNK_SIZE]; diff --git a/math/ReObfuscator.cpp b/math/ReObfuscator.cpp index 0597115..73246cd 100644 --- a/math/ReObfuscator.cpp +++ b/math/ReObfuscator.cpp @@ -1,6 +1,6 @@ /* * ReObfuscator.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. diff --git a/math/ReObfuscator.hpp b/math/ReObfuscator.hpp index 267002d..1ee648b 100644 --- a/math/ReObfuscator.hpp +++ b/math/ReObfuscator.hpp @@ -1,6 +1,6 @@ /* * ReObfuscator.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. diff --git a/math/ReRPD64.cpp b/math/ReRPD64.cpp index 929eab3..1ff5c3e 100644 --- a/math/ReRPD64.cpp +++ b/math/ReRPD64.cpp @@ -1,6 +1,6 @@ /* * ReRPD64.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. diff --git a/math/ReRPD64.hpp b/math/ReRPD64.hpp index 2a2e732..b5e244b 100644 --- a/math/ReRPD64.hpp +++ b/math/ReRPD64.hpp @@ -1,6 +1,6 @@ /* * ReRPD64.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. diff --git a/math/ReRandomizer.cpp b/math/ReRandomizer.cpp index 7dbab47..8500e34 100644 --- a/math/ReRandomizer.cpp +++ b/math/ReRandomizer.cpp @@ -1,6 +1,6 @@ /* * ReRandomizer.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -158,7 +158,7 @@ ReRandomizer::seed_t ReCongruentialGenerator::nextSeed() { * @result The buffer. */ const char* ReRandomizer::nextString(int minLength, int maxLength, - ReByteBuffer &buffer) { + ReByteArray &buffer) { int len = nextInt(maxLength, minLength); buffer.setLength(len); char* ptr = buffer.buffer(); diff --git a/math/ReRandomizer.hpp b/math/ReRandomizer.hpp index 861a894..29a8346 100644 --- a/math/ReRandomizer.hpp +++ b/math/ReRandomizer.hpp @@ -1,6 +1,6 @@ /* * ReRandomizer.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -30,7 +30,7 @@ public: virtual int64_t nextInt64(int64_t maxValue = LLONG_MAX, int64_t minValue = 0); char nextChar(); - const char* nextString(int minLength, int maxLength, ReByteBuffer& buffer); + const char* nextString(int minLength, int maxLength, ReByteArray& buffer); void shuffle(void* array, size_t length, size_t elemSize); /** @brief Sets the instance to a defined start state. */ diff --git a/math/remath.hpp b/math/remath.hpp index e6a2a90..db090fe 100644 --- a/math/remath.hpp +++ b/math/remath.hpp @@ -1,6 +1,6 @@ /* * remath.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. diff --git a/net/ReTCP.cpp b/net/ReTCP.cpp index 300c6db..8abebb5 100644 --- a/net/ReTCP.cpp +++ b/net/ReTCP.cpp @@ -1,6 +1,6 @@ /* * ReTCP.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -168,7 +168,7 @@ bool ReTCPClient::connect(const char* ip, int port) { hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; - getaddrinfo(ip, ReByteBuffer("").appendInt(port).str(), &hints, &addr); + getaddrinfo(ip, ReByteArray("").appendInt(port).str(), &hints, &addr); if (addr == NULL) { m_logger->sayF(LOG_ERROR | CAT_NETWORK, LC_CONNECT_1, i18n("ip not reachable: $1")).arg(ip).end(); @@ -279,7 +279,7 @@ void ReTCPConnection::setConnectedAddress(int family, const char* ip, * * @throws ReTCPBrokenPipeException */ -void ReTCPConnection::receive(ReByteBuffer& command, ReByteBuffer& data) { +void ReTCPConnection::receive(ReByteArray& command, ReByteArray& data) { command.setLength(8); int received = recv(m_handleSocket, command.buffer(), 8, 0); if (received == 0) { @@ -331,7 +331,7 @@ void ReTCPConnection::receive(ReByteBuffer& command, ReByteBuffer& data) { LC_RECEIVE_5, i18n("received: $1 bytes in $2 round(s) [$3]: $4")).arg( length).arg(rounds).arg(m_peerName).arg( - ReByteBuffer().appendDump(data.str(), data.length(), 80).str()) + ReByteArray().appendDump(data.str(), data.length(), 80).str()) .end(); } command.setLength(0); @@ -383,7 +383,7 @@ void ReTCPConnection::send(const char* command, const char* data, int length) { m_loggerOwner->logger()->sayF(LOG_DEBUG | CAT_NETWORK, LC_WRITE_2, i18n("sent: $1 bytes in $2 round(s): $3 $4")).arg(length).arg( rounds).arg(command).arg( - ReByteBuffer().appendDump(data, length, 80).str()).end(); + ReByteArray().appendDump(data, length, 80).str()).end(); } /** @@ -411,7 +411,7 @@ ReTCPServerConnection::~ReTCPServerConnection() { * Serves the commands of a single connection (in a single thread). */ void ReTCPServerConnection::run() { - ReByteBuffer command; + ReByteArray command; ReNetCommandHandler::ProcessingState rc = ReNetCommandHandler::PS_UNDEF; m_loggerOwner->logger()->sayF(LOG_INFO | CAT_NETWORK, LC_SERVER_CONNECTION_RUN_1, i18n("new connection to $1")).arg(m_name) @@ -528,7 +528,7 @@ bool ReTCPServer::listenForAll() { memcpy(m_ip, "0.0.0.0", 8); m_name.set(m_ip).appendChar(':').appendInt(m_port); - getaddrinfo(NULL, ReByteBuffer().appendInt(m_port).str(), &hints, + getaddrinfo(NULL, ReByteArray().appendInt(m_port).str(), &hints, &addrInfo); m_family = addrInfo->ai_family; // make a socket: @@ -659,7 +659,7 @@ ReTCPEchoServer::~ReTCPEchoServer() { * PS_ABORT: connection should be finished */ ReNetCommandHandler::ProcessingState ReTCPEchoServer::handleNetCommand( - ReByteBuffer& command, ReByteBuffer& data, ReTCPConnection* connection) { + ReByteArray& command, ReByteArray& data, ReTCPConnection* connection) { ProcessingState rc = PS_UNDEF; if (command.equals("echo ")) { connection->send("Echo", data.str(), data.length()); diff --git a/net/ReTCP.hpp b/net/ReTCP.hpp index 85d0347..6892be5 100644 --- a/net/ReTCP.hpp +++ b/net/ReTCP.hpp @@ -1,6 +1,6 @@ /* * ReTCP.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -81,7 +81,7 @@ protected: int m_port; ReLoggerOwner* m_loggerOwner; char m_ip[INET6_ADDRSTRLEN + 1]; - ReByteBuffer m_name; + ReByteArray m_name; }; /** @@ -100,7 +100,7 @@ public: inline int id() const { return m_id; } - void receive(ReByteBuffer& command, ReByteBuffer& data); + void receive(ReByteArray& command, ReByteArray& data); void send(const char* command, const char* data, int length = -1); void setConnectedAddress(int family, const char* ip, int port); /** Sets the socket handle. @@ -122,9 +122,9 @@ public: m_logSendReceive = value; } protected: - ReByteBuffer m_peerName; - ReByteBuffer m_received; - ReByteBuffer m_toSend; + ReByteArray m_peerName; + ReByteArray m_received; + ReByteArray m_toSend; int m_handleSocket; int m_id; uint32_t m_noSent; @@ -223,8 +223,8 @@ public: * PS_FAILED: command processed, error occurred
* PS_ABORT: connection should be finished */ - virtual ProcessingState handleNetCommand(ReByteBuffer& command, - ReByteBuffer& data, ReTCPConnection* connection) = 0; + virtual ProcessingState handleNetCommand(ReByteArray& command, + ReByteArray& data, ReTCPConnection* connection) = 0; protected: ReNetCommandHandler* m_nextHandler; @@ -245,8 +245,8 @@ public: ReTCPEchoServer(int port, ReLogger* logger); virtual ~ReTCPEchoServer(); public: - virtual ProcessingState handleNetCommand(ReByteBuffer& command, - ReByteBuffer& data, ReTCPConnection* connection); + virtual ProcessingState handleNetCommand(ReByteArray& command, + ReByteArray& data, ReTCPConnection* connection); }; /** diff --git a/net/ReUdpConnection.cpp b/net/ReUdpConnection.cpp index 4d45632..5afca30 100644 --- a/net/ReUdpConnection.cpp +++ b/net/ReUdpConnection.cpp @@ -1,6 +1,6 @@ /* * ReUdpConnection.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -76,7 +76,7 @@ const char* ReUdpConnection::address() const { * Otherwise: The length of the received message. * */ -int ReUdpConnection::receive(int timeout, ReByteBuffer* buffer, bool doLog) { +int ReUdpConnection::receive(int timeout, ReByteArray* buffer, bool doLog) { socklen_t addrLength = sizeof m_address; bool doRead = true; if (buffer == NULL) { @@ -139,7 +139,7 @@ int ReUdpConnection::send(const char* buffer, int bufferLength) { * * @return The internal buffer. */ -ReByteBuffer& ReUdpConnection::buffer() { +ReByteArray& ReUdpConnection::buffer() { return m_buffer; } @@ -272,14 +272,14 @@ ReUdpMaster::~ReUdpMaster() { * @return true: The message should be logged. * false: Otherwise. */ -bool ReUdpMaster::canLog(ReByteBuffer& message) { +bool ReUdpMaster::canLog(ReByteArray& message) { return true; } /** @brief Receives UDP messages and send answers. */ void ReUdpMaster::run() { - ReByteBuffer answer; + ReByteArray answer; bool again = true; while (again) { receive(0, NULL, false); diff --git a/net/ReUdpConnection.hpp b/net/ReUdpConnection.hpp index fd27d19..3208da2 100644 --- a/net/ReUdpConnection.hpp +++ b/net/ReUdpConnection.hpp @@ -1,6 +1,6 @@ /* * ReUdpConnection.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -24,15 +24,15 @@ public: int port() const { return m_port; } - int receive(int timeout = 0, ReByteBuffer* buffer = NULL, + int receive(int timeout = 0, ReByteArray* buffer = NULL, bool doLog = true); int send(const char* buffer, int bufferLength = -1); void close(); - ReByteBuffer& buffer(); + ReByteArray& buffer(); protected: int m_socket; struct sockaddr_in m_address; - ReByteBuffer m_buffer; + ReByteArray m_buffer; int m_port; time_t m_lastReceipt; ReLogger* m_logger; @@ -61,11 +61,11 @@ class ReUdpMaster: public ReUdpServer { public: ReUdpMaster(int port, ReLogger* logger); virtual ~ReUdpMaster(); - virtual bool canLog(ReByteBuffer& message); + virtual bool canLog(ReByteArray& message); public: void run(); protected: - virtual bool handlePage(ReByteBuffer& buffer, ReByteBuffer& answer, + virtual bool handlePage(ReByteArray& buffer, ReByteArray& answer, ReUdpMaster& server) = 0; }; diff --git a/net/renet.hpp b/net/renet.hpp index 11bf45d..183bd57 100644 --- a/net/renet.hpp +++ b/net/renet.hpp @@ -1,6 +1,6 @@ /* * renet.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. diff --git a/os/ReDirTools.cpp b/os/ReDirTools.cpp index d83356e..aef9a3b 100644 --- a/os/ReDirTools.cpp +++ b/os/ReDirTools.cpp @@ -1,6 +1,6 @@ /* * ReDirTools.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -38,6 +38,8 @@ enum LOCATION_DIRTOOL { LC_COMPARE_STORAGE_7, // 50121 LC_COMPARE_DIR_1, // 50122 LC_DELETE_1, // 50123 + LC_DELETE_SUPERFLUOUS_1, // 50124 + LC_SYNC_1, // 50125 }; const char* ReDirTools::m_version = "2015.03.22"; ReLogger* ReDirTools::m_logger = NULL; @@ -136,7 +138,7 @@ const char* s_syncUsage[] = const char* s_syncExamples[] = { "dirtool sync --basename-pattern=;*.txt;*.doc e:\\data\\ d:\\backup\\data2", "dirtool sync --type=r --max-size=1G usr etc /media/backup", - "dirtool sync --delete=7d /home/ /backup", + "dirtool sync --delete=7d --editor=kate /home/ /backup", NULL }; const char* s_tcpUsage[] = { @@ -259,7 +261,7 @@ void ReDirOptions::addStandardFilterOptions() { m_programArgs.addString("verbose", i18n( "verbose level: 0: no info, 1: summary only, 2: normal, 3: chatter mode, 4: debug"), - 'v', "verbose", false, "1"); + 'v', "verbose", false, "2"); m_programArgs.addInt("trace", i18n("all seconds the current path will be traced\n" "0: no trace"), 'T', "trace-interval", 0); @@ -300,7 +302,7 @@ void ReDirOptions::addStandardFilterOptions() { * @throws ReOptionExecption */ ReFileTime_t ReDirOptions::checkDate(const char* value) { - ReByteBuffer theValue(value, -1); + ReByteArray theValue(value, -1); time_t rcTime; if (theValue.count(".") == 2) { // a date: @@ -540,7 +542,7 @@ ReDirStatus_t::Type_t ReDirOptions::checkType(const char* value) { */ void ReDirOptions::help(const char* errorMessage, const char* message2) const { - ReByteBuffer msg; + ReByteArray msg; if (errorMessage != 0) msg.append(errorMessage, -1); if (message2 != NULL) @@ -555,7 +557,7 @@ void ReDirOptions::help(const char* errorMessage, const char* message2) const { * @throws */ void ReDirOptions::checkStandardFilterOptions() { - ReByteBuffer buffer; + ReByteArray buffer; if (m_programArgs.getString("older", buffer)[0] != '\0') checkDate(buffer.str()); if (m_programArgs.getString("younger", buffer)[0] != '\0') @@ -614,12 +616,12 @@ void ReDirOptions::initCompoundUsage(size_t size) { * * @param buffer the pattern list as string, e.g. ";*;-cache" */ -void ReDirOptions::optimizePathPattern(ReByteBuffer& buffer) { +void ReDirOptions::optimizePathPattern(ReByteArray& buffer) { ReStringList list; ReStringList rootList; list.split(buffer.str() + 1, buffer.str()[0]); buffer.replaceAll(OS_SEPARATOR, 1, "/", 1); - ReByteBuffer item; + ReByteArray item; for (int ix = 0; ix < (int) list.count(); ix++) { item.set(list.strOf(ix), -1); if (item.endsWith("/*")) @@ -646,7 +648,7 @@ void ReDirOptions::optimizePathPattern(ReByteBuffer& buffer) { * @param filter OUT: the filter to set */ void ReDirOptions::setFilterFromProgramArgs(ReDirEntryFilter& filter) { - ReByteBuffer buffer; + ReByteArray buffer; if (m_programArgs.getString("younger", buffer)[0] != '\0') filter.m_maxAge = checkDate(buffer.str()); if (m_programArgs.getString("older", buffer)[0] != '\0') @@ -670,8 +672,9 @@ void ReDirOptions::setFilterFromProgramArgs(ReDirEntryFilter& filter) { m_pathPatterns.set(buffer.str()); filter.m_pathPatterns = &m_pathPatterns; } - if ((m_interval = m_programArgs.getInt("trace")) != 0) + if ((m_interval = m_programArgs.getInt("trace") * CLOCKS_PER_SEC) != 0){ m_triggerCount = 10; + } if (m_programArgs.getString("output", buffer)[0] != '\0') { if ((m_output = fopen(buffer.str(), "w")) == NULL) { help("cannot open output file", buffer.str()); @@ -681,7 +684,7 @@ void ReDirOptions::setFilterFromProgramArgs(ReDirEntryFilter& filter) { m_programArgs.getString("verbose", buffer); unsigned int nValue = 0; int length; - if (buffer.length() == 0) + if (buffer.empty()) m_verboseLevel = V_NORMAL; else if ( (length = ReStringUtils::lengthOfUnsigned(buffer.str(), buffer.length(), &nValue)) == 0 || length != buffer.length()) @@ -717,7 +720,7 @@ ReTool::ReTool(const char* usage[], const char* example[], int minArguments, m_hasStandardArgs(true), m_traverser(NULL, this, logger), m_filter(), - m_start(time(NULL)), + m_start(clock()), //m_statInfo(), m_logger(logger) { #pragma warning( pop ) @@ -738,7 +741,7 @@ ReTool::~ReTool() { * @return true (for chaining) */ bool ReTool::trace(const char* currentFile) { - ReByteBuffer buffer(" "); + ReByteArray buffer(" "); int duration = int(time(NULL) - m_startTime); buffer.appendInt(duration / 60).appendInt(duration % 60, ":%02d: "); buffer.appendInt(m_files).appendChar('/').appendInt( @@ -767,8 +770,10 @@ void ReTool::run(int argc, const char** argv) { m_programArgs.init(argc, argv); if (m_programArgs.argCount() < m_minArguments) m_programArgs.help(i18n("too few arguments"), false, stdout); - if (m_hasStandardArgs) + if (m_hasStandardArgs){ + checkStandardFilterOptions(); setFilterFromProgramArgs(m_filter); + } doIt(); if (m_output != stdout) { fclose(m_output); @@ -789,12 +794,12 @@ void ReTool::run(int argc, const char** argv) { void ReTool::processFileArguments() { int max = m_programArgs.argCount() - m_reservedLast; // Test whether the arguments are files or directories: - ReByteBuffer arg; + ReByteArray arg; for (int ii = m_reservedFirst; ii < max; ii++) { arg = m_programArgs.arg(ii); if (!exists(arg) != 0) m_programArgs.help( - ReByteBuffer(i18n("not a file or a directory: ")).append(arg) + ReByteArray(i18n("not a file or a directory: ")).append(arg) .str(), false, stderr); } // process the files: @@ -814,13 +819,13 @@ void ReTool::processFileArguments() { * @param filename the name of the file */ void ReTool::processSingleFile(const char* filename) { - ReByteBuffer protocol; - ReByteBuffer path; - ReByteBuffer name; - ReByteBuffer ext; + ReByteArray protocol; + ReByteArray path; + ReByteArray name; + ReByteArray ext; ReStringUtils::splitPath(filename, &protocol, &path, &name, &ext); protocol.append(path); - if (protocol.length() == 0) + if (protocol.empty()) protocol.append("."); else protocol.reduceLength(); @@ -887,15 +892,15 @@ void ReTool::processFile(ReDirStatus_t* entry) { */ void ReTool::printSummary(const char* prefix) { if (m_verboseLevel >= V_SUMMARY) { - int duration = int(time(NULL) - m_start); - ReByteBuffer line; - ReByteBuffer line2; + double duration = (double) (clock() - m_start) / CLOCKS_PER_SEC; + ReByteArray line; + ReByteArray line2; statisticAsString(line); double rate = - duration == 0 ? 0.0 : (m_files + m_directories) / duration; + duration == 0.0 ? 0.0 : (m_files + m_directories) / duration; line.append(rate, " %.1f").append(i18n("/sec"), -1); m_traverser.statisticAsString(line2); - line2.appendChar(' ').appendTime(duration).append(" ", 1).append( + line2.appendChar(' ').appendTime(int(duration * 1000)).append(" ", 1).append( i18n("sec")); fprintf(m_output, "%s=== filtered: %s\n", prefix == NULL ? "" : prefix, line.str()); @@ -1029,13 +1034,13 @@ ReDirBatch::ReDirBatch(ReLogger* logger) : } static void replaceMakros(const char* arguments, ReDirStatus_t* entry, - const char* delim, ReByteBuffer& line) { + const char* delim, ReByteArray& line) { line.set(arguments, -1); // we prepare the removal of unwanted delimiters in constructed placeholders: // example: !path!!name!: without correction: "e:\\data\\""xxx" // We want: "e:\\data\\xxx" line.replaceAll("!!", 2, "!\x01!", 3); - ReByteBuffer replacement; + ReByteArray replacement; if (strstr(arguments, "!full!") != NULL) { replacement.set(delim, -1).append(entry->m_path); replacement.append(entry->node(), -1).append(delim, -1); @@ -1069,7 +1074,7 @@ static void replaceMakros(const char* arguments, ReDirStatus_t* entry, line.replaceAll("!ext!", 5, replacement.str(), replacement.length()); } // We remove the unwanted delimiters (see above): - ReByteBuffer buffer; + ReByteArray buffer; buffer.set(delim, -1).appendChar('\01').append(delim, -1); line.replaceAll(buffer.str(), buffer.length(), "", 0); } @@ -1077,7 +1082,7 @@ static void replaceMakros(const char* arguments, ReDirStatus_t* entry, * Creates the batch file. */ void ReDirBatch::doIt() { - ReByteBuffer buffer; + ReByteArray buffer; m_programArgs.getString("arguments", m_arguments); m_programArgs.getString("script", m_script); if (m_arguments.length() + m_script.length() == 0) @@ -1114,7 +1119,7 @@ void ReDirBatch::processDir(ReDirStatus_t* entry) { * @param entry the properties of the file to process */ void ReDirBatch::processFile(ReDirStatus_t* entry) { - ReByteBuffer line; + ReByteArray line; #if defined __linux__ static const char* delim = "'"; #elif defined __WIN32__ @@ -1180,7 +1185,7 @@ void ReDirChecksum::buildStorage(const char* path, const char* storageFile) { ReDirStatus_t* entry; ReRPD64 digest2; digest2.setSalt(0x2004199111121989ll); - ReByteBuffer line; + ReByteArray line; FILE* fp = fopen(storageFile, "w"); if (fp == NULL) { m_logger->sayF(LOG_ERROR | CAT_FILE, LC_BUILD_DIRECTORY_1, @@ -1261,7 +1266,7 @@ void ReDirChecksum::compareStorage(const char* path, const char* storageFile) { i18n("corrupted storage file: $1")).arg(storageFile).end(); } else { ReStringList cols; - ReByteBuffer fullname(path); + ReByteArray fullname(path); fullname.ensureLastChar(OS_SEPARATOR_CHAR); int pathLength = fullname.length(); struct stat info; @@ -1347,7 +1352,7 @@ bool ReDirChecksum::isValid(const ReStringList& storage) { void ReDirChecksum::doIt() { int size = m_programArgs.getInt("buffersize") * 1024; m_buffer.setLength(size); - ReByteBuffer value; + ReByteArray value; m_programArgs.getString("command", value); if (value.equals("list", -1, true)) m_command = CMD_LIST; @@ -1382,7 +1387,7 @@ void ReDirChecksum::doIt() { * @param entry the properties of the directory to process */ void ReDirChecksum::processDir(ReDirStatus_t* entry) { - ReByteBuffer storageFile; + ReByteArray storageFile; if (m_command != CMD_LIST) { storageFile.append(entry->fullName()); storageFile.ensureLastChar(OS_SEPARATOR_CHAR); @@ -1439,7 +1444,7 @@ void ReDirChecksum::updateStorage(const char* path, const char* storageFile) { * @return digest (for chaining) */ ReDigest& ReDirChecksum::calculateChecksum(const char* name, ReDigest& digest, - ReByteBuffer& buffer, ReLogger* logger) { + ReByteArray& buffer, ReLogger* logger) { FILE* fp = fopen(name, "rb"); if (fp == NULL) { if (logger != NULL) @@ -1552,8 +1557,8 @@ void ReDirList::processDir(ReDirStatus_t* entry) { * @param entry the properties of the file to process */ void ReDirList::processFile(ReDirStatus_t* entry) { - ReByteBuffer bufferRights; - ReByteBuffer bufferTime; + ReByteArray bufferRights; + ReByteArray bufferTime; if (m_shortFormat) fprintf(m_output, "%s%s\n", entry->m_path.str(), entry->node()); else { @@ -1605,12 +1610,12 @@ void ReDirRandom::doIt() { int numbersPerLine = m_programArgs.getInt("perline"); int width = m_programArgs.getInt("width"); if (width <= 0) - width = ReByteBuffer("").appendInt(to).length(); - ReByteBuffer format("%"); + width = ReByteArray("").appendInt(to).length(); + ReByteArray format("%"); format.appendInt(width).append("d%s"); int found = 0; ReSeqArray values(count); - ReByteBuffer value; + ReByteArray value; if (!multiple && count >= to - from + 1) help( i18n( @@ -1643,7 +1648,7 @@ void ReDirRandom::doIt() { */ const ReStringList& ReDirStatistic::calculate(const char* base, int level, void (*formatter)(const ReDirStatisticData& data, ReDirStatistic& parent, - ReByteBuffer& line)) { + ReByteArray& line)) { ReDirEntryFilter filter; ReTraverser traverser(base, this); setFilterFromProgramArgs(filter); @@ -1661,7 +1666,7 @@ const ReStringList& ReDirStatistic::calculate(const char* base, int level, int currentDepth = -1; ReDirStatisticData* current = dataStack[0]; current->m_path.set(base, -1); - ReByteBuffer line; + ReByteArray line; bool useFilter = filter.m_minSize > 0 || filter.m_maxSize != -1 || !filetimeIsUndefined(filter.m_minAge) || !filetimeIsUndefined(filter.m_maxAge) || m_nodePatterns.count() > 0; @@ -1741,17 +1746,17 @@ void ReDirStatistic::doIt() { m_programArgs.help("depth is not an integer", false, stdout); } void (*proc)(const ReDirStatisticData& data, ReDirStatistic& parent, - ReByteBuffer& line) = &formatWithSizeFilesAndDirs; + ReByteArray& line) = &formatWithSizeFilesAndDirs; if (m_programArgs.getBool("kbyte")) proc = &formatLikeDu; const ReStringList& list = calculate(m_programArgs.arg(0), depth, proc); - ReByteBuffer buffer; + ReByteArray buffer; for (size_t ix = 0; ix < list.count(); ix++) { buffer.set(list.strOf(ix), list.strLengthOf(ix)); fprintf(m_output, "%s\n", buffer.str()); } if (m_verboseLevel >= V_SUMMARY) { - int duration = int(time(NULL) - m_start); + int duration = int((clock() - m_start) / CLOCKS_PER_SEC); fprintf(m_output, "=== duration: "); if (duration >= 3600) fprintf(m_output, "%d:", duration / 3600); @@ -1771,7 +1776,7 @@ void ReDirStatistic::doIt() { * @param line OUT: the formatted line, the conclusion of the statistic data */ void formatLikeDu(const ReDirStatisticData& data, ReDirStatistic& parent, - ReByteBuffer& line) { + ReByteArray& line) { line.setLength(0); // Round up to the next KiByte: line.appendInt(int((data.m_sizes + 1023) / 1024)).append("\t").append( @@ -1790,7 +1795,7 @@ void formatLikeDu(const ReDirStatisticData& data, ReDirStatistic& parent, * @param line OUT: the formatted line, the conclusion of the statistic data */ void formatWithSizeFilesAndDirs(const ReDirStatisticData& data, - ReDirStatistic& parent, ReByteBuffer& line) { + ReDirStatistic& parent, ReByteArray& line) { line.setLength(0); // Round up to the next KiByte: char buffer[256]; @@ -1828,7 +1833,7 @@ ReDirTouch::ReDirTouch(ReLogger* logger) : * Sets the filetime for the specified files. */ void ReDirTouch::doIt() { - ReByteBuffer buffer; + ReByteArray buffer; if (m_programArgs.getString("modified", buffer)[0] != '\0') m_modified = checkDate(buffer.str()); if (m_programArgs.getString("accessed", buffer)[0] != '\0') @@ -1901,8 +1906,8 @@ void ReDirTouch::processFile(ReDirStatus_t* entry) { const char* name = entry->fullName(); if (touch(name, modified, accessed, ReLogger::globalLogger()) == 0 && m_verboseLevel >= V_NORMAL) { - ReByteBuffer bufferTime; - ReByteBuffer bufferTime2; + ReByteArray bufferTime; + ReByteArray bufferTime2; if (m_verboseLevel == V_NORMAL) { if (countTimes == 2) fprintf(m_output, "%s | %s | %s\n", @@ -1916,8 +1921,8 @@ void ReDirTouch::processFile(ReDirStatus_t* entry) { fprintf(m_output, "%s %s\n", bufferTime.str(), name); } } else { - ReByteBuffer bufferTime3; - ReByteBuffer bufferTime4; + ReByteArray bufferTime3; + ReByteArray bufferTime4; if (countTimes == 2) fprintf(m_output, "%s -> %s | %s -> %s | %s\n", ReDirStatus_t::filetimeToString(entry->modified(), @@ -2014,7 +2019,7 @@ void ReDirTools::usage(const char* msg, const char* msg2) { * * @param path the name of the subdir to create */ -void ReDirSync::makeDirWithParents(ReByteBuffer& path, int minWidth, +void ReDirSync::makeDirWithParents(ReByteArray& path, int minWidth, ReTraverser& traverser) { if (!exists(path)) { ReFileProperties_t* props = NULL; @@ -2042,13 +2047,21 @@ ReDirSync::ReDirSync(ReLogger* logger) : i18n("does nothing, but says what should be done"), 'Y', "dry", false); m_programArgs.addString("delete", i18n( - "delete the files/folders of the target directory not existing in the source directory.\n" + "deletes the files/folders of the target directory not existing in the source directory.\n" "If a time expression is given only files will be deleted if they are older than this.\n" "a time expression is a date, a time, a date/time or a relative time.\n" "relative times are a number and a unit.\n" "units: m(inutes) h(hours), d(days). Default: m(inutes)\n" - "examples: -D7d --delete=30d -D24h -D2009.3.2/12:00 -D1999.01.01"), - 'E', "delete", false, NULL); + "examples: -E7d --delete=30d -E24h -E2009.3.2/12:00 -E1999.01.01"), + 'E', "delete", true, NULL); + m_programArgs.addBool("deletebefore", + i18n("deletes the superfluous files before copying.\n" + "This needs fewer space but it is more dangerous:\n" + "you have no time if the target is wrong: all files will be deleted"), 'B', "delete-before", false); + m_programArgs.addString("editor", + i18n( + "this editor will be started with a file containing a summary message (signals the end)"), + 'e', "editor", false, NULL); m_programArgs.addInt("timediff", i18n("filetime difference is considered to be equal\n" "if the difference is less than this value (in seconds)"), 'I', @@ -2097,7 +2110,7 @@ void ReDirSync::copyFile(ReDirStatus_t* entry, const char* target) { * falseerror occurred */ bool ReDirSync::copyFile(const char* source, ReFileProperties_t* properties, - const char* target, ReByteBuffer& buffer, ReLogger* logger) { + const char* target, ReByteArray& buffer, ReLogger* logger) { bool rc = false; #ifdef __linux__ struct stat info; @@ -2164,6 +2177,53 @@ bool ReDirSync::copyFile(const char* source, ReFileProperties_t* properties, #endif return rc; } +/** + * Delete the files existing in the target directory tree and not in the source tree. + * + * @param source the source directory + * @param target the target directory + * @param deleteTime UNDEF or a time: only files older than this will be deleted + */ +void ReDirSync::deleteSuperfluous(const ReByteArray& source, const ReByteArray& target, + const ReFileTime_t& deleteTime){ + ReTraceUnit& tracer = *this; + ReDirectory trg(target.str()); + if (trg.findFirst(ReDirectory::ALL_FILES, false)) { + ReByteArray src, trg2; + struct stat info; + ReFileTime_t modified; + bool ignoreTime = filetimeIsUndefined(deleteTime); + bool dry = m_programArgs.getBool("dry"); + do { + if (strcmp(".", trg.currentNode()) == 0 || strcmp("..", trg.currentNode()) == 0) + continue; + if (tracer.isCountTriggered() && tracer.isTimeTriggered()) + tracer.trace(trg.currentFull().str()); + + src.set(source).append(trg.currentNode()); + if (lstat(src.str(), &info) == 0){ + if (S_ISDIR(info.st_mode)){ + trg2.set(target).append(trg.currentNode()); + deleteSuperfluous(src, trg2, deleteTime); + } + } else if (ignoreTime || trg.currentModified() >= deleteTime){ + if (trg.currentIsDir()){ + if (! dry) + ReDirectory::deleteTree(trg.currentFull().str(), true); + if (m_verboseLevel >= V_NORMAL) + fprintf(m_output, "-%s%s\n", trg.currentFull().str(), dry ? " would be deleted (dir)" : ""); + } else { + if (unlink(trg.currentFull().str()) != 0) + m_logger->sayF(LOG_ERROR | CAT_FILE, LC_DELETE_SUPERFLUOUS_1, + i18n("cannot delete file: $1 (errno: $2)")).arg(trg.currentFull()).arg( + errno).end(); + else if (m_verboseLevel >= V_NORMAL) + fprintf(m_output, "-%s%s\n", trg.currentFull().str(), dry ? " would be deleted" : ""); + } + } + } while (trg.findNext()); + } +} /** * Sets the file properties. * @@ -2220,7 +2280,7 @@ bool ReDirSync::setProperties(const char* fullName, bool ReDirSync::makeDirectory(const char* directory, int minLength, ReFileProperties_t* properties, ReLogger* logger) { bool rc = true; - ReByteBuffer path(directory); + ReByteArray path(directory); int start = 0; #if defined __WIN32__ start = path.indexOf(':'); @@ -2263,17 +2323,27 @@ bool ReDirSync::makeDirectory(const char* directory, int minLength, return rc; } +static void printStatus(FILE* fp, double duration, int files, int sumSizes, int treeDirs, + int treeFiles, int64_t treeSumSizes){ + fprintf(fp, + i18n( + "=== copied: %02d:%02d sec %7d file(s) %12.6f MByte (%.3f MB/sec).\n" + "=== tree: %5d dir(s) %7d file(s) %12.6f MByte\n"), + int(duration) / 60, int(duration) % 60, files, sumSizes / 1E6, + sumSizes / 1E6 / (duration == 0.0 ? 0.001 : duration), treeDirs, + treeFiles, treeSumSizes / 1E6); +} /** * Synchronizes two directory trees. */ void ReDirSync::doIt() { ReDirEntryFilter filter; const char* sep = OS_SEPARATOR; - ReByteBuffer buffer; - ReByteBuffer target(m_programArgs.arg(m_programArgs.argCount() - 1)); + ReByteArray buffer; + ReByteArray target(m_programArgs.arg(m_programArgs.argCount() - 1)); target.removeLastChar(OS_SEPARATOR_CHAR); if (!exists(target)) - help(i18n("target does not exist: $1"), target.str()); + help(i18n("target does not exist: "), target.str()); else if (!S_ISDIR(m_statInfo.st_mode)) help(i18n("target is not a directory: $1"), target.str()); size_t lengthTargetBase = target.length(); @@ -2282,16 +2352,22 @@ void ReDirSync::doIt() { bool dry = m_programArgs.getBool("dry"); bool ignoreDate = m_programArgs.getBool("ignoredate"); bool mustExist = m_programArgs.getBool("mustexist"); - if (m_programArgs.getString("delete", buffer)[0] != '\0') - checkDate(buffer.str()); + bool deleteTarget = false; + ReFileTime_t deleteDate; + setFiletimeUndef(deleteDate); + bool deleteBefore = m_programArgs.getBool("deletebefore"); + if (m_programArgs.getString("delete", buffer) != NULL){ + deleteTarget = true; + if (! buffer.empty()) + deleteDate = checkDate(buffer.str()); + } - setFilterFromProgramArgs(filter); int64_t sumSizes = 0; int files = 0; int treeFiles = 0; int treeDirs = 0; int64_t treeSumSizes = 0ll; - ReByteBuffer source, targetFile; + ReByteArray source, targetFile; for (int ix = 0; ix < m_programArgs.argCount() - 1; ix++) { source.set(m_programArgs.arg(ix), -1); target.setLength(lengthTargetBase); @@ -2311,18 +2387,20 @@ void ReDirSync::doIt() { size_t ixSourceRelative = source.length(); size_t ixTargetRelative = target.length(); + if (deleteTarget && deleteBefore) + deleteSuperfluous(source, target, deleteDate); m_traverser.changeBase(source.str()); m_traverser.setPropertiesFromFilter(&filter); int level; ReDirStatus_t* entry; - ReByteBuffer line; + ReByteArray line; while ((entry = m_traverser.nextFile(level, &filter)) != NULL) { if (entry->isDirectory()) continue; // append the new relative path from source to target: target.setLength(ixTargetRelative); target.append(entry->m_path.str() + ixSourceRelative, -1); - if (!exists(target)) + if (!exists(target) && ! dry) makeDirWithParents(target, ixTargetRelative, m_traverser); targetFile.set(target).append(entry->node(), -1); const char* targetRelativePath = targetFile.str() + ixTargetRelative @@ -2366,19 +2444,33 @@ void ReDirSync::doIt() { if (!dry) copyFile(entry, targetFile.str()); } + if (deleteTarget && ! deleteBefore) + deleteSuperfluous(source, target, deleteDate); treeFiles += m_traverser.files(); treeDirs += m_traverser.directories(); treeSumSizes += m_traverser.sizes(); } + double duration = double((clock() - m_start)) / CLOCKS_PER_SEC; if (m_verboseLevel >= V_SUMMARY) { - int duration = int(time(NULL) - m_start); - fprintf(m_output, - i18n( - "=== copied: %02d:%02d sec %7d file(s) %12.6f MByte (%.3f MB/sec).\n" - "=== tree: %5d dir(s) %7d file(s) %12.6f MByte\n"), - duration / 60, duration % 60, files, sumSizes / 1E6, - sumSizes / 1E6 / (duration == 0 ? 1 : duration), treeDirs, - treeFiles, treeSumSizes / 1E6); + printStatus(m_output, duration, files, sumSizes, treeDirs, + treeFiles, treeSumSizes); + } + if (m_programArgs.getString("editor", buffer) != NULL){ + ReByteArray tempFile = ReFileUtils::tempDir("redirtool.status."); + tempFile.appendInt(time(NULL), "%x").append(".txt"); + FILE* fp = fopen(tempFile.str(), "w"); + if (fp == NULL) + m_logger->sayF(LOG_ERROR | CAT_FILE, LC_SYNC_1, + i18n("cannot open status file ($1): $2")).arg(errno).arg(tempFile).end(); + else { + fprintf(fp, i18n("backup finished!\n\n")); + printStatus(fp, duration, files, sumSizes, treeDirs, + treeFiles, treeSumSizes); + fclose(fp); + buffer.insert(0, "\"", -1); + buffer.append("\" ").append(tempFile); + system(buffer.str()); + } } } @@ -2404,20 +2496,20 @@ ReDirTCP::ReDirTCP(ReLogger* logger) : */ void ReDirTCP::doIt() { int port = m_programArgs.getInt("port"); - ReByteBuffer buffer; + ReByteArray buffer; int64_t bufferSize = checkSize(m_programArgs.getString("size", buffer)); // the protocol does not allow more than 16 MiByte because of the flags: if (bufferSize > 16LL * 1024 * 1024 - 64LL) help(i18n("buffersize exceeds 16777184 = 16MiByte - 32: "), buffer.str()); - ReByteBuffer command = m_programArgs.arg(0); + ReByteArray command = m_programArgs.arg(0); if (command.isPrefixOf("server", -1, true)) { ReTCPEchoServer server(port, m_logger); server.setLogSendReceive(false); server.listenForAll(); } else if (command.isPrefixOf("client", -1, true)) { const char* ip = m_programArgs.arg(1); - ReByteBuffer direction("download"); + ReByteArray direction("download"); int rounds = 10; int interval = 5; if (m_programArgs.argCount() > 2) { @@ -2451,7 +2543,7 @@ void ReDirTCP::runOneThreadClient(const char* ip, int port, int rounds, if (client.connect(ip, port)) { time_t start = time(NULL); const char* command = upload ? "strlen" : "filldata"; - ReByteBuffer message; + ReByteArray message; if (upload) message.appendChar('x', bufferSize); else @@ -2459,7 +2551,7 @@ void ReDirTCP::runOneThreadClient(const char* ip, int port, int rounds, time_t lastPrint = start; int64_t size = 0; int duration = 0; - ReByteBuffer answer, data; + ReByteArray answer, data; client.setLogSendReceive(false); int64_t sizeCurrent = 0; for (int ii = 0; ii < rounds; ii++) { @@ -2519,12 +2611,12 @@ ReDirWhich::ReDirWhich(ReLogger* logger) : * Creates the batch file. */ void ReDirWhich::doIt() { - ReByteBuffer value, path; + ReByteArray value, path; bool all = false; ReStringList items; char sep = 0; m_programArgs.getString("list", path); - if (path.length() == 0) { + if (path.empty()) { m_programArgs.getString("variable", value); if (getenv(value.str()) == NULL) help("Umgebungsvariable nicht definiert: ", value.str()); @@ -2535,11 +2627,11 @@ void ReDirWhich::doIt() { } items.split(path.str(), sep); struct stat info; - ReByteBuffer full; + ReByteArray full; for (int ix = 0; ix < m_programArgs.argCount(); ix++) { bool found = false; - ReByteBuffer arg(m_programArgs.arg(ix)); + ReByteArray arg(m_programArgs.arg(ix)); for (size_t ixItem = 0; ixItem < items.count(); ixItem++) { full.set(items.strOf(ixItem)); if (arg.indexOf('*') < 0) { @@ -2553,7 +2645,7 @@ void ReDirWhich::doIt() { if (dir.findFirst(arg.str(), false)) { do { printf("%s%c%s\n", full.str(), OS_SEPARATOR_CHAR, - dir.currentFile()); + dir.currentNode()); } while (dir.findNext()); } } @@ -2570,7 +2662,7 @@ void ReDirWhich::doIt() { * @return true: part is a prefix of full */ static bool isArg(const char* full, const char* part) { - ReByteBuffer fullArg(full); + ReByteArray fullArg(full); bool rc = fullArg.startsWith(part, -1); return rc; } diff --git a/os/ReDirTools.hpp b/os/ReDirTools.hpp index be38e98..a792ec6 100644 --- a/os/ReDirTools.hpp +++ b/os/ReDirTools.hpp @@ -1,6 +1,6 @@ /* * ReDirTools.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -56,7 +56,7 @@ public: } void setFilterFromProgramArgs(ReDirEntryFilter& filter); protected: - void optimizePathPattern(ReByteBuffer& buffer); + void optimizePathPattern(ReByteArray& buffer); protected: ReProgramArgs m_programArgs; RePatternList m_nodePatterns; @@ -104,7 +104,7 @@ protected: @param name can be changed and recovered! @return true: a file with the given name exists */ - inline bool exists(ReByteBuffer& name) { + inline bool exists(ReByteArray& name) { #if defined __linux__ // linux ignores a trailing slash: return stat(name.str(), &m_statInfo) == 0; @@ -128,7 +128,7 @@ protected: bool m_hasStandardArgs; ReTraverser m_traverser; ReDirEntryFilter m_filter; - int64_t m_start; + clock_t m_start; struct stat m_statInfo; ReLogger* m_logger; }; @@ -141,8 +141,8 @@ protected: virtual void processDir(ReDirStatus_t* entry); virtual void processFile(ReDirStatus_t* entry); protected: - ReByteBuffer m_arguments; - ReByteBuffer m_script; + ReByteArray m_arguments; + ReByteArray m_script; bool m_isExe; }; @@ -178,11 +178,11 @@ private: void updateStorage(const char* path, const char* storageFile); public: static ReDigest& calculateChecksum(const char* name, ReDigest& digest, - ReByteBuffer& buffer, ReLogger* logger); + ReByteArray& buffer, ReLogger* logger); protected: Command m_command; ReDigest* m_digest; - ReByteBuffer m_buffer; + ReByteArray m_buffer; }; /** @@ -233,14 +233,14 @@ public: void clear(); ReDirStatisticData& add(const ReDirStatisticData& source); public: - ReByteBuffer m_path; + ReByteArray m_path; }; class ReDirStatistic; extern void formatLikeDu(const ReDirStatisticData& data, ReDirStatistic& parent, - ReByteBuffer& line); + ReByteArray& line); extern void formatWithSizeFilesAndDirs(const ReDirStatisticData& data, - ReDirStatistic& parent, ReByteBuffer& line); + ReDirStatistic& parent, ReByteArray& line); /** * Calculates a statistic of a directory tree. @@ -253,7 +253,7 @@ public: public: const ReStringList& calculate(const char* base, int depth, void (*format)(const ReDirStatisticData& data, ReDirStatistic& parent, - ReByteBuffer& line) = formatLikeDu); + ReByteArray& line) = formatLikeDu); void doIt(); private: ReStringList m_list; @@ -270,17 +270,19 @@ public: protected: virtual void doIt(); void copyFile(ReDirStatus_t* entry, const char* target); - void makeDirWithParents(ReByteBuffer& path, int minWidth, + void deleteSuperfluous(const ReByteArray& source, const ReByteArray& target, + const ReFileTime_t& deleteTime); + void makeDirWithParents(ReByteArray& path, int minWidth, ReTraverser& traverser); public: static bool copyFile(const char* source, ReFileProperties_t* properties, - const char* target, ReByteBuffer& buffer, ReLogger* logger = NULL); + const char* target, ReByteArray& buffer, ReLogger* logger = NULL); static bool makeDirectory(const char* directory, int minLength, ReFileProperties_t* properties, ReLogger* logger = NULL); static bool setProperties(const char* fullName, ReFileProperties_t* properties, ReLogger* logger = NULL); protected: - ReByteBuffer m_buffer; + ReByteArray m_buffer; }; /** @@ -312,7 +314,7 @@ public: static ReErrNo_t touch(const char* filename, const ReFileTime_t& modified, const ReFileTime_t& accessed, ReLogger* logger = NULL); protected: - ReByteBuffer m_buffer; + ReByteArray m_buffer; ReFileTime_t m_modified; ReFileTime_t m_accessed; }; diff --git a/os/ReFileUtils.cpp b/os/ReFileUtils.cpp index b0dd7eb..97c979b 100644 --- a/os/ReFileUtils.cpp +++ b/os/ReFileUtils.cpp @@ -1,13 +1,13 @@ -/* - * ReFileUtils.cpp - * - * License: Public Domain - * You can use and modify this file without any restriction. - * Do what you want. - * No warranties and disclaimer of any damages. - * You also can use this license: http://www.wtfpl.net - * The latest sources: https://github.com/republib - */ +/* + * ReFileUtils.cpp + * + * License: Public Domain + * You can use and modify this file without any restriction. + * Do what you want. + * No warranties and disclaimer of any damages. + * You also can use this license: http://www.wtfpl.net + * The latest sources: https://github.com/republib + */ #include "base/rebase.hpp" #include "os/reos.hpp" @@ -19,8 +19,8 @@ * @param node the name of the subdirectory * @return the full name of the subdirectory */ -ReByteBuffer ReFileUtils::tempDir(const char* node){ - ReByteBuffer rc; +ReByteArray ReFileUtils::tempDir(const char* node){ + ReByteArray rc; if (getenv("TMP") != NULL) { rc = getenv("TMP"); } else if (getenv("TEMP")) { @@ -48,8 +48,8 @@ ReByteBuffer ReFileUtils::tempDir(const char* node){ * @param node the name of the subdirectory * @param the full name of the subdirectory */ -ReByteBuffer ReFileUtils::tempFile(const char* node, const char* subdir){ - ReByteBuffer rc = tempDir(subdir); +ReByteArray ReFileUtils::tempFile(const char* node, const char* subdir){ + ReByteArray rc = tempDir(subdir); rc.ensureLastChar(OS_SEPARATOR_CHAR); rc.append(node); return rc; diff --git a/os/ReFileUtils.hpp b/os/ReFileUtils.hpp index 5d3972c..f4b8e1b 100644 --- a/os/ReFileUtils.hpp +++ b/os/ReFileUtils.hpp @@ -1,19 +1,19 @@ -/* - * ReFileUtils.hpp - * - * License: Public Domain - * You can use and modify this file without any restriction. - * Do what you want. - * No warranties and disclaimer of any damages. - * You also can use this license: http://www.wtfpl.net - * The latest sources: https://github.com/republib - */ +/* + * ReFileUtils.hpp + * + * License: Public Domain + * You can use and modify this file without any restriction. + * Do what you want. + * No warranties and disclaimer of any damages. + * You also can use this license: http://www.wtfpl.net + * The latest sources: https://github.com/republib + */ #if ! defined REFILE_UTILS_HPP #define REFILE_UTILS_HPP class ReFileUtils { public: - static ReByteBuffer tempDir(const char* node); - static ReByteBuffer tempFile(const char* node, const char* subdir); + static ReByteArray tempDir(const char* node); + static ReByteArray tempFile(const char* node, const char* subdir); }; #endif \ No newline at end of file diff --git a/os/ReRemoteDir.cpp b/os/ReRemoteDir.cpp index e1fce50..9dc789f 100644 --- a/os/ReRemoteDir.cpp +++ b/os/ReRemoteDir.cpp @@ -1,6 +1,6 @@ /* * ReRemoteDir.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -57,7 +57,7 @@ void ReRemoteDir::populate(const char* path) { * * @param sequence IN/OUT: the place for the byte sequence */ -ReByteBuffer& ReRemoteDir::serialize(ReByteBuffer& sequence) { +ReByteArray& ReRemoteDir::serialize(ReByteArray& sequence) { return sequence; } @@ -73,7 +73,7 @@ ReRemoteDirService::~ReRemoteDirService() { } ReNetCommandHandler::ProcessingState ReRemoteDirService::handleNetCommand( - ReByteBuffer& command, ReByteBuffer& data, ReTCPConnection* connection) { + ReByteArray& command, ReByteArray& data, ReTCPConnection* connection) { return ReNetCommandHandler::PS_UNDEF; } diff --git a/os/ReRemoteDir.hpp b/os/ReRemoteDir.hpp index 9e257c1..6f595c7 100644 --- a/os/ReRemoteDir.hpp +++ b/os/ReRemoteDir.hpp @@ -1,6 +1,6 @@ /* * ReRemoteDir.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -33,11 +33,11 @@ public: public: virtual void deserialize(uint8_t*& sequence, size_t& length); void populate(const char* path); - virtual ReByteBuffer& serialize(ReByteBuffer& sequence); + virtual ReByteArray& serialize(ReByteArray& sequence); protected: ReRemoteDir* m_parent; int m_indexFileInParent; - ReByteBuffer m_namePool; + ReByteArray m_namePool; int m_fileCount; ReRemoteFile* m_files; private: @@ -52,7 +52,7 @@ public: ReRemoteDirService(); ~ReRemoteDirService(); public: - virtual ProcessingState handleNetCommand(ReByteBuffer& command, - ReByteBuffer& data, ReTCPConnection* connection); + virtual ProcessingState handleNetCommand(ReByteArray& command, + ReByteArray& data, ReTCPConnection* connection); }; #endif /* REREMOTEDIR_HPP_ */ diff --git a/os/ReTraverser.cpp b/os/ReTraverser.cpp index 6acb28e..d09ad83 100644 --- a/os/ReTraverser.cpp +++ b/os/ReTraverser.cpp @@ -1,6 +1,6 @@ /* * ReTraverser.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -87,7 +87,7 @@ ReFileSize_t ReDirStatus_t::fileSize() { * @param buffer OUT: the file time * @return buffer.str() (for chaining) */ -const char* ReDirStatus_t::filetimeAsString(ReByteBuffer& buffer) { +const char* ReDirStatus_t::filetimeAsString(ReByteArray& buffer) { return filetimeToString(modified(), buffer); } @@ -99,7 +99,7 @@ const char* ReDirStatus_t::filetimeAsString(ReByteBuffer& buffer) { * @return buffer.str(), e.g. "2014.01.07 02:59:43" */ const char* ReDirStatus_t::filetimeToString(const ReFileTime_t* time, - ReByteBuffer& buffer) { + ReByteArray& buffer) { time_t time1 = filetimeToTime(time); struct tm* time2 = localtime(&time1); buffer.setLength(4 + 2 * 2 + 2 * 2 + 1 + 3 * 2 + 2 * 1); @@ -131,7 +131,7 @@ time_t ReDirStatus_t::filetimeToTime(const ReFileTime_t* filetime) { static int s_diffTime = 0x7fffffff; if (s_diffTime == 0x7fffffff){ s_diffTime = 0; - ReByteBuffer tempFile = ReFileUtils::tempFile("$$redir$$.tmp", NULL); + ReByteArray tempFile = ReFileUtils::tempFile("$$redir$$.tmp", NULL); const char* filename = tempFile.str(); FILE* fp = fopen(filename, "w"); if (fp != NULL){ @@ -171,7 +171,7 @@ bool ReDirStatus_t::findFirst() { #elif defined __WIN32__ if (m_handle != INVALID_HANDLE_VALUE) FindClose(m_handle); - ReByteBuffer thePath(m_path); + ReByteArray thePath(m_path); thePath.append(m_path.lastChar() == '\\' ? "*" : "\\*"); m_handle = FindFirstFileA(thePath.str(), &m_data); rc = m_handle != INVALID_HANDLE_VALUE; @@ -221,7 +221,7 @@ void ReDirStatus_t::freeEntry() { * @return the filename with path */ const char* ReDirStatus_t::fullName() { - if (m_fullName.length() == 0) + if (m_fullName.empty()) m_fullName.set(m_path).append(node(), -1); return m_fullName.str(); } @@ -234,7 +234,7 @@ const char* ReDirStatus_t::fullName() { * @return true: success */ bool ReDirStatus_t::getFileOwner(HANDLE handle, const char* file, - ReByteBuffer& name, ReLogger* logger) { + ReByteArray& name, ReLogger* logger) { bool rc = false; PSID pSidOwner = NULL; PSECURITY_DESCRIPTOR pSD = NULL; @@ -391,7 +391,7 @@ const char* ReDirStatus_t::node() const { #endif } -inline void addRight(int mode, ReByteBuffer& buffer) { +inline void addRight(int mode, ReByteArray& buffer) { char right; switch (mode & 7) { case 1: @@ -421,7 +421,7 @@ inline void addRight(int mode, ReByteBuffer& buffer) { } buffer.appendChar(right); } -inline void addId(const char* id, int maxLength, ReByteBuffer& buffer) { +inline void addId(const char* id, int maxLength, ReByteArray& buffer) { int length = strlen(id); if (length == maxLength) buffer.append(id, length); @@ -440,7 +440,7 @@ inline void addId(const char* id, int maxLength, ReByteBuffer& buffer) { * @param ownerWidth the width for group/owner * @return buffer.str() (for chaining) */ -const char* ReDirStatus_t::rightsAsString(ReByteBuffer& buffer, bool numerical, +const char* ReDirStatus_t::rightsAsString(ReByteArray& buffer, bool numerical, int ownerWidth) { buffer.setLength(0); #if defined __linux__ @@ -486,7 +486,7 @@ const char* ReDirStatus_t::rightsAsString(ReByteBuffer& buffer, bool numerical, } } - ReByteBuffer owner; + ReByteArray owner; if (handle != INVALID_HANDLE_VALUE) getFileOwner(handle, name, owner, m_logger); CloseHandle(handle); @@ -632,7 +632,7 @@ void ReDirEntryFilter::deserialize(const uint8_t*& sequence, size_t& length) { unpackInt24(sequence, length, id); if (id != m_serialId) throw ReSerializeFormatException("wrong serialId", this); - ReByteBuffer buffer; + ReByteArray buffer; unpackString64k(sequence, length, buffer); bool ignoreCase; unpackBool(sequence, length, ignoreCase); @@ -652,7 +652,7 @@ void ReDirEntryFilter::deserialize(const uint8_t*& sequence, size_t& length) { * * @param sequence IN/OUT: the place for the byte sequence */ -ReByteBuffer& ReDirEntryFilter::serialize(ReByteBuffer& sequence) { +ReByteArray& ReDirEntryFilter::serialize(ReByteArray& sequence) { sequence.appendBits24(m_serialId); packString64k(sequence, m_nodePatterns->patternString()); packBool(sequence, m_nodePatterns->ignoreCase()); @@ -742,7 +742,7 @@ ReDirTreeStatistic::ReDirTreeStatistic() : * @param formatFiles the sprintf format for the directory count, e.g. "%6d" * @return a human readable string */ -const char* ReDirTreeStatistic::statisticAsString(ReByteBuffer& buffer, +const char* ReDirTreeStatistic::statisticAsString(ReByteArray& buffer, bool append, const char* formatFiles, const char* formatSizes, const char* formatDirs) { if (!append) @@ -766,8 +766,8 @@ ReTraceUnit::ReTraceUnit(int triggerCount, int interval) : m_count(0), m_triggerCount(triggerCount), m_lastTrace(0), - m_interval(interval), - m_startTime(time(NULL)) { + m_interval(interval * CLOCKS_PER_SEC), + m_startTime(clock()) { m_lastTrace = m_startTime; } /** @@ -810,7 +810,7 @@ ReTraverser::ReTraverser(const char* base, ReTraceUnit* tracer, m_dirs[0] = new ReDirStatus_t(m_logger); // remove a preceeding "./". This simplifies the pattern expressions: if (m_base.startsWith( - ReByteBuffer(".").appendChar(OS_SEPARATOR_CHAR).str())) { + ReByteArray(".").appendChar(OS_SEPARATOR_CHAR).str())) { m_base.remove(0, 2); } } @@ -834,7 +834,7 @@ void ReTraverser::changeBase(const char* base) { m_dirs[0] = new ReDirStatus_t(m_logger); // remove a preceeding "./". This simplifies the pattern expressions: if (m_base.startsWith( - ReByteBuffer(".").appendChar(OS_SEPARATOR_CHAR).str())) { + ReByteArray(".").appendChar(OS_SEPARATOR_CHAR).str())) { m_base.remove(0, 2); } } @@ -965,7 +965,7 @@ ReDirStatus_t* ReTraverser::nextFile(int& level, ReDirEntryFilter* filter) { * @return true: a new file is available
* false/code>: findFirstEntry() signals: no entry. */ -bool ReTraverser::initEntry(const ReByteBuffer& parent, const char* node, +bool ReTraverser::initEntry(const ReByteArray& parent, const char* node, int level) { bool rc = false; if (level < MAX_ENTRY_STACK_DEPTH) { diff --git a/os/ReTraverser.hpp b/os/ReTraverser.hpp index 241b913..865f2fd 100644 --- a/os/ReTraverser.hpp +++ b/os/ReTraverser.hpp @@ -1,6 +1,6 @@ /* * ReTraverser.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -19,27 +19,6 @@ typedef DIR* FindFileHandle_t; #endif -/** Returns whether a filetime is undefined. - * @param time the filetime to test - * @return true: the given filetime is undefined - */ -inline bool filetimeIsUndefined(ReFileTime_t& time) { -#if defined __linux__ - return time.tv_sec == 0 && time.tv_nsec == 0; -#elif defined __WIN32__ - return time.dwHighDateTime == 0 && time.dwLowDateTime == 0; -#endif -} -/** Sets the filetime to undefined. - * @param time the filetime to clear - */ -inline void setFiletimeUndef(ReFileTime_t& time) { -#if defined __linux__ - time.tv_sec = time.tv_nsec = 0; -#elif defined __WIN32__ - time.dwHighDateTime = time.dwLowDateTime = 0; -#endif -} class ReDirStatus_t { public: @@ -66,7 +45,7 @@ public: public: const ReFileTime_t* accessed(); ReFileSize_t fileSize(); - const char* filetimeAsString(ReByteBuffer& buffer); + const char* filetimeAsString(ReByteArray& buffer); bool findFirst(); bool findNext(); void freeEntry(); @@ -77,23 +56,23 @@ public: bool isRegular(); const ReFileTime_t* modified(); const char* node() const; - const char* rightsAsString(ReByteBuffer& buffer, bool numerical, + const char* rightsAsString(ReByteArray& buffer, bool numerical, int ownerWidth); Type_t type(); char typeAsChar(); public: static const char* filetimeToString(const ReFileTime_t* time, - ReByteBuffer& buffer); + ReByteArray& buffer); static time_t filetimeToTime(const ReFileTime_t* time); #if defined __WIN32__ - static bool getFileOwner(HANDLE handle, const char* file, ReByteBuffer& name, + static bool getFileOwner(HANDLE handle, const char* file, ReByteArray& name, ReLogger* logger = NULL); static bool getPrivilege(const char* privilege, ReLogger* logger); #endif static void timeToFiletime(time_t time, ReFileTime_t& filetime); public: - ReByteBuffer m_path; - ReByteBuffer m_fullName; + ReByteArray m_path; + ReByteArray m_fullName; int m_passNo; ReLogger* m_logger; #ifdef __linux__ @@ -115,7 +94,7 @@ public: public: virtual void deserialize(const uint8_t*& sequence, size_t& length); bool match(ReDirStatus_t& entry); - virtual ReByteBuffer& serialize(ReByteBuffer& sequence); + virtual ReByteArray& serialize(ReByteArray& sequence); public: ReDirStatus_t::Type_t m_types; RePatternList* m_nodePatterns; @@ -150,8 +129,8 @@ public: * at least m_interval seconds */ inline bool isTimeTriggered() { - time_t now = time(NULL); - bool rc = now - m_lastTrace > m_interval; + clock_t now = clock(); + bool rc = (now - m_lastTrace) >= m_interval; if (rc) { m_lastTrace = now; } @@ -161,16 +140,17 @@ public: protected: int m_count; int m_triggerCount; - time_t m_lastTrace; - int m_interval; - time_t m_startTime; + clock_t m_lastTrace; + /// time interval in clocks (sec * CLOCK_PER_SEC) + clock_t m_interval; + clock_t m_startTime; }; class ReDirTreeStatistic { public: ReDirTreeStatistic(); public: - const char* statisticAsString(ReByteBuffer& buffer, bool append = false, + const char* statisticAsString(ReByteArray& buffer, bool append = false, const char* formatFiles = "%8d ", const char* formatSizes = "%12.6f", const char* formatDirs = "%7d "); /** @@ -259,7 +239,7 @@ public: protected: void destroy(); void freeEntry(int level); - bool initEntry(const ReByteBuffer& parent, const char* node, int level); + bool initEntry(const ReByteArray& parent, const char* node, int level); /** * Tests whether a directory should be processed. * @param node the base name of the subdir @@ -274,7 +254,7 @@ protected: int m_minLevel; int m_maxLevel; int m_level; - ReByteBuffer m_base; + ReByteArray m_base; ReDirStatus_t* m_dirs[MAX_ENTRY_STACK_DEPTH]; /// each directory will be passed twice: for all files + for directories only /// 1: depth first 2: breadth first diff --git a/os/reos.hpp b/os/reos.hpp index 030811b..d92d4cd 100644 --- a/os/reos.hpp +++ b/os/reos.hpp @@ -1,6 +1,6 @@ /* * reos.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -25,21 +25,6 @@ #error "unknown os" #endif -/** Returns whether a time is greater (younger) than another. - * @param time1 first operand - * @param time2 second operand - * @return true: time1 > time2 - */ -inline bool operator >(const ReFileTime_t& time1, const ReFileTime_t& time2) { -#if defined __linux__ - return time1.tv_sec > time2.tv_sec - || (time1.tv_sec == time2.tv_sec && time1.tv_nsec > time2.tv_nsec); -#else - return time1.dwHighDateTime > time2.dwHighDateTime - || (time1.dwHighDateTime == time2.dwHighDateTime - && time1.dwLowDateTime > time2.dwLowDateTime); -#endif -} #include "os/ReFileUtils.hpp" #include "os/ReTraverser.hpp" #include "os/ReDirTools.hpp" diff --git a/string/ReMatcher.cpp b/string/ReMatcher.cpp index 55f784e..0e04309 100644 --- a/string/ReMatcher.cpp +++ b/string/ReMatcher.cpp @@ -1,6 +1,6 @@ /* * ReMatcher.cpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -86,7 +86,7 @@ bool ReSimpleMatcher::compile(const char* pattern) { * @param prefix NULL or a introduction */ void ReSimpleMatcher::dump(FILE* fp, const char* prefix) const { - ReByteBuffer buffer; + ReByteArray buffer; if (prefix != NULL) fprintf(fp, "%s\n", prefix); fprintf(fp, "pattern: %s token (%d): %s\n", m_pattern.str(), @@ -103,7 +103,7 @@ void ReSimpleMatcher::dump(FILE* fp, const char* prefix) const { * m_notPattern: the name matches not
* false: otherwise */ -bool ReSimpleMatcher::match(const ReByteBuffer& toTest, ReHit* hit) const { +bool ReSimpleMatcher::match(const ReByteArray& toTest, ReHit* hit) const { bool rc = m_findAll; if (!rc) { do { @@ -153,7 +153,7 @@ bool ReSimpleMatcher::match(const ReByteBuffer& toTest, ReHit* hit) const { * m_notPattern: the name matches not
* false: otherwise */ -bool ReSimpleMatcher::searchTokens(const ReByteBuffer& toTest, int from, int to, +bool ReSimpleMatcher::searchTokens(const ReByteArray& toTest, int from, int to, ReHit* hit, bool greedy) const { bool rc = true; if (!greedy) { @@ -191,7 +191,7 @@ bool ReSimpleMatcher::searchTokens(const ReByteBuffer& toTest, int from, int to, * m_notPattern: the name matches not
* false: otherwise */ -bool ReSimpleMatcher::search(const ReByteBuffer& toTest, ReHit* hit, +bool ReSimpleMatcher::search(const ReByteArray& toTest, ReHit* hit, bool greedy) const { bool rc = m_findAll; if (!rc) { @@ -212,7 +212,7 @@ bool ReSimpleMatcher::search(const ReByteBuffer& toTest, ReHit* hit, * @param prefix NULL or a prefix of the output * @return buffer.str() (for chaining) */ -const char* ReSimpleMatcher::status(ReByteBuffer& buffer, +const char* ReSimpleMatcher::status(ReByteArray& buffer, const char* prefix) const { if (prefix != NULL) buffer.append(prefix); @@ -254,7 +254,7 @@ void RePatternList::destroy() { * @param prefix NULL or a introduction */ void RePatternList::dump(FILE* fp, const char* prefix) const { - ReByteBuffer buffer; + ReByteArray buffer; if (prefix != NULL) fprintf(fp, "%s\n", prefix); for (int ix = 0; ix < m_count; ix++) { @@ -278,7 +278,7 @@ void RePatternList::dump(FILE* fp, const char* prefix) const { * false: no pattern matches or at least one * "not-pattern" matches */ -bool RePatternList::match(const ReByteBuffer& name) { +bool RePatternList::match(const ReByteArray& name) { bool rc = false; int count = m_startNot < 0 ? m_count : m_count - m_startNot + 1; // matches at least one positive pattern? @@ -320,8 +320,8 @@ void RePatternList::set(const char* patterns, bool ignoreCase, patterns++; } int sepLength = strlen(separator); - ReByteBuffer theNotPattern(notPrefix == NULL ? "" : notPrefix); - ReByteBuffer thePatterns(patterns); + ReByteArray theNotPattern(notPrefix == NULL ? "" : notPrefix); + ReByteArray thePatterns(patterns); if (thePatterns.endsWith(separator)) { thePatterns.setLength(thePatterns.length() - sepLength); } @@ -357,8 +357,8 @@ void RePatternList::set(const char* patterns, bool ignoreCase, * ix + 1: otherwise */ int RePatternList::setOne(int index, const char* pattern, size_t patternLength, - bool ignoreCase, const ReByteBuffer& notPrefix) { - ReByteBuffer thePattern(pattern, patternLength); + bool ignoreCase, const ReByteArray& notPrefix) { + ReByteArray thePattern(pattern, patternLength); bool isNotPattern = (notPrefix.length() > 0 && thePattern.startsWith(notPrefix.str(), notPrefix.length())); int start = isNotPattern ? notPrefix.length() : 0; @@ -376,7 +376,7 @@ int RePatternList::setOne(int index, const char* pattern, size_t patternLength, * @param prefix NULL or a prefix of the output * @return buffer.str() (for chaining) */ -const char* RePatternList::status(ReByteBuffer& buffer, +const char* RePatternList::status(ReByteArray& buffer, const char* prefix) const { if (prefix != NULL) buffer.append(prefix); diff --git a/string/ReMatcher.hpp b/string/ReMatcher.hpp index 7bf0467..5b9c00f 100644 --- a/string/ReMatcher.hpp +++ b/string/ReMatcher.hpp @@ -1,6 +1,6 @@ /* * ReMatcher.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want. @@ -42,8 +42,8 @@ public: virtual ~ReMatcher(); public: virtual bool compile(const char* pattern) = 0; - virtual bool match(const ReByteBuffer& toTest, ReHit* hit = NULL) const = 0; - virtual bool search(const ReByteBuffer& toTest, ReHit* hit = NULL, + virtual bool match(const ReByteArray& toTest, ReHit* hit = NULL) const = 0; + virtual bool search(const ReByteArray& toTest, ReHit* hit = NULL, bool greedy = false) const = 0; public: inline bool isIgnoreCase() const { @@ -82,8 +82,8 @@ public: inline bool ignoreCase() const { return m_ignoreCase; } - virtual bool match(const ReByteBuffer& toTest, ReHit* hit = NULL) const; - virtual bool search(const ReByteBuffer& toTest, ReHit* hit = NULL, + virtual bool match(const ReByteArray& toTest, ReHit* hit = NULL) const; + virtual bool search(const ReByteArray& toTest, ReHit* hit = NULL, bool greedy = false) const; /** Sets the mode whether the case will be ignored or not. * @param onNotOff true: the case will be ignored. @@ -91,12 +91,12 @@ public: void setIgnoreCase(bool onNotOff) { m_ignoreCase = onNotOff; } - const char* status(ReByteBuffer& buffer, const char* prefix) const; + const char* status(ReByteArray& buffer, const char* prefix) const; protected: - bool searchTokens(const ReByteBuffer& toTest, int from, int to, ReHit* hit, + bool searchTokens(const ReByteArray& toTest, int from, int to, ReHit* hit, bool greedy) const; private: - ReByteBuffer m_pattern; + ReByteArray m_pattern; ReStringList m_tokens; bool m_ignoreCase; }; @@ -121,13 +121,13 @@ public: bool rc = m_count == 0 ? false : m_patterns[0]->ignoreCase(); return rc; } - bool match(const ReByteBuffer& name); + bool match(const ReByteArray& name); /** @brief Tests whether a string matches the patterns. * @param name the string to Test * @return true: the string matches */ inline bool match(const char* name) { - return match(ReByteBuffer(name)); + return match(ReByteArray(name)); } /** Returns the original pattern string. * @return the string describing the patterns. @@ -137,7 +137,7 @@ public: } void set(const char* patterns, bool ignoreCase = false, const char* separator = NULL, const char* notPrefix = "-"); - const char* status(ReByteBuffer& buffer, const char* prefix) const; + const char* status(ReByteArray& buffer, const char* prefix) const; /** Sets the mode whether the case will be ignored or not. * @param onNotOff true: the case will be ignored. */ @@ -147,9 +147,9 @@ public: } private: int setOne(int index, const char* pattern, size_t patternLength, - bool ignoreCase, const ReByteBuffer& notPrefix); + bool ignoreCase, const ReByteArray& notPrefix); private: - ReByteBuffer m_patternString; + ReByteArray m_patternString; // store of all patterns: the not patterns are at the bottom ReSimpleMatcher** m_patterns; // count of all patterns (including not patterns: diff --git a/string/restring.hpp b/string/restring.hpp index 46a5069..04ac1d3 100644 --- a/string/restring.hpp +++ b/string/restring.hpp @@ -1,6 +1,6 @@ /* * restring.hpp - * + * * License: Public Domain * You can use and modify this file without any restriction. * Do what you want.