From 046c80278c4468fd28c57794e81fb56390d3e16b Mon Sep 17 00:00:00 2001 From: hama Date: Sun, 23 Aug 2015 22:57:37 +0200 Subject: [PATCH] ReFileUtils, ReSettings * ReFileUtils extracted from ReFile * Storage moved to gui/ReSettings --- appl/reditor/mainwindow.cpp | 4 +- appl/reditor/project.cpp | 2 +- appl/reditor/reditor.hpp | 1 - appl/reditor/reditor.pro | 24 +- appl/reditor/storage.cpp | 160 -------- appl/reditor/workspace.cpp | 8 +- base/ReContainer.cpp | 12 +- base/ReFile.cpp | 62 +++- base/ReFile.hpp | 3 +- base/ReFileUtils.cpp | 196 ++++++++++ base/ReFileUtils.hpp | 41 ++ .../{ReQStringUtil.cpp => ReQStringUtils.cpp} | 36 +- .../{ReQStringUtil.hpp => ReQStringUtils.hpp} | 2 +- base/{ReStringUtil.cpp => ReStringUtils.cpp} | 40 +- base/{ReStringUtil.hpp => ReStringUtils.hpp} | 2 +- base/ReTest.cpp | 8 +- base/rebase.hpp | 5 +- cunit/allTests.cpp | 6 +- cunit/cuReConfig.cpp | 4 +- cunit/cuReFile.cpp | 18 +- cunit/cuReFileUtils.cpp | 94 +++++ cunit/cuReQStringUtil.cpp | 202 ---------- cunit/cuReQStringUtils.cpp | 202 ++++++++++ cunit/cuReSettings.cpp | 95 +++++ cunit/cuReStringUtil.cpp | 206 ----------- cunit/cuReStringUtils.cpp | 206 +++++++++++ cunit/cuReWriter.cpp | 2 +- cunit/cunit.pro | 14 +- gui/ReSettings.cpp | 349 ++++++++++++++++++ .../reditor/storage.hpp => gui/ReSettings.hpp | 44 ++- gui/regui.hpp | 1 + remodules.hpp | 13 +- 32 files changed, 1374 insertions(+), 688 deletions(-) delete mode 100644 appl/reditor/storage.cpp create mode 100644 base/ReFileUtils.cpp create mode 100644 base/ReFileUtils.hpp rename base/{ReQStringUtil.cpp => ReQStringUtils.cpp} (94%) rename base/{ReQStringUtil.hpp => ReQStringUtils.hpp} (99%) rename base/{ReStringUtil.cpp => ReStringUtils.cpp} (90%) rename base/{ReStringUtil.hpp => ReStringUtils.hpp} (98%) create mode 100644 cunit/cuReFileUtils.cpp delete mode 100644 cunit/cuReQStringUtil.cpp create mode 100644 cunit/cuReQStringUtils.cpp create mode 100644 cunit/cuReSettings.cpp delete mode 100644 cunit/cuReStringUtil.cpp create mode 100644 cunit/cuReStringUtils.cpp create mode 100644 gui/ReSettings.cpp rename appl/reditor/storage.hpp => gui/ReSettings.hpp (56%) diff --git a/appl/reditor/mainwindow.cpp b/appl/reditor/mainwindow.cpp index 9a84764..341dd7f 100644 --- a/appl/reditor/mainwindow.cpp +++ b/appl/reditor/mainwindow.cpp @@ -114,11 +114,11 @@ ReLogger* MainWindow::logger() const { * * @return the current workspace */ -Storage* MainWindow::project() const { +ReSettings* MainWindow::project() const { return m_project; } -Storage* MainWindow::workspace() const { +ReSettings* MainWindow::workspace() const { return m_workspace; } diff --git a/appl/reditor/project.cpp b/appl/reditor/project.cpp index 314cb1f..52629d8 100644 --- a/appl/reditor/project.cpp +++ b/appl/reditor/project.cpp @@ -18,6 +18,6 @@ * @param logger the logger */ Project::Project(const QString& path, ReLogger* logger) : - Storage(path, "proj", logger) { + ReSettings(path, ".reditor.proj", logger) { } diff --git a/appl/reditor/reditor.hpp b/appl/reditor/reditor.hpp index 4d083d1..2088b69 100644 --- a/appl/reditor/reditor.hpp +++ b/appl/reditor/reditor.hpp @@ -13,7 +13,6 @@ #define REDITOR_HPP #include "base/rebase.hpp" #include "gui/regui.hpp" -#include "storage.hpp" #include "workspace.hpp" #include "project.hpp" #include "mainwindow.hpp" diff --git a/appl/reditor/reditor.pro b/appl/reditor/reditor.pro index 22e1ff5..ede1294 100644 --- a/appl/reditor/reditor.pro +++ b/appl/reditor/reditor.pro @@ -13,32 +13,34 @@ TEMPLATE = app INCLUDEPATH += ../.. -SOURCES += main.cpp\ +SOURCES += \ ../../gui/ReEdit.cpp \ ../../gui/ReStateStorage.cpp \ + ../../gui/ReStorage.cpp \ ../../base/ReFile.cpp \ mainwindow.cpp \ ../../base/ReLogger.cpp \ - ../../base/ReQStringUtil.cpp \ + ../../base/ReQStringUtils.cpp \ + ../../base/ReFileUtils.cpp \ ../../base/ReException.cpp \ projectselection.cpp \ - workspace.cpp \ - project.cpp \ - storage.cpp + workspace.cpp \ + project.cpp \ + main.cpp HEADERS += mainwindow.hpp \ ../../base/rebase.hpp \ ../../gui/regui.hpp \ ../../gui/ReEdit.hpp \ - ../../base/ReStringUtil.hpp \ - ../../base/ReQStringUtil.hpp \ + ../../base/ReStringUtils.hpp \ + ../../base/ReQStringUtils.hpp \ ../../base/ReException.hpp \ projectselection.hpp \ - workspace.hpp \ - project.hpp \ - reditor.hpp \ - storage.hpp + workspace.hpp \ + project.hpp \ + reditor.hpp \ + storage.hpp FORMS += mainwindow.ui \ projectselection.ui diff --git a/appl/reditor/storage.cpp b/appl/reditor/storage.cpp deleted file mode 100644 index f13c302..0000000 --- a/appl/reditor/storage.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* - * storage.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 "reditor.hpp" - -enum { - LOC_BOOL_VALUE_1 = LOC_FIRST_OF(LOC_STORAGE), // 11701 - LOC_BOOL_VALUE_2, // 11702 - LOC_INT_VALUE_1, // 11703 - LOC_INT_VALUE_2, // 11704 - LOC_STRING_VALUE_1, // 11705 - LOC_STRING_VALUE_2, // 11706 -}; - -/** - * Constructor. - * - * @param path the parent directory for the storage files - * @param prefix type of the storage: "proj" or "ws" (workspace) - */ -Storage::Storage(const QString& path, const QString prefix, ReLogger* logger) : - m_path(path), - m_fileHistory(path + OS_SEPARATOR + ".reditor." + prefix + ".history"), - m_fileSettings( - path + OS_SEPARATOR + ".reditor." + prefix + ".settings"), - m_settings(), - m_chapters(), - m_logger(logger) { - -} - -/* - * Adds an entry to a history item at the first position. - * - * The entry will removed from the other positions. - * - * @param key the key in the map - * @param value the value to add - * @param separator separates the entries in the history item - * @param maxEntries the maximal count of entries in the history item.
- * If the number exceeds the last entries will be removed - * @param form the prefix of the key. If NULL the current form will be taken - */ -void Storage::addHistoryEntry(const char* key, const QString& value, - char separator, int maxEntries) { - ReStateStorage store(m_fileHistory); - store.addHistoryEntry(key, value, separator, maxEntries); - store.close(); - store.flushMap(); -} - -/** - * Returns the value of a boolean property. - * - * @param name the name of the property - * @return the value of the property - */ -bool Storage::boolValue(const char* name) { - bool rc = false; - Property* property = m_settings.value(name, NULL); - if (property == NULL) - m_logger->logv(LOG_ERROR, LOC_BOOL_VALUE_1, "missing bool property %s", - name); - else if (property->m_type != PT_BOOL) - m_logger->logv(LOG_ERROR, LOC_BOOL_VALUE_2, "not a bool property %s", - name); - else - rc = !property->m_value.isEmpty(); - return rc; -} -/** - * Returns a history item as a list. - * - * @param key key of the history item - * @param list OUT: the list is filled with the history entries - * @param form a common prefix of the key. If NULL the current form is used - * @return list (for chaining) - */ -QStringList&Storage::historyAsList(const char* key, QStringList& list, - const char* form) { - ReStateStorage store(m_fileHistory); - QStringList& rc = store.historyAsList(key, list, form); - store.close(); - return rc; -} - -/** - * Returns the value of an integer property. - * - * @param name the name of the property - * @return the value of the property - */ -int Storage::intValue(const char* name) { - int rc = 0; - Property* property = m_settings.value(name, NULL); - if (property == NULL) - m_logger->logv(LOG_ERROR, LOC_INT_VALUE_1, "missing int property %s", - name); - else if (property->m_type != PT_INT) - m_logger->logv(LOG_ERROR, LOC_INT_VALUE_2, "not a int property %s", - name); - else - rc = property->m_value.toInt(); - return rc; -} - -/** - * Returns the directory containing the configuration data. - * - * @return the name of the storage's directory - */ -QString Storage::path() const { - return m_path; -} - -/** - * Returns the value of a string property. - * - * @param name the name of the property - * @return the value of the property - */ -QString Storage::stringValue(const char* name) { - QString rc = ""; - Property* property = m_settings.value(name, NULL); - if (property == NULL) - m_logger->logv(LOG_ERROR, LOC_STRING_VALUE_1, - "missing string property %s", name); - else if (property->m_type != PT_STRING) - m_logger->logv(LOG_ERROR, LOC_STRING_VALUE_2, - "not a string property %s", name); - else - rc = property->m_value; - return rc; -} - -/** - * Inserts a property. - * - * @param property the property to insert - */ -void Storage::insertProperty(Property* property) { - m_settings.insert(property->m_name, property); - QByteArray chapter(property->m_name); - int ix = chapter.lastIndexOf('.'); - chapter = chapter.left(ix); - QList* list = m_chapters.value(chapter, NULL); - if (list == NULL) { - m_chapters.insert(chapter, list = new QList()); - } - list->append(property); -} - diff --git a/appl/reditor/workspace.cpp b/appl/reditor/workspace.cpp index 64d54a3..5b5c64e 100644 --- a/appl/reditor/workspace.cpp +++ b/appl/reditor/workspace.cpp @@ -18,19 +18,19 @@ * @param logger the logger */ Workspace::Workspace(const QString& path, ReLogger* logger) : - Storage(path, "ws", logger) { + ReSettings(path, ".reditor.ws", logger) { insertProperty( - new Property("editor.tabwidth", QObject::tr("Tabulator width"), + new ReProperty("editor.tabwidth", QObject::tr("Tabulator width"), QObject::tr("Maximal length of the gap displaying a tabulator"), "4", PT_INT, "[1,16]")); insertProperty( - new Property("history.max_projects", + new ReProperty("history.max_projects", QObject::tr("Maximal project entries"), QObject::tr( "Maximal number of projects in the 'last opened projects'"), "20", PT_INT, "[1,100]")); insertProperty( - new Property("history.max_files", QObject::tr("Maximal file entries"), + new ReProperty("history.max_files", QObject::tr("Maximal file entries"), QObject::tr("Maximal number of files in the 'last opened files'"), "20", PT_INT, "[1,100]")); } diff --git a/base/ReContainer.cpp b/base/ReContainer.cpp index 84ec460..81a44c6 100644 --- a/base/ReContainer.cpp +++ b/base/ReContainer.cpp @@ -396,7 +396,7 @@ QByteArray ReContainer::dump(const char* title, int maxBags, QByteArray rc; rc.reserve(64000); rc.append("=== ").append(title).append('\n'); - rc.append("Bags: ").append(ReStringUtil::toNumber(m_countBags)); + rc.append("Bags: ").append(ReStringUtils::toNumber(m_countBags)); rc.append(" Types: ").append(m_typeList).append('\n'); // save the current state: int safeIxBag = m_ixBag; @@ -408,7 +408,7 @@ QByteArray ReContainer::dump(const char* title, int maxBags, if (maxBags > m_countBags) maxBags = m_countBags; for (int ixBag = 0; ixBag < maxBags; ixBag++) { - rc.append("--- bag ").append(ReStringUtil::toNumber(ixBag)).append( + rc.append("--- bag ").append(ReStringUtils::toNumber(ixBag)).append( ":\n"); nextBag(); QByteArray item; @@ -421,9 +421,9 @@ QByteArray ReContainer::dump(const char* title, int maxBags, break; case TAG_INT: iValue = nextInt(); - rc.append(" i: ").append(ReStringUtil::toNumber(iValue)).append( + rc.append(" i: ").append(ReStringUtils::toNumber(iValue)).append( " / "); - rc.append(ReStringUtil::toNumber(iValue, "%x")).append( + rc.append(ReStringUtils::toNumber(iValue, "%x")).append( separatorItems); break; case TAG_STRING: @@ -437,11 +437,11 @@ QByteArray ReContainer::dump(const char* title, int maxBags, case TAG_DATA4G: nextData(item, false); rc.append(' ').append((char) currentType).append(": ["); - rc.append(ReStringUtil::toNumber(item.length())).append("] "); + rc.append(ReStringUtils::toNumber(item.length())).append("] "); maxLength = item.length() < maxBlobLength ? item.length() : maxBlobLength; - rc.append(ReStringUtil::hexDump(item.data(), maxLength, 16)) + rc.append(ReStringUtils::hexDump(item.data(), maxLength, 16)) .append(separatorItems); break; default: diff --git a/base/ReFile.cpp b/base/ReFile.cpp index 31abc84..dc04fed 100644 --- a/base/ReFile.cpp +++ b/base/ReFile.cpp @@ -11,6 +11,12 @@ #include "base/rebase.hpp" +enum { + LOC_DELETE_TREE_1 = LOC_FIRST_OF(LOC_FILE), // 11801 + LOC_DELETE_TREE_2, // 11802 + LOC_DELETE_TREE_3, // 11803 +}; + #if defined __linux__ || defined WIN32 void* memichr(void* heap, int cc, size_t length) { const char* heap2 = reinterpret_cast(heap); @@ -83,6 +89,60 @@ void ReLines::clear() { QStringList::clear(); } +/** + * Delete a directory tree. + * + * @param path the directory to delete + * @param withBase true: the directory itself will be deleted
+ * false: only all files/dirs inside will be + * deleted + * @param logger NULL or error logger + * @return true: all files deleted
+ * false: at least one deletion failed + */ +bool ReFile::deleteTree(const QString& path, bool withBase, ReLogger* logger) { + bool rc = true; + QDir dir(path); + + if (dir.exists(path)) { + QFileInfo info; + QStringList names = dir.entryList( + QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs + | QDir::Files); + QStringList::const_iterator it; + for (it = names.constBegin(); it != names.constEnd(); ++it) { + QString full(path); + full.append(OS_SEPARATOR_STR).append(*it); + QFileInfo info(full); + if (info.isDir()) { + if (!deleteTree(full, true, logger)) + rc = false; + else if (rmdir(full.toUtf8()) != 0) { + rc = false; + if (logger != NULL) + logger->logv(LOG_ERROR, LOC_DELETE_TREE_1, + "cannot delete directory (%d): %s", errno, + full.toUtf8().constData()); + } + } else { + if (!QFile::remove(full)) { + rc = false; + if (logger != NULL) + logger->logv(LOG_ERROR, LOC_DELETE_TREE_2, + "cannot delete file (%d): %s", errno, + full.toUtf8().constData()); + } + } + } + } + if (withBase && (rmdir(path.toUtf8())) != 0) { + rc = false; + logger->logv(LOG_ERROR, LOC_DELETE_TREE_3, + "cannot delete directory (%d): %s", errno, path.toUtf8()); + } + return rc; +} + /** * Inserts one or more lines into the lines. * @@ -97,7 +157,7 @@ void ReLines::insertLines(int lineNo, const QString& text, bool withUndo) { if (text.isEmpty()) count = 1; else { - count = ReQStringUtil::countOf(text, '\n'); + count = ReQStringUtils::countOf(text, '\n'); if (text.at(text.length() - 1) != '\n') count++; } diff --git a/base/ReFile.hpp b/base/ReFile.hpp index 5123c68..953b74f 100644 --- a/base/ReFile.hpp +++ b/base/ReFile.hpp @@ -155,7 +155,8 @@ public: static QByteArray& readFromFile(const char* filename, QByteArray& buffer); static void writeToFile(const char* filename, const char* content, size_t contentLength = (size_t) - 1, const char* mode = "w"); - + static bool deleteTree(const QString& path, bool withBase, + ReLogger* logger); private: QByteArray m_endOfLine; QString m_filename; diff --git a/base/ReFileUtils.cpp b/base/ReFileUtils.cpp new file mode 100644 index 0000000..7228f05 --- /dev/null +++ b/base/ReFileUtils.cpp @@ -0,0 +1,196 @@ +/* + * 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" + +enum { + LOC_DELETE_TREE_1 = LOC_FIRST_OF(LOC_FILE), // 11801 + LOC_DELETE_TREE_2, // 11802 + LOC_DELETE_TREE_3, // 11803 +}; + + +/** + * Constructor. + */ +ReTreeStatistic::ReTreeStatistic() : + m_files(0), + m_directories(0), + m_fileSizes(0L){ +} + +/** + * Delete a directory tree. + * + * @param path the directory to delete + * @param withBase true: the directory itself will be deleted
+ * false: only all files/dirs inside will be + * deleted + * @param logger NULL or error logger + * @return true: all files deleted
+ * false: at least one deletion failed + */ +bool ReFileUtils::deleteTree(const QString& path, bool withBase, ReLogger* logger){ + bool rc = true; + QDir dir(path); + + if (dir.exists(path)) { + QFileInfo info; + QStringList names = dir.entryList(QDir::NoDotAndDotDot + | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files); + QStringList::const_iterator it; + for (it = names.constBegin(); it != names.constEnd(); ++it){ + QString full(path); + full.append(OS_SEPARATOR_STR).append(*it); + QFileInfo info(full); + if (info.isDir()) { + if (! deleteTree(full, false, logger)) + rc = false; + else if (rmdir(full.toUtf8()) != 0){ + rc = false; + if (logger != NULL) + logger->logv(LOG_ERROR, LOC_DELETE_TREE_1, + "cannot delete directory (%d): %s", + errno, full.toUtf8().constData()); + } + } else { + if (! QFile::remove(full)){ + rc = false; + if (logger != NULL) + logger->logv(LOG_ERROR, LOC_DELETE_TREE_2, + "cannot delete file (%d): %s", + errno, full.toUtf8().constData()); + } + } + } + } + if (withBase && (rmdir(path.toUtf8())) != 0){ + rc = false; + logger->logv(LOG_ERROR, LOC_DELETE_TREE_3, + "cannot delete directory (%d): %s", + errno, path.toUtf8()); + } + return rc; +} + + + + + +/** + * Reads a string from a given file. + * + * @param filename name of the file to read + * @param buffer OUT: the buffer to write + * @return buffer (for chaining) + */ +QByteArray& ReFileUtils::readFromFile(const char* filename, QByteArray& buffer) { + FILE* fp = fopen(filename, "r"); + if (fp != NULL) { + struct stat info; + stat(filename, &info); + buffer.resize(info.st_size); + size_t newLength = fread(buffer.data(), 1, info.st_size, fp); + if (newLength != (size_t) info.st_size) + buffer.truncate(newLength == (size_t) - 1 ? 0 : newLength); + fclose(fp); + } + return buffer; +} + +/** + * @brief Returns the name of a directory in the temp dir. + * + * If the named directory does not exist it will be created. + * + * @param node NULL or the node (name without path) + * @param parent NULL or a node of the parent + * @param withSeparator true: the result ends with slash/backslash + * @return the name of an existing directory + */ +QByteArray ReFileUtils::tempDir(const char* node, const char* parent, + bool withSeparator) { +#if defined __linux__ + QByteArray temp("/tmp"); + static const char* firstVar = "TMP"; + static const char* secondVar = "TEMP"; +#elif defined WIN32 + QByteArray temp("c:\\temp"); + static const char* firstVar = "TEMP"; + static const char* secondVar = "TMP"; +#endif + struct stat info; + const char* ptr; + if ((ptr = getenv(firstVar)) != NULL) + temp = ptr; + else if ((ptr = getenv(secondVar)) != NULL) + temp = ptr; +#if defined WIN32 + temp.replace('\\', '/'); +#endif + if (temp.at(temp.length() - 1) != '/') + temp += '/'; + if (parent != NULL) { + temp += parent; + if (stat(temp.constData(), &info) != 0) + _mkdir(temp.constData()); + temp += '/'; + } + if (node != NULL) { + temp += node; + if (stat(temp.data(), &info) != 0) + _mkdir(temp.data()); + temp += '/'; + } + if (!withSeparator) + temp.resize(temp.length() - 1); + return temp; +} + +/** + * @brief Returns a name of a file in a temporary directory. + * + * @param node the file's name without path + * @param parent NULL or the name of a subdirectory the file will be inside + * @param deleteIfExists true: if the file exists it will be removed + * @return the full name of a temporary file + */ +QByteArray ReFileUtils::tempFile(const char* node, const char* parent, + bool deleteIfExists) { + QByteArray rc(tempDir(parent)); + if (!rc.endsWith('/')) + rc += '/'; + rc += node; + struct stat info; + if (deleteIfExists && stat(rc.constData(), &info) == 0) + unlink(rc.constData()); + return rc; +} + +/** + * Writes a string into a given file. + * + * @param filename name of the file to write + * @param content the content to write + * @param contentLength -1: strlen(content)
+ * otherwise: the length of content + * @param mode file write mode: "w" (write) or "a" (append) + */ +void ReFileUtils::writeToFile(const char* filename, const char* content, + size_t contentLength, const char* mode) { + FILE* fp = fopen(filename, mode); + if (fp != NULL) { + if (contentLength == (size_t) - 1) + contentLength = strlen(content); + fwrite(content, 1, contentLength, fp); + fclose(fp); + } +} diff --git a/base/ReFileUtils.hpp b/base/ReFileUtils.hpp new file mode 100644 index 0000000..1fe2154 --- /dev/null +++ b/base/ReFileUtils.hpp @@ -0,0 +1,41 @@ +/* + * 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 + */ + +#ifndef REFILEUTILS_HPP +#define REFILEUTILS_HPP + +/** + * Statistic of a directory tree. + */ +class ReTreeStatistic { + ReTreeStatistic(); +public: + int m_files; + int m_directories; + int64_t m_fileSizes; +}; + +/** + * Usefull static methods around files/directories missing in QT. + */ +class ReFileUtils { +public: + static QByteArray tempDir(const char* node, const char* parent = NULL, + bool withSeparator = true); + static QByteArray tempFile(const char* node, const char* parent = NULL, + bool deleteIfExists = true); + static QByteArray& readFromFile(const char* filename, QByteArray& buffer); + static void writeToFile(const char* filename, const char* content, + size_t contentLength = (size_t) - 1, const char* mode = "w"); + static bool deleteTree(const QString& path, bool withBase, ReLogger* logger); +}; + +#endif // REFILEUTILS_HPP diff --git a/base/ReQStringUtil.cpp b/base/ReQStringUtils.cpp similarity index 94% rename from base/ReQStringUtil.cpp rename to base/ReQStringUtils.cpp index 0b5b7c9..e1f5d25 100644 --- a/base/ReQStringUtil.cpp +++ b/base/ReQStringUtils.cpp @@ -26,7 +26,7 @@ * @param text text to inspect * @return text without trailing '\n' and/or '\r' */ -ReString ReQStringUtil::chomp(const ReString& text) { +ReString ReQStringUtils::chomp(const ReString& text) { int last = text.length() - 1; while (last >= 0 && (text[last] == '\n' || text[last] == '\r')) { last--; @@ -43,7 +43,7 @@ ReString ReQStringUtil::chomp(const ReString& text) { * * @return the count of occurrencies of the character */ -int ReQStringUtil::countOf(const QString& value, QChar toFind, int start) { +int ReQStringUtils::countOf(const QString& value, QChar toFind, int start) { int rc = 0; if (start >= 0) { for (int ix = start; ix < value.length(); ix++) @@ -59,7 +59,7 @@ int ReQStringUtil::countOf(const QString& value, QChar toFind, int start) { * @param value string to test * @param lastChar the last character */ -QString& ReQStringUtil::ensureLastChar(QString& value, QChar lastChar) { +QString& ReQStringUtils::ensureLastChar(QString& value, QChar lastChar) { if (value.isEmpty() || value.at(value.length() - 1) != lastChar) value += lastChar; return value; @@ -72,7 +72,7 @@ QString& ReQStringUtil::ensureLastChar(QString& value, QChar lastChar) { * @return "": no extension found
* otherwise: the extension of filename */ -ReString ReQStringUtil::extensionOf(const ReString& filename) { +ReString ReQStringUtils::extensionOf(const ReString& filename) { QString rc; int index = filename.lastIndexOf('.'); int index2 = 0; @@ -105,7 +105,7 @@ ReString ReQStringUtil::extensionOf(const ReString& filename) { * @return <=0: no integer found * otherwise: the length of the integer */ -int ReQStringUtil::lengthOfUInt64(const ReString& text, int start, int radix, +int ReQStringUtils::lengthOfUInt64(const ReString& text, int start, int radix, quint64* pValue) { int inputLength = text.size(); int64_t value = 0; @@ -158,7 +158,7 @@ int ReQStringUtil::lengthOfUInt64(const ReString& text, int start, int radix, * @return 0: no integer found * otherwise: the length of the integer */ -int ReQStringUtil::lengthOfUInt(const ReString& text, int start, int radix, +int ReQStringUtils::lengthOfUInt(const ReString& text, int start, int radix, uint* pValue) { quint64 value; int rc = lengthOfUInt64(text, start, radix, &value); @@ -179,7 +179,7 @@ int ReQStringUtil::lengthOfUInt(const ReString& text, int start, int radix, * @return 0: no date found
* otherwise: the length of the date in the string */ -int ReQStringUtil::lengthOfDate(const ReString& text, int start, QDate* value) { +int ReQStringUtils::lengthOfDate(const ReString& text, int start, QDate* value) { uint day = 0; uint month = 0; uint year = 0; @@ -248,7 +248,7 @@ int ReQStringUtil::lengthOfDate(const ReString& text, int start, QDate* value) { * @return 0: no date found
* otherwise: the length of the date in the string */ -int ReQStringUtil::lengthOfDateTime(const ReString& text, int start, +int ReQStringUtils::lengthOfDateTime(const ReString& text, int start, bool allowDateOnly, bool allowTimeOnly, QDateTime* value) { QDate date; QTime time; @@ -290,7 +290,7 @@ int ReQStringUtil::lengthOfDateTime(const ReString& text, int start, * @return 0: no date found
* otherwise: the length of the date in the string */ -int ReQStringUtil::lengthOfTime(const ReString& text, int start, QTime* value) { +int ReQStringUtils::lengthOfTime(const ReString& text, int start, QTime* value) { uint hour = 0; uint minute = 0; uint sec = 0; @@ -333,7 +333,7 @@ int ReQStringUtil::lengthOfTime(const ReString& text, int start, QTime* value) { * @return <=0: no real number found * otherwise: the length of the floating point number */ -int ReQStringUtil::lengthOfReal(const ReString& text, int start, +int ReQStringUtils::lengthOfReal(const ReString& text, int start, qreal* pValue) { int inputLength = text.size(); qreal value = 0.0; @@ -401,7 +401,7 @@ int ReQStringUtil::lengthOfReal(const ReString& text, int start, * @param filename the filename (with or without path) * @return the node of filename */ -ReString ReQStringUtil::nodeOf(const ReString& filename) { +ReString ReQStringUtils::nodeOf(const ReString& filename) { QString rc; int index = filename.lastIndexOf('/'); @@ -426,7 +426,7 @@ ReString ReQStringUtil::nodeOf(const ReString& filename) { * @param toAdd a relative path (relative to base) * @return the combined path */ -QString ReQStringUtil::pathAppend(const QString& base, const QString& path) { +QString ReQStringUtils::pathAppend(const QString& base, const QString& path) { QString rc; if (!base.isEmpty()) rc = QDir::cleanPath(base + QDir::separator() + path); @@ -447,7 +447,7 @@ QString ReQStringUtil::pathAppend(const QString& base, const QString& path) { * @return path with a new file extension */ -QString ReQStringUtil::replaceExtension(const QString& path, +QString ReQStringUtils::replaceExtension(const QString& path, const QString& ext) { QString oldExt = extensionOf(path); QString rc; @@ -468,7 +468,7 @@ QString ReQStringUtil::replaceExtension(const QString& path, * @return true: success
* false: unknown name found (not replaced) */ -bool ReQStringUtil::replacePlaceholders(QString& text, +bool ReQStringUtils::replacePlaceholders(QString& text, const QMap& placeholders, QString* error) { int start = 0; bool rc = true; @@ -507,7 +507,7 @@ bool ReQStringUtil::replacePlaceholders(QString& text, * OUT: 0: the expected character was not found. * otherwise: the length is incremented */ -void ReQStringUtil::skipExpected(const ReString& text, QChar expected, +void ReQStringUtils::skipExpected(const ReString& text, QChar expected, int& index, int& length) { if (length == 0) { // error state, do nothing @@ -530,7 +530,7 @@ void ReQStringUtil::skipExpected(const ReString& text, QChar expected, * @param bufferSize size of the target buffer * @return buffer */ -char*ReQStringUtil::utf8(const ReString& source, char buffer[], +char*ReQStringUtils::utf8(const ReString& source, char buffer[], size_t bufferSize) { QByteArray val = source.toUtf8(); if (val.length() < (int) bufferSize) @@ -693,7 +693,7 @@ void ReUnitParser::parse() { */ uint64_t ReUnitParser::valueOf(const QString& value) const { uint64_t rc = 0; - int ix = ReQStringUtil::lengthOfUInt64(value, 0, 10, &rc); + int ix = ReQStringUtils::lengthOfUInt64(value, 0, 10, &rc); if (ix == 0) throw ReParserException(QObject::tr("number expected: ") + value); QString unit = value.mid(ix); @@ -783,7 +783,7 @@ QDateTime ReDateTimeParser::parseDateTime(const QString& expr) { bool checkSum = true; if (m_expr.startsWith("now", Qt::CaseInsensitive)) { m_expr.remove(0, 3); - } else if ((length2 = ReQStringUtil::lengthOfDateTime(m_expr, 0, true, + } else if ((length2 = ReQStringUtils::lengthOfDateTime(m_expr, 0, true, true, &dateTime)) > 0) { rc = dateTime; m_expr.remove(0, length2); diff --git a/base/ReQStringUtil.hpp b/base/ReQStringUtils.hpp similarity index 99% rename from base/ReQStringUtil.hpp rename to base/ReQStringUtils.hpp index 2a860c6..0552f9d 100644 --- a/base/ReQStringUtil.hpp +++ b/base/ReQStringUtils.hpp @@ -12,7 +12,7 @@ #ifndef RPLQSTRING_HPP #define RPLQSTRING_HPP -class ReQStringUtil { +class ReQStringUtils { public: static ReString chomp(const ReString& text); static int countOf(const QString& value, QChar toFind, int start = 0); diff --git a/base/ReStringUtil.cpp b/base/ReStringUtils.cpp similarity index 90% rename from base/ReStringUtil.cpp rename to base/ReStringUtils.cpp index 9333a70..0faf845 100644 --- a/base/ReStringUtil.cpp +++ b/base/ReStringUtils.cpp @@ -31,7 +31,7 @@ * @param cc the char to count * @return the number of cc in the text */ -int ReStringUtil::countChar(const char* line, char cc) { +int ReStringUtils::countChar(const char* line, char cc) { const char* ptr = line; int rc = 0; while ((ptr = strchr(ptr, cc)) != NULL) { @@ -47,7 +47,7 @@ int ReStringUtil::countChar(const char* line, char cc) { * @param item this item will be searched * @return the count of occurrences */ -int ReStringUtil::count(const char* source, const char* item) { +int ReStringUtils::count(const char* source, const char* item) { const char* end = source; int rc = 0; int lengthItem = strlen(item); @@ -75,7 +75,7 @@ int ReStringUtil::count(const char* source, const char* item) { * @return source: the source is enough short
* the prefix of source with the given length */ -const QByteArray& ReStringUtil::cutString(const QByteArray& source, +const QByteArray& ReStringUtils::cutString(const QByteArray& source, int maxLength, QByteArray& buffer, const char* appendix) { QByteArray& rc = source.length() <= maxLength ? (QByteArray&) source : buffer; @@ -92,7 +92,7 @@ static char s_fileSeparator = 0; * @brief Returns the os specific file path separator. * @return the file path separator, e.g. "/" for linux */ -const char* ReStringUtil::fileSeparator() { +const char* ReStringUtils::fileSeparator() { return fileSeparatorChar() == '/' ? "/" : "\\"; } @@ -100,7 +100,7 @@ const char* ReStringUtil::fileSeparator() { * @brief Returns the os specific file path separator. * @return the file path separator, e.g. '/' for linux */ -char ReStringUtil::fileSeparatorChar() { +char ReStringUtils::fileSeparatorChar() { if (s_fileSeparator == 0) { const char* path = getenv("PATH"); if (path != NULL) { @@ -129,7 +129,7 @@ char ReStringUtil::fileSeparatorChar() { * @param bytesPerLine one line containes so many bytes of data * @return the hex dump */ -QByteArray ReStringUtil::hexDump(uint8_t* data, int length, int bytesPerLine) { +QByteArray ReStringUtils::hexDump(uint8_t* data, int length, int bytesPerLine) { QByteArray rc; int fullLines = length / bytesPerLine; int expectedLength = (bytesPerLine * 4 + 2) * (fullLines + 1); @@ -178,7 +178,7 @@ QByteArray ReStringUtil::hexDump(uint8_t* data, int length, int bytesPerLine) { * the result will not contain this * @return the file's content */ -QByteArray ReStringUtil::read(const char* file, bool removeLastNewline) { +QByteArray ReStringUtils::read(const char* file, bool removeLastNewline) { QByteArray rc; struct stat info; size_t size; @@ -196,7 +196,7 @@ QByteArray ReStringUtil::read(const char* file, bool removeLastNewline) { return rc; } -QByteArray ReStringUtil::replaceNode(const char* source, const char* newNode) { +QByteArray ReStringUtils::replaceNode(const char* source, const char* newNode) { char sep = fileSeparatorChar(); const char* ptr = strrchr(source, sep); QByteArray rc; @@ -218,7 +218,7 @@ QByteArray ReStringUtil::replaceNode(const char* source, const char* newNode) { * @param separator the separator between the items to split * @return an array with the splitted source */ -QList ReStringUtil::toArray(const char* source, +QList ReStringUtils::toArray(const char* source, const char* separator) { const char* end = source; QList < QByteArray > rc; @@ -237,7 +237,7 @@ QList ReStringUtil::toArray(const char* source, return rc; } -QByteArray ReStringUtil::toCString(const char* source, int maxLength) { +QByteArray ReStringUtils::toCString(const char* source, int maxLength) { if (maxLength <= 0) maxLength = strlen(source); int binaries = 0; @@ -286,7 +286,7 @@ QByteArray ReStringUtil::toCString(const char* source, int maxLength) { * @param format format like in sprintf() * @return the ascii form of the value */ -QByteArray ReStringUtil::toNumber(int value, const char* format) { +QByteArray ReStringUtils::toNumber(int value, const char* format) { char buffer[128]; qsnprintf(buffer, sizeof buffer, format, value); return QByteArray(buffer); @@ -301,7 +301,7 @@ QByteArray ReStringUtil::toNumber(int value, const char* format) { * @return true: successful
* false: error occurred */ -bool ReStringUtil::write(const char* file, const char* content, +bool ReStringUtils::write(const char* file, const char* content, const char* mode) { FILE* fp = fopen(file, mode); if (fp != NULL) { @@ -319,7 +319,7 @@ bool ReStringUtil::write(const char* file, const char* content, * @return 0: not a number
* otherwise: the length of the number string */ -int ReStringUtil::lengthOfNumber(const char* text, bool skipTrailingSpaces) { +int ReStringUtils::lengthOfNumber(const char* text, bool skipTrailingSpaces) { int rc = 0; bool found = false; const char* ptr = text; @@ -369,10 +369,10 @@ int ReStringUtil::lengthOfNumber(const char* text, bool skipTrailingSpaces) { */ static void addSeparators(const char* line, int& commas, int& semicolons, int& pipes, int& blanks) { - commas += ReStringUtil::countChar(line, ','); - semicolons += ReStringUtil::countChar(line, ';'); - pipes += ReStringUtil::countChar(line, '|'); - blanks += ReStringUtil::countChar(line, ' '); + commas += ReStringUtils::countChar(line, ','); + semicolons += ReStringUtils::countChar(line, ';'); + pipes += ReStringUtils::countChar(line, '|'); + blanks += ReStringUtils::countChar(line, ' '); } /** @@ -387,7 +387,7 @@ static void addSeparators(const char* line, int& commas, int& semicolons, * @param buffer a line buffer * @param bufferSize the size of buffer[] */ -char ReStringUtil::findCsvSeparator(FILE* fp, char* buffer, size_t bufferSize) { +char ReStringUtils::findCsvSeparator(FILE* fp, char* buffer, size_t bufferSize) { char rc = '\0'; int lineNo = 0; int maxLines = 5; @@ -433,7 +433,7 @@ char ReStringUtil::findCsvSeparator(FILE* fp, char* buffer, size_t bufferSize) { * @return <=0: no integer found * otherwise: the length of the integer */ -int ReStringUtil::lengthOfUInt64(const char* text, int radix, quint64* pValue) { +int ReStringUtils::lengthOfUInt64(const char* text, int radix, quint64* pValue) { int64_t value = 0; int length = 0; int cc; @@ -480,7 +480,7 @@ int ReStringUtil::lengthOfUInt64(const char* text, int radix, quint64* pValue) { * @return <=0: no real number found * otherwise: the length of the floating point number */ -int ReStringUtil::lengthOfReal(const char* text, qreal* pValue) { +int ReStringUtils::lengthOfReal(const char* text, qreal* pValue) { qreal value = 0.0; int cc; int length = 0; diff --git a/base/ReStringUtil.hpp b/base/ReStringUtils.hpp similarity index 98% rename from base/ReStringUtil.hpp rename to base/ReStringUtils.hpp index 555db1a..a896bce 100644 --- a/base/ReStringUtil.hpp +++ b/base/ReStringUtils.hpp @@ -11,7 +11,7 @@ #ifndef RPLSTRING_HPP #define RPLSTRING_HPP -class ReStringUtil { +class ReStringUtils { public: static int countChar(const char* line, char cc); static int count(const char* source, const char* item); diff --git a/base/ReTest.cpp b/base/ReTest.cpp index c16e430..d57229d 100644 --- a/base/ReTest.cpp +++ b/base/ReTest.cpp @@ -174,8 +174,8 @@ bool ReTest::assertEquals(const char* expected, const char* current, bool equal = strcmp(expected, current) == 0; if (!equal) { if (strchr(expected, '\n') != NULL || strchr(current, '\n')) { - QList < QByteArray > exp = ReStringUtil::toArray(expected, "\n"); - QList < QByteArray > cur = ReStringUtil::toArray(current, "\n"); + QList < QByteArray > exp = ReStringUtils::toArray(expected, "\n"); + QList < QByteArray > cur = ReStringUtils::toArray(current, "\n"); equal = assertEquals(exp, cur, file, lineNo); } else { int ix = 0; @@ -397,8 +397,8 @@ bool ReTest::assertNotNull(const void* ptr, const char* file, int lineNo) { bool ReTest::assertEqualFiles(const char* expected, const char* current, const char* file, int lineNo) { bool rc = false; - QByteArray expectedContent = ReStringUtil::read(expected, true); - QByteArray currentContent = ReStringUtil::read(current, true); + QByteArray expectedContent = ReStringUtils::read(expected, true); + QByteArray currentContent = ReStringUtils::read(current, true); if (expectedContent.isEmpty()) { char buffer[512]; qsnprintf(buffer, sizeof buffer, "%s has no content. Does it exist?", diff --git a/base/rebase.hpp b/base/rebase.hpp index ba1697e..599a5b1 100644 --- a/base/rebase.hpp +++ b/base/rebase.hpp @@ -94,12 +94,13 @@ inline int roundInt(double value) { #include "base/ReLogger.hpp" #include "base/ReException.hpp" #include "base/ReContainer.hpp" -#include "base/ReStringUtil.hpp" -#include "ReQStringUtil.hpp" +#include "base/ReStringUtils.hpp" +#include "ReQStringUtils.hpp" #include "base/ReConfigurator.hpp" #include "base/ReConfig.hpp" #include "base/ReTerminator.hpp" #include "base/ReLineSource.hpp" +#include "base/ReFileUtils.hpp" #include "base/ReFile.hpp" #include "base/ReTest.hpp" diff --git a/cunit/allTests.cpp b/cunit/allTests.cpp index da2369b..2010274 100644 --- a/cunit/allTests.cpp +++ b/cunit/allTests.cpp @@ -21,8 +21,10 @@ static void testGui() { int argc = 1; QApplication a(argc, argv); void testReStateStorage(); - testReStateStorage(); void testReEdit(); + void testReSettings(); + testReSettings(); + testReStateStorage(); testReEdit(); } @@ -36,7 +38,9 @@ static void testBase() { void testReStringUtil(); void testReWriter(); void testReFile(); + void testReFileUtils(); testReFile(); + testReFileUtils(); if (s_allTest) { testReQStringUtil(); testReByteStorage(); diff --git a/cunit/cuReConfig.cpp b/cunit/cuReConfig.cpp index af08cd0..02c5c65 100644 --- a/cunit/cuReConfig.cpp +++ b/cunit/cuReConfig.cpp @@ -23,7 +23,7 @@ public: public: void testBasic() { QByteArray fn = getTempFile("test.data", "config"); - ReStringUtil::write(fn, "#comment\na=1\nb.1==x\n#=\nB=zzz"); + ReStringUtils::write(fn, "#comment\na=1\nb.1==x\n#=\nB=zzz"); ReConfig config(fn.constData()); checkEqu(3, config.size()); checkEqu("1", config["a"]); @@ -32,7 +32,7 @@ public: } void testAsX() { QByteArray fn = getTempFile("test.data", "config"); - ReStringUtil::write(fn, "i=123\nb=1\nb2=true\nb3=yes\ns=abc"); + ReStringUtils::write(fn, "i=123\nb=1\nb2=true\nb3=yes\ns=abc"); ReConfig config(fn.constData()); checkEqu(5, config.size()); checkEqu(123, config.asInt("i", -1)); diff --git a/cunit/cuReFile.cpp b/cunit/cuReFile.cpp index bf1bf80..28865f8 100644 --- a/cunit/cuReFile.cpp +++ b/cunit/cuReFile.cpp @@ -17,7 +17,7 @@ class TestReFile: public ReTest { public: TestReFile() : - ReTest("ReFile") { + ReTest("ReFile") { doIt(); } @@ -25,7 +25,7 @@ public: void testBasic() { QByteArray fn(ReFile::tempFile("big.txt", NULL, true)); const char* content = - "123456789 123456789 123456789 123456789 123456789\n"; + "123456789 123456789 123456789 123456789 123456789\n"; int contentLength = strlen(content); ReFile::writeToFile(fn.constData(), content); ReFile file(fn.constData()); @@ -36,19 +36,19 @@ public: checkNN(ptr); checkEqu(4, length); checkEqu(0, - strncmp(content, reinterpret_cast(ptr), length)); + strncmp(content, reinterpret_cast(ptr), length)); int part = size / 2; ptr = file.remap(contentLength - part, size, length); checkEqu(size / 2, length); checkEqu(content + contentLength - part, - reinterpret_cast(ptr)); + reinterpret_cast(ptr)); for (int ix = 0; ix < contentLength - size; ix++) { ptr = file.remap(ix, size, length); checkNN(ptr); checkEqu(length, size); checkEqu(0, - strncmp(content + ix, reinterpret_cast(ptr), - length)); + strncmp(content + ix, reinterpret_cast(ptr), + length)); } } @@ -93,7 +93,7 @@ public: } double duration = double(clock() - start) / CLOCKS_PER_SEC; printf("linecount (ReFile, %d kB): %d lines %.3f sec\n", - int(blocksize / 1024), lines, duration); + int(blocksize / 1024), lines, duration); } void countLinesFopen(const char* filename) { @@ -367,7 +367,6 @@ public: checkEqu("2", lines.lineAt(1)); checkEqu("", lines.lineAt(2)); } - virtual void run() { testReLinesInsert(); testReLinesSplitLine(); @@ -378,9 +377,6 @@ public: testWritableFile(); testPerformance(); testBasic(); - testTempDir(); - testTempFile(); - testWriteRead(); } }; void testReFile() { diff --git a/cunit/cuReFileUtils.cpp b/cunit/cuReFileUtils.cpp new file mode 100644 index 0000000..5889992 --- /dev/null +++ b/cunit/cuReFileUtils.cpp @@ -0,0 +1,94 @@ +/* + * cuReFileUtils.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" + +/** @file + * @brief Unit test of the basic exceptions. + */ + +class TestReFileUtils: public ReTest { +public: + TestReFileUtils() : + ReTest("ReFileUtils") { + doIt(); + } + +public: + void testTempFile() { + QByteArray fn(ReFileUtils::tempFile("node.txt", "subdir", true)); + QByteArray content; + ReFileUtils::writeToFile(fn, "123"); + struct stat info; + checkEqu(0, stat(fn.constData(), &info)); + checkEqu(3, (int ) info.st_size); + ReFileUtils::tempFile("node.txt", "subdir", true); + checkEqu(-1, stat(fn.constData(), &info)); + } + void testTempDir() { + QByteArray dir(ReFileUtils::tempDir("subdir", "cuReFileUtils", false)); + checkT(dir.endsWith("subdir")); + checkT(dir.endsWith("cuReFileUtils/subdir")); + struct stat info; + checkEqu(0, stat(dir, &info)); + checkT(S_ISDIR(info.st_mode)); + } + void testWriteRead() { + QByteArray fn(ReFileUtils::tempFile("node.txt", "subdir", true)); + ReFileUtils::writeToFile(fn, "123"); + QByteArray content; + ReFileUtils::readFromFile(fn, content); + checkEqu("123", content); + ReFileUtils::writeToFile(fn, "abcdef", 2); + ReFileUtils::readFromFile(fn, content); + checkEqu("ab", content); + } + QByteArray buildTree(){ + QByteArray base = ReFileUtils::tempDir("ReFileUtils"); + for (char cc = 'a'; cc < 'f'; cc++){ + QByteArray subdir(base + cc); + mkdir(subdir.constData(), ALLPERMS); + for (char cc2 = '1'; cc2 < '5'; cc2++){ + QByteArray name( subdir); + name.append(OS_SEPARATOR_STR).append(&cc2, 1); + ReFileUtils::writeToFile(name, name); + name += "dir"; + mkdir(name.constData(), ALLPERMS); + name.append(OS_SEPARATOR_STR).append("x.txt"); + ReFileUtils::writeToFile(name, name); + } + } + // remove the separator: + base.remove(base.length() - 1, 1); + return base; + } + void testDeleteTree(){ + QByteArray base = buildTree(); + checkT(ReFileUtils::deleteTree(QString(base), false, &m_logger)); + struct stat info; + // the dir must exist: + checkEqu(0, stat(base, &info)); + // rmdir() works only if the dir is empty: + checkEqu(0, rmdir(base)); + buildTree(); + checkT(ReFileUtils::deleteTree(QString(base), false, &m_logger)); + checkEqu(0, stat(base, &info)); + } + virtual void run() { + testDeleteTree(); + testTempDir(); + testTempFile(); + testWriteRead(); + } +}; +void testReFileUtils() { + TestReFileUtils test; +} + diff --git a/cunit/cuReQStringUtil.cpp b/cunit/cuReQStringUtil.cpp deleted file mode 100644 index 1aae6fa..0000000 --- a/cunit/cuReQStringUtil.cpp +++ /dev/null @@ -1,202 +0,0 @@ -/* - * cuReQStringUtil.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 - */ -/** @file - * @brief Unit test of the ReString tools. - */ - -#include "../base/rebase.hpp" - -class TestReQStringUtil: public ReTest { -public: - TestReQStringUtil() : - ReTest("ReQStringUtil") { - doIt(); - } - -public: - void testCountOf() { - checkEqu(2, ReQStringUtil::countOf(QString("axbx"), 'x')); - checkEqu(2, ReQStringUtil::countOf(QString("axbx"), 'x', 1)); - checkEqu(1, ReQStringUtil::countOf(QString("axbx"), 'x', 2)); - checkEqu(1, ReQStringUtil::countOf(QString("axbx"), 'x', 3)); - checkEqu(0, ReQStringUtil::countOf(QString("axbx"), 'x', 4)); - checkEqu(0, ReQStringUtil::countOf(QString("axbx"), 'x', 5)); - checkEqu(0, ReQStringUtil::countOf(QString("axbx"), 'x', -1)); - } - - void testLengthOfUInt64() { - quint64 value = -3; - checkEqu(1, - ReQStringUtil::lengthOfUInt64(ReString("0"), 0, 10, &value)); - checkEqu(int64_t(0), value); - checkEqu(3, ReQStringUtil::lengthOfUInt64("x432", 1, 10, &value)); - checkEqu(int64_t(432LL), value); - checkEqu(3, ReQStringUtil::lengthOfUInt64("x432 x", 1, 10, &value)); - checkEqu(int64_t(432LL), value); - checkEqu(3, ReQStringUtil::lengthOfUInt64("x432fabc x", 1, 10, &value)); - checkEqu(int64_t(432LL), value); - checkEqu(16, - ReQStringUtil::lengthOfUInt64("a1234567890123567", 1, 10, &value)); - checkEqu(int64_t(1234567890123567LL), value); - checkEqu(10, - ReQStringUtil::lengthOfUInt64("x1234abcdef", 1, 16, &value)); - checkEqu(int64_t(0x1234abcdefLL), value); - checkEqu(3, ReQStringUtil::lengthOfUInt64("432", 0, 8, &value)); - checkEqu(int64_t(0432LL), value); - checkEqu(6, ReQStringUtil::lengthOfUInt64(" 765432 ", 1, 8, &value)); - checkEqu(int64_t(0765432LL), value); - - checkEqu(0, ReQStringUtil::lengthOfUInt64("1 ", 1, 8, &value)); - checkEqu(0, ReQStringUtil::lengthOfUInt64("", 1, 8, &value)); - } - void testLengthOfUInt() { - uint value = 3; - checkEqu(1, ReQStringUtil::lengthOfUInt(ReString("0"), 0, 10, &value)); - checkEqu(0, value); - checkEqu(3, ReQStringUtil::lengthOfUInt("x432", 1, 10, &value)); - checkEqu(432, value); - checkEqu(3, ReQStringUtil::lengthOfUInt("x432 x", 1, 10, &value)); - checkEqu(432, value); - checkEqu(3, ReQStringUtil::lengthOfUInt("x432fabc x", 1, 10, &value)); - checkEqu(432, value); - checkEqu(3, ReQStringUtil::lengthOfUInt("432", 0, 8, &value)); - checkEqu(0432, value); - checkEqu(6, ReQStringUtil::lengthOfUInt(" 765432 ", 1, 8, &value)); - checkEqu(0765432, value); - - checkEqu(0, ReQStringUtil::lengthOfUInt("1 ", 1, 8, &value)); - checkEqu(0, ReQStringUtil::lengthOfUInt("", 1, 8, &value)); - } - void testLengthOfReal() { - qreal value; - checkEqu(4, ReQStringUtil::lengthOfReal(ReString("0.25"), 0, &value)); - checkEqu(0.25, value); - checkEqu(3, ReQStringUtil::lengthOfReal(ReString("X.25"), 1, &value)); - checkEqu(0.25, value); - checkEqu(1, ReQStringUtil::lengthOfReal(ReString(" 0"), 1, &value)); - checkEqu(0.0, value); - checkEqu(17, - ReQStringUtil::lengthOfReal(ReString("X12345678901234567"), 1, - &value)); - checkEqu(12345678901234567.0, value); - checkEqu(2, ReQStringUtil::lengthOfReal(ReString(".5"), 0, &value)); - checkEqu(0.5, value); - checkEqu(5, ReQStringUtil::lengthOfReal(ReString("2.5e2x"), 0, &value)); - checkEqu(250.0, value); - checkEqu(6, ReQStringUtil::lengthOfReal(ReString("2.5e+2"), 0, &value)); - checkEqu(250.0, value); - checkEqu(7, - ReQStringUtil::lengthOfReal(ReString("2.5E-33"), 0, &value)); - checkEqu(2.5e-33, value); - - checkEqu(3, ReQStringUtil::lengthOfReal(ReString("2.5E"), 0, &value)); - checkEqu(2.5, value); - checkEqu(3, ReQStringUtil::lengthOfReal(ReString("2.5E+"), 0, &value)); - checkEqu(2.5, value); - checkEqu(3, ReQStringUtil::lengthOfReal(ReString("2.5E-a"), 0, &value)); - checkEqu(2.5, value); - } - - void testValueOfHexDigit() { - checkEqu(0, ReQStringUtil::valueOfHexDigit('0')); - checkEqu(9, ReQStringUtil::valueOfHexDigit('9')); - checkEqu(10, ReQStringUtil::valueOfHexDigit('a')); - checkEqu(15, ReQStringUtil::valueOfHexDigit('f')); - checkEqu(10, ReQStringUtil::valueOfHexDigit('A')); - checkEqu(15, ReQStringUtil::valueOfHexDigit('F')); - - checkEqu(-1, ReQStringUtil::valueOfHexDigit('0' - 1)); - checkEqu(-1, ReQStringUtil::valueOfHexDigit('9' + 1)); - checkEqu(-1, ReQStringUtil::valueOfHexDigit('A' - 1)); - checkEqu(-1, ReQStringUtil::valueOfHexDigit('F' + 1)); - checkEqu(-1, ReQStringUtil::valueOfHexDigit('a' - 1)); - checkEqu(-1, ReQStringUtil::valueOfHexDigit('f' + 1)); - } - void testUtf8() { - ReString name = "Heinz Müller"; - char buffer[32]; - checkEqu("Heinz Müller", - ReQStringUtil::utf8(name, buffer, sizeof buffer)); - memset(buffer, 'x', sizeof buffer); - checkEqu("Heinz", ReQStringUtil::utf8(name, buffer, (size_t)(5 + 1))); - checkEqu(buffer[6], 'x'); - } - - void testUnitParser() { - ReUnitParser parser("-1-2*3*4+2^3*4", NULL); - checkT(parser.isValid()); - checkEqu(7, parser.asInt()); - checkEqu(7LL, parser.asInt64()); - checkEqu(7.0, parser.asReal()); - } - void testSizeParser() { - ReSizeParser parser("2^3byte+2*1k+1m+1g+1t"); - checkT(parser.isValid()); - checkEqu(1001001002008LL, parser.asInt64()); - - ReSizeParser parser2("1ki+1mi+1gi+1ti"); - checkT(parser2.isValid()); - checkEqu(1100586419200ll, parser2.asInt64()); - } - void testDateTimeParser() { - ReDateTimeParser parser("3.4.2014"); - checkEqu(QDateTime(QDate(2014, 4, 3)), parser.asDateTime()); - ReDateTimeParser parser2("21.4.2014-2w"); - checkEqu(QDateTime(QDate(2014, 4, 7)), parser2.asDateTime()); - ReDateTimeParser parserB2("1+1min+1h+1day+1week"); - checkT(parserB2.isValid()); - checkEqu(-694861, parserB2.asInt()); - } - void testLengtOfDate() { - QDate date; - checkEqu(8, ReQStringUtil::lengthOfDate("1.2.2001", 0, &date)); - checkEqu(QDate(2001, 2, 1), date); - checkEqu(9, ReQStringUtil::lengthOfDate("5.12.2001xxx", 0, &date)); - checkEqu(QDate(2001, 12, 5), date); - checkEqu(10, ReQStringUtil::lengthOfDate("011.10.2001xxx", 1, &date)); - checkEqu(QDate(2001, 10, 11), date); - - checkEqu(8, ReQStringUtil::lengthOfDate("2001.2.1", 0, &date)); - checkEqu(QDate(2001, 2, 1), date); - checkEqu(9, ReQStringUtil::lengthOfDate("2001.12.5xxx", 0, &date)); - checkEqu(QDate(2001, 12, 5), date); - checkEqu(10, ReQStringUtil::lengthOfDate("02001.03.01xxx", 1, &date)); - checkEqu(QDate(2001, 3, 1), date); - } - void testLengtOfTime() { - QTime time; - checkEqu(3, ReQStringUtil::lengthOfTime("1:2", 0, &time)); - checkEqu(QTime(1, 2, 0), time); - checkEqu(5, ReQStringUtil::lengthOfTime("301:02", 1, &time)); - checkEqu(QTime(1, 2, 0), time); - checkEqu(7, ReQStringUtil::lengthOfTime("301:02:9", 1, &time)); - checkEqu(QTime(1, 2, 9), time); - checkEqu(8, ReQStringUtil::lengthOfTime("301:02:09x", 1, &time)); - checkEqu(QTime(1, 2, 9), time); - } - - virtual void run(void) { - testLengtOfTime(); - testLengtOfDate(); - testDateTimeParser(); - testUnitParser(); - testSizeParser(); - testUtf8(); - testLengthOfUInt64(); - testLengthOfUInt(); - testLengthOfReal(); - testValueOfHexDigit(); - } -}; -void testReQStringUtil() { - TestReQStringUtil test; -} - diff --git a/cunit/cuReQStringUtils.cpp b/cunit/cuReQStringUtils.cpp new file mode 100644 index 0000000..3c06e38 --- /dev/null +++ b/cunit/cuReQStringUtils.cpp @@ -0,0 +1,202 @@ +/* + * cuReQStringUtil.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 + */ +/** @file + * @brief Unit test of the ReString tools. + */ + +#include "../base/rebase.hpp" + +class TestReQStringUtil: public ReTest { +public: + TestReQStringUtil() : + ReTest("ReQStringUtil") { + doIt(); + } + +public: + void testCountOf() { + checkEqu(2, ReQStringUtils::countOf(QString("axbx"), 'x')); + checkEqu(2, ReQStringUtils::countOf(QString("axbx"), 'x', 1)); + checkEqu(1, ReQStringUtils::countOf(QString("axbx"), 'x', 2)); + checkEqu(1, ReQStringUtils::countOf(QString("axbx"), 'x', 3)); + checkEqu(0, ReQStringUtils::countOf(QString("axbx"), 'x', 4)); + checkEqu(0, ReQStringUtils::countOf(QString("axbx"), 'x', 5)); + checkEqu(0, ReQStringUtils::countOf(QString("axbx"), 'x', -1)); + } + + void testLengthOfUInt64() { + quint64 value = -3; + checkEqu(1, + ReQStringUtils::lengthOfUInt64(ReString("0"), 0, 10, &value)); + checkEqu(int64_t(0), value); + checkEqu(3, ReQStringUtils::lengthOfUInt64("x432", 1, 10, &value)); + checkEqu(int64_t(432LL), value); + checkEqu(3, ReQStringUtils::lengthOfUInt64("x432 x", 1, 10, &value)); + checkEqu(int64_t(432LL), value); + checkEqu(3, ReQStringUtils::lengthOfUInt64("x432fabc x", 1, 10, &value)); + checkEqu(int64_t(432LL), value); + checkEqu(16, + ReQStringUtils::lengthOfUInt64("a1234567890123567", 1, 10, &value)); + checkEqu(int64_t(1234567890123567LL), value); + checkEqu(10, + ReQStringUtils::lengthOfUInt64("x1234abcdef", 1, 16, &value)); + checkEqu(int64_t(0x1234abcdefLL), value); + checkEqu(3, ReQStringUtils::lengthOfUInt64("432", 0, 8, &value)); + checkEqu(int64_t(0432LL), value); + checkEqu(6, ReQStringUtils::lengthOfUInt64(" 765432 ", 1, 8, &value)); + checkEqu(int64_t(0765432LL), value); + + checkEqu(0, ReQStringUtils::lengthOfUInt64("1 ", 1, 8, &value)); + checkEqu(0, ReQStringUtils::lengthOfUInt64("", 1, 8, &value)); + } + void testLengthOfUInt() { + uint value = 3; + checkEqu(1, ReQStringUtils::lengthOfUInt(ReString("0"), 0, 10, &value)); + checkEqu(0, value); + checkEqu(3, ReQStringUtils::lengthOfUInt("x432", 1, 10, &value)); + checkEqu(432, value); + checkEqu(3, ReQStringUtils::lengthOfUInt("x432 x", 1, 10, &value)); + checkEqu(432, value); + checkEqu(3, ReQStringUtils::lengthOfUInt("x432fabc x", 1, 10, &value)); + checkEqu(432, value); + checkEqu(3, ReQStringUtils::lengthOfUInt("432", 0, 8, &value)); + checkEqu(0432, value); + checkEqu(6, ReQStringUtils::lengthOfUInt(" 765432 ", 1, 8, &value)); + checkEqu(0765432, value); + + checkEqu(0, ReQStringUtils::lengthOfUInt("1 ", 1, 8, &value)); + checkEqu(0, ReQStringUtils::lengthOfUInt("", 1, 8, &value)); + } + void testLengthOfReal() { + qreal value; + checkEqu(4, ReQStringUtils::lengthOfReal(ReString("0.25"), 0, &value)); + checkEqu(0.25, value); + checkEqu(3, ReQStringUtils::lengthOfReal(ReString("X.25"), 1, &value)); + checkEqu(0.25, value); + checkEqu(1, ReQStringUtils::lengthOfReal(ReString(" 0"), 1, &value)); + checkEqu(0.0, value); + checkEqu(17, + ReQStringUtils::lengthOfReal(ReString("X12345678901234567"), 1, + &value)); + checkEqu(12345678901234567.0, value); + checkEqu(2, ReQStringUtils::lengthOfReal(ReString(".5"), 0, &value)); + checkEqu(0.5, value); + checkEqu(5, ReQStringUtils::lengthOfReal(ReString("2.5e2x"), 0, &value)); + checkEqu(250.0, value); + checkEqu(6, ReQStringUtils::lengthOfReal(ReString("2.5e+2"), 0, &value)); + checkEqu(250.0, value); + checkEqu(7, + ReQStringUtils::lengthOfReal(ReString("2.5E-33"), 0, &value)); + checkEqu(2.5e-33, value); + + checkEqu(3, ReQStringUtils::lengthOfReal(ReString("2.5E"), 0, &value)); + checkEqu(2.5, value); + checkEqu(3, ReQStringUtils::lengthOfReal(ReString("2.5E+"), 0, &value)); + checkEqu(2.5, value); + checkEqu(3, ReQStringUtils::lengthOfReal(ReString("2.5E-a"), 0, &value)); + checkEqu(2.5, value); + } + + void testValueOfHexDigit() { + checkEqu(0, ReQStringUtils::valueOfHexDigit('0')); + checkEqu(9, ReQStringUtils::valueOfHexDigit('9')); + checkEqu(10, ReQStringUtils::valueOfHexDigit('a')); + checkEqu(15, ReQStringUtils::valueOfHexDigit('f')); + checkEqu(10, ReQStringUtils::valueOfHexDigit('A')); + checkEqu(15, ReQStringUtils::valueOfHexDigit('F')); + + checkEqu(-1, ReQStringUtils::valueOfHexDigit('0' - 1)); + checkEqu(-1, ReQStringUtils::valueOfHexDigit('9' + 1)); + checkEqu(-1, ReQStringUtils::valueOfHexDigit('A' - 1)); + checkEqu(-1, ReQStringUtils::valueOfHexDigit('F' + 1)); + checkEqu(-1, ReQStringUtils::valueOfHexDigit('a' - 1)); + checkEqu(-1, ReQStringUtils::valueOfHexDigit('f' + 1)); + } + void testUtf8() { + ReString name = "Heinz Müller"; + char buffer[32]; + checkEqu("Heinz Müller", + ReQStringUtils::utf8(name, buffer, sizeof buffer)); + memset(buffer, 'x', sizeof buffer); + checkEqu("Heinz", ReQStringUtils::utf8(name, buffer, (size_t)(5 + 1))); + checkEqu(buffer[6], 'x'); + } + + void testUnitParser() { + ReUnitParser parser("-1-2*3*4+2^3*4", NULL); + checkT(parser.isValid()); + checkEqu(7, parser.asInt()); + checkEqu(7LL, parser.asInt64()); + checkEqu(7.0, parser.asReal()); + } + void testSizeParser() { + ReSizeParser parser("2^3byte+2*1k+1m+1g+1t"); + checkT(parser.isValid()); + checkEqu(1001001002008LL, parser.asInt64()); + + ReSizeParser parser2("1ki+1mi+1gi+1ti"); + checkT(parser2.isValid()); + checkEqu(1100586419200ll, parser2.asInt64()); + } + void testDateTimeParser() { + ReDateTimeParser parser("3.4.2014"); + checkEqu(QDateTime(QDate(2014, 4, 3)), parser.asDateTime()); + ReDateTimeParser parser2("21.4.2014-2w"); + checkEqu(QDateTime(QDate(2014, 4, 7)), parser2.asDateTime()); + ReDateTimeParser parserB2("1+1min+1h+1day+1week"); + checkT(parserB2.isValid()); + checkEqu(-694861, parserB2.asInt()); + } + void testLengtOfDate() { + QDate date; + checkEqu(8, ReQStringUtils::lengthOfDate("1.2.2001", 0, &date)); + checkEqu(QDate(2001, 2, 1), date); + checkEqu(9, ReQStringUtils::lengthOfDate("5.12.2001xxx", 0, &date)); + checkEqu(QDate(2001, 12, 5), date); + checkEqu(10, ReQStringUtils::lengthOfDate("011.10.2001xxx", 1, &date)); + checkEqu(QDate(2001, 10, 11), date); + + checkEqu(8, ReQStringUtils::lengthOfDate("2001.2.1", 0, &date)); + checkEqu(QDate(2001, 2, 1), date); + checkEqu(9, ReQStringUtils::lengthOfDate("2001.12.5xxx", 0, &date)); + checkEqu(QDate(2001, 12, 5), date); + checkEqu(10, ReQStringUtils::lengthOfDate("02001.03.01xxx", 1, &date)); + checkEqu(QDate(2001, 3, 1), date); + } + void testLengtOfTime() { + QTime time; + checkEqu(3, ReQStringUtils::lengthOfTime("1:2", 0, &time)); + checkEqu(QTime(1, 2, 0), time); + checkEqu(5, ReQStringUtils::lengthOfTime("301:02", 1, &time)); + checkEqu(QTime(1, 2, 0), time); + checkEqu(7, ReQStringUtils::lengthOfTime("301:02:9", 1, &time)); + checkEqu(QTime(1, 2, 9), time); + checkEqu(8, ReQStringUtils::lengthOfTime("301:02:09x", 1, &time)); + checkEqu(QTime(1, 2, 9), time); + } + + virtual void run(void) { + testLengtOfTime(); + testLengtOfDate(); + testDateTimeParser(); + testUnitParser(); + testSizeParser(); + testUtf8(); + testLengthOfUInt64(); + testLengthOfUInt(); + testLengthOfReal(); + testValueOfHexDigit(); + } +}; +void testReQStringUtil() { + TestReQStringUtil test; +} + diff --git a/cunit/cuReSettings.cpp b/cunit/cuReSettings.cpp new file mode 100644 index 0000000..f79c3f4 --- /dev/null +++ b/cunit/cuReSettings.cpp @@ -0,0 +1,95 @@ +/* + * cuReSettings.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 + */ + +/** @file + * @brief Unit test of the ReSettings tools. + */ +#include "base/rebase.hpp" +#include "gui/regui.hpp" +/** + * @brief Unit test for ReSettings. + */ +class TestReSettings: public ReTest { +public: + TestReSettings() : + ReTest("ReSettings") { + doIt(); + } + +public: + void testAddHistoryEntry(){ + QByteArray dir(ReFile::tempDir("resettings", NULL, false)); + ReFile::deleteTree((QString) dir, false, &m_logger); + { + ReSettings settings(dir, "test", &m_logger); + settings.addHistoryEntry("digits", "4", ' ', 3); + settings.addHistoryEntry("digits", "3", ' ', 3); + settings.addHistoryEntry("digits", "2", ' ', 3); + settings.addHistoryEntry("digits", "1", ' ', 3); + } + ReSettings settings(dir, "test", &m_logger); + QStringList list; + settings.historyAsList("digits", list); + checkEqu("1 2 3", list.join(' ')); + } + void setSettings(ReSettings& settings){ + settings.insertProperty(new ReProperty("level1.boolVal", "Boolean", + "Boolean value for test", ReSettings::TRUE, PT_BOOL)); + settings.insertProperty(new ReProperty("level1.intVal", "Integer", + "Integer value for test", "4711", PT_INT, "[0,9999]")); + settings.insertProperty(new ReProperty("level2.strVal", "String", + "String value for test", "crazy horse", PT_STRING)); + + } + + void testBasic(){ + QByteArray dir(ReFile::tempDir("resettings", NULL, false)); + ReFile::deleteTree((QString) dir, false, &m_logger); + ReSettings settings(dir, "test", &m_memoryLogger); + setSettings(settings); + settings.writeSettings(); + checkT(settings.boolValue("level1.boolVal")); + checkEqu(4711, settings.intValue("level1.intVal")); + checkEqu("crazy horse", settings.stringValue("level2.strVal")); + // unknown names: + checkF(settings.boolValue("level2.boolVal")); + logContains("level2.boolValue"); + m_memoryAppender.clear(); + checkEqu(0, settings.intValue("level2.intVal")); + logContains("level2.intVal"); + m_memoryAppender.clear(); + checkEqu("", settings.stringValue("strVal")); + logContains("stringVal"); + m_memoryAppender.clear(); + + ReSettings settings2(dir, "test", &m_memoryLogger); + setSettings(settings2); + settings2.changeValue("level1.boolVal", ReSettings::FALSE); + settings2.changeValue("level1.intVal", "1234"); + settings2.changeValue("level2.strVal", "pretty women"); + settings2.writeSettings(); + + settings.readSettings(); + checkF(settings.boolValue("level1.boolVal")); + checkEqu(1234, settings.intValue("level1.intVal")); + checkEqu("pretty woman", settings.stringValue("level2.strVal")); + } + + virtual void run() { + testBasic(); + testAddHistoryEntry(); + } +}; + +void testReSettings() { + TestReSettings test; +} + diff --git a/cunit/cuReStringUtil.cpp b/cunit/cuReStringUtil.cpp deleted file mode 100644 index d71ab6d..0000000 --- a/cunit/cuReStringUtil.cpp +++ /dev/null @@ -1,206 +0,0 @@ -/* - * cuReStringUtil.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 - */ - -/** @file - * @brief Unit test of the QByteArray tools. - */ -#include "base/rebase.hpp" -/** - * @brief Unit test for ReStringUtil. - */ -class TestReStringUtil: public ReTest { -public: - TestReStringUtil() : - ReTest("ReStringUtil") { - doIt(); - } - -public: - void testCountChar() { - checkEqu(1, ReStringUtil::countChar("x", 'x')); - checkEqu(0, ReStringUtil::countChar("X", 'x')); - checkEqu(2, ReStringUtil::countChar("xbxxbxx", 'b')); - } - - void testCount() { - checkEqu(0, ReStringUtil::count("abc", " ")); - checkEqu(1, ReStringUtil::count("abc", "b")); - checkEqu(2, ReStringUtil::count("axx", "x")); - - checkEqu(0, ReStringUtil::count("abbc", "bbb")); - checkEqu(1, ReStringUtil::count("\n\n", "\n\n")); - checkEqu(2, ReStringUtil::count(" a ", " ")); - } - - void testCutString() { - QByteArray source("123"); - QByteArray buffer; - checkEqu(QByteArray("123"), ReStringUtil::cutString(source, 4, buffer)); - checkEqu(QByteArray("123"), ReStringUtil::cutString(source, 3, buffer)); - checkEqu(QByteArray("12..."), - ReStringUtil::cutString(source, 2, buffer)); - checkEqu(QByteArray("12"), - ReStringUtil::cutString(source, 2, buffer, "")); - } - - void testHexDump() { - QByteArray data("abc123\nxyz"); - checkEqu(QByteArray("61 62 63 31 abc1\n" - "32 33 0a 78 23.x\n" - "79 7a yz\n"), - ReStringUtil::hexDump((uint8_t* ) data.constData(), data.length(), - 4)); - checkEqu(QByteArray("61 62 63 31 32 33 0a 78 79 7a abc123.xyz"), - ReStringUtil::hexDump((uint8_t* ) data.constData(), data.length(), - 10)); - checkEqu(QByteArray("61 62 63 31 32 33 0a 78 79 7a abc123.xyz"), - ReStringUtil::hexDump((uint8_t* ) data.constData(), data.length(), - 12)); - } - - void testReadWrite() { - QByteArray fn = getTempFile("test.dat"); - const char* content = "Hello world\nLine2\n"; - checkT(ReStringUtil::write(fn, content)); - checkEqu(content, ReStringUtil::read(fn, false)); - checkEqu(content, ReStringUtil::read(fn, true) + "\n"); - } - - void testToArray() { - QList < QByteArray > array = ReStringUtil::toArray("1 abc 3", " "); - checkEqu(3, array.size()); - checkEqu("1", array.at(0)); - checkEqu("abc", array.at(1)); - checkEqu("3", array.at(2)); - } - - void testToNumber() { - checkEqu("3", ReStringUtil::toNumber(3)); - checkEqu("-33", ReStringUtil::toNumber(-33)); - checkEqu("003", ReStringUtil::toNumber(3, "%03d")); - } - - void testLengthOfNumber() { - checkEqu(3, ReStringUtil::lengthOfNumber("0.3xxx")); - checkEqu(5, ReStringUtil::lengthOfNumber(" \t0.3xxx")); - checkEqu(3, ReStringUtil::lengthOfNumber("-.3xxx")); - checkEqu(2, ReStringUtil::lengthOfNumber(".3exxx")); - checkEqu(2, ReStringUtil::lengthOfNumber(".3e+xxx")); - checkEqu(16, ReStringUtil::lengthOfNumber("1234567.9012E+77")); - checkEqu(17, ReStringUtil::lengthOfNumber("-1234567.9012E+77 ")); - checkEqu(18, ReStringUtil::lengthOfNumber("-1234567.9012E+77 ", true)); - checkEqu(18, ReStringUtil::lengthOfNumber("-1234567.9012E+77 x", true)); - checkEqu(20, - ReStringUtil::lengthOfNumber(" -1234567.9012E+77 x", true)); - } - - void checkCsv(const char* content, char expected) { - QByteArray fn = getTempFile("testrplstring.csv"); - ReStringUtil::write(fn, content); - FILE* fp = fopen(fn, "r"); - checkNN(fp); - char buffer[256]; - checkEqu(expected, - ReStringUtil::findCsvSeparator(fp, buffer, sizeof buffer)); - fclose(fp); - } - - void testFindCsvSeparator() { - const char* content = ",,,\t;;;||||"; - checkCsv(content, '\t'); - - content = "col1,col2\n1.5,3,5\n"; - checkCsv(content, ','); - - content = "col1;col2\n1,50;3.5\n" - "7;8\n10;12\n13;14"; - checkCsv(content, ';'); - - content = "0.3 7.8 8.9\n7.8 9.4 8.3"; - checkCsv(content, ' '); - - content = "0.3|7.8|8.9\n7.8| 9.4|8.3"; - checkCsv(content, '|'); - - content = "0,3;7.8;8.9"; - checkCsv(content, ';'); - } - void testLengthOfUInt64() { - quint64 value = -3; - checkEqu(1, ReStringUtil::lengthOfUInt64("0", 10, &value)); - checkEqu((int64_t ) 0LL, value); - checkEqu(3, ReStringUtil::lengthOfUInt64("432", 10, &value)); - checkEqu((int64_t ) 432LL, value); - checkEqu(3, ReStringUtil::lengthOfUInt64("432 x", 10, &value)); - checkEqu((int64_t ) 432LL, value); - checkEqu(3, ReStringUtil::lengthOfUInt64("432fabc x", 10, &value)); - checkEqu((int64_t ) 432LL, value); - checkEqu(16, - ReStringUtil::lengthOfUInt64("1234567890123567", 10, &value)); - checkEqu((int64_t ) 1234567890123567LL, value); - checkEqu(10, ReStringUtil::lengthOfUInt64("1234abcdef", 16, &value)); - checkEqu((int64_t ) 0x1234abcdefLL, value); - checkEqu(3, ReStringUtil::lengthOfUInt64("432", 8, &value)); - checkEqu((int64_t ) 0432LL, value); - checkEqu(6, ReStringUtil::lengthOfUInt64("765432 ", 8, &value)); - checkEqu((int64_t ) 0765432LL, value); - - checkEqu(0, ReStringUtil::lengthOfUInt64(" ", 8, &value)); - checkEqu(0, ReStringUtil::lengthOfUInt64("", 8, &value)); - } - void testLengthOfReal() { - qreal value; - checkEqu(1, ReStringUtil::lengthOfReal("0", &value)); - checkEqu(0.0, value); - checkEqu(1, ReStringUtil::lengthOfReal("0%", &value)); - checkEqu(0.0, value); - checkEqu(4, ReStringUtil::lengthOfReal("0.25", &value)); - checkEqu(0.25, value); - checkEqu(3, ReStringUtil::lengthOfReal(".25", &value)); - checkEqu(0.25, value); - checkEqu(17, ReStringUtil::lengthOfReal("12345678901234567", &value)); - checkEqu(12345678901234567.0, value); - checkEqu(2, ReStringUtil::lengthOfReal(".5", &value)); - checkEqu(0.5, value); - checkEqu(5, ReStringUtil::lengthOfReal("2.5e2x", &value)); - checkEqu(250.0, value); - checkEqu(6, ReStringUtil::lengthOfReal("2.5e+2", &value)); - checkEqu(250.0, value); - checkEqu(7, ReStringUtil::lengthOfReal("2.5E-33", &value)); - checkEqu(2.5e-33, value); - - checkEqu(3, ReStringUtil::lengthOfReal("2.5E", &value)); - checkEqu(2.5, value); - checkEqu(3, ReStringUtil::lengthOfReal("2.5E+", &value)); - checkEqu(2.5, value); - checkEqu(3, ReStringUtil::lengthOfReal("2.5E-a", &value)); - checkEqu(2.5, value); - } - - virtual void run() { - testLengthOfReal(); - testLengthOfUInt64(); - testCountChar(); - testCount(); - testCutString(); - testToNumber(); - testToArray(); - testHexDump(); - testReadWrite(); - testLengthOfNumber(); - testFindCsvSeparator(); - } -}; - -void testReStringUtil() { - TestReStringUtil test; -} - diff --git a/cunit/cuReStringUtils.cpp b/cunit/cuReStringUtils.cpp new file mode 100644 index 0000000..bb987ab --- /dev/null +++ b/cunit/cuReStringUtils.cpp @@ -0,0 +1,206 @@ +/* + * cuReStringUtil.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 + */ + +/** @file + * @brief Unit test of the QByteArray tools. + */ +#include "base/rebase.hpp" +/** + * @brief Unit test for ReStringUtil. + */ +class TestReStringUtil: public ReTest { +public: + TestReStringUtil() : + ReTest("ReStringUtil") { + doIt(); + } + +public: + void testCountChar() { + checkEqu(1, ReStringUtils::countChar("x", 'x')); + checkEqu(0, ReStringUtils::countChar("X", 'x')); + checkEqu(2, ReStringUtils::countChar("xbxxbxx", 'b')); + } + + void testCount() { + checkEqu(0, ReStringUtils::count("abc", " ")); + checkEqu(1, ReStringUtils::count("abc", "b")); + checkEqu(2, ReStringUtils::count("axx", "x")); + + checkEqu(0, ReStringUtils::count("abbc", "bbb")); + checkEqu(1, ReStringUtils::count("\n\n", "\n\n")); + checkEqu(2, ReStringUtils::count(" a ", " ")); + } + + void testCutString() { + QByteArray source("123"); + QByteArray buffer; + checkEqu(QByteArray("123"), ReStringUtils::cutString(source, 4, buffer)); + checkEqu(QByteArray("123"), ReStringUtils::cutString(source, 3, buffer)); + checkEqu(QByteArray("12..."), + ReStringUtils::cutString(source, 2, buffer)); + checkEqu(QByteArray("12"), + ReStringUtils::cutString(source, 2, buffer, "")); + } + + void testHexDump() { + QByteArray data("abc123\nxyz"); + checkEqu(QByteArray("61 62 63 31 abc1\n" + "32 33 0a 78 23.x\n" + "79 7a yz\n"), + ReStringUtils::hexDump((uint8_t* ) data.constData(), data.length(), + 4)); + checkEqu(QByteArray("61 62 63 31 32 33 0a 78 79 7a abc123.xyz"), + ReStringUtils::hexDump((uint8_t* ) data.constData(), data.length(), + 10)); + checkEqu(QByteArray("61 62 63 31 32 33 0a 78 79 7a abc123.xyz"), + ReStringUtils::hexDump((uint8_t* ) data.constData(), data.length(), + 12)); + } + + void testReadWrite() { + QByteArray fn = getTempFile("test.dat"); + const char* content = "Hello world\nLine2\n"; + checkT(ReStringUtils::write(fn, content)); + checkEqu(content, ReStringUtils::read(fn, false)); + checkEqu(content, ReStringUtils::read(fn, true) + "\n"); + } + + void testToArray() { + QList < QByteArray > array = ReStringUtils::toArray("1 abc 3", " "); + checkEqu(3, array.size()); + checkEqu("1", array.at(0)); + checkEqu("abc", array.at(1)); + checkEqu("3", array.at(2)); + } + + void testToNumber() { + checkEqu("3", ReStringUtils::toNumber(3)); + checkEqu("-33", ReStringUtils::toNumber(-33)); + checkEqu("003", ReStringUtils::toNumber(3, "%03d")); + } + + void testLengthOfNumber() { + checkEqu(3, ReStringUtils::lengthOfNumber("0.3xxx")); + checkEqu(5, ReStringUtils::lengthOfNumber(" \t0.3xxx")); + checkEqu(3, ReStringUtils::lengthOfNumber("-.3xxx")); + checkEqu(2, ReStringUtils::lengthOfNumber(".3exxx")); + checkEqu(2, ReStringUtils::lengthOfNumber(".3e+xxx")); + checkEqu(16, ReStringUtils::lengthOfNumber("1234567.9012E+77")); + checkEqu(17, ReStringUtils::lengthOfNumber("-1234567.9012E+77 ")); + checkEqu(18, ReStringUtils::lengthOfNumber("-1234567.9012E+77 ", true)); + checkEqu(18, ReStringUtils::lengthOfNumber("-1234567.9012E+77 x", true)); + checkEqu(20, + ReStringUtils::lengthOfNumber(" -1234567.9012E+77 x", true)); + } + + void checkCsv(const char* content, char expected) { + QByteArray fn = getTempFile("testrplstring.csv"); + ReStringUtils::write(fn, content); + FILE* fp = fopen(fn, "r"); + checkNN(fp); + char buffer[256]; + checkEqu(expected, + ReStringUtils::findCsvSeparator(fp, buffer, sizeof buffer)); + fclose(fp); + } + + void testFindCsvSeparator() { + const char* content = ",,,\t;;;||||"; + checkCsv(content, '\t'); + + content = "col1,col2\n1.5,3,5\n"; + checkCsv(content, ','); + + content = "col1;col2\n1,50;3.5\n" + "7;8\n10;12\n13;14"; + checkCsv(content, ';'); + + content = "0.3 7.8 8.9\n7.8 9.4 8.3"; + checkCsv(content, ' '); + + content = "0.3|7.8|8.9\n7.8| 9.4|8.3"; + checkCsv(content, '|'); + + content = "0,3;7.8;8.9"; + checkCsv(content, ';'); + } + void testLengthOfUInt64() { + quint64 value = -3; + checkEqu(1, ReStringUtils::lengthOfUInt64("0", 10, &value)); + checkEqu((int64_t ) 0LL, value); + checkEqu(3, ReStringUtils::lengthOfUInt64("432", 10, &value)); + checkEqu((int64_t ) 432LL, value); + checkEqu(3, ReStringUtils::lengthOfUInt64("432 x", 10, &value)); + checkEqu((int64_t ) 432LL, value); + checkEqu(3, ReStringUtils::lengthOfUInt64("432fabc x", 10, &value)); + checkEqu((int64_t ) 432LL, value); + checkEqu(16, + ReStringUtils::lengthOfUInt64("1234567890123567", 10, &value)); + checkEqu((int64_t ) 1234567890123567LL, value); + checkEqu(10, ReStringUtils::lengthOfUInt64("1234abcdef", 16, &value)); + checkEqu((int64_t ) 0x1234abcdefLL, value); + checkEqu(3, ReStringUtils::lengthOfUInt64("432", 8, &value)); + checkEqu((int64_t ) 0432LL, value); + checkEqu(6, ReStringUtils::lengthOfUInt64("765432 ", 8, &value)); + checkEqu((int64_t ) 0765432LL, value); + + checkEqu(0, ReStringUtils::lengthOfUInt64(" ", 8, &value)); + checkEqu(0, ReStringUtils::lengthOfUInt64("", 8, &value)); + } + void testLengthOfReal() { + qreal value; + checkEqu(1, ReStringUtils::lengthOfReal("0", &value)); + checkEqu(0.0, value); + checkEqu(1, ReStringUtils::lengthOfReal("0%", &value)); + checkEqu(0.0, value); + checkEqu(4, ReStringUtils::lengthOfReal("0.25", &value)); + checkEqu(0.25, value); + checkEqu(3, ReStringUtils::lengthOfReal(".25", &value)); + checkEqu(0.25, value); + checkEqu(17, ReStringUtils::lengthOfReal("12345678901234567", &value)); + checkEqu(12345678901234567.0, value); + checkEqu(2, ReStringUtils::lengthOfReal(".5", &value)); + checkEqu(0.5, value); + checkEqu(5, ReStringUtils::lengthOfReal("2.5e2x", &value)); + checkEqu(250.0, value); + checkEqu(6, ReStringUtils::lengthOfReal("2.5e+2", &value)); + checkEqu(250.0, value); + checkEqu(7, ReStringUtils::lengthOfReal("2.5E-33", &value)); + checkEqu(2.5e-33, value); + + checkEqu(3, ReStringUtils::lengthOfReal("2.5E", &value)); + checkEqu(2.5, value); + checkEqu(3, ReStringUtils::lengthOfReal("2.5E+", &value)); + checkEqu(2.5, value); + checkEqu(3, ReStringUtils::lengthOfReal("2.5E-a", &value)); + checkEqu(2.5, value); + } + + virtual void run() { + testLengthOfReal(); + testLengthOfUInt64(); + testCountChar(); + testCount(); + testCutString(); + testToNumber(); + testToArray(); + testHexDump(); + testReadWrite(); + testLengthOfNumber(); + testFindCsvSeparator(); + } +}; + +void testReStringUtil() { + TestReStringUtil test; +} + diff --git a/cunit/cuReWriter.cpp b/cunit/cuReWriter.cpp index 586567a..f9d45f7 100644 --- a/cunit/cuReWriter.cpp +++ b/cunit/cuReWriter.cpp @@ -36,7 +36,7 @@ private: writer.format("%3c%.2f", ':', 3.1415); writer.writeLine(); writer.close(); - QByteArray current = ReStringUtil::read(fn, false); + QByteArray current = ReStringUtils::read(fn, false); checkEqu("abc\n0042\n\t\t\t123\n\t\tpi :3.14\n", current); } diff --git a/cunit/cunit.pro b/cunit/cunit.pro index f04aecf..6bb2b9e 100644 --- a/cunit/cunit.pro +++ b/cunit/cunit.pro @@ -16,8 +16,10 @@ TEMPLATE = app INCLUDEPATH = .. SOURCES += main.cpp \ - cuReQStringUtil.cpp \ - cuReStringUtil.cpp \ + cuReQStringUtils.cpp \ + cuReStringUtils.cpp \ + cuReFile.cpp \ + cuReFileUtils.cpp \ cuReByteStorage.cpp \ cuReException.cpp \ ../base/ReByteStorage.cpp \ @@ -26,21 +28,23 @@ SOURCES += main.cpp \ ../base/ReContainer.cpp \ ../base/ReException.cpp \ ../base/ReFile.cpp \ - ../base/ReQStringUtil.cpp \ + ../base/ReFileUtils.cpp \ + ../base/ReQStringUtils.cpp \ ../base/ReLogger.cpp \ - ../base/ReStringUtil.cpp \ + ../base/ReStringUtils.cpp \ ../base/ReTerminator.cpp \ ../base/ReTest.cpp \ ../base/ReWriter.cpp \ ../gui/ReStateStorage.cpp \ + ../gui/ReSettings.cpp \ ../gui/ReEdit.cpp \ cuReConfig.cpp \ cuReContainer.cpp \ cuReWriter.cpp \ cuReCharPtrMap.cpp \ - cuReFile.cpp \ cuReEdit.cpp \ cuReStateStorage.cpp \ + cuReSettings.cpp \ allTests.cpp HEADERS += \ diff --git a/gui/ReSettings.cpp b/gui/ReSettings.cpp new file mode 100644 index 0000000..2133768 --- /dev/null +++ b/gui/ReSettings.cpp @@ -0,0 +1,349 @@ +/* + * storage.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 "gui/regui.hpp" + +enum { + LOC_BOOL_VALUE_1 = LOC_FIRST_OF(LOC_SETTINGS), // 11701 + LOC_BOOL_VALUE_2, // 11702 + LOC_INT_VALUE_1, // 11703 + LOC_INT_VALUE_2, // 11704 + LOC_STRING_VALUE_1, // 11705 + LOC_STRING_VALUE_2, // 11706 + LOC_WRITE_SETTINGS_1, // 11707 + LOC_READ_SETTINGS_1, // 11708 + LOC_READ_SETTINGS_2, // 11709 + LOC_READ_SETTINGS_3, // 11710 + LOC_CHANGE_VALUE_1, // 11711 + LOC_CHANGE_VALUE_2, // 11712 +}; + +QString ReSettings::TRUE = "t"; +QString ReSettings::FALSE = ""; + +/** + * Constructor. + * + * @param name name of the property + * @param title title in the configuration form (translated) + * @param description description in the form (translated) + * @param defaultValue the value if not user defined + * @param type the type of the property + * @param limits NULL or some rules for the property value + */ +ReProperty::ReProperty(const char* name, const QString& title, const QString& description, const QString& defaultValue, RePropertyType type, const char* limits) : + m_name(name), + m_title(title), + m_description(description), + m_value(defaultValue), + m_defaultValue(defaultValue), + m_type(type), + m_limits(limits) { +} + +/** + * Tests whether a given value is allowed respecting the m_limits + * @param value the value to test + * @param error OUT: NULL or the error message + * @return true: the value is allowed
+ */ +bool ReProperty::isValid(const QString& value, QString* error) +{ + bool rc = true; + if (error != NULL) + *error = ""; + if (m_limits != NULL){ + switch(m_type){ + case PT_BOOL: + break; + case PT_INT: + { + int nValue = value.toInt(&rc); + if (! rc){ + if (error != NULL) + *error = QObject::tr("not an integer: ") + value; + } else { + int minimum, maximum; + if (sscanf(m_limits, "[%d,%d]", &minimum, &maximum) == 2) + { + if (nValue < minimum){ + rc = false; + if (error != NULL) + *error = value + " < " + minimum; + } else if (nValue > maximum){ + rc = false; + if (error != NULL) + *error = value + " < " + maximum; + } + } + } + break; + } + case PT_STRING: + break; + default: + break; + } + } + return rc; +} + +/** + * Constructor. + * + * @param path the parent directory for the storage files + * @param prefix type of the storage: "proj" or "ws" (workspace) + */ +ReSettings::ReSettings(const QString& path, const QString prefix, ReLogger* logger) : + m_path(path), + m_fileHistory(path + OS_SEPARATOR + prefix + ".history"), + m_fileSettings( + path + OS_SEPARATOR + prefix + ".settings"), + m_settings(), + m_chapters(), + m_logger(logger) { + +} + +/* + * Adds an entry to a history item at the first position. + * + * The entry will removed from the other positions. + * + * @param key the key in the map + * @param value the value to add + * @param separator separates the entries in the history item + * @param maxEntries the maximal count of entries in the history item.
+ * If the number exceeds the last entries will be removed + * @param form the prefix of the key. If NULL the current form will be taken + */ +void ReSettings::addHistoryEntry(const char* key, const QString& value, + char separator, int maxEntries) { + ReStateStorage store(m_fileHistory); + store.addHistoryEntry(key, value, separator, maxEntries); + store.close(); + store.flushMap(); +} + +/** + * Returns the value of a boolean property. + * + * @param name the name of the property + * @return the value of the property + */ +bool ReSettings::boolValue(const char* name) { + bool rc = false; + ReProperty* property = m_settings.value(name, NULL); + if (property == NULL) + m_logger->logv(LOG_ERROR, LOC_BOOL_VALUE_1, "missing bool property %s", + name); + else if (property->m_type != PT_BOOL) + m_logger->logv(LOG_ERROR, LOC_BOOL_VALUE_2, "not a bool property %s", + name); + else + rc = !property->m_value.isEmpty(); + return rc; +} + +/** + * Changes the value of an existing property. + * + * @param name the name of the property + * @param value the new value + */ +void ReSettings::changeValue(const char* name, const QString& value) +{ + QString error; + ReProperty* property = m_settings.value(name, NULL); + if (property == NULL) + m_logger->logv(LOG_ERROR, LOC_CHANGE_VALUE_1, "unknown property: %s", + name); + else if (!property->isValid(value, &error)) + m_logger->logv(LOG_ERROR, LOC_CHANGE_VALUE_2, "invalid value for %s: %s\n+++ %s", + name, value.toUtf8().constData(), + error.toUtf8().constData()); + else + property->m_value = value; +} + +/** + * Returns a history item as a list. + * + * @param key key of the history item + * @param list OUT: the list is filled with the history entries + * @param form a common prefix of the key. If NULL the current form is used + * @return list (for chaining) + */ +QStringList&ReSettings::historyAsList(const char* key, QStringList& list, + const char* form) { + ReStateStorage store(m_fileHistory); + QStringList& rc = store.historyAsList(key, list, form); + store.close(); + return rc; +} + +/** + * Inserts a property. + * + * @param property the property to insert + */ +void ReSettings::insertProperty(ReProperty* property) { + m_settings.insert(property->m_name, property); + QByteArray chapter(property->m_name); + int ix = chapter.lastIndexOf('.'); + chapter = chapter.left(ix); + QList* list = m_chapters.value(chapter, NULL); + if (list == NULL) { + m_chapters.insert(chapter, list = new QList()); + } + list->append(property); +} + +/** + * Returns the value of an integer property. + * + * @param name the name of the property + * @return the value of the property + */ +int ReSettings::intValue(const char* name) { + int rc = 0; + ReProperty* property = m_settings.value(name, NULL); + if (property == NULL) + m_logger->logv(LOG_ERROR, LOC_INT_VALUE_1, "missing int property %s", + name); + else if (property->m_type != PT_INT) + m_logger->logv(LOG_ERROR, LOC_INT_VALUE_2, "not a int property %s", + name); + else + rc = property->m_value.toInt(); + return rc; +} + +/** + * Returns the directory containing the configuration data. + * + * @return the name of the storage's directory + */ +QString ReSettings::path() const { + return m_path; +} + +/** + * Reads the configuration file. + */ +void ReSettings::readSettings() +{ + QFile file(m_fileSettings); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) + m_logger->logv(LOG_ERROR, LOC_READ_SETTINGS_1, "cannot open (%d): ", + errno, m_fileSettings.toUtf8().constData()); + else{ + QTextStream input(&file); + int lineNo = 0; + while (!input.atEnd()) { + lineNo++; + QString line = input.readLine(); + int ix = line.indexOf('='); + if (ix < 0) + m_logger->logv(LOG_ERROR, LOC_READ_SETTINGS_2, "missing '=': %s-%d: %s", + m_fileSettings.toUtf8().constData(), lineNo, + line.mid(0, 20).toUtf8().constData()); + else if (ix == 0 || ix == 1 && line.at(0) == '!') + m_logger->logv(LOG_ERROR, LOC_READ_SETTINGS_3, "line starts with '=': %s-%d: %s", + m_fileSettings.toUtf8().constData(), lineNo, + line.mid(0, 20).toUtf8().constData()); + else { + QByteArray name; + QString value; + if (line.at(ix-1) == '!'){ + name = line.left(ix - 1).toUtf8(); + value = line.mid(ix + 1); + value.replace("\\\\", "\01").replace("\\n", "\n") + .replace("\\r", "\r").replace('\01', '\\'); + } else { + name = line.left(ix).toUtf8(); + value = line.mid(ix + 1); + } + ReProperty* property = m_settings.value(name, NULL); + if (property != NULL){ + switch(property->m_type){ + case PT_BOOL: + property->m_value = value.isEmpty() ? ReSettings::FALSE + : ReSettings::TRUE; + break; + case PT_INT: + if (property->isValid(value)) + property->m_value = value; + break; + case PT_STRING: + if (property->isValid(value)) + property->m_value = value; + break; + default: + break; + } + } + } + } + file.close(); + } +} + +/** + * Returns the value of a string property. + * + * @param name the name of the property + * @return the value of the property + */ +QString ReSettings::stringValue(const char* name) { + QString rc = ""; + ReProperty* property = m_settings.value(name, NULL); + if (property == NULL) + m_logger->logv(LOG_ERROR, LOC_STRING_VALUE_1, + "missing string property %s", name); + else if (property->m_type != PT_STRING) + m_logger->logv(LOG_ERROR, LOC_STRING_VALUE_2, + "not a string property %s", name); + else + rc = property->m_value; + return rc; +} + +/** + * Writes the values into the configuration file. + */ +void ReSettings::writeSettings() +{ + QFile file(m_fileSettings); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) + m_logger->logv(LOG_ERROR, LOC_WRITE_SETTINGS_1, "cannot open (%d): ", + errno, m_fileSettings.toUtf8().constData()); + else{ + QTextStream out(&file); + QMap::const_iterator it; + for (it = m_settings.cbegin(); it != m_settings.cend(); ++it){ + ReProperty* property = it.value(); + if (property->m_value == property->m_defaultValue){ + // we do not write the default value + } else if (it.value()->m_value.indexOf('\n') <= 0) + out << it.key() << "=" << it.value()->m_value << "\n"; + else{ + QString value = it.value()->m_value; + out << it.key() << "!=" << value.replace("\\", "\\\\") + .replace("\n", "\\n").replace("\r", "\\r") << "\n"; + } + } + file.close(); + } +} + + diff --git a/appl/reditor/storage.hpp b/gui/ReSettings.hpp similarity index 56% rename from appl/reditor/storage.hpp rename to gui/ReSettings.hpp index 84f7c7b..210c7bd 100644 --- a/appl/reditor/storage.hpp +++ b/gui/ReSettings.hpp @@ -12,57 +12,55 @@ #ifndef STORAGE_HPP #define STORAGE_HPP -enum PropertyType { +enum RePropertyType { PT_UNDEF, PT_INT, PT_STRING, PT_BOOL }; -class Property { +class ReProperty { public: - Property(const char* name, const QString& title, const QString& description, - const QString& defaultValue, PropertyType type, const char* limits = - NULL) : - m_name(name), - m_title(title), - m_description(description), - m_value(defaultValue), - m_defaultValue(defaultValue), - m_type(type), - m_limits(limits) { - } - + ReProperty(const char* name, const QString& title, const QString& description, + const QString& defaultValue, RePropertyType type, const char* limits = + NULL); +public: + bool isValid(const QString& value, QString* error = NULL); public: const char* m_name; QString m_title; QString m_description; QString m_value; QString m_defaultValue; - PropertyType m_type; + RePropertyType m_type; const char* m_limits; }; -class Storage { +class ReSettings { public: - Storage(const QString& path, const QString prefix, ReLogger* logger); + static QString TRUE; + static QString FALSE; +public: + ReSettings(const QString& path, const QString prefix, ReLogger* logger); public: void addHistoryEntry(const char* key, const QString& value, char separator, - int maxEntries); + int maxEntries); bool boolValue(const char* name); + void changeValue(const char* name, const QString& value); QStringList& historyAsList(const char* key, QStringList& list, - const char* form = NULL); + const char* form = NULL); + void insertProperty(ReProperty* property); int intValue(const char* name); QString path() const; + void readSettings(); QString stringValue(const char* name); -protected: - void insertProperty(Property* property); + void writeSettings(); protected: QString m_path; QString m_fileHistory; QString m_fileSettings; - QMap m_settings; - QMap*> m_chapters; + QMap m_settings; + QMap*> m_chapters; ReLogger* m_logger; }; diff --git a/gui/regui.hpp b/gui/regui.hpp index ba1fc14..f5dc636 100644 --- a/gui/regui.hpp +++ b/gui/regui.hpp @@ -15,6 +15,7 @@ #include "gui/ReStateStorage.hpp" #include "gui/ReGuiValidator.hpp" #include "gui/ReEdit.hpp" +#include "gui/ReSettings.hpp" /** * Tests whether a point is inside the rectangle (including border). * @param rect rectangle to test diff --git a/remodules.hpp b/remodules.hpp index ee1cb35..af5562c 100644 --- a/remodules.hpp +++ b/remodules.hpp @@ -12,7 +12,11 @@ #define RPLMODULES_HPP enum { - LOC_LOGGER = 101, LOC_CONFIG, LOC_CONTAINER, LOC_EXCEPTION, LOC_TEST, // 105 + LOC_LOGGER = 101, + LOC_CONFIG, + LOC_CONTAINER, + LOC_EXCEPTION, + LOC_TEST, // 105 LOC_TCPSERVER, LOC_TCPCLIENT, LOC_TCPPEER, @@ -24,13 +28,14 @@ enum { LOC_VM, LOC_MFPARSER, // 115 LOC_TRAVERSER, - LOC_STORAGE + LOC_SETTINGS, + LOC_FILE, }; #define LOC_FIRST_OF(moduleNo) (moduleNo*100+1) class RplModules { public: - static int fileToNumber(const char* file); - static const char* numberToFile(int location); + static int fileToNumber(const char* file); + static const char* numberToFile(int location); }; #endif // RPLMODULES_HPP -- 2.39.5