}
#elif defined __WIN32__
struct stat info;
- m_valid = stat(path, &info) == 0 && S_ISDIR(info.st_mode);
+ ReByteBuffer thePath(m_path);
+ if (m_path.endsWith(ReStringUtils::pathSeparatorStr()))
+ thePath.setLength(thePath.length() - 1);
+ m_valid = stat(thePath.str(), &info) == 0 && S_ISDIR(info.st_mode);
#endif
}
/** @brief Returns the name of the directory.
rc = findNext();
}
#elif defined __WIN32__
- m_handle = FindFirstFileA(pattern, &m_data);
+ ReByteBuffer full(m_path);
+ full.append(ReStringUtils::pathSeparatorStr(), -1).append(pattern, -1);
+ m_handle = FindFirstFileA(full.str(), &m_data);
rc = m_handle != INVALID_HANDLE_VALUE;
#endif
}
m_values(),
m_args(NULL),
m_argCount(0),
+ m_program("?"),
m_lastError()
{
m_usage.split(usageString, '\n');
ReByteBuffer buffer;
ReVarArgs args;
if (! m_properties.get(name, -1, buffer))
- ReOptionException(this, i18n("$1 is not an option name"), name);
+ throw ReOptionException(this, i18n("$1 is not an option name"), name);
properties.split(buffer.str(), '\1');
if (properties.strOf(IxType)[0] != 'b')
- ReOptionException(this, i18n("$1 is not an boolean option. Type is $2"), name,
+ throw ReOptionException(this, i18n("$1 is not an boolean option. Type is $2"), name,
properties.strOf(IxType));
m_values.get(name, -1, buffer);
ReByteBuffer buffer;
ReVarArgs args;
if (! m_properties.get(name, -1, buffer))
- ReOptionException(this, i18n("$1 is not an option name"), name);
+ throw ReOptionException(this, i18n("$1 is not an option name"), name);
properties.split(buffer.str(), '\1');
if (properties.strOf(IxType)[0] != DT_INT)
- ReOptionException(this, i18n("$1 is not an integer option. Type is $2"), name,
+ throw ReOptionException(this, i18n("$1 is not an integer option. Type is $2"), name,
properties.strOf(IxType));
m_values.get(name, -1, buffer);
ReStringList properties;
ReVarArgs args;
if (! m_properties.get(name, -1, buffer))
- ReOptionException(this, i18n("$1 is not an option name"), name);
+ throw ReOptionException(this, i18n("$1 is not an option name"), name);
properties.split(buffer.str(), '\1');
DataType dataType = (DataType) properties.strOf(IxType)[0];
if (dataType != DT_STRING && dataType != DT_STRING_EMPTY)
- ReOptionException(this, i18n("$1 is not a string option. Type is $2"), name,
+ throw ReOptionException(this, i18n("$1 is not a string option. Type is $2"), name,
properties.strOf(IxType));
m_values.get(name, -1, buffer);
name.set(&shortName, 1);
else
name.set(longName, lengthLongName);
- ReOptionException(this, i18n("Unknown option: $1"), name.str());
+ throw ReOptionException(this, i18n("Unknown option: $1"), name.str());
}
}
/** @brief Sets the option value.
switch(dataType[0]){
case DT_INT:
if (strspn(value, "01234567890") != strlen(value))
- ReOptionException(this, i18n("Option $1 expect an integer as parameter, not $2"),
+ throw ReOptionException(this, i18n("Option $1 expect an integer as parameter, not $2"),
name, value);
break;
case DT_STRING:
if (value[0] == '\0')
- ReOptionException(this, i18n("Option $1: Empty parameter is not allowed"), name);
+ throw ReOptionException(this, i18n("Option $1: Empty parameter is not allowed"), name);
break;
case DT_STRING_EMPTY:
case DT_BOOL:
if (dataType[0] == DT_STRING_EMPTY)
setValue(nameStr, "", dataType);
else
- ReOptionException(this, i18n("Option $1 has type $2! There is no parameter."),
+ throw ReOptionException(this, i18n("Option $1 has type $2! There is no parameter."),
nameStr, dataType);
} else {
setValue(nameStr, nextArg, dataType);
switch(dataType[0]){
case DT_INT:
if (value == NULL)
- ReOptionException(this, i18n("Option $1: parameter expected. Use --$2=number"),
+ throw ReOptionException(this, i18n("Option $1: parameter expected. Use --$2=number"),
nameStr, nameStr);
else
setValue(nameStr, value, dataType);
break;
case DT_STRING:
if (value == NULL)
- ReOptionException(this, i18n("Option $1: parameter expected. Use --$2=string"),
+ throw ReOptionException(this, i18n("Option $1: parameter expected. Use --$2=string"),
nameStr, nameStr);
setValue(nameStr, value, dataType);
break;
boolValue = "t";
else if (! ReStringUtils::isInList(value, ReConfigFile::m_falseValues,
true, ReStringUtils::AUTO_SEPARATOR))
- ReOptionException(this, i18n("Option $1: Not a boolean value: $2. Use true or false"),
+ throw ReOptionException(this, i18n("Option $1: Not a boolean value: $2. Use true or false"),
nameStr, value);
// Invert the default value:
if (properties.strOf(IxDefault)[0] == 't')
* @return the instance itself (for chaining)
*/
ReStringList& ReStringList::append(const char* source, Tag tagOf){
- add(-1, source, -1, tagOf);
+ add(-1, source, strlen(source) + 1, tagOf);
return *this;
}
/** @brief Appends a string at the end.
* @return the instance itself (for chaining)
*/
ReStringList& ReStringList::append(const ReByteBuffer& source, Tag tagOf){
- add(-1, source.str(), source.length(), tagOf);
+ add(-1, source.str(), source.length() + 1, tagOf);
return *this;
}
*/
ReStringList& ReStringList::append(ReStringList& source){
for (size_t ii = 0; ii < source.count(); ii++)
- add(-1, source.strOf(ii), -1, source.tagOf(ii));
+ add(-1, source.strOf(ii), source.sizeOf(ii), source.tagOf(ii));
return *this;
}
/** @brief Inserts a string at a given index.
* This class knows nothing about this.
*/
void ReStringList::insert(Index index, const char* source, Tag tagOf){
- add(index, source, -1, tagOf);
+ add(index, source, strlen(source) + 1, tagOf);
}
/** @brief Replaces an element in the internal array: a string and a tagOf.
*
* @param tagOf The tagOf of the replace element.
*/
void ReStringList::replace(Index index, const char* source, Tag tagOf){
- set(index, source, -1, tagOf);
+ set(index, source, strlen(source) + 1, tagOf);
}
/** @brief Replaces a string in the internal array.
*
void ReStringList::replaceString(Index index, const char* source){
if (index < count()){
Sequence* seq = getInfo(index);
- set(index, source, -1, seq->m_tag);
+ set(index, source, strlen(source) + 1, seq->m_tag);
}
}
/** @brief Replaces a tagOf in the internal array.
#include "base/rebase.hpp"
-char ReStringUtils::slash = ReStringUtils::initPathSeparator();
-const char* ReStringUtils::slashStr = NULL;
+#if defined __linux__
+char ReStringUtils::slash = '/';
+const char* ReStringUtils::slashStr = "/";
+#elif defined __WIN32__
+char ReStringUtils::slash = '\\';
+const char* ReStringUtils::slashStr = "\\";
+#endif
const char ReStringUtils::AUTO_SEPARATOR = '\0';
*/
void ReStringUtils::splitPath(const char* fullname,
ReByteBuffer* protocol, ReByteBuffer* path, ReByteBuffer* name, ReByteBuffer* ext){
+ const char currentSlash = strchr(fullname, '/') != NULL ? '/' : slash;
const char* start = strchr(fullname, ':');
if (protocol != NULL){
protocol->setLength(0);
else
start++;
- const char* end = strrchr(start, slash);
+ const char* end = strrchr(start, currentSlash);
if (path != 0){
path->setLength(0);
*/
ReTestUnit::~ReTestUnit() {
if (m_errorCount > 0)
- logF(true, i18n("%s: %d error(s)"), m_name, m_errorCount);
+ logF(false, i18n("+++ %s: %d error(s)"), m_name, m_errorCount);
free((void*) m_name);
free((void*) m_sourceFile);
}
{
if (! condition){
logF(true, i18n("%s-%d: not true!"), m_sourceFile, lineNo);
- m_errorCount++;
}
}
/** @brief Checks a boolean expression. A true value will be logged.
{
if (condition){
logF(true, i18n("%s-%d: not false!"), m_sourceFile, lineNo);
- m_errorCount++;
}
}
/** @brief Checks a pointer expression. A not <code>null</code> value will be logged.
void ReTestUnit::assertNull(void* pointer, int lineNo){
if (pointer != NULL){
logF(true, "%s-%d: is not null %lx", m_sourceFile, lineNo, pointer);
- m_errorCount++;
}
}
/** @brief Checks a pointer expression. A <code>null</code> value will be logged.
void ReTestUnit::assertNotNull(void* pointer, int lineNo){
if (pointer == NULL){
logF(true, i18n("%s-%d: is null"), m_sourceFile, lineNo);
- m_errorCount++;
}
}
/** @brief Compares two integer values. If not equal this will be logged.
if (expected != current){
logF(true, i18n("%s-%d: expected: %ld (%lx) current: %ld (%lx)"),
m_sourceFile, lineNo, expected, expected, current, current);
- m_errorCount++;
}
}
/** @brief Compares two integer values. If not equal this will be logged.
if (expected != current){
logF(true, i18n("%s-%d: expected: %ld (%lx) current: %ld (%lx)"),
m_sourceFile, lineNo, expected, expected, current, current);
- m_errorCount++;
}
}
/** @brief Compares two integer values. If not equal this will be logged.
if (expected != current){
logF(true, i18n("%s-%d: expected: %lld (%llx) current: %lld (%llx)"),
m_sourceFile, lineNo, expected, expected, current, current);
- m_errorCount++;
}
}
/** @brief Compares two string values. If not equal this will be logged.
logF(true, i18n("%s-%d: expected / current: length: %d / %d\n%.512s\n%.512s"),
m_sourceFile, lineNo, strlen(expected), current == NULL ? 0 : strlen(current),
expected, current == NULL ? "<null>" : current);
- m_errorCount++;
}
}
/** @brief Checks whether a file exists. If not this will be logged.
if (stat(name, &info) != 0){
logF(true, i18n("%s-%d: File does not exist: %s"),
m_sourceFile, lineNo, name);
- m_errorCount++;
} else if (S_ISDIR(info.st_mode)){
logF(true, i18n("%s-%d: File does exist but this is a directory: %s"),
m_sourceFile, lineNo, name);
- m_errorCount++;
}
}
/** @brief Creates an empty temporary directory.
if (stat(dir, &info) != 0){
logF(true, i18n("%s-%d: Directory does not exist: %s"),
m_sourceFile, lineNo, dir);
- m_errorCount++;
} else if (! S_ISDIR(info.st_mode)){
logF(true, i18n("%s-%d: File exists but this is not a directory: %s"),
m_sourceFile, lineNo, dir);
- m_errorCount++;
}
}
*/
bool ReTestUnit::log(bool isError, const char* message){
printf("%s%s\n", isError ? "+++ " : "", message);
+ if (isError)
+ m_errorCount++;
return ! isError;
}
/** @brief Logs a formated message with placeholders.
checkEqu("abc.2.txt", finder.currentFile());
checkF(finder.findNext());
checkF(finder.findFirst("abx.*.txt", false));
-
+#ifdef __linux__
checkT(finder.findFirst("abc[.][0-9][.]txt", true));
checkEqu("abc.1.txt", finder.currentFile());
checkT(finder.findNext());
checkEqu("abc.2.txt", finder.currentFile());
checkF(finder.findNext());
checkF(finder.findFirst("abx[.][0-9][.]txt", true));
+#endif
}
};
extern void testReDirectory(void);
}
private:
void run(){
- checkEqu("dies ist ein Test", i18n("this is a test"));
- checkEqu("eins: 1 zwei: 2", i18nf("one: $1 two: $2").arg(1).arg(2).asCString());
+ checkEqu("this is a test", i18n("this is a test"));
+ checkEqu("one: 1 two: 2", i18nf("one: $1 two: $2").arg(1).arg(2).asCString());
}
};
void run(){
testLong();
testShort();
+ testWrong();
}
+ void testWrong(){
+ ReProgramArgs args("test","example");
+ args.addBool("boolarg", "This is a boolean arg", 'b', "boolval", false);
+ try {
+ char* argv[] = { "test", "-v" };
+ args.init(2, argv);
+ checkF(true);
+ } catch (ReOptionException& exc) {
+ checkEqu("Unknown option: v", exc.getMessage());
+ }
+ }
void testShort(){
ReProgramArgs args("test <opts> <args>\nThis tests the usage of ReProgramArgs",
"$0 -b+ -B- file dir\n\ttest of an example");
ReStringList list;
ReByteBuffer line;
line.set("Hi", -1);
- list.append(line, 1ll).append(line.append("!", -1), -5ll);
+ list.append(line, 99ll);
+ line.append("!", -1);
+ list.append(line, -5ll);
checkEqu(2u, list.count());
- checkEqu(1ll, list.tagOf(0));
+ checkEqu(99ll, list.tagOf(0));
checkEqu("Hi", list.strOf(0));
checkEqu(-5ll, list.tagOf(1));
TestReTraverser() : ReTestUnit("ReTraverser", __FILE__){
createTestDir();
m_base = getTestDir();
+ m_base.append("traverser").append(ReTraverser::m_separatorStr, -1);
+ _mkdir(m_base.str());
run();
}
private:
ReByteBuffer path(m_base);
path.append("/").append(relPath);
path.replaceAll("/", 1, ReTraverser::m_separatorStr, -1);
- createFile(path.str(), path.str());
+ createFile(path.str(), relPath);
struct stat info;
if (stat(path.str(), &info) != 0){
logF(true, "cannot create file %1$s", path.str());
// "1 t:\temp\winfried\2\retestunit\dir1\n"
buffer.set(list.strOf(0), list.strLengthOf(0));
checkT(buffer.startsWith("1\t"));
- expected.set(m_base.str(), m_base.length()).append("dir1", -1);
+ expected.set(m_base.str(), m_base.length()).append("dir1", -1)
+ .append(ReTraverser::m_separatorStr);
// .append(ReTraverser::m_separatorStr, -1)
checkT(buffer.endsWith(expected.str()));
log(false, list2.join("\n", buffer).str());
buffer.set(list.strOf(0), list.strLengthOf(0));
- checkT(buffer.startsWith(" 0.000116 MB 2 3\t"));
- expected.set(m_base.str(), m_base.length()).append("dir1", -1);
+ checkT(buffer.startsWith(" 0.000054 MB 2 3\t"));
+ expected.set(m_base.str(), m_base.length()).append("dir1", -1)
+ .append(ReTraverser::m_separatorStr);
checkT(buffer.endsWith(expected.str()));
buffer.set(list.strOf(1), list.strLengthOf(1));
- checkT(buffer.startsWith(" 0.000039 MB 1 0\t"));
- expected.set(m_base.str(), m_base.length()).append("dir2", -1);
+ checkT(buffer.startsWith(" 0.000008 MB 1 0\t"));
+ expected.set(m_base.str(), m_base.length()).append("dir2", -1)
+ .append(ReTraverser::m_separatorStr);
checkT(buffer.endsWith(expected.str()));
buffer.set(list.strOf(2), list.strLengthOf(2));
- checkT(buffer.startsWith(" 0.000191 MB 4 5\t"));
+ checkT(buffer.startsWith(" 0.000067 MB 4 5\t"));
expected.set(m_base.str(), m_base.length());
}
};
testReString();
extern void testReVarArgs(void);
testReVarArgs();
- extern void testReLogger(void);
- testReLogger();
extern void testReDirectory(void);
testReDirectory();
extern void testReProgramArgs(void);
testReProgramArgs();
+ extern void testReLogger(void);
+ testReLogger();
}
void testString(){
- void testReString();
+ extern void testReStringList(void);
+ testReStringList();
+
+ void testReString();
testReString();
extern void testReI18N(void);
testReI18N();
void testAll(){
try
{
+ testString();
testOs();
testBase();
- testString();
} catch (ReException e){
fprintf(stderr, "testBase.cpp: unexpected exception: %s\n", e.getMessage());
}
exit(1);
}
+static const char* statisticCall[] = {
+ "<command>:"
+ "st(atistic) [<opts_stat>] <path> [<depth>]",
+ " shows a statistic about a directory tree",
+ "<path> a directory path: relative or absolute",
+ "<depth> 0: only the summary of <path> will be shown",
+ " 1: shows the summery of each subdir of <path> and the total",
+ " n: shows the summery of each subdir until level <n> and the total",
+ " default: 1",
+ "<opts_stat>:",
+ "--quiet",
+ "-q no additional information, e.g. runtime",
+ "--trace-interval=<n>",
+ "-t<n> trace the current path every <n> seconds.",
+ " If n<=0: no trace. Default: 60",
+ "--kbyte",
+ "-k output is '<kbyte> path' (like du)",
+ NULL
+};
+const char* statisticExamples[] = {
+ "Examples:",
+ "dirtool st -q -t0 e:\\windows",
+ "dirtool statistic --quiet --kbyte --trace-interval=60 ../mail 2",
+ "dirtool stat -q --kbyte d:data 2",
+ NULL
+};
+
+static void printField(const char** lines){
+ for (int ix = 0; lines[ix] != NULL; ix++){
+ printf("%s\n", lines[ix]);
+ }
+}
/**
* Prints an message how to use the statistic module and exits.
*/
void ReDirTools::statisticUsage(){
- printf ("<command>:\nstatistic <path> [<depth>] [<opts_stat>]\n");
- printf ("<opts_stat>:\n -v verbose\n -t<n> trace interval\n");
- printf ("example: dirtool statistic c:\\windows 2 -v -t60\n");
+ printField(statisticCall);
+ printField(statisticExamples);
}
+
/**
* Gets the arguments for the "statistic" command and execute this.
*
*/
void ReDirTools::dirStatistic(int argc, char* argv[]){
time_t start = time(NULL);
- bool verbose = true;
- int traceInterval = 60;
- if (argc < 1)
- usage("statistic: missing path");
- int depth = 1;
- if (argc > 1)
- depth = atol(argv[1]);
- ReDirStatistic statistic;
- statistic.setTraceInterval(traceInterval);
- const ReStringList& list = statistic.calculate(argv[0], depth, formatWithSizeFilesAndDirs);
- ReByteBuffer buffer;
- for (size_t ix = 0; ix < list.count(); ix++){
- buffer.set(list.strOf(ix), list.strLengthOf(ix));
- printf("%s\n", buffer.str());
- }
- if (verbose){
- int duration = int(time(NULL) - start);
- printf("Duration: ");
- if (duration >= 3600)
- printf("%d:", duration / 3600);
- printf("%02d:%02d\n", duration % 3600 / 60, duration % 60);
+ ReProgramArgs args(statisticCall, statisticExamples);
+ args.addBool("quiet", "no additional information", 'q', "quiet", false);
+ args.addBool("kbyte", "output is '<kbyte> <path>'", 'k', "kbyte", false);
+ args.addInt("trace", "trace each <n> seconds the current path", 't', "trace-interval", 60);
+ try {
+ args.init(argc, argv);
+ if (args.getArgCount() < 1)
+ usage("statistic: missing path");
+ int depth = 1;
+ if (args.getArgCount() > 1)
+ depth = atol(args.getArg(1));
+ ReDirStatistic statistic;
+ statistic.setTraceInterval(args.getInt("trace"));
+ void (*proc) (const ReDirStatisticData& data,
+ ReDirStatistic& parent, ReByteBuffer& line) = &formatWithSizeFilesAndDirs;
+ if (args.getBool("kbyte"))
+ proc = &formatLikeDu;
+ const ReStringList& list = statistic.calculate(args.getArg(0), depth, proc);
+ ReByteBuffer buffer;
+ for (size_t ix = 0; ix < list.count(); ix++){
+ buffer.set(list.strOf(ix), list.strLengthOf(ix));
+ printf("%s\n", buffer.str());
+ }
+ if (! args.getBool("quiet")){
+ int duration = int(time(NULL) - start);
+ printf("Duration: ");
+ if (duration >= 3600)
+ printf("%d:", duration / 3600);
+ printf("%02d:%02d\n", duration % 3600 / 60, duration % 60);
+ }
+ } catch (ReOptionException& exc) {
+ usage(exc.getMessage());
}
}
+/**
+ * Tests whether a abrevation of an argument is given.
+ * @param full the full name
+ * @param part the part to test
+ * @return <code>true</code>: part is a prefix of full
+ */
+static bool isArg(const char* full, const char* part){
+ ReByteBuffer fullArg(full);
+ bool rc = fullArg.startsWith(part, -1);
+ return rc;
+}
+
/**
* Gets the arguments for any command and execute this.
*
ReDirTools tools;
if (argc < 2)
tools.usage("missing arguments");
- if (strcmp(argv[1], "statistic") == 0)
- tools.dirStatistic(argc - 2, argv + 2);
- else
+ if (isArg("statistic", argv[1]))
+ tools.dirStatistic(argc - 1, argv + 1);
+ else if (isArg("test", argv[1])){
+ void testAll();
+ testAll();
+ }else
tools.usage("command not implemented: ", argv[1]);
//testOs();
ReLogger::freeGlobalLogger();
--- /dev/null
+/*
+ * DirTools.hpp
+ *
+ * Created on: 30.12.2014
+ * Author: hm
+ */
+
+#ifndef OS_DIRTOOLS_HPP_
+#define OS_DIRTOOLS_HPP_
+
+class ReDirStatisticData{
+public:
+ ReDirStatisticData();
+ ReDirStatisticData(const ReDirStatisticData& source);
+ ReDirStatisticData& operator =(const ReDirStatisticData& source);
+public:
+ void clear();
+ ReDirStatisticData& add(const ReDirStatisticData& source);
+public:
+ int64_t m_sizes;
+ int m_files;
+ int m_dirs;
+ ReByteBuffer m_path;
+};
+
+class ReDirStatistic;
+extern void formatLikeDu(const ReDirStatisticData& data, ReDirStatistic& parent,
+ ReByteBuffer& line);
+extern void formatWithSizeFilesAndDirs(const ReDirStatisticData& data,
+ ReDirStatistic& parent, ReByteBuffer& line);
+
+/**
+ * Calculates a statistic of a directory tree.
+ */
+class ReDirStatistic {
+public:
+ ReDirStatistic(int deltaList = 512, int deltaBuffer = 0x10000);
+ ~ReDirStatistic();
+public:
+ const ReStringList& calculate(const char* base, int depth,
+ void (*format)(const ReDirStatisticData& data, ReDirStatistic& parent,
+ ReByteBuffer& line) = formatLikeDu);
+ void setTraceInterval(int interval){
+ m_traceInterval = interval;
+ }
+private:
+ ReStringList m_list;
+ int m_traceInterval;
+ time_t m_lastTrace;
+};
+
+class ReDirTools {
+public:
+ virtual void usage(const char* msg, const char* msg2 = NULL);
+ void statisticUsage();
+ void dirStatistic(int argc, char* argv[]);
+public:
+ static int main(int argc, char* argv[]);
+public:
+ static const char* m_version;
+};
+#endif /* OS_DIRTOOLS_HPP_ */