*
* @return *this (for chaining).
*/
-ReByteBuffer& ReByteBuffer::append(ReByteBuffer& source){
- return append(source.buffer(), source.length());
+ReByteBuffer& ReByteBuffer::append(const ReByteBuffer& source){
+ return append(source.str(), source.length());
}
/** Converts a subsequence into an integer.
ReByteBuffer& operator =(const ReByteBuffer& source);
public:
ReByteBuffer& append(const Byte* source, size_t length = -1);
- ReByteBuffer& append(ReByteBuffer& source);
+ ReByteBuffer& append(const ReByteBuffer& source);
ReByteBuffer& appendInt(int number, const char* format = "%d");
/** @brief Returns the n-th byte of the internal buffer.
* @param index The index of the wanted byte.
inline Byte* buffer() const{
return m_buffer;
}
+ int count(const char* toCount, size_t lengthToCount = -1);
/**@brief Returns the minimum allocation unit.
* @return The minimum of bytes to allocate.
*/
inline size_t delta() const{
return m_delta;
}
- int count(const char* toCount, size_t lengthToCount = -1);
+ /** @brief Tests whether another instance is equal to this instance.
+ * @param buffer the buffer to compare
+ * @return <code>true</code>: the buffer's contents are equal
+ */
+ inline bool equals(const ReByteBuffer& buffer){
+ bool rc = buffer.length() == m_length && memcmp(buffer.str(), m_buffer, m_length) == 0;
+ return rc;
+ }
/**@brief Returns the length of the buffer (the count of used bytes).
* @return The count of the allocated bytes in the internal buffer.
*/
* @param true: An item was found. false: No more items.
*/
bool ReHashList::next(size_t& position, ReByteBuffer* key, ReByteBuffer* value){
- bool rc = position < m_keys.getCount();
+ bool rc = position < m_keys.count();
if (rc){
ReSeqList::Sequence* seq = m_keys.getInfo(position++);
if (key != NULL){
if (length == (size_t) -1)
length = strlen(key) + 1;
int rc = -1;
- int count = m_keys.getCount();
+ int count = m_keys.count();
for (int ii = 0; rc < 0 && ii < count; ii++){
ReSeqList::Sequence* seq = m_keys.getInfo(ii);
if (seq->m_length == length){
changeFile();
else{
m_stream = fopen(fullname.str(), "a");
- if (m_stream == NULL)
- assert(m_stream != NULL);
+ if (m_stream == NULL){
+ fprintf (stderr, "+++ ReFileAppender::setConfig(): cannot open: '%s'\n", fullname.str());
+ //assert(m_stream != NULL);
+ }
}
}
}
line.set("\t", 1).append(properties.strOf(IxDescr), -1);
lines.append(line.str());
}
- if (m_examples.getCount() > 0){
+ if (m_examples.count() > 0){
lines.append(i18n("Example:"));
lines.append(m_examples);
}
void ReProgramArgs::help(const char* message, bool issueLastError, FILE* stream){
ReStringList lines;
help(message, issueLastError, lines);
- for(size_t ii = 0; ii < lines.getCount(); ii++){
+ for(size_t ii = 0; ii < lines.count(); ii++){
fputs(lines.strOf(ii), stream);
fputc('\n', stream);
}
seq.m_length = sourceLength;
seq.m_tag = tag;
m_content.append(source, sourceLength);
- if (index >= getCount()){
+ if (index >= count()){
m_list.append((Byte*) &seq, sizeof seq);
}else{
m_list.insert(index * sizeof(Sequence), (Byte*) &seq, sizeof seq);
*/
bool ReSeqList::get(Index index, ReByteBuffer& value, Tag* tag) const{
bool rc = false;
- if (index < getCount()){
+ if (index < count()){
Sequence* seq = ((Sequence*)m_list.buffer()) + index;
value.set(m_content.buffer() + seq->m_index, seq->m_length);
if (tag != NULL)
* @param tag An additional info associated to the source.
*/
void ReSeqList::set(Index index, const Byte* source, size_t sourceLength, Tag tag){
- if (index >= getCount())
+ if (index >= count())
add(index, source, sourceLength, tag);
else {
if (sourceLength == (size_t) -1)
* @param index The index of the entry to remove.
*/
void ReSeqList::remove(Index index){
- if (index <= getCount()){
+ if (index <= count()){
Sequence* seq = getInfo(index);
// Is this the last entry in m_content?
if (seq->m_index + seq->m_length >= m_content.length()){
/** @brief Returns the count of defined entries in the list.
* @return The number of defined entries in the list (array).
*/
- inline Index getCount() const {
+ inline Index count() const {
return m_list.length() / sizeof (Sequence);
}
protected:
#include "base/rebase.hpp"
/** @brief Constructor.
+ *
+ * @param deltaList list reservation will be incremented by this amount
+ * @param deltaBuffer buffer reservation will be incremented by this amount
*/
-ReStringList::ReStringList()
- :
- ReSeqList()
+ReStringList::ReStringList(int deltaList, int deltaBuffer) :
+ ReSeqList(deltaList, deltaBuffer)
{
-
}
/** @brief Destructor.
/** @brief Appends a string at the end.
*
* @param source The new string.
- * @param tagOf An item which will stored with the string. It can be retrieved by the same index.
- * T his class knows nothing about this.
+ * @param tagOf An item which will stored with the string. It can be retrieved
+ * by the same index.This class knows nothing about this.
+ * @return the instance itself (for chaining)
*/
-void ReStringList::append(const char* source, Tag tagOf){
+ReStringList& ReStringList::append(const char* source, Tag tagOf){
add(-1, source, -1, tagOf);
+ return *this;
}
+/** @brief Appends a string at the end.
+ *
+ * @param source The new string.
+ * @param tagOf An item which will stored with the string. It can be retrieved
+ * by the same index.This class knows nothing about this.
+ * @return the instance itself (for chaining)
+ */
+ReStringList& ReStringList::append(const ReByteBuffer& source, Tag tagOf){
+ add(-1, source.str(), source.length(), tagOf);
+ return *this;
+}
+
/** @brief Appends a stringlist at the end.
*
* @param source The new stringlist.
+ * @return the instance itself (for chaining)
*/
-void ReStringList::append(ReStringList& source){
- for (size_t ii = 0; ii < source.getCount(); ii++)
+ReStringList& ReStringList::append(ReStringList& source){
+ for (size_t ii = 0; ii < source.count(); ii++)
add(-1, source.strOf(ii), -1, source.tagOf(ii));
+ return *this;
}
/** @brief Inserts a string at a given index.
*
* @param source The new string of the replaced element.
*/
void ReStringList::replaceString(Index index, const char* source){
- if (index < getCount()){
+ if (index < count()){
Sequence* seq = getInfo(index);
set(index, source, -1, seq->m_tag);
}
* @param source The new string of the replaced element.
*/
void ReStringList::replaceTag(Index index, Tag tagOf){
- if (index < getCount()){
+ if (index < count()){
Sequence* seq = getInfo(index);
seq->m_tag = tagOf;
}
*/
const char* ReStringList::strOf(Index index) const{
const char* rc = NULL;
- if (index < getCount()){
+ if (index < count()){
Sequence* seq = getInfo(index);
rc = m_content.buffer() + seq->m_index;
}
*/
ReSeqList::Tag ReStringList::tagOf(Index index) const{
Tag rc = -1;
- if (index < getCount()){
+ if (index < count()){
Sequence* seq = getInfo(index);
rc = seq->m_tag;
}
*/
size_t ReStringList::sizeOf(Index index) const{
size_t rc = 0;
- if (index < getCount()){
+ if (index < count()){
Sequence* seq = getInfo(index);
rc = seq->m_length;
}
*/
size_t ReStringList::strLengthOf(Index index) const{
size_t rc = 0;
- if (index < getCount()){
+ if (index < count()){
Sequence* seq = getInfo(index);
rc = seq->m_length - 1;
}
size_t ReStringList::sumOfSizes() const{
size_t rc = 0;
- for (int ii = getCount() - 1; ii >= 0; ii--){
+ for (int ii = count() - 1; ii >= 0; ii--){
Sequence* seq = getInfo(ii);
rc += seq->m_length;
}
size_t ReStringList::sumOfStrLengths() const{
size_t rc = 0;
- for (int ii = getCount() - 1; ii >= 0; ii--){
+ for (int ii = count() - 1; ii >= 0; ii--){
Sequence* seq = getInfo(ii);
rc += seq->m_length - 1;
}
ReSeqList::Index ReStringList::indexOf(const char* toFind,
bool ignoreCase, Index start) const{
Index rc = (Index) -1;
- Index count = getCount();
+ Index theCount = count();
- for (; rc == (Index) -1 && start < count; start++){
+ for (; rc == (Index) -1 && start < theCount; start++){
const char* item = strOf(start);
int rc2;
if (ignoreCase)
ReSeqList::Index ReStringList::nextStartingWith(Index start,
const char* prefix, bool ignoreCase){
Index rc = (Index) -1;
- Index count = getCount();
+ Index theCount = count();
size_t length = strlen(prefix);
- for (; rc == (Index) -1 && start < count; start++){
+ for (; rc == (Index) -1 && start < theCount; start++){
const char* item = strOf(start);
int rc2;
if (ignoreCase)
*
* @param separator This string was put between the substrings. May be NULL or "".
* @param result Out: The result buffer.
+ * @return <code>buffer</code> (for chaining)
*/
-void ReStringList::join(const char* separator, ReByteBuffer& result){
- size_t count = getCount();
+ReByteBuffer& ReStringList::join(const char* separator, ReByteBuffer& result) const{
+ size_t theCount = count();
result.setLength(0);
size_t lengthSep = strlen(separator);
- for (size_t ix = 0; ix < count; ix++){
+ for (size_t ix = 0; ix < theCount; ix++){
result.append(strOf(ix), sizeOf(ix) - 1);
- if (ix != count - 1 && separator != NULL)
+ if (ix != theCount - 1 && separator != NULL)
result.append(separator, lengthSep);
}
+ return result;
}
/** @brief Writes the stringlist to a file.
*
bool rc = false;
FILE* fp = fopen(filename, mode);
if (fp){
- size_t count = getCount();
- for (size_t ix = 0; ix < count; ix++){
+ size_t aCount = count();
+ for (size_t ix = 0; ix < aCount; ix++){
fputs(strOf(ix), fp);
- if (ix != count - 1 && separator != NULL)
+ if (ix != aCount - 1 && separator != NULL)
fputs(separator, fp);
}
fclose(fp);
*/
int ReStringList::firstDiff(const ReStringList& toCompare) const{
int rc = -1;
- for (size_t ix = 0; rc == -1 && ix < getCount(); ix++){
- if (ix >= toCompare.getCount())
+ for (size_t ix = 0; rc == -1 && ix < count(); ix++){
+ if (ix >= toCompare.count())
rc = (int) ix;
else if (sizeOf(ix) != toCompare.sizeOf(ix)
|| strcmp(strOf(ix), toCompare.strOf(ix)) != 0)
rc = (int) ix;
}
- if (rc == -1 && getCount() < toCompare.getCount())
- rc = getCount();
+ if (rc == -1 && count() < toCompare.count())
+ rc = count();
return rc;
}
/** @brief Tests the equality with another instance.
* @return true: The other instance is equal. false: Otherwise.
*/
bool ReStringList::equal(const ReStringList& toCompare) const{
- bool rc = getCount() == toCompare.getCount() && firstDiff(toCompare) == -1;
+ bool rc = count() == toCompare.count() && firstDiff(toCompare) == -1;
return rc;
}
* <code>
* ReStringList listIn, listOut;
* listIn.readFromFile("abc.csv");
- * for (int ii = 0; ii < listIn.getCount(); ii++){
+ * for (int ii = 0; ii < listIn.count(); ii++){
* ReStringList cols;
* cols.split(list.getCStr(ii), ',');
* char number[20]; sprintf(number, "%d", ii + 1);
*/
class ReStringList : public ReSeqList {
public:
- ReStringList();
+ ReStringList(int deltaList = 1024, int deltaBuffer = 1024);
virtual ~ReStringList();
public:
- void append(const char* source, Tag tag = 0);
- void append(ReStringList& source);
+ ReStringList& append(const char* source, Tag tag = 0);
+ ReStringList& append(const ReByteBuffer& source, Tag tag = 0);
+ ReStringList& append(ReStringList& source);
Index indexOf(const char* toFind, bool ignoreCase = false, Index start = 0) const;
void insert(Index index, const char* source, Tag tag = 0);
- void join(const char* separator, ReByteBuffer& result);
+ ReByteBuffer& join(const char* separator, ReByteBuffer& result) const;
Index nextStartingWith(Index index, const char* prefix, bool ignoreCase = false);
void replace(Index index, const char* source, Tag tag = 0);
void replaceString(Index index, const char* source);
#define ALLPERMS 0
#endif
if (lstat(name, &info) != 0)
- mkdir(name, ALLPERMS);
+ _mkdir(name);
else{
char cmd[512 + 128];
snprintf(cmd, sizeof cmd, "rm -Rf %s*", name);
* @param content The content of the file. If NULL the file will be empty.
*/
void ReTestUnit::createDir(const char* filename){
- mkdir(filename, ALLPERMS);
+ _mkdir(filename);
}
#define _strdup strdup
#define _unlink unlink
+#define _mkdir(path) mkdir(path, ALLPERMS)
//#define _
#elif defined __WIN32__
ReSeqList::Tag tag = 0;
list.add(-1, "123", -1, 100);
- checkEqu(1u, list.getCount());
+ checkEqu(1u, list.count());
checkT(list.get(0, value, &tag));
checkEqu("123", value.str());
checkEqu((int64_t) 100, tag);
list.add(-1, "ab", -1, 200);
- checkEqu(2u, list.getCount());
+ checkEqu(2u, list.count());
checkT(list.get(0, value));
checkEqu("123", value.str());
checkT(list.get(1, value, &tag));
checkEqu(200ll, tag);
list.add(0, "xyz", -1, 300);
- checkEqu(3u, list.getCount());
+ checkEqu(3u, list.count());
checkT(list.get(0, value, &tag));
checkEqu("xyz", value.str());
checkT(list.get(1, value));
checkEqu(300ll, tag);
list.add(1, "vw", -1, 400);
- checkEqu(4u, list.getCount());
+ checkEqu(4u, list.count());
checkT(list.get(0, value));
checkEqu("xyz", value.str());
checkT(list.get(1, value, &tag));
checkEqu(400ll, tag);
list.clear();
- checkEqu(0u, list.getCount());
+ checkEqu(0u, list.count());
checkF(list.get(0, value));
}
void testRemove(){
list.add(-1, "jkl134", -1, 400);
list.remove(3);
- checkEqu(3u, list.getCount());
+ checkEqu(3u, list.count());
list.get(0, value, &tag);
checkEqu("abc", value.str());
checkEqu(100ll, tag);
list.remove(1);
- checkEqu(2u, list.getCount());
+ checkEqu(2u, list.count());
list.get(0, value, &tag);
checkEqu("abc", value.str());
checkEqu(100ll, tag);
checkEqu(300ll, tag);
list.remove(0);
- checkEqu(1u, list.getCount());
+ checkEqu(1u, list.count());
list.get(0, value, &tag);
checkEqu("ghi", value.str());
checkEqu(300ll, tag);
}
private:
void run(){
+ testAppendByteBuffer();
testBase();
testReplace();
testJoin();
testEqu();
testFile();
}
+ void testAppendByteBuffer(){
+ ReStringList list;
+ ReByteBuffer line;
+ line.set("Hi", -1);
+ list.append(line, 1ll).append(line.append("!", -1), -5ll);
+ checkEqu(2u, list.count());
+ checkEqu(1ll, list.tagOf(0));
+ checkEqu("Hi", list.strOf(0));
+
+ checkEqu(-5ll, list.tagOf(1));
+ checkEqu("Hi!", list.strOf(1));
+ }
void testReplace(){
ReStringList list;
ReStringList list;
const char* str = "1;abc;xyz;4;;99";
list.split(str, ';');
- checkEqu(6U, list.getCount());
+ checkEqu(6U, list.count());
checkEqu("1", list.strOf(0));
checkEqu("abc", list.strOf(1));
checkEqu("xyz", list.strOf(2));
checkEqu(str, value.str());
list.split("1\r\n2\n\r3", '\n');
- checkEqu(3U, list.getCount());
+ checkEqu(3U, list.count());
checkEqu("1", list.strOf(0));
checkEqu("2", list.strOf(1));
checkEqu("3", list.strOf(2));
list.split("xyz\tXYZ", '\t', true);
- checkEqu(5U, list.getCount());
+ checkEqu(5U, list.count());
checkEqu("1", list.strOf(0));
checkEqu("2", list.strOf(1));
checkEqu("3", list.strOf(2));
list.append("a", 200);
list.append("vwxyz", 300);
- checkEqu(3U, list.getCount());
+ checkEqu(3U, list.count());
int index = 0;
checkEqu("123", list.strOf(index));
checkEqu(4U, list.sizeOf(index));
checkEqu(12U, list.sumOfSizes());
list.insert(0, "0", 50);
- checkEqu(4U, list.getCount());
+ checkEqu(4U, list.count());
checkEqu(14U, list.sumOfSizes());
index = 0;
list3.append("y", 2000);
list2.append(list3);
- checkEqu(5u, list2.getCount());
+ checkEqu(5u, list2.count());
checkEqu("a", list2.strOf(0));
checkEqu(100ll, list2.tagOf(0));
checkEqu("b", list2.strOf(1));
makeFile("dir1/dir1_2/dir1_2_1/x2.txt");
}
void run(){
- initTree();
+ initTree();
+ testDirStatistic();
testBasic();
}
void checkOneFile(const char* node, const char* parent, const ReHashList& hash){
void testBasic(){
ReTraverser traverser(m_base.str());
int level = 0;
- DirStatus_t* entry;
- ReHashList hash;
- while( (entry = traverser.rawNextFile(level)) != NULL){
- hash.put(ReByteBuffer(entry->node(), -1), entry->m_path);
- logF(false, "%d: %-12s %2d %s",
- level, entry->node(),
- int(entry->fileSize()),
- entry->m_path.str());
- }
- checkOneFile("x1.txt", "dir1_2_1", hash);
- checkOneFile("x2.txt", "dir1_2_1", hash);
- checkOneFile("dir1_2_1", "dir1_2", hash);
- checkOneFile("dir1_1", "dir1", hash);
- checkOneFile("dir1_2", "dir1", hash);
- checkOneFile("dir1", m_base.str(), hash);
-
- //checkEqu("xy12.ab", nameOfEntry(entry));
+ ReDirStatus_t* entry;
+ ReHashList hash;
+ while( (entry = traverser.rawNextFile(level)) != NULL){
+ hash.put(ReByteBuffer(entry->node(), -1), entry->m_path);
+ logF(false, "%d: %-12s %2d %s",
+ level, entry->node(),
+ int(entry->fileSize()),
+ entry->m_path.str());
+ }
+ checkOneFile("x1.txt", "dir1_2_1", hash);
+ checkOneFile("x2.txt", "dir1_2_1", hash);
+ checkOneFile("dir1_2_1", "dir1_2", hash);
+ checkOneFile("dir1_1", "dir1", hash);
+ checkOneFile("dir1_2", "dir1", hash);
+ checkOneFile("dir1", m_base.str(), hash);
+ }
+ void testDirStatistic(){
+ ReDirStatistic stat;
+ const ReStringList& list = stat.calculate(m_base.str(), 1);
+ ReByteBuffer buffer;
+ log(false, list.join("\n", buffer).str());
+ checkEqu(3u, list.count());
+ checkEqu("", list.strOf(0));
}
};
extern void testReTraverser(void);
--- /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);
+/**
+ * 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);
+private:
+ ReStringList m_list;
+};
+
+
+#endif /* OS_DIRTOOLS_HPP_ */
--- /dev/null
+/*
+ * DirTools.cpp
+ *
+ * Created on: 30.12.2014
+ * Author: hm
+ */
+
+#include "base/rebase.hpp"
+#include "os/reos.hpp"
+
+/**
+ * Constructor.
+ */
+ReDirStatisticData::ReDirStatisticData() :
+ m_sizes(0),
+ m_files(0),
+ m_dirs(0),
+ m_path()
+{
+}
+/**
+ * Copy constructor.
+ *
+ * @param source the source to copy
+ */
+ReDirStatisticData::ReDirStatisticData(const ReDirStatisticData& source) :
+ m_sizes(source.m_sizes),
+ m_files(source.m_files),
+ m_dirs(source.m_dirs),
+ m_path(source.m_path)
+{
+}
+/**
+ * Assignment operator.
+ *
+ * @param source the source to copy
+ * @return the instance itself
+ */
+ReDirStatisticData& ReDirStatisticData::operator =(const ReDirStatisticData& source){
+ m_sizes = source.m_sizes;
+ m_files = source.m_files;
+ m_dirs = source.m_dirs;
+ m_path = source.m_path;
+ return *this;
+}
+/**
+ * Initializes the data of the instance.
+ */
+void ReDirStatisticData::clear(){
+ m_sizes = 0;
+ m_files = 0;
+ m_dirs = 0;
+ m_path.setLength(0);
+}
+
+/**
+ * Adds the data from another instance.
+ *
+ * @param source the other instance
+ * @return the instance itself
+ */
+ReDirStatisticData& ReDirStatisticData::add(const ReDirStatisticData& source){
+ m_sizes += source.m_sizes;
+ m_files += source.m_files;
+ m_dirs += source.m_dirs;
+ return *this;
+}
+
+/**
+ * Constructor.
+ */
+ReDirStatistic::ReDirStatistic(int deltaList, int deltaBuffer) :
+ m_list(deltaList, deltaBuffer)
+{
+}
+/**
+ * Destructor.
+ */
+ReDirStatistic::~ReDirStatistic(){
+
+}
+
+/**
+ * Calculates the statistic of a directory tree.
+ *
+ *
+ */
+const ReStringList& ReDirStatistic::calculate(const char* base, int level,
+ void (*formatter)(const ReDirStatisticData& data, ReDirStatistic& parent,
+ ReByteBuffer& line)){
+ ReTraverser traverser(base);
+ if (level > 1024)
+ level = 1024;
+ else if (level < 0)
+ level = 0;
+ ReDirStatisticData** dataStack = new ReDirStatisticData*[level + 1];
+ memset(dataStack, 0, sizeof dataStack[0] * (level + 1));
+ dataStack[0] = new ReDirStatisticData();
+ int topOfStack = 0;
+ ReDirStatus_t* entry;
+ int currentDepth = -1;
+ ReDirStatisticData* current = dataStack[0];
+ current->m_path.set(base, -1);
+ ReByteBuffer line;
+ while( (entry = traverser.rawNextFile(currentDepth))){
+ if (! entry->m_path.equals(current->m_path)){
+ if (currentDepth <= topOfStack){
+ // close the entries of the stack above the new current:
+ while(topOfStack > currentDepth){
+ // Add the data to the parent:
+ dataStack[topOfStack - 1]->add(*dataStack[topOfStack]);
+ // Append it to the result:
+ (*formatter)(*dataStack[topOfStack - 1], *this, line);
+ m_list.append(line);
+ }
+ } else if (currentDepth < level){
+ // set up a new stack entry:
+ if (currentDepth != topOfStack + 1)
+ assert(currentDepth == topOfStack + 1);
+ topOfStack++;
+ if (dataStack[topOfStack] == NULL)
+ dataStack[topOfStack] = new ReDirStatisticData();
+ else
+ dataStack[topOfStack]->clear();
+ current = dataStack[topOfStack];
+ current->m_path.set(entry->m_path.str(), entry->m_path.length());
+ }
+ }
+ if (entry->isDirectory()){
+ current->m_dirs++;
+ } else {
+ current->m_sizes += entry->fileSize();
+ current->m_files++;
+ }
+ }
+ while(topOfStack > 0){
+ // Add the data to the parent:
+ dataStack[topOfStack - 1]->add(*dataStack[topOfStack]);
+ // Append it to the result:
+ (*formatter)(*dataStack[topOfStack - 1], *this, line);
+ m_list.append(line);
+ }
+ // free the resources:
+ for (int ix = 0; ix <= level; ix++)
+ delete dataStack[ix];
+ delete[] dataStack;
+ return m_list;
+}
+
+/**
+ * Formats a line like the du (disk usage) command.
+ *
+ * This is a possible parameter of <code>ReDirStatistic::calculate()</code>.
+ *
+ * @param data statistic data, including path name
+ * @param parent the caller (<code>ReDirStatistic</code>). This allows to deliver
+ * a context to this formatting routine (through derivation of
+ * <code>ReDirStatistic</code>)
+ * @param line OUT: the formatted line, the conclusion of the statistic data
+ */
+void formatLikeDu(const ReDirStatisticData& data,
+ ReDirStatistic& parent, ReByteBuffer& line){
+ line.setLength(0);
+ line.append(int(data.m_sizes / 1024)).append("\t").append(data.m_path);
+}
#endif\r
\r
#ifdef __linux__\r
-#define isUndefHandle(handle) ((handle) == NULL)\r
-#define findFirstEntry(path, data) opendir(path)\r
-#define findNextEntry(handle,data) (((data) = readdir(handle)) != NULL)\r
+//#define isUndefHandle(handle) ((handle) == NULL)\r
+//#define findNextEntry(handle,data) (((data) = readdir(handle)) != NULL)\r
#define closeDir(handle) closedir(handle)\r
-#define initEntryBuffer(entry)\r
-#define setHandleUndef(h) ((h) = NULL)\r
+//#define setHandleUndef(h) ((h) = NULL)\r
#else\r
#define isUndefHandle(handle) ((handle) == INVALID_HANDLE_VALUE)\r
#define setHandleUndef(h) ((h) = INVALID_HANDLE_VALUE)\r
-HANDLE findFirstEntry(const char* path, DirInfoStruct_t* data){\r
- ReByteBuffer thePath(path);\r
- thePath.append("\\*");\r
- HANDLE rc = FindFirstFileA(thePath.str(), data);\r
- return rc;\r
-}\r
#define findNextEntry(handle, data) (FindNextFileA(handle, data) != 0)\r
-#define closeDir(handle) FindClose(handle)\r
#define initEntryBuffer(entry) ((entry)->m_data = &(entry)->m_dataBuffer)\r
#endif\r
\r
-const char* DirStatus_t::node() const{\r
+ReDirStatus_t::ReDirStatus_t() :\r
+#ifdef __linux__\r
+ m_handle(NULL),\r
+ m_data(NULL)\r
+ //m_status;\r
+#elif defined WIN32\r
+ m_handle(INVALID_HANDLE_VALUE)\r
+ //m_data;\r
+#endif\r
+{\r
+#ifdef __linux__\r
+ memset(&m_status, 0, sizeof m_status);\r
+#elif defined WIN32\r
+ memset(&m_data, 0, sizeof m_data);\r
+#endif\r
+}\r
+\r
+/**\r
+ * Frees the resources of an instance.\r
+ */\r
+void ReDirStatus_t::freeEntry(){\r
+#if defined __linux__\r
+ if (m_handle != NULL){\r
+ closedir(m_handle);\r
+ m_handle = NULL;\r
+ }\r
+#elif defined __WIN32__\r
+ if (m_handle != INVALID_HANDLE_VALUE){\r
+ CloseDir(m_handle);\r
+ m_handle = INVALID_HANDLE_VALUE;\r
+ }\r
+#endif\r
+ m_path.setLength(0);\r
+}\r
+\r
+/**\r
+ * Returns the name of the current file (without path).\r
+ *\r
+ * @return the name of the current file.\r
+ */\r
+const char* ReDirStatus_t::node() const{\r
#ifdef __linux__\r
return m_data->d_name;\r
#elif defined __WIN32__\r
return m_data->cFileName;\r
#endif\r
}\r
-bool DirStatus_t::isDotDir() const{\r
+/**\r
+ * Tests whether the instance contains data about "." or "..".\r
+ *\r
+ * @return <code>true</code>: an ignorable entry has been found\r
+ */\r
+bool ReDirStatus_t::isDotDir() const{\r
#ifdef __linux__\r
- bool rc = m_data->d_name[0] == '.' && (m_data->d_name[1] == '\0' \r
- || (m_data->d_name[1] == '.' && m_data->d_name[2] == '\0'));\r
+ bool rc = m_data == NULL || (m_data->d_name[0] == '.' && (m_data->d_name[1] == '\0'\r
+ || (m_data->d_name[1] == '.' && m_data->d_name[2] == '\0')));\r
#elif defined __WIN32__\r
bool rc = m_data->cFileName[0] == '.' && (m_data->cFileName[1] == '\0' \r
|| (m_data->cFileName[1] == '.' && m_data->cFileName[2] == '\0'));\r
return rc;\r
}\r
\r
-bool DirStatus_t::isDirectory() {\r
+/**\r
+ * Loads the info about the first file into the instance.\r
+ *\r
+ * @return <code>true</code>: success\r
+ */\r
+bool ReDirStatus_t::findFirst(){\r
+ bool rc = false;\r
+#if defined __linux__\r
+ if (m_handle != NULL)\r
+ closedir(m_handle);\r
+ m_handle = opendir(m_path.str());\r
+ rc = m_handle != NULL && (m_data = readdir(m_handle)) != NULL;\r
+#elif defined __WIN32__\r
+ if (m_handle != INVALID_HANDLE_VALUE)\r
+ FindClose(m_handle);\r
+ ReByteBuffer thePath(m_path);\r
+ thePath.append("\\*");\r
+ m_handle = FindFirstFileA(thePath.str(), &m_data);\r
+ rc = m_handle != INVALID_HANDLE_VALUE;\r
+#endif\r
+ return rc;\r
+}\r
+\r
+/**\r
+ * Loads the info about the next file into the instance.\r
+ *\r
+ * @return <code>true</code>: success\r
+ */\r
+bool ReDirStatus_t::findNext(){\r
+#if defined __linux__\r
+ bool rc = m_handle != NULL && (m_data = readdir(m_handle)) != NULL;\r
+#elif defined __WIN32__\r
+ bool rc = m_handle != INVALID_HANDLE_VALUE && FindNextFileA(m_handle, &m_data);\r
+#endif\r
+ return rc;\r
+}\r
+/**\r
+ * Tests whether the instance is a directory.\r
+ *\r
+ * @return <code>true</code>: instance contains the data of a directory\r
+ */\r
+bool ReDirStatus_t::isDirectory() {\r
#ifdef __linux__\r
return (m_data->d_type != DT_UNKNOWN && m_data->d_type == DT_DIR) || S_ISDIR(getStatus()->st_mode);\r
#elif defined __WIN32__\r
return 0 != (m_dataBuffer.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);\r
#endif\r
}\r
-bool DirStatus_t::isLink() {\r
+/**\r
+ * Tests whether the instance is a symbolic link.\r
+ *\r
+ * Unter windows it tests whether the the instance is a reparse point.\r
+ *\r
+ * @return <code>true</code>: instance contains the data of a link\r
+ */\r
+bool ReDirStatus_t::isLink() {\r
bool rc;\r
#ifdef __linux__\r
rc = (m_data->d_type != DT_UNKNOWN && m_data->d_type == DT_LNK) || S_ISLNK(getStatus()->st_mode);\r
#endif\r
return rc;\r
}\r
-bool DirStatus_t::isRegular() {\r
+/**\r
+ * Tests whether the instance is a "normal" file.\r
+ *\r
+ * @return <code>true</code>: instance contains the data of a not special file\r
+ */\r
+bool ReDirStatus_t::isRegular() {\r
#ifdef __linux__\r
return (m_data->d_type != DT_UNKNOWN && m_data->d_type == DT_REG) || S_ISREG(getStatus()->st_mode);\r
#elif defined __WIN32__\r
return 0 != (m_dataBuffer.dwFileAttributes & (FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE));\r
#endif\r
}\r
-FileSize_t DirStatus_t::fileSize() {\r
+/**\r
+ * Returns the filesize.\r
+ *\r
+ * @return the filesize\r
+ */\r
+FileSize_t ReDirStatus_t::fileSize() {\r
#ifdef __linux__\r
return getStatus()->st_size;\r
#elif defined __WIN32__\r
return ((int64_t) m_dataBuffer.nFileSizeHigh << 32) + m_dataBuffer.nFileSizeLow;\r
#endif\r
}\r
-const FileTime_t* DirStatus_t::modified() {\r
+/**\r
+ * Returns the modification time.\r
+ *\r
+ * @return the modification time\r
+ */\r
+const FileTime_t* ReDirStatus_t::modified() {\r
#ifdef __linux__\r
return &(getStatus()->st_mtime);\r
#elif defined __WIN32__\r
#endif\r
}\r
\r
-time_t DirStatus_t::filetimeToTime(const FileTime_t* filetime){\r
+time_t ReDirStatus_t::filetimeToTime(const FileTime_t* filetime){\r
#ifdef __linux__\r
return *filetime;\r
#elif defined __WIN32__\r
return (time_t) (date.QuadPart / 10000000);\r
#endif\r
}\r
-\r
-void DirStatus_t::timeToFiletime(time_t time, FileTime_t& filetime){\r
+/**\r
+ * Converts the unix time (time_t) to the file time.\r
+ *\r
+ * @param time the unix time (secondes since 1.1.1970)\r
+ * @param filetime OUT: the OS specific filetime\r
+ */\r
+void ReDirStatus_t::timeToFiletime(time_t time, FileTime_t& filetime){\r
#ifdef __linux__\r
filetime = time;\r
#elif defined __WIN32__\r
LONGLONG ll = Int32x32To64(time, 10000000) + 116444736000000000;\r
filetime.dwLowDateTime = (DWORD)ll;\r
- filetime.dwHighDateTime = ll >> 32;;\r
+ filetime.dwHighDateTime = ll >> 32;\r
#endif\r
}\r
\r
/**\r
*\r
*/\r
-bool DirEntryFilter_t::match(DirStatus_t& entry){\r
+bool DirEntryFilter_t::match(ReDirStatus_t& entry){\r
bool rc = false;\r
do {\r
if (! m_directories && entry.isDirectory())\r
break;\r
if (m_maxSize >= 0 && entry.fileSize() < m_maxSize)\r
break;\r
- if (m_minAge != 0 && DirStatus_t::filetimeToTime(entry.modified()) < m_minAge)\r
+ if (m_minAge != 0 && ReDirStatus_t::filetimeToTime(entry.modified()) < m_minAge)\r
break;\r
- if (m_maxAge != 0 && DirStatus_t::filetimeToTime(entry.modified()) > m_maxAge)\r
+ if (m_maxAge != 0 && ReDirStatus_t::filetimeToTime(entry.modified()) > m_maxAge)\r
break;\r
if (m_nodePatterns != NULL && ! m_nodePatterns->match(entry.node()))\r
break;\r
*\r
* @return the status of the current file\r
*/\r
-struct stat* DirStatus_t::getStatus() {\r
+struct stat* ReDirStatus_t::getStatus() {\r
if (m_status.st_ino == 0)\r
if (stat(m_data->d_name, &m_status) != 0)\r
memset((void*) &m_status, 0, sizeof m_status);\r
// m_dirs\r
m_passNoForDirSearch(2)\r
{\r
+ memset(m_dirs, 0, sizeof m_dirs);\r
+ m_dirs[0] = new ReDirStatus_t();\r
}\r
\r
/**\r
* Destructor.\r
*/\r
ReTraverser::~ReTraverser() {\r
+ for (size_t ix = 0; ix < sizeof m_dirs / sizeof m_dirs[0]; ix++){\r
+ if (m_dirs[ix] != NULL){\r
+ m_dirs[ix]->freeEntry();\r
+ delete m_dirs[ix];\r
+ m_dirs[ix] = NULL;\r
+ }\r
+ }\r
}\r
\r
/**\r
* otherwise: the stack entry with the next file in the\r
* directory tree. May be a directory too\r
*/\r
-DirStatus_t* ReTraverser::rawNextFile(int& level)\r
+ReDirStatus_t* ReTraverser::rawNextFile(int& level)\r
{\r
- DirStatus_t* rc = NULL;\r
+ ReDirStatus_t* rc = NULL;\r
bool alreadyRead = false;\r
bool again;\r
do{\r
// first call:\r
if (initEntry(m_base.str(), NULL, 0)){\r
if (1 != m_passNoForDirSearch)\r
- rc = &m_dirs[0];\r
+ rc = m_dirs[0];\r
else\r
again = alreadyRead = true;\r
}\r
} else {\r
- DirStatus_t* current = &m_dirs[m_level];\r
- if (alreadyRead || findNextEntry(current->m_handle, current->m_data)){\r
- alreadyRead = false;\r
+ ReDirStatus_t* current = m_dirs[m_level];\r
+ if (alreadyRead || current->findNext()){\r
+ alreadyRead = false;\r
// a file or directory found:\r
if (current->m_passNo != m_passNoForDirSearch){\r
// we search for any file:\r
- rc = &m_dirs[m_level];\r
+ rc = m_dirs[m_level];\r
} else {\r
// we are interested only in subdirectories:\r
again = true;\r
again = true;\r
} else {\r
// this subdirectory is complete. We continue in the parent directory:\r
- closeDir(current->m_handle);\r
- setHandleUndef(current->m_handle);\r
+ current->freeEntry();\r
if ( --m_level > 0){\r
again = true;\r
}\r
* otherwise: the info about the next file in the\r
* directory tree\r
*/\r
-DirStatus_t* ReTraverser::nextFile(int& level, DirEntryFilter_t* filter){\r
- DirStatus_t* rc = rawNextFile(level);\r
+ReDirStatus_t* ReTraverser::nextFile(int& level, DirEntryFilter_t* filter){\r
+ ReDirStatus_t* rc = rawNextFile(level);\r
while (rc != NULL){\r
if (filter == NULL || filter->match(*rc)){\r
break;\r
if (level < MAX_ENTRY_STACK_DEPTH){\r
if (level >= 0)\r
m_level = level;\r
- DirStatus_t* current = &m_dirs[m_level];\r
- initEntryBuffer(current);\r
+ if (m_dirs[m_level] == NULL)\r
+ m_dirs[m_level] = new ReDirStatus_t();\r
+ ReDirStatus_t* current = m_dirs[m_level];\r
current->m_passNo = 1;\r
if (level >= 0){\r
current->m_path.set(parent.str(), parent.length());\r
if (node != NULL)\r
current->m_path.append(node).append(m_separatorStr);\r
}\r
- current->m_handle = findFirstEntry(current->m_path.str(), current->m_data);\r
- rc = ! isUndefHandle(current->m_handle);\r
+ rc = current->findFirst();\r
}\r
return rc;\r
}\r
\r
-/**\r
- * Frees the resources of an entry of the directory entry stack.\r
- *\r
- * @param level the index of the entry in the stack\r
- */\r
-void ReTraverser::freeEntry(int level){\r
- if (level < MAX_ENTRY_STACK_DEPTH){\r
- DirStatus_t* current = &m_dirs[level];\r
- if (! isUndefHandle(current->m_handle)){\r
- closeDir(current->m_handle);\r
- setHandleUndef(current->m_handle);\r
- }\r
- current->m_path.setLength(0);\r
- }\r
-}\r
\r
#include "string/ReMatcher.hpp"
#ifdef __linux__
#include <sys/types.h>
- #include <sys/stat.h>
+#include <sys/stat.h>
typedef DIR* FindFileHandle_t;
typedef __off_t FileSize_t;
-typedef struct dirent DirInfoStruct_t;
typedef time_t FileTime_t;
-#if 0
-#define nameOfEntry(entry) ((entry)->m_data->d_name)
-#define isDirEntry(entry) (((entry)->m_data->d_type != DT_UNKNOWN && (entry)->m_data->d_type == DT_DIR) \
- || S_ISDIR((entry)->getStatus()->st_mode))
-#define isLinkEntry(entry) (((entry)->m_data->d_type != DT_UNKNOWN && (entry)->m_data->d_type == DT_LINK) \
- || S_ISLNK(entry.getStatus()->st_mode)))
-#define isRegularEntry(entry) (((entry)->m_data->d_type != DT_UNKNOWN && (entry)->m_data->d_type == DT_REG) \
- || S_ISREG((entry)->getStatus()->st_mode))
-#define sizeOfEntry(entry) ((entry)->getStatus()->st_size)
-#define modifiedOfEntry(entry) ((entry)->getStatus()->st_mtime)
-#endif
#else
typedef int64_t FileSize_t;
typedef FILETIME FileTime_t;
-typedef HANDLE FindFileHandle_t;
-typedef WIN32_FIND_DATAA DirInfoStruct_t;
#endif
-class DirStatus_t{
+class ReDirStatus_t{
+public:
+ ReDirStatus_t();
public:
+ void freeEntry();
const char* node() const;
+ bool findFirst();
+ bool findNext();
+ bool hasData() const;
bool isDirectory();
bool isLink();
bool isRegular();
bool isDotDir() const;
public:
ReByteBuffer m_path;
- // a pointer to the data:
- DirInfoStruct_t* m_data;
- FindFileHandle_t m_handle;
int m_passNo;
-#if defined __linux__
+#ifdef __linux__
+ DIR* m_handle;
+ struct dirent* m_data;
struct stat m_status;
public:
struct stat* getStatus();
#elif defined WIN32
- // the buffer for m_data:
- DirInfoStruct_t m_dataBuffer;
+ HANDLE m_handle;
+ WIN32_FIND_DATAA m_data;
#endif
public:
static time_t filetimeToTime(const FileTime_t* time);
DirEntryFilter_t();
~DirEntryFilter_t();
public:
- bool match(DirStatus_t& entry);
+ bool match(ReDirStatus_t& entry);
public:
bool m_regulars;
bool m_specials;
ReTraverser(const char* base);
virtual ~ReTraverser();
public:
- DirStatus_t* rawNextFile(int& level);
- DirStatus_t* nextFile(int& level, DirEntryFilter_t* filter = NULL);
+ ReDirStatus_t* rawNextFile(int& level);
+ ReDirStatus_t* nextFile(int& level, DirEntryFilter_t* filter = NULL);
protected:
bool initEntry(const ReByteBuffer& parent, const char* node, int level);
void freeEntry(int level);
protected:
int m_level;
ReByteBuffer m_base;
- DirStatus_t m_dirs[MAX_ENTRY_STACK_DEPTH];
+ ReDirStatus_t* m_dirs[MAX_ENTRY_STACK_DEPTH];
/// each directory will be passed twice: for all files + for directories only
/// 1: depth first 2: breadth first
int m_passNoForDirSearch;
#endif
#include "os/ReTraverser.hpp"
-
+#include "os/DirTools.hpp"
#endif /* OS_REOS_HPP_ */
break;
}
// Does the tail match?
- int last = m_tokens.getCount() - 1;
+ int last = m_tokens.count() - 1;
if (last == 0){
rc = true;
break;
bool ReSimpleMatcher::search(const ReByteBuffer& toTest, ReHit* hit, bool greedy) const{
bool rc = m_findAll;
if (! rc){
- size_t last = m_tokens.getCount();
+ size_t last = m_tokens.count();
size_t length0 = m_tokens.strLengthOf(0);
size_t lengthLast = m_tokens.strLengthOf(last);
rc = searchTokens(toTest, length0 == 0 ? 1 : 0,