ReByteBuffer& ReByteBuffer::append(const ReByteBuffer& source){
return append(source.str(), source.length());
}
+/** @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)<br>
+ * > 6: at least MM:SS.sss<br>
+ * > 9: at least HH:MM:SS.sss<br>
+ * > 12: at least dd:HH:MM:SS.sss<br>
+ * @return <code>buffer</code> (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");
+}
/** Converts a subsequence into an integer.
*
m_capacity = size;
}
}
+/**
+ * @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. <code>0 <= start < m_length</code>
+ * @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 > m_length)
+ setLength(end);
+ memset(m_buffer + start, filler, end - start);
+ }
+ return *this;
+}
/** @brief Checks for the index of the first different byte.
*
* will be filled with this value
* @return *this (for chaining)
*/
-ReByteBuffer& ReByteBuffer::setLengthAndFill(size_t length, Byte filler){
+ReByteBuffer& ReByteBuffer::setLengthAndFillOut(size_t length, Byte filler){
ensureSize(length);
if (length > m_length)
memset(m_buffer + m_length, filler, length - m_length);
ReByteBuffer& append(const Byte* source, size_t length = -1);
ReByteBuffer& append(const ReByteBuffer& source);
ReByteBuffer& appendInt(int number, const char* format = "%d");
+ ReByteBuffer& appendMilliSec(int time, int minLength = 5);
/** @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.
bool rc = buffer.length() == m_length && _memcmp(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.
}
void setDelta(int delta);
ReByteBuffer& setLength(size_t length);
- ReByteBuffer& setLengthAndFill(size_t length, Byte filler = 0);
-
+ 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;
}
while (! found && m_properties.next(position, &name, &properties)){
const char* ptr = properties.str();
- printf("%s\n", ptr);
list.split(properties.str(), '\1');
if (longName == NULL && list.count() > IxShort && shortName == list.strOf(IxShort)[0])
found = true;
*/
ReStringList::~ReStringList() {
}
-/** @brief Appends a string at the end.
+/** @brief Appends a string at the end
*
- * @param source The new string.
+ * @param source the new string
* @param tagOf An item which will stored with the string. It can be retrieved
- * by the same index.This class knows nothing about this.
+ * by the same index.This class knows nothing about this
* @return the instance itself (for chaining)
*/
ReStringList& ReStringList::append(const char* source, Tag tagOf){
}
/** @brief Appends a string at the end.
*
- * @param source The new string.
+ * @param source the new string
* @param tagOf An item which will stored with the string. It can be retrieved
- * by the same index.This class knows nothing about this.
+ * by the same index.This class knows nothing about this
* @return the instance itself (for chaining)
*/
ReStringList& ReStringList::append(const ReByteBuffer& source, Tag tagOf){
- add(-1, source.str(), source.length() + 1, tagOf);
+ int ix = add(-1, source.str(), source.length() + 1, tagOf);
return *this;
}
/** @brief Appends a stringlist at the end.
*
- * @param source The new stringlist.
+ * @param source the new stringlist
* @return the instance itself (for chaining)
*/
ReStringList& ReStringList::append(const ReStringList& source){
for (size_t ii = 0; ii < source.count(); ii++)
- add(-1, source.strOf(ii), source.sizeOf(ii), source.tagOf(ii));
+ add(-1, source.strOf(ii), source.strLengthOf(ii), source.tagOf(ii));
return *this;
}
/** @brief Inserts a string at a given index.
*
* If the index exceeds the length of the array it will be appended.
*
- * @param source The new string.
- * @param tagOf An item which will stored with the string. It can be retrieved by the same index.
- * This class knows nothing about this.
+ * @param source the new string
+ * @param tagOf an item which will stored with the string. It can be retrieved by the same index.
+ * This class knows nothing about this
*/
void ReStringList::insert(Index index, const char* source, Tag tagOf){
add(index, source, strlen(source) + 1, tagOf);
}
/** @brief Replaces an element in the internal array: a string and a tagOf.
*
- * @param index The element with this index will be replaced.
- * @param source The new string of the replaced element.
- * @param tagOf The tagOf of the replace element.
+ * @param index the element with this index will be replaced
+ * @param source the new string of the replaced element
+ * @param tagOf the tagOf of the replace element
*/
void ReStringList::replace(Index index, const char* source, Tag tagOf){
- set(index, source, strlen(source), tagOf);
+ set(index, source, strlen(source) + 1, tagOf);
}
/** @brief Replaces a string in the internal array.
*
* The tagOf of the element remains unchanged.
*
- * @param index The element with this index will be replaced.
- * @param source The new string of the replaced element.
+ * @param index the element with this index will be replaced
+ * @param source the new string of the replaced element
*/
void ReStringList::replaceString(Index index, const char* source){
if (index < count()){
Sequence* seq = getInfo(index);
- set(index, source, strlen(source), seq->m_tag);
+ set(index, source, strlen(source) + 1, seq->m_tag);
}
}
/** @brief Replaces a tagOf in the internal array.
*
* The string of the element remains unchanged.
*
- * @param index The element with this index will be replaced.
- * @param source The new string of the replaced element.
+ * @param index the element with this index will be replaced
+ * @param source the new string of the replaced element
*/
void ReStringList::replaceTag(Index index, Tag tagOf){
if (index < count()){
/** @brief Returns the C string given by an index.
*
- * @param index The index of the wanted string.
+ * @param index the index of the wanted string
*
- * @return NULL: The index is too large.
- * Otherwise: The wanted string.
+ * @return NULL: the index is too large.
+ * Otherwise: the wanted string
*/
const char* ReStringList::strOf(Index index) const{
const char* rc = NULL;
*
* A tagOf is an additional info stored with the string.
*
- * @param index The index of the wanted tagOf.
+ * @param index the index of the wanted tagOf
*
- * @return -1: The index is too large.
- * Otherwise: The wanted tagOf.
+ * @return -1: the index is too large.<br>
+ * Otherwise: the wanted tag
*/
ReSeqArray::Tag ReStringList::tagOf(Index index) const{
Tag rc = -1;
}
/** @brief Returns the length of the byte sequence given by an index.
*
- * @param index The index of the wanted string length.
+ * @param index the index of the wanted string length
*
- * @return 0: The index is too large.
- * Otherwise: The length of the <code>index</code>-th sequence
- * (including the trailing '\0').
+ * @return 0: the index is too large
+ * Otherwise: the length of the <code>index</code>-th sequence
+ * (including the trailing '\0')
*/
size_t ReStringList::sizeOf(Index index) const{
size_t rc = 0;
}
/** @brief Returns the length of the string given by an index.
*
- * @param index The index of the wanted string length.
+ * @param index the index of the wanted string length
*
- * @return 0: The index is too large.
- * Otherwise: The length of the <code>index</code>-th sequence
- * (excluding the trailing '\0').
+ * @return 0: the index is too large.<br>
+ * Otherwise: the length of the <code>index</code>-th sequence
+ * (excluding the trailing '\0')
*/
size_t ReStringList::strLengthOf(Index index) const{
size_t rc = 0;
}
/** @brief Returns the sum of all string lengths stored in the array.
*
- * @return The sum of all string lengths stored in the array.
+ * @return the sum of all string lengths stored in the array
*/
size_t ReStringList::sumOfSizes() const{
size_t rc = 0;
}
/** @brief Returns the sum of all string lengths stored in the array.
*
- * @return The sum of all string lengths stored in the array.
+ * @return the sum of all string lengths stored in the array
*/
size_t ReStringList::sumOfStrLengths() const{
size_t rc = 0;
}
/** @brief Returns the index of a given string in the array.
*
- * @param toFind The string which will be searched.
- * @param ignoreCase true: The search is case insensitive.
- * false: The search is case sensitive.
- * @param start The search starts at this index.
+ * @param toFind the string which will be searched
+ * @param ignoreCase true: the search is case insensitive.<br<
+ * false: the search is case sensitive
+ * @param start the search starts at this index
*
- * @return -1: The string was not found. Otherwise: The index of the string.
+ * @return -1: the string was not found. Otherwise: the index of the string
*/
ReSeqArray::Index ReStringList::indexOf(const char* toFind,
bool ignoreCase, Index start) const{
}
/** Returns the index of the next string starting with a given substring.
*
- * @param start The search starts at this index.
- * @param prefix The substring which will be searched.
- * @param ignoreCase true: The search is case insensitive.
- * false: The search is case sensitive.
+ * @param start the search starts at this index
+ * @param prefix the substring which will be searched
+ * @param ignoreCase true: the search is case insensitive<br>
+ * false: the search is case sensitive
*
- * @return -1: The string was not found. Otherwise: The index of the string.
+ * @return -1: the string was not found. Otherwise: the index of the string
*/
ReSeqArray::Index ReStringList::nextStartingWith(Index start,
const char* prefix, bool ignoreCase){
}
/** @brief Splits a string in an array.
*
- * @param list The string which is splitted.
- * @param separator The separator of the substrings.
- * If '\\n' a preceeding or trailing '\\r' will be ignored too.
- * @param append false: The list will be cleared at the beginning.
- * true: The new content is stored at the end.
+ * @param list the string which is splitted
+ * @param separator the separator of the substrings.<br>
+ * If '\\n' a preceeding or trailing '\\r' will be ignored too
+ * @param append false: the list will be cleared at the beginning.<br>
+ * true: the new content is stored at the end
*/
void ReStringList::split(const char* list, char separator, bool append){
if (! append)
}
/** @brief Joins all string of the array into a string.
*
- * @param separator This string was put between the substrings. May be NULL or "".
- * @param result Out: The result buffer.
+ * @param separator This string was put between the substrings. May be NULL or ""
+ * @param result Out: the result buffer
* @return <code>buffer</code> (for chaining)
*/
ReByteBuffer& ReStringList::join(const char* separator, ReByteBuffer& result) const{
}
/** @brief Writes the stringlist to a file.
*
- * @param filename The name of the file.
- * @param separator This string was put between the substrings. May be NULL.
- * @param mode The file open mode: "w" for truncate and write, "a" for append.
+ * @param filename the name of the file
+ * @param separator this string was put between the substrings. May be NULL
+ * @param mode the file open mode: "w" for truncate and write, "a" for append
*
- * @return true: The file could be opened. false: otherwise.
+ * @return true: the file could be opened. false: otherwise
*/
bool ReStringList::writeToFile(const char* filename,
const char* separator, const char* mode){
}
/** @brief Reads a file into the array.
*
- * Every line is stored as entry of the array.
+ * Each line is stored as an element of the array.
*
- * @param filename The name of the file.
- * @param cutNewline true: The newline characters will be cut.
- * false: The newline characters will be stored.
+ * @param filename the name of the file
+ * @param cutNewline true: the newline characters will be cut<br>
+ * false: the newline characters will be stored
*
- * @return true: The file could be opened. false: otherwise.
+ * @return true: the file could be opened. false: otherwise
*/
bool ReStringList::readFromFile(const char* filename, bool cutNewline){
FILE* fp = fopen(filename, "r");
bool rc = false;
if (fp != NULL){
char line[8096];
-
+ char cc;
while(fgets(line, sizeof line, fp) != NULL){
size_t length = strlen(line);
if (cutNewline){
- while(--length > 0 && (line[length] == '\n' || line[length] == '\r'))
- line[length] = '\n';
+ while(length > 0 && ( (cc = line[length - 1]) == '\n' || cc == '\r'))
+ line[--length] = '\0';
}
add(-1, line, length + 1);
}
}
/** @brief Returns the index of the first different string.
*
- * Compares the internal array of strings with another instance.
+ * Compares the internal array of strings with another instance
*
- * @param toCompare The other instance which will be compared.
+ * @param toCompare the other instance which will be compared
*
- * @return -1: The instances are equal. Otherwise: The index of the first different string.
+ * @return -1: the instances are equal. Otherwise: the index of the first different string
*
*/
int ReStringList::firstDiff(const ReStringList& toCompare) const{
* Two instances are equal when the number of strings are equal
* and the n.th string is equal to the n.th string in the other instance.
*
- * @param toCompare The other instance which will be compared.
+ * @param toCompare the other instance which will be compared
*
- * @return true: The other instance is equal. false: Otherwise.
+ * @return true: the other instance is equal. false: Otherwise
*/
bool ReStringList::equal(const ReStringList& toCompare) const{
bool rc = count() == toCompare.count() && firstDiff(toCompare) == -1;
/**
* This class implements a dynamic array of C strings.
- * <p>With this class it is very simple to break a string into a vector of substrings.</p>
+ * With this class it is very simple to break a string into a vector of substrings.
+ *
* <pre>
* <strong>Example:</strong>
* This example adds a column with a current number to a CSV file (comma separated file):
m_buffer()
{
logF(false, i18n("Start %s"), name);
+ createTestDir();
}
/** @brief Destructor.
list1.readFromFile(name1);
list2.readFromFile(name2);
int ix = list1.firstDiff(list2);
- if (ix < 0){
+ if (ix >= 0){
ReByteBuffer 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"),
- m_sourceFile.str(), lineNo, ix, ixLine,
+ m_sourceFile.str(), lineNo, ix + 1, ixLine,
(int) list1.count() > ix ? list1.strOf(ix) : "",
(int) list2.count() > ix ? list2.strOf(ix) : "",
colMarker(ixLine));
}
+/** @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 <code>buffer.str()</code>: the full filename
+ */
+const char* ReTestUnit::buildFilename(const char* node, ReByteBuffer& buffer){
+ createTestDir();
+ buffer.setLength(0).append(m_tempDir).append(node);
+ return buffer.str();
+}
+
/**
* Returns a string usable as a marker of a given column.
*
*/
const char* ReTestUnit::colMarker(int col){
if (col > 0)
- m_buffer.setLengthAndFill(col - 1, '-');
+ m_buffer.fill('-', 0, col - 1);
else
m_buffer.setLength(0);
m_buffer.append("^", 1);
* the name can be retrieved by <code>getTestDir()</code>.
*/
void ReTestUnit::createTestDir(){
- char name[512];
- if (getenv("TMP") != NULL){
- strcpy(name, getenv("TMP"));
- } else if (getenv("TEMP")){
- strcpy(name, getenv("TEMP"));
- } else {
- strcpy(name, "/tmp/");
+ if (m_tempDir.length() == 0){
+ char name[512];
+ if (getenv("TMP") != NULL){
+ strcpy(name, getenv("TMP"));
+ } else if (getenv("TEMP")){
+ strcpy(name, getenv("TEMP"));
+ } else {
+ strcpy(name, "/tmp/");
+ }
+ char* ptr = name + strlen(name) - 1;
+ if (*ptr != ReStringUtils::pathSeparator())
+ strcpy(ptr + 1, ReStringUtils::pathSeparatorStr());
+ strcat(ptr, "retestunit");
+ strcat(ptr, ReStringUtils::pathSeparatorStr());
+ struct stat info;
+ #ifdef __WIN32__
+ #define ALLPERMS 0
+ #endif
+ if (lstat(name, &info) != 0)
+ _mkdir(name);
+ else{
+ char cmd[512 + 128];
+ _snprintf(cmd, sizeof cmd, "rm -Rf %s*", name);
+ system(cmd);
+ }
+ m_tempDir.set(name, -1);
}
- char* ptr = name + strlen(name) - 1;
- if (*ptr != ReStringUtils::pathSeparator())
- strcpy(ptr + 1, ReStringUtils::pathSeparatorStr());
- strcat(ptr, "retestunit");
- strcat(ptr, ReStringUtils::pathSeparatorStr());
- struct stat info;
-#ifdef __WIN32__
-#define lstat stat
-#define mkdir(name, flags) _mkdir(name)
-#define ALLPERMS 0
+}
+
+/**
+ * @brief Calculates the time since a given start.
+ *
+ * <pre>int64_t start = test.timer();
+ * ...
+ * int duration = test.milliSecSince(start);
+ * </pre>
+ *
+ * @return a time usable for for runtime measurement
+ */
+int ReTestUnit::milliSecSince(int64_t start){
+#if defined __linux__
+ int64_t diff = clock() - start;
+ return diff * 1000 / CLOCKS_PER_SEC;
+#else
+# error "timer not defined"
+#endif
+}
+
+/**
+ * @brief Returns a time value usable for runtime measurement.
+ *
+ * Note: The value is platform dependent. Use with <code>milliSecSince()</code>.
+ * <pre>int64_t start = test.timer();
+ * ...
+ * int duration = test.milliSecSince(start);
+ * </pre>
+ * @return a time usable for for runtime measurement
+ */
+int64_t ReTestUnit::timer(){
+#if defined __linux__
+ return clock();
+#else
+# error "timer not defined"
#endif
- if (lstat(name, &info) != 0)
- _mkdir(name);
- else{
- char cmd[512 + 128];
- _snprintf(cmd, sizeof cmd, "rm -Rf %s*", name);
- system(cmd);
- }
- m_tempDir.set(name, -1);
}
+
/** @brief Returns the temporary directory.
*
* @return the name of a temporary directory
*/
-const char* ReTestUnit::getTestDir(){
+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
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);
void createDir(const char* filename);
void createFile(const char* filename, const char* content);
- void createTestDir();
const char* colMarker(int col);
- const char* getTestDir();
+ const char* testDir();
virtual bool log(bool isError, const char* message);
virtual bool logF(bool isError, const char* format, ...);
+ int milliSecSince(int64_t start);
+ int64_t timer();
+private:
+ void createTestDir();
protected:
int m_errorCount;
ReByteBuffer m_name;
store(value, maxWidth);
} else {
ReByteBuffer buffer;
- buffer.setLengthAndFill(minWidth, ' ');
+ buffer.setLengthAndFillOut(minWidth, ' ');
if (alignRight)
memcpy(buffer.buffer() + minWidth - length, value, length);
else
#include <ctype.h>
#include <assert.h>
#include <stdarg.h>
+#include <limits.h>
#if defined __linux__
# include <regex.h>
# include <unistd.h>
# include <inttypes.h>
-
+# include <fcntl.h>
+typedef u_int64_t uint64_t;
# define _strdup strdup
# define _unlink unlink
# define _strnicmp(s1, s2, n) strncasecmp(s1, s2, n)
# include <direct.h>
# include <windows.h>
# define _memcmp(t,s,n) memcmp(t,s,n)
+# define lstat stat
typedef _int64 int64_t;
typedef unsigned long long uint64_t;
typedef unsigned char uint8_t;
+++ /dev/null
-#include "base/rebase.hpp"
-
-class TestReHashList : public ReTestUnit {
-public:
- TestReHashList() : ReTestUnit("ReHashList", __FILE__){
- run();
- }
-private:
- void run(){
- testBasic();
- testNext();
- }
- void massTest(){
- ReHashList hash();
- ReByteBuffer key, value;
- log(false, "missing masstest");
- }
- void testBasic(){
- ReHashList hash;
- ReByteBuffer key, value;
-
- hash.put("abc", "123");
- checkT(hash.get("abc", -1, value));
- checkEqu("123", value.str());
-
- hash.put("ab", "999");
- checkT(hash.get("ab", -1, value));
- checkEqu("999", value.str());
-
- checkT(hash.get("abc", -1, value));
- checkEqu("123", value.str());
-
- hash.put("abc", "!!!");
- checkT(hash.get("abc", -1, value));
- checkEqu("!!!", value.str());
-
- checkT(hash.get("ab", -1, value));
- checkEqu("999", value.str());
-
- hash.put("abc", "longer");
- checkT(hash.get("abc", -1, value));
- checkEqu("longer", value.str());
-
- checkT(hash.get("ab", -1, value));
- checkEqu("999", value.str());
- }
- void testNext(){
- ReHashList hash;
- hash.put("4", "2");
- hash.put("1", "8");
- hash.put("2", "4");
- hash.put("8", "1");
- int flagsKey = 0;
- int flagsVal = 0;
- ReArrayPosition pos;
- ReByteBuffer key, value;
- while(hash.next(pos, &key, &value)){
- int x = atol(key.buffer());
- int y = atol(value.buffer());
- checkEqu(8, x * y);
- flagsKey += x;
- flagsVal += y;
- }
- checkEqu(15, flagsKey);
- checkEqu(15, flagsVal);
- }
-};
-extern void testReHashList(void);
-
-void testReHashList(void){
- TestReHashList unit;
-}
* cuReByteBuffer.cpp
*
* Created on: 27.11.2010
- * Author: wk
*/
#include "base/rebase.hpp"
class TestReByteBuffer : public ReTestUnit {
}
private:
void run(){
+ testFill();
+ testAppendMilliSec();
testSetDelta();
testFirstDiff();
testCount();
testSplice();
testReplace();
}
+ void testFill(){
+ ReByteBuffer buf;
+ buf.fill('=', 0, 3);
+ checkEqu("===", buf.str());
+ buf.fill('x', 1, 2);
+ checkEqu("=x=", buf.str());
+ }
+ void testAppendMilliSec(){
+ ReByteBuffer buf;
+ checkEqu("5.123", buf.appendMilliSec(5123).str());
+ checkEqu("32:45.789", buf.setLength(0)
+ .appendMilliSec(32*60*1000+45789).str());
+ checkEqu("17:04:06.976", buf.setLength(0)
+ .appendMilliSec(17*3600*1000 + 4*60*1000 + 6976).str());
+ }
void testSetDelta(){
ReByteBuffer buf("abcd");
int maxDelta = 512 * (1 << 10);
checkEqu("123ab", buffer.buffer());
checkEqu(5u, buffer.length());
- buffer.setLengthAndFill(8, 'x');
+ buffer.setLengthAndFillOut(8, 'x');
checkEqu("123abxxx", buffer.buffer());
checkEqu(8u, buffer.length());
buffer.setLength(3);
checkEqu("123", buffer.buffer());
checkEqu(3u, buffer.length());
- buffer.setLengthAndFill(511, 'y');
- buffer.setLengthAndFill(512, 'z');
+ buffer.setLengthAndFillOut(511, 'y');
+ buffer.setLengthAndFillOut(512, 'z');
checkEqu("yyz", buffer.buffer() + 509);
checkEqu(521u, buffer.capacity());
checkEqu("01234", buf1.str());
checkEqu(5u, buf1.length());
- buf1.setLengthAndFill(8, 'X');
+ buf1.setLengthAndFillOut(8, 'X');
checkEqu("01234XXX", buf1.str());
checkEqu(8u, buf1.length());
checkEqu(2000u, buf1.capacity());
}
private:
void run(){
- createTestDir();
ReByteBuffer dir;
- dir.set(getTestDir(), -1);
+ dir.set(testDir(), -1);
ReByteBuffer file1 = dir;
file1.append("abc.1.txt", -1);
createFile(file1.str(), "abc1");
--- /dev/null
+#include "base/rebase.hpp"
+#include "math/remath.hpp"
+
+class TestReHashList : public ReTestUnit {
+public:
+ TestReHashList() : ReTestUnit("ReHashList", __FILE__){
+ run();
+ }
+private:
+ void run(){
+ testBasic();
+ testNext();
+ }
+ void massTest(){
+ ReCongruentialGenerator rand;
+ ReHashList hash();
+ ReByteBuffer key, value;
+ log(false, "missing masstest");
+ }
+ void testBasic(){
+ ReHashList hash;
+ ReByteBuffer key, value;
+
+ hash.put("abc", "123");
+ checkT(hash.get("abc", -1, value));
+ checkEqu("123", value.str());
+
+ hash.put("ab", "999");
+ checkT(hash.get("ab", -1, value));
+ checkEqu("999", value.str());
+
+ checkT(hash.get("abc", -1, value));
+ checkEqu("123", value.str());
+
+ hash.put("abc", "!!!");
+ checkT(hash.get("abc", -1, value));
+ checkEqu("!!!", value.str());
+
+ checkT(hash.get("ab", -1, value));
+ checkEqu("999", value.str());
+
+ hash.put("abc", "longer");
+ checkT(hash.get("abc", -1, value));
+ checkEqu("longer", value.str());
+
+ checkT(hash.get("ab", -1, value));
+ checkEqu("999", value.str());
+ }
+ void testNext(){
+ ReHashList hash;
+ hash.put("4", "2");
+ hash.put("1", "8");
+ hash.put("2", "4");
+ hash.put("8", "1");
+ int flagsKey = 0;
+ int flagsVal = 0;
+ ReArrayPosition pos;
+ ReByteBuffer key, value;
+ while(hash.next(pos, &key, &value)){
+ int x = atol(key.buffer());
+ int y = atol(value.buffer());
+ checkEqu(8, x * y);
+ flagsKey += x;
+ flagsVal += y;
+ }
+ checkEqu(15, flagsKey);
+ checkEqu(15, flagsVal);
+ }
+};
+extern void testReHashList(void);
+
+void testReHashList(void){
+ TestReHashList unit;
+}
} catch (ReOptionException& exc) {
checkEqu("Unknown option: v", exc.getMessage());
}
+ }
+ void createExpectedShortHelp(const char* filename){
+ createFile(filename,
+"test <opts> <args>This tests the usage of ReProgramArg\n"
+"This tests the usage of ReProgramArg\n"
+"\n"
+"<options>:\n"
+"-B or --boolval2\n"
+" This is the 2nd boolean arg\n"
+"-x or --boolval3\n"
+" This is the 3rd boolean arg\n"
+"-Y or --boolval4\n"
+" This is the 4th boolean arg\n"
+"-S[<string>] or --estring=[<string>] Default value: empty\n"
+" This string may be empty\n"
+"-U[<string>] or --estring2=[<string>] Default value: undef2\n"
+" This 2nd string may be empty\n"
+"-i<number> or --intval=<number> Default value: 9\n"
+" This is an integer arg\n"
+"-I<number> or --intval=<number> Default value: 1000\n"
+" This is the 2nd integer arg\n"
+"-s<not empty string> or --string=<not empty string> Default value: 'abc'\n"
+" This string must be non empty\n"
+"-u<not empty string> or --string2=<not empty string> Default value: 'undef'\n"
+" This 2nd string must be non empty\n"
+"Example(s):\n"
+"$0 -b+ -B- file dir\ttest of an exampl+++ Not really an error!\n"
+"\ttest of an exampl+++ Not really an error!\n"
+"+++ Not really an error!\n"
+ );
}
void testShort(){
ReProgramArgs args("test <opts> <args>\nThis tests the usage of ReProgramArgs",
checkEqu("arg1", args.getArg(0));
checkEqu("arg2", args.getArg(1));
checkEqu(2, args.getArgCount());
-
- args.help("Not really an error!", false, stdout);
+ ReByteBuffer 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;
+ buildFilename("help.exp.txt", fnExpected);
+ createExpectedShortHelp(fnExpected.str());
+ checkFileEqu(fnExpected.str(), fn.str());
+ }
}
void testSetUsage(){
class MyArgs : public ReProgramArgs {
args.setUsage(usage);
checkEqu("x1", args.usage().strOf(0));
checkEqu("x2", args.usage().strOf(1));
+ }
+ void createExpectedLongHelp(const char* filename){
+ createFile(filename,
+"test <opts> <argsThis tests the usage of ReProgramArg\n"
+"This tests the usage of ReProgramArg\n"
+"\n"
+"<options>:\n"
+"--boolval2\n"
+" This is the 2nd boolean arg\n"
+"-x or --boolval3\n"
+" This is the 3rd boolean arg\n"
+"--boolval4\n"
+" This is the 3rd boolean arg\n"
+"--estring=[<string>] Default value: empty\n"
+" This string may be empty\n"
+"-U[<string>] or --estring2=[<string>] Default value: undef2\n"
+" This 2nd string may be empty\n"
+"-V[<string>] or --estring3=[<string>] Default value: undef3\n"
+" This 3thrd string may be empty\n"
+"-i<number> or --intval=<number> Default value: 9\n"
+" This is an integer arg\n"
+"-s<not empty string> or --string=<not empty string> Default value: 'abc'\n"
+" This string must be non empty\n"
+"Example(s):\n"
+"test -intval=10 --boolval=t\n"
+ );
}
void testLong(){
const char* call[] = {
checkEqu("arg1", args.getArg(0));
checkEqu("arg2", args.getArg(1));
checkEqu(2, args.getArgCount());
- args.help(NULL, false, stdout);
+ ReByteBuffer fn;
+ FILE* fp = fopen(buildFilename("help.tmp.txt", fn), "w");
+ checkT(fp != NULL);
+ if (fp){
+ args.help(NULL, false, fp);
+ fclose(fp);
+ ReByteBuffer fnExpected;
+ createExpectedLongHelp(buildFilename("help.exp.txt", fnExpected));
+ checkFileEqu(fnExpected.str(), fn.str());
+ }
}
};
extern void testReProgramArgs(void);
--- /dev/null
+#include "base/rebase.hpp"
+#include "math/remath.hpp"
+
+class TestReRandomizer : public ReTestUnit {
+public:
+ TestReRandomizer() :
+ ReTestUnit("ReRandomizer", __FILE__)
+ {
+ run();
+ }
+private:
+ void run(){
+ testNextInt64Repeater();
+ testNextInt64();
+
+ }
+ void testNextInt64Repeater(){
+ ReCongruentialGenerator rand;
+ const int MAX = 16;
+ time_t start = time(NULL);
+ ReRandomizer::seed_t field[MAX];
+ for (int ix = 0; ix < MAX; ix++)
+ field[ix] = rand.nextInt64();
+ rand.reset();
+ for (int ix = 0; ix < MAX; ix++){
+ checkEqu(field[ix], rand.nextInt64(ix + 10));
+ }
+ }
+ void testNextInt64(){
+ ReCongruentialGenerator rand;
+ const int MAX = 16;
+ time_t start = time(NULL);
+ ReRandomizer::seed_t field[MAX];
+ for (int ix = 0; ix < MAX; ix++)
+ field[ix] = rand.nextInt64(ix + 10);
+ rand.reset();
+ for (int ix = 0; ix < MAX; ix++){
+ checkEqu(field[ix], rand.nextInt64(ix + 10));
+ checkT(field[ix] >= 0 && field[ix] < ix + 10);
+ }
+ time_t diff = time(NULL) - start;
+ }
+};
+extern void testReRandomizer(void);
+
+void testReRandomizer(void){
+ TestReRandomizer unit;
+}
+
}
void testFile(){
if (true){
- createTestDir();
ReByteBuffer file;
- file.set(getTestDir(), -1).append("abc.csv", -1);
+ buildFilename("abc.csv", file);
ReStringList list;
const char* str = "1;abc;xyz;4;;99";
ReStringList list2;
list2.readFromFile(file.str(), true);
+ checkEqu("1", list2.strOf(0));
+ checkEqu("abc", list2.strOf(1));
+ checkEqu("xyz", list2.strOf(2));
+ checkEqu("4", list2.strOf(3));
+ checkEqu("", list2.strOf(4));
+ checkEqu("99", list2.strOf(5));
+ list2.clear();
+ list2.readFromFile(file.str(), false);
+ checkEqu("1", list2.strOf(0));
+ checkEqu("abc", list2.strOf(1));
+ checkEqu("xyz", list2.strOf(2));
+ checkEqu("4", list2.strOf(3));
+ checkEqu("", list2.strOf(4));
+ checkEqu("99", list2.strOf(5));
checkEqu(-1, list2.firstDiff(list2));
}
}
private:
void run(){
+ testFileNameInTestDir();
+ testTimer();
testBasic();
testColMarker();
testEquFiles();
}
+ void testFileNameInTestDir(){
+ ReByteBuffer fn;
+ const char* name = buildFilename("xyz.txt", fn);
+ checkEqu(name, fn.str());
+ checkT(fn.endsWith("xyz.txt"));
+ checkT(fn.startsWith(testDir()));
+ }
+ void testTimer(){
+ int64_t start = timer();
+ // busy wait (clock() measures only busy times):
+ time_t to = time(NULL) + 1;
+ while(time(NULL) <= to){
+ // do nothing
+ }
+ int duration = milliSecSince(start);
+ checkT(duration >= 1000 && duration < 3000);
+ }
void testBasic(){
checkT(true);
checkF(false);
log(false, "end of 8 expected errors");
}
void testColMarker(){
- checkEqu("--^", colMarker(2));
+ checkEqu("-^", colMarker(2));
checkEqu("^", colMarker(0));
}
void testEquFiles(){
- createTestDir();
- ReByteBuffer dir = getTestDir();
- ReByteBuffer fn1(dir);
- fn1.append("x1.txt");
- ReByteBuffer fn2(dir);
- fn2.append("x2.txt");
+ ReByteBuffer fn1;
+ buildFilename("x1.txt", fn1);
+ ReByteBuffer fn2;
+ buildFilename("x2.txt", fn2);
createFile(fn1.str(), "123\nline 2");
createFile(fn2.str(), "123\nline 2");
checkFileEqu(fn1.str(), fn2.str());
class TestReTraverser : public ReTestUnit {
public:
TestReTraverser() : ReTestUnit("ReTraverser", __FILE__){
- createTestDir();
- m_base = getTestDir();
+ m_base = testDir();
m_base.append("traverser").append(ReTraverser::m_separatorStr, -1);
_mkdir(m_base.str());
run();
void testCopyFile(){
ReByteBuffer src(m_base);
src.append("dir1/dir1_2/dir1_2_1/x1.txt");
- ReByteBuffer trg(getTestDir());
+ ReByteBuffer trg(testDir());
trg.append("copy_x1.txt");
ReByteBuffer buffer;
buffer.ensureSize(5);
testBasic();
}
void testBasic(){
- createTestDir();
ReByteBuffer fn;
- fn.append(getTestDir(), -1).append("reconfigfile.cfg", -1);
+ 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");
ReConfigFile config(fn.str());
checkT(config.isValid());
#endif
void testBase(){
- extern void testReLogger(void);
- testReLogger();
- testReLogger();
extern void testReTestUnit();
testReTestUnit();
}
void testOs(){
void testReTraverser();
- testReTraverser();
+ //testReTraverser();
+}
+void testMath(){
+ extern void testReRandomizer();
+ testReRandomizer();
}
void testAll(){
try
{
- testOs();
testBase();
+ testMath();
+ testOs();
testString();
} catch (ReException e){
fprintf(stderr, "testBase.cpp: unexpected exception: %s\n", e.getMessage());
* Author: wk
*/
-#include "assert.h"
-#include "memory.h"
-#include "limits.h"
-#include "math.h"
-#include "remath.hpp"
+
+#include "base/rebase.hpp"
+#include "math/remath.hpp"
static bool s_trace = false;
/**
* @brief Constructor.
*/
-ReRandomizer::ReRandomizer(){
+ReRandomizer::ReRandomizer()
+{
}
/**
* @brief Destructor.
return rc;
}
+/**
+ * @brief Returns a random number which is not predictable.
+ *
+ * @return a number which is not predictable
+ */
+ReRandomizer::seed_t ReRandomizer::nearTrueRandom(){
+ time_t random = time(NULL);
+ static int dummy = 5;
+ void* dummy2 = malloc(1);
+ free(dummy2);
+ seed_t rc = (((seed_t) random) << 31) + ((seed_t) &dummy << 9) + (-random ^ 0x20111958)
+ ^ (seed_t(dummy2));
+#if defined __linux__
+ int fh = open("/dev/urandom", O_RDONLY);
+ char buffer[sizeof (seed_t)];
+ size_t length = 0;
+
+ if (read(fh, buffer, sizeof buffer) > 0)
+ rc ^= *(seed_t*) buffer;
+ close(fh);
+#else
+#error "no true random"
+#endif
+}
/**
* @brief Returns the next random integer.
*
*
+ * @param maxValue The maximum of the result (including).
* @param minValue The minimum of the result.
+ *
+ * @return The next seed.
+ */
+int ReRandomizer::nextInt(int maxValue, int minValue){
+ int rc;
+ if (minValue > maxValue){
+ rc = minValue;
+ minValue = maxValue;
+ maxValue = rc;
+ }
+ seed_t seed = nextSeed();
+ if (minValue == maxValue)
+ rc = minValue;
+ else
+ // we calculate in 64 bit:
+ rc = (int) (minValue + seed % (maxValue - minValue + 1));
+ if (s_trace){
+ static int count = 0;
+ printf ("%c %8x ", count++ % 4 == 0 ? '\n' : ' ', rc);
+ }
+ return rc;
+}
+
+/**
+ * @brief Returns the next random integer.
+ *
+ *
* @param maxValue The maximum of the result (including).
+ * @param minValue The minimum of the result.
*
* @return The next seed.
*/
-int ReRandomizer::nextInt(int minValue, int maxValue){
+int64_t ReRandomizer::nextInt64(int64_t maxValue, int64_t minValue){
int rc;
if (minValue > maxValue){
rc = minValue;
seed_t seed = nextSeed();
if (minValue == maxValue)
rc = minValue;
- else if (minValue == 0 && maxValue == INT_MAX)
+ else if (minValue == 0 && maxValue == LLONG_MAX)
rc = abs(seed);
- else if (unsigned(maxValue - minValue) < INT_MAX)
+ else if (uint64_t(maxValue - minValue) < LLONG_MAX)
+ // no signed int64 overflow:
rc = minValue + seed % (maxValue - minValue + 1);
else {
+ // int64 overflow: we need a higher precision:
double rc2 = minValue + fmod((double) seed, maxValue - minValue);
rc = (int) rc2;
}
if (s_trace){
static int count = 0;
- printf ("%c %8x ", count++ % 4 == 0 ? '\n' : ' ', rc);
+ printf ("%c %16llx ", count++ % 4 == 0 ? '\n' : ' ', rc);
}
return rc;
}
buffer[len] = '\0';
return buffer;
}
+
/**
* @brief Builds a random permutation of an array.
*
ReCongruentialGenerator::ReCongruentialGenerator() :
m_seed(0x4711),
m_factor(2631),
- m_increment(0x9)
+ m_increment(0x9),
+ m_lastSetSeed(0x4711)
{
}
/**
*
* @return The current factor.
*/
-ReRandomizer::seed_t ReCongruentialGenerator::getFactor() const
+ReRandomizer::seed_t ReCongruentialGenerator::factor() const
{
return m_factor;
}
*
* @return The current increment.
*/
-ReRandomizer::seed_t ReCongruentialGenerator::getIncrement() const
+ReRandomizer::seed_t ReCongruentialGenerator::increment() const
{
return m_increment;
}
*
* @return The current seed.
*/
-ReRandomizer::seed_t ReCongruentialGenerator::getSeed() const
+ReRandomizer::seed_t ReCongruentialGenerator::seed() const
{
return m_seed;
}
+/**
+ * @brief Sets the seed to the value given by the last <code>setSeed()</code>.
+ *
+ * Note: The constructor does the first <code>setSeed()</code>.
+ */
+void ReCongruentialGenerator::reset(){
+ m_seed = m_lastSetSeed;
+}
+
/**
* Sets the factor.
*
*/
void ReCongruentialGenerator::setSeed(seed_t seed)
{
- this->m_seed = seed;
+ m_seed = m_lastSetSeed = seed;
if (s_trace)
- printf(" Seed: %x ", seed);
+ printf(" Seed: %llx ", seed);
}
#ifndef RANDOMIZER_H_
#define RANDOMIZER_H_
-#include "stdio.h"
-#include "limits.h"
/**
* This implements an abstract base class for random generators.
*/
class ReRandomizer {
public:
- enum { CHARRANGE = 128 - ' ' };
- typedef unsigned int seed_t;
+ enum { START_RANGE = ' ',
+ CHARRANGE = 128 - START_RANGE };
+ typedef uint64_t seed_t;
public:
ReRandomizer();
virtual ~ReRandomizer();
public:
- virtual int nextInt(int minValue = 0, int maxValue = INT_MAX);
- void shuffle(void* array, size_t length, size_t elemSize);
+ virtual int nextInt(int maxValue = INT_MAX, int minValue = 0);
+ virtual int64_t nextInt64(int64_t maxValue = LLONG_MAX, int64_t minValue = 0);
char nextChar();
char* nextString(char* buffer, int maxLength = 80, int minLength = 0);
+ void shuffle(void* array, size_t length, size_t elemSize);
+ /** @brief Sets the instance to a defined start state.
+ */
+ virtual void reset() = 0;
protected:
+ /** @brief Returns the next pseudo random number.
+ * @return the next pseudo random number
+ * */
virtual seed_t nextSeed() = 0;
+public:
+ seed_t nearTrueRandom();
};
/**
* Implements a simple random generator.
* A linear congruential generator produces the next value using this formula:
* seed = (seed * factor + increment) % modulus
- * In this implementation modulus is 2**32.
+ * In this implementation modulus is 2**64.
*/
class ReCongruentialGenerator : public ReRandomizer {
public:
ReCongruentialGenerator();
virtual ~ReCongruentialGenerator();
public:
- seed_t getFactor() const;
- seed_t getIncrement() const;
+ seed_t factor() const;
+ seed_t increment() const;
+ seed_t seed() const;
+ virtual void reset();
void setFactor(seed_t factor);
void setIncrement(seed_t increment);
- seed_t getSeed() const;
void setSeed(seed_t m_seed);
private:
virtual seed_t nextSeed();
seed_t m_seed;
seed_t m_factor;
seed_t m_increment;
+ seed_t m_lastSetSeed;
};
#endif /* RANDOMIZER_H_ */
#ifndef REMATH_HPP_
#define REMATH_HPP_
+#include "math.h"
-#include "ReObfuscator.hpp"
-#include "ReRandomizer.hpp"
+#include "math/ReObfuscator.hpp"
+#include "math/ReRandomizer.hpp"
#endif /* REMATH_HPP_ */