return rc;
}
+/** Sets the read position of a file.
+ * @param file file to process
+ * @param offset the position. @see <code>whence</code>
+ * @param whence SEEK_SET: offset is absolute (from file's start)
+ * SEEK_END: offset is relative to the file' end
+ * SEEK_CUR: offset is relative to the current position
+ * @return 0: success<br>
+ * otherwise: error code
+ */
+int ReFileUtils::seek(FILE* file, int64_t offset, int whence){
+ int rc;
+#if defined __linux__
+ rc = fseeko(file, offset, whence);
+#elif defined __WIN32__
+ rc = _fseek64(file, offset, whence);
+#endif
+ return rc;
+}
+
+/**
+ * Returns the current file position.
+ *
+ * @param file file to process
+ * @return < 0: error occurred<br>
+ * otherwise: the current read/write position (from the file's start)
+ */
+int64_t ReFileUtils::tell(FILE* file)
+{
+ int64_t rc;
+#if defined __linux__
+ rc = ftello(file);
+#elif defined __WIN32__
+ rc = _ftell64(file);
+#endif
+ return rc;
+}
+
/**
* Delete a directory tree.
*
*/
class ReFileUtils {
public:
+ static bool deleteTree(const QString& path, bool withBase, ReLogger* logger);
static bool isAbsolutPath(const QString& path);
static bool isAbsolutPath(const char* path);
+ static int seek(FILE* file, int64_t offset, int whence);
+ static int64_t tell(FILE* file);
static QByteArray tempDir(const char* node, const char* parent = NULL,
- bool withSeparator = true);
+ bool withSeparator = true);
static QByteArray tempFile(const char* node, const char* parent = NULL,
- bool deleteIfExists = true);
+ 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);
+ size_t contentLength = (size_t) - 1, const char* mode = "w");
};
#endif // REFILEUTILS_HPP
ReMatcher::ReMatcher(const QString& pattern, Qt::CaseSensitivity caseSensivity,
bool anchored) :
+ m_pattern(),
m_needles(),
m_restLengths(),
m_anchored(anchored),
* @return <code>true</code>: the pattern matches
*/
bool ReMatcher::matches(const QString& text) {
- bool found = m_needles.size() == 0;
- if (!found) {
- found =
- m_anchored ?
- text.startsWith(m_needles.at(0), m_caseSensivitiy) : true;
- if (found) {
- int startIx = m_anchored ? 1 : 0;
- int textIndex = m_anchored ? m_needles.at(0).length() : 0;
- for (int ix = startIx; found && ix < m_needles.size(); ix++) {
- found = text.size() - textIndex >= m_restLengths.at(ix);
- if (found)
- found = (textIndex = text.indexOf(m_needles.at(ix),
- textIndex, m_caseSensivitiy)) >= 0;
- }
+ bool found = m_allMatching || m_needles.size() == 0;
+ int endIx = m_needles.size() - 1;
+ if (! found && m_anchored){
+ found = m_needles.at(0).size() == 0
+ || text.startsWith(m_needles.at(0), m_caseSensivitiy);
+ if (found && (endIx > 0 || text.length() != m_pattern.length())){
+ found = m_needles.at(endIx).size() == 0
+ || text.endsWith(m_needles.at(endIx), m_caseSensivitiy);
+ }
+ }
+ if (!found || m_anchored && endIx > 1) {
+ int startIx = 0;
+ int textIndex = 0;
+ if (! m_anchored)
+ found = true;
+ else {
+ startIx++;
+ endIx--;
+ textIndex = m_needles.at(0).length();
+ }
+ for (int ix = startIx; found && ix <= endIx; ix++) {
+ found = text.size() - textIndex >= m_restLengths.at(ix);
+ if (found)
+ found = (textIndex = text.indexOf(m_needles.at(ix),
+ textIndex, m_caseSensivitiy)) >= 0;
}
}
return found;
void ReMatcher::setPattern(const QString& pattern, bool anchored) {
m_anchored = anchored;
m_allMatching = false;
+ m_pattern = pattern;
+ m_needles.clear();
if (pattern.isEmpty())
m_needles.clear();
else {
- if (pattern.startsWith("*")){
- m_anchored = false;
- if (pattern.length() == 1)
- m_allMatching = true;
- }
m_needles = pattern.split('*');
- // Eliminate empty entries:
- for (int ix = m_needles.size() - 1; ix >= 0; ix--) {
+ // Eliminate empty entries but not first and next:
+ for (int ix = m_needles.size() - 2; ix > 0; ix--) {
if (m_needles.at(ix).length() == 0)
m_needles.removeAt(ix);
else
}
}
}
+/**
+ * Returns the current pattern.
+ *
+ * @return the current pattern
+ */
+const QString& ReMatcher::pattern() const
+{
+ return m_pattern;
+}
+
/**
* Returns whether the matcher accepts all strings (pattern "*").
*
/**
* Tests whether at least one pattern of the list matches the given text
+ *
* @param text text to test
- * @return <code>true</code>: one of the stored patterns matches the text<br>
+ * @return <code>true</code>: empty list or one of the stored patterns
+ * matches the text<br>
* <code>false</code>: none of the patterns matches
*/
bool ReListMatcher::matches(const QString& text)
{
QList<ReMatcher*>::const_iterator it;
- bool rc = false;
- for (it = m_list.constBegin(); ! rc && it != m_list.cend(); ++it){
+ bool rc = m_list.size() == 0;
+ for (it = m_list.cbegin(); ! rc && it != m_list.cend(); ++it){
rc = (*it)->matches(text);
}
return rc;
bool allMatching() const;
Qt::CaseSensitivity caseSensivitiy() const;
bool matches(const QString& text);
+ const QString& pattern() const;
void setCaseSensivitiy(const Qt::CaseSensitivity& caseSensivitiy);
void setPattern(const QString& pattern, bool anchored = false);
+
protected:
+ QString m_pattern;
QStringList m_needles;
// m_restLengths[ix] = sum(m_needles[ix..last].size()
QList<int> m_restLengths;
testReFileSystem();
}
void allTests() {
+ testOs();
testBase();
testGui();
if (s_allTest) {
fn.append("text").append(QByteArray::number(ix));
ReFileUtils::writeToFile(fn.constData(), fn.constData());
}
+ ReFileUtils::tempFile("abc.txt", "refilesytem", true);
}
- void testContains(const char* name, QList<ReFileMetaData*> nodes){
+ void testContains(const char* name, ReFileMetaDataList nodes){
bool rc = false;
- QList<ReFileMetaData*>::const_iterator it;
+ ReFileMetaDataList::const_iterator it;
for (it = nodes.cbegin(); it != nodes.cend(); ++it){
- if ((*it)->m_node == name)
+ if ((*it).m_node == name)
rc = true;
}
if (! rc)
checkT(rc);
}
- void testReLocalFileSystem() {
- ReLocalFileSytem fs(m_base);
+ void testReListInfos() {
+ ReLocalFileSytem fs(m_base, &m_logger);
checkEqu(QString(m_base), fs.directory());
checkEqu(QString(m_base), fs.basePath());
- QList<ReFileMetaData*> nodes;
+ ReFileMetaDataList nodes;
ReIncludeExcludeMatcher matcher(ReListMatcher::allMatchingList(),
ReQStringUtils::m_emptyList, Qt::CaseInsensitive, false);
fs.listInfos(matcher, nodes);
testContains("test1.txt", nodes);
testContains("test7.txt", nodes);
}
+ void testReadWrite(){
+ ReLocalFileSytem fs(m_base, &m_logger);
+ QByteArray buffer;
+ buffer.append("abcdefghijklmnopqrstuvwxyz");
+ checkEqu(0, fs.write("abc.txt", 0LL, buffer));
+ checkEqu(0, fs.write("abc.txt", 26LL, buffer));
+ QByteArray buffer2;
+ ReFileMetaDataList nodes;
+ QStringList names;
+ names.append("abc.txt");
+ ReIncludeExcludeMatcher matcher(names,
+ ReQStringUtils::m_emptyList, Qt::CaseInsensitive, true);
+ checkEqu(1, fs.listInfos(matcher, nodes));
+ checkEqu(1, nodes.size());
+ checkEqu(0, fs.read(nodes.at(0), 0LL, 3, buffer2));
+ checkEqu("abc", buffer2);
+ checkEqu(0, fs.read(nodes.at(0), 3LL, 7, buffer2));
+ checkEqu("defghij", buffer2);
+ checkEqu(0, fs.read(nodes.at(0), 10LL, 99, buffer2));
+ checkEqu("klmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", buffer2);
+ }
+ void testCopy(){
+
+ }
+
virtual void run() {
init();
- testReLocalFileSystem();
+ testReListInfos();
+ testReadWrite();
}
};
void testReFileSystem() {
#endif
checkF(ReFileUtils::isAbsolutPath(""));
}
+ void testSeekTell(){
+ QByteArray fn(ReFileUtils::tempFile("seektest.txt", NULL, false));
+ ReFileUtils::writeToFile(fn.constData(), "0123456789");
+ FILE* fp = fopen(fn.constData(), "rb");
+ checkNN(fp);
+ if (fp != NULL){
+ checkEqu(0LL, ReFileUtils::tell(fp));
+ checkEqu(0, ReFileUtils::seek(fp, 3, SEEK_SET));
+ checkEqu(3LL, ReFileUtils::tell(fp));
+ char cc;
+ checkEqu(1, fread(&cc, 1, 1, fp));
+ checkEqu('3', cc);
+ checkEqu(4LL, ReFileUtils::tell(fp));
+
+ checkEqu(0, ReFileUtils::seek(fp, -2, SEEK_CUR));
+ checkEqu(2LL, ReFileUtils::tell(fp));
+
+ checkEqu(0, ReFileUtils::seek(fp, -2, SEEK_END));
+ checkEqu(8LL, ReFileUtils::tell(fp));
+ }
+
+ }
virtual void run() {
+ testSeekTell();
testIsAbsolutePath();
testDeleteTree();
testTempDir();
public:
void testBasics() {
- ReMatcher m1("a*b*c", Qt::CaseSensitive, true);
+ ReMatcher m1("a*b*c*", Qt::CaseSensitive, true);
checkT(m1.matches("a b c d"));
checkT(m1.matches("abc d"));
checkT(m1.matches("ababc"));
checkT(m2.matches("a b c d"));
checkT(m2.matches("ababc"));
checkT(m2.matches("a b a b c"));
- checkT(m2.matches(" abc"));
+ checkT(m2.matches(" abc "));
checkF(m2.matches(" ab"));
ReMatcher m3("a**B*C", Qt::CaseInsensitive, true);
- checkT(m3.matches("a b c d"));
- checkT(m3.matches("abc d"));
+ checkT(m3.matches("a b C"));
+ checkT(m3.matches("ab c"));
checkT(m3.matches("ababc"));
checkT(m3.matches("abc"));
+ checkF(m3.matches("abcd"));
ReMatcher m4("A*B*c", Qt::CaseInsensitive, false);
checkT(m4.matches("a b c d"));
m4.setPattern("");
checkT(m4.matches("any"));
}
+ void test1Star(){
+ ReMatcher matcher("*abc", Qt::CaseSensitive, true);
+ checkT(matcher.matches("abc"));
+ checkF(matcher.matches("aBc"));
+ checkT(matcher.matches("xyzabc"));
+ checkF(matcher.matches("abc "));
+
+ matcher.setCaseSensivitiy(Qt::CaseInsensitive);
+ checkT(matcher.matches("abc"));
+ checkT(matcher.matches("aBc"));
+ checkT(matcher.matches("xyzabc"));
+ checkF(matcher.matches("abc "));
+
+ checkT(matcher.matches("AbC"));
+ checkT(matcher.matches("aBc"));
+ checkT(matcher.matches("xyzAbc"));
+ checkF(matcher.matches("abC "));
+
+ matcher.setPattern(matcher.pattern(), false);
+ matcher.setCaseSensivitiy(Qt::CaseSensitive);
+ checkT(matcher.matches("abc"));
+ checkF(matcher.matches("aBc"));
+ checkT(matcher.matches("xyzabc"));
+ checkT(matcher.matches("abc "));
+ checkT(matcher.matches("_abc_"));
+ checkF(matcher.matches("_a bc_"));
+
+ matcher.setCaseSensivitiy(Qt::CaseInsensitive);
+ checkT(matcher.matches("abc"));
+ checkT(matcher.matches("aBc"));
+ checkT(matcher.matches("xyzAbc"));
+ checkT(matcher.matches("aBc "));
+ checkT(matcher.matches("_abC_"));
+ checkF(matcher.matches("_a bc_"));
+
+ matcher.setPattern("x*y", true);
+ matcher.setCaseSensivitiy(Qt::CaseSensitive);
+ checkT(matcher.matches("x y"));
+ checkF(matcher.matches("X y"));
+ checkF(matcher.matches("x Y"));
+ checkT(matcher.matches("xy"));
+ checkF(matcher.matches("Xy"));
+ checkF(matcher.matches(" xy"));
+ checkF(matcher.matches("xy "));
+
+ matcher.setCaseSensivitiy(Qt::CaseInsensitive);
+ checkT(matcher.matches("X Y"));
+ checkT(matcher.matches("xY"));
+ checkT(matcher.matches("Xy"));
+ checkF(matcher.matches(" xy"));
+ checkF(matcher.matches("xy "));
+
+ matcher.setPattern(matcher.pattern(), false);
+ matcher.setCaseSensivitiy(Qt::CaseSensitive);
+ checkT(matcher.matches("x y"));
+ checkT(matcher.matches("ax y"));
+ checkT(matcher.matches("x y!"));
+ checkT(matcher.matches("123xyz!"));
+ checkF(matcher.matches("x"));
+ checkF(matcher.matches("xY"));
+ checkF(matcher.matches("Xy"));
+
+ matcher.setCaseSensivitiy(Qt::CaseInsensitive);
+ checkT(matcher.matches("X y"));
+ checkT(matcher.matches("aX y"));
+ checkT(matcher.matches("x Y!"));
+ checkT(matcher.matches("123XY!"));
+ checkF(matcher.matches("x"));
+ checkF(matcher.matches("xY"));
+ checkF(matcher.matches("Xy"));
+ }
+ void test0Star(){
+ ReMatcher matcher("abc", Qt::CaseSensitive, true);
+ checkT(matcher.matches("abc"));
+ checkF(matcher.matches("aBc"));
+ checkF(matcher.matches(" abc"));
+ checkF(matcher.matches("abc "));
+
+ checkT(matcher.caseSensivitiy());
+ matcher.setCaseSensivitiy(Qt::CaseInsensitive);
+ checkF(matcher.caseSensivitiy());
+
+ checkT(matcher.matches("abc"));
+ checkT(matcher.matches("aBc"));
+ checkF(matcher.matches(" aBc"));
+ checkF(matcher.matches("aBc "));
+
+ matcher.setPattern(matcher.pattern(), false);
+ matcher.setCaseSensivitiy(Qt::CaseSensitive);
+ checkT(matcher.matches("abc"));
+ checkF(matcher.matches("aBc"));
+ checkT(matcher.matches(" abc"));
+ checkT(matcher.matches("abc "));
+ }
+
void testList(){
QStringList patterns;
patterns << "*.txt" << "*.doc";
ReListMatcher matcher(patterns, Qt::CaseInsensitive, true);
checkT(matcher.matches("README.TXT"));
+ checkF(matcher.matches("readme_txt"));
checkT(matcher.matches("Xyz.Doc"));
checkF(matcher.matches("a.doc.bak"));
virtual void run(void) {
testBasics();
+ test0Star();
+ test1Star();
testList();
}
};
class TestReQStringUtil: public ReTest {
public:
TestReQStringUtil() :
- ReTest("ReQStringUtil") {
+ ReTest("ReQStringUtil") {
doIt();
}
void testLengthOfUInt64() {
quint64 value = -3;
checkEqu(1,
- ReQStringUtils::lengthOfUInt64(ReString("0"), 0, 10, &value));
+ 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));
+ ReQStringUtils::lengthOfUInt64("x432fabc x", 1, 10, &value));
checkEqu(int64_t(432LL), value);
checkEqu(16,
- ReQStringUtils::lengthOfUInt64("a1234567890123567", 1, 10, &value));
+ ReQStringUtils::lengthOfUInt64("a1234567890123567", 1, 10, &value));
checkEqu(int64_t(1234567890123567LL), value);
checkEqu(10,
- ReQStringUtils::lengthOfUInt64("x1234abcdef", 1, 16, &value));
+ 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(1, ReQStringUtils::lengthOfReal(ReString(" 0"), 1, &value));
checkEqu(0.0, value);
checkEqu(17,
- ReQStringUtils::lengthOfReal(ReString("X12345678901234567"), 1,
- &value));
+ 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));
+ ReQStringUtils::lengthOfReal(ReString("2.5e2x"), 0, &value));
checkEqu(250.0, value);
checkEqu(6,
- ReQStringUtils::lengthOfReal(ReString("2.5e+2"), 0, &value));
+ ReQStringUtils::lengthOfReal(ReString("2.5e+2"), 0, &value));
checkEqu(250.0, value);
checkEqu(7,
- ReQStringUtils::lengthOfReal(ReString("2.5E-33"), 0, &value));
+ ReQStringUtils::lengthOfReal(ReString("2.5E-33"), 0, &value));
checkEqu(2.5e-33, value);
checkEqu(3, ReQStringUtils::lengthOfReal(ReString("2.5E"), 0, &value));
checkEqu(3, ReQStringUtils::lengthOfReal(ReString("2.5E+"), 0, &value));
checkEqu(2.5, value);
checkEqu(3,
- ReQStringUtils::lengthOfReal(ReString("2.5E-a"), 0, &value));
+ ReQStringUtils::lengthOfReal(ReString("2.5E-a"), 0, &value));
checkEqu(2.5, value);
}
ReString name = "Heinz Müller";
char buffer[32];
checkEqu("Heinz Müller",
- ReQStringUtils::utf8(name, buffer, sizeof buffer));
+ 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');
checkEqu(8, ReQStringUtils::lengthOfTime("301:02:09x", 1, &time));
checkEqu(QTime(1, 2, 9), time);
}
- void testReMatcher() {
- ReMatcher m1("a*b*c", Qt::CaseSensitive, true);
- checkT(m1.matches("a b c d"));
- checkT(m1.matches("abc d"));
- checkT(m1.matches("ababc"));
- checkT(m1.matches("abc"));
- checkF(m1.matches("aBc"));
-
- ReMatcher m2("a*b*c", Qt::CaseSensitive, false);
- checkT(m2.matches("a b c d"));
- checkT(m2.matches("ababc"));
- checkT(m2.matches("a b a b c"));
- checkT(m2.matches(" abc"));
- checkF(m2.matches(" ab"));
-
- ReMatcher m3("a**B*C", Qt::CaseInsensitive, true);
- checkT(m3.matches("a b c d"));
- checkT(m3.matches("abc d"));
- checkT(m3.matches("ababc"));
- checkT(m3.matches("abc"));
-
- ReMatcher m4("A*B*c", Qt::CaseInsensitive, false);
- checkT(m4.matches("a b c d"));
- checkT(m4.matches("ababc"));
- checkT(m4.matches("a b a b c"));
- checkT(m4.matches(" abc"));
- checkF(m4.matches(" ab"));
-
- m4.setPattern("*");
- checkT(m4.matches("x"));
- m4.setPattern("");
- checkT(m4.matches("any"));
- }
virtual void run(void) {
- testReMatcher();
testLengtOfTime();
testLengtOfDate();
testDateTimeParser();
* @param edit the parent
*/
ReLook::ReLook() :
- m_font(NULL),
- m_metrics(NULL),
- m_foreground(FG_STANDARD),
- m_background(BG_STANDARD),
- m_edit(NULL) {
+ m_font(NULL),
+ m_metrics(NULL),
+ m_foreground(FG_STANDARD),
+ m_background(BG_STANDARD),
+ m_edit(NULL) {
}
/**
* @param look the presentation of the text
*/
ReEditText::ReEditText(const QString& text, ReLook* look) :
- m_text(text),
- m_look(look) {
+ m_text(text),
+ m_look(look) {
}
* @param edit the edit field (parent)
*/
void ReCursortLineBuilder::buildParagraph(ReParagraph& paragraph, int lineNo,
- ReEdit* edit) {
+ ReEdit* edit) {
if (lineNo == edit->cursorLineNo()) {
for (int ix = 0; ix < paragraph.length(); ix++) {
ReEditText* text = paragraph.at(ix);
* @param parent NULL or a widget which destroy the instance
*/
ReEdit::ReEdit(QWidget* parent) :
- QWidget(parent),
- ReMouseCatcher(),
- m_widthEdit(0),
- m_heightEdit(0),
- m_insertMode(true),
- m_breakLines(false),
- m_widthLineNumbers(50),
- m_widthVScrollBar(16),
- m_heightHScrollBar(16),
- m_looks(),
- m_standardBrush(new QBrush(Qt::SolidPattern)),
- m_scrollbarBrush(new QBrush(Qt::SolidPattern)),
- m_sliderBrush(new QBrush(Qt::ConicalGradientPattern)),
- m_brushColors(),
- m_standardPen(new QPen(Qt::SolidLine)),
- m_standardFont(NULL),
- m_standardMetrics(NULL),
- m_fontColors(),
- m_keyAlt(),
- m_keyAltControl(),
- m_keyAltControlShift(),
- m_keyAltShift(),
- m_keyControl(),
- m_keyControlShift(),
- m_keyRaw(),
- m_keyShift() {
+ QWidget(parent),
+ ReMouseCatcher(),
+ m_widthEdit(0),
+ m_heightEdit(0),
+ m_insertMode(true),
+ m_breakLines(false),
+ m_widthLineNumbers(50),
+ m_widthVScrollBar(16),
+ m_heightHScrollBar(16),
+ m_looks(),
+ m_standardBrush(new QBrush(Qt::SolidPattern)),
+ m_scrollbarBrush(new QBrush(Qt::SolidPattern)),
+ m_sliderBrush(new QBrush(Qt::ConicalGradientPattern)),
+ m_brushColors(),
+ m_standardPen(new QPen(Qt::SolidLine)),
+ m_standardFont(NULL),
+ m_standardMetrics(NULL),
+ m_fontColors(),
+ m_keyAlt(),
+ m_keyAltControl(),
+ m_keyAltControlShift(),
+ m_keyAltShift(),
+ m_keyControl(),
+ m_keyControlShift(),
+ m_keyRaw(),
+ m_keyShift() {
setFocusPolicy(Qt::WheelFocus);
m_standardFont = new QFont("Courier");
m_standardFont->setStyleHint(QFont::TypeWriter);
appendBuilder(new ReCursortLineBuilder());
assignKeysStandard();
}
+
+/**
+ * Destructor.
+ */
+ReEdit::~ReEdit()
+{
+ for (size_t ix = 0; ix < sizeof(m_fontColors) / sizeof m_fontColors[0]; ix++)
+ delete m_fontColors[ix];
+ for (size_t ix = 0; ix < sizeof(m_brushColors) / sizeof m_brushColors[0]; ix++)
+ delete m_brushColors[ix];
+ delete m_standardBrush;
+ delete m_scrollbarBrush;
+ delete m_sliderBrush;
+ delete m_standardPen;
+ delete m_standardFont;
+ delete m_standardMetrics;
+}
/**
* Assigns a standard version of colors to symbolic colors.
*/
* @param length OUT: the slider length in pixel
*/
void calcSliderSize(int size, int minSize, double sizeFactor, double posFactor,
- int& position, int& length) {
+ int& position, int& length) {
if (sizeFactor > 1.0)
sizeFactor = 1.0;
if (posFactor > 100)
* @param posHorizontal the position of the scrollbar as factor [0..1]
*/
void ReEdit::drawScrollbars(QPainter& painter, const QRect& rect,
- double sizeVertical, double posVertical, double sizeHorizontal,
- double posHorizontal) {
+ double sizeVertical, double posVertical, double sizeHorizontal,
+ double posHorizontal) {
// We paint the vertical scrollbar:
QBrush brush(*m_brushColors[ReLook::BG_SCROLLBAR], Qt::SolidPattern);
painter.setBrush(brush);
static int width = 1;
static int width2 = 2 * width;
m_vScrollBar->setRect(x + width2, rect.top(), m_widthVScrollBar - width2,
- rect.height() - m_heightHScrollBar - width);
+ rect.height() - m_heightHScrollBar - width);
painter.drawRect(*m_vScrollBar);
// We paint the horizontal scrollbar:
m_hScrollBar->setRect(rect.left() + m_widthLineNumbers,
- rect.bottom() - m_heightHScrollBar + width,
- rect.width() - m_widthVScrollBar - m_widthLineNumbers,
- m_heightHScrollBar - width2);
+ rect.bottom() - m_heightHScrollBar + width,
+ rect.width() - m_widthVScrollBar - m_widthLineNumbers,
+ m_heightHScrollBar - width2);
painter.drawRect(*m_hScrollBar);
// Slider (vertical)
int sliderSize = 0;
int sliderPos = 0;
calcSliderSize(rect.height() - m_heightHScrollBar, m_heightHScrollBar,
- sizeVertical, posVertical, sliderPos, sliderSize);
+ sizeVertical, posVertical, sliderPos, sliderSize);
m_vSlider->setRect(x + width2, rect.top() + sliderPos + width,
- m_widthVScrollBar - width2, sliderSize - width2);
+ m_widthVScrollBar - width2, sliderSize - width2);
painter.drawRect(*m_vSlider);
int middle = m_vSlider->top() + m_vSlider->height() / 2;
painter.drawLine(m_vSlider->left() + 2, middle, m_vSlider->right() - 2,
- middle);
+ middle);
middle -= m_heightHScrollBar / 2 - 2;
painter.drawLine(m_vSlider->left() + 2, middle, m_vSlider->right() - 2,
- middle);
+ middle);
middle += m_heightHScrollBar - 4;
painter.drawLine(m_vSlider->left() + 2, middle, m_vSlider->right() - 2,
- middle);
+ middle);
// Slider (horizontal)
calcSliderSize(rect.width() - m_widthLineNumbers - m_widthVScrollBar,
- m_heightHScrollBar, sizeHorizontal, posHorizontal, sliderPos,
- sliderSize);
+ m_heightHScrollBar, sizeHorizontal, posHorizontal, sliderPos,
+ sliderSize);
m_hSlider->setRect(rect.left() + m_widthLineNumbers + sliderPos,
- rect.bottom() - m_heightHScrollBar + width, sliderSize - width,
- m_heightHScrollBar - width2);
+ rect.bottom() - m_heightHScrollBar + width, sliderSize - width,
+ m_heightHScrollBar - width2);
painter.drawRect(*m_hSlider);
middle = m_hSlider->left() + m_hSlider->width() / 2;
painter.drawLine(middle, m_hSlider->top() + 2, middle,
- m_hSlider->bottom() - 2);
+ m_hSlider->bottom() - 2);
middle -= m_heightHScrollBar / 2 - 2;
painter.drawLine(middle, m_hSlider->top() + 2, middle,
- m_hSlider->bottom() - 2);
+ m_hSlider->bottom() - 2);
middle += m_heightHScrollBar - 4;
painter.drawLine(middle, m_hSlider->top() + 2, middle,
- m_hSlider->bottom() - 2);
+ m_hSlider->bottom() - 2);
}
/**
m_cursorCol = m_lines->lineAt(m_cursorLineNo - 1).length() - 1;
}
if (m_lines->removePart(m_cursorLineNo, columnToIndex(currentCol), 1,
- true))
+ true))
m_cursorLineNo = max(0, m_cursorLineNo - 1);
break;
int lastIx = lastColOfCurrent();
if (m_cursorCol <= lastIx) {
m_lines->removePart(m_cursorLineNo, m_cursorCol + 1,
- lastIx - m_cursorCol, true);
+ lastIx - m_cursorCol, true);
ensureCursorVisible();
}
break;
*/
void ReEdit::ensureCursorVisible() {
if (m_cursorLineNo < m_firstLine
- || m_cursorLineNo >= m_firstLine + pageSize()) {
+ || m_cursorLineNo >= m_firstLine + pageSize()) {
reposition(m_cursorLineNo, m_cursorCol);
}
if (m_cursorCol < 0)
break;
}
} else if (shift && !keyText.isEmpty() && key != Qt::Key_Delete
- && key != Qt::Key_Backspace) {
+ && key != Qt::Key_Backspace) {
m_lines->insertText(m_cursorLineNo, m_cursorCol + 1, keyText);
m_cursorCol++;
} else {
* @return
*/
ReLook* ReEdit::lookOf(ReLook::ForeGround foreground,
- ReLook::BackGround background) {
+ ReLook::BackGround background) {
int index = foreground * ReLook::BG_COUNT + background;
ReLook* rc = m_looks[index];
if (rc == NULL) {
*/
void ReEdit::mouseMoveEvent(QMouseEvent* event) {
if (m_lastMousePosition.x() >= 0
- && (handleHScrollBar(event, true, this)
- || handleVScrollBar(event, true, this))) {
+ && (handleHScrollBar(event, true, this)
+ || handleVScrollBar(event, true, this))) {
emit repaint();
}
}
} else {
QPoint position = event->pos();
m_cursorLineNo = position.y()
- / heightToFullHeight(m_standardMetrics->height()) + m_firstLine;
+ / heightToFullHeight(m_standardMetrics->height()) + m_firstLine;
int x = position.x();
int charWidth = m_standardMetrics->width('x');
x -= m_widthLineNumbers;
if (x >= 0
- && x < m_widthEdit - m_widthLineNumbers - m_widthVScrollBar) {
+ && x < m_widthEdit - m_widthLineNumbers - m_widthVScrollBar) {
if (x <= +charWidth / 2)
m_cursorCol = m_firstCol - 1;
else
int pageSize = (rect.height() - m_heightHScrollBar) / lineHeight;
int charWidth = m_standardMetrics->averageCharWidth();
int pageWidth = (rect.width() - m_widthVScrollBar - m_widthLineNumbers)
- / charWidth;
+ / charWidth;
int firstLine = m_firstLine;
load(firstLine, pageSize, pageWidth, this);
QPainter painter(this);
ReLook* look = lookOf(ReLook::FG_STANDARD, ReLook::BG_STANDARD);
painter.setBrush(*look->m_brush);
QRect editArea(rect.left() + m_widthLineNumbers, rect.top(),
- rect.right() - m_widthVScrollBar, rect.bottom() - m_heightHScrollBar);
+ rect.right() - m_widthVScrollBar, rect.bottom() - m_heightHScrollBar);
// Painting the frame of the edit field:
painter.drawRect(editArea);
// Painting the edit field area (text...)
for (int ix = 0; ix < maxIx; ix++, lineNo++) {
QString number = QString::number(lineNo);
ReLook* look =
- lineNo == m_cursorLineNo + 1 ?
- lookOf(ReLook::FG_CURRENT_LINE, ReLook::BG_CURRENT_LINE) :
- lookStd;
+ lineNo == m_cursorLineNo + 1 ?
+ lookOf(ReLook::FG_CURRENT_LINE, ReLook::BG_CURRENT_LINE) :
+ lookStd;
int width = look->m_metrics->width(number);
if (ix == 0)
y = rect.top() + look->m_metrics->height()
- - look->m_metrics->descent();
+ - look->m_metrics->descent();
painter.setFont(*look->m_font);
painter.setPen(*look->m_pen);
painter.drawText(left + m_widthLineNumbers - width - 5, y, number);
}
// We paint the cursor:
if (m_cursorVisible && m_cursorLineNo >= firstLine
- && m_cursorLineNo < firstLine + pageSize) {
+ && m_cursorLineNo < firstLine + pageSize) {
ReParagraph* cursorPara = cursorParagraph();
int col = min(m_cursorCol, cursorPara->m_columns - 1);
col = indexToColumn(col + 1, m_tabWidth,
- m_lines->lineAt(m_cursorLineNo)) - m_firstCol;
+ m_lines->lineAt(m_cursorLineNo)) - m_firstCol;
int x = rect.left() + m_widthLineNumbers + 1
- + col * lookStd->m_metrics->width('x');
+ + col * lookStd->m_metrics->width('x');
int y = rect.top() + (m_cursorLineNo - firstLine) * lineHeight;
painter.setPen(*look->m_pen);
painter.drawLine(x, y, x, y + lineHeight);
int maxLines = max(1, m_lines->lineCount() - pageSize);
drawScrollbars(painter, rect, fraction(pageSize, maxLines, 1.0),
- fraction(m_firstLine, maxLines, 0.0),
- fraction(m_screenWidth, m_maxCols, 1.0),
- fraction(m_firstCol, max(0, m_maxCols - m_screenWidth), 0.0));
+ fraction(m_firstLine, maxLines, 0.0),
+ fraction(m_screenWidth, m_maxCols, 1.0),
+ fraction(m_firstCol, max(0, m_maxCols - m_screenWidth), 0.0));
ReLogger::globalLogger()->logv(LOG_INFO, 3, "draw: %.4f",
- double(clock() - start) / CLOCKS_PER_SEC);
+ double(clock() - start) / CLOCKS_PER_SEC);
}
/**
* Constructor.
*/
ReParagraphs::ReParagraphs() :
- m_builders(),
- m_firstLine(0),
- m_firstCol(0),
- m_cursorLineNo(0),
- m_cursorCol(-1),
- m_lines(NULL),
- m_list(),
- m_maxCols(0),
- m_screenWidth(0),
- m_cursorVisible(true) {
+ m_builders(),
+ m_firstLine(0),
+ m_firstCol(0),
+ m_cursorLineNo(0),
+ m_cursorCol(-1),
+ m_lines(NULL),
+ m_list(),
+ m_maxCols(0),
+ m_screenWidth(0),
+ m_cursorVisible(true) {
}
/**
* expanded tabs
*/
int ReParagraphs::columnToIndex(int column, int tabWidth,
- const QString& string) {
+ const QString& string) {
int rc = 0;
if (column < 0)
rc = -1;
ReParagraph* ReParagraphs::cursorParagraph() {
ReParagraph* rc = NULL;
if (m_cursorLineNo >= m_firstLine
- && m_cursorLineNo < m_firstLine + m_list.length()) {
+ && m_cursorLineNo < m_firstLine + m_list.length()) {
rc = m_list.at(m_cursorLineNo - m_firstLine);
}
return rc;
*/
int ReParagraphs::columnToIndex(int cursorCol) {
int rc = columnToIndex(cursorCol, m_tabWidth,
- m_lines->lineAt(m_cursorLineNo));
+ m_lines->lineAt(m_cursorLineNo));
return rc;
}
* @return
*/
int ReParagraphs::indexToColumn(int index, int tabWidth,
- const QString& string) {
+ const QString& string) {
int rc = 0;
if (index > 0) {
int length = string.length();
* @param edit the parent, the edit field
*/
void ReParagraphBuilder::buildParagraph(ReParagraph& paragraph, int lineNo,
- ReEdit* edit) {
+ ReEdit* edit) {
if (paragraph.length() == 0) {
int firstCol = edit->m_firstCol;
const QString& text = edit->lines().lineAt(lineNo);
ReLook* look = edit->lookOf(ReLook::FG_STANDARD, ReLook::BG_STANDARD);
ReLook* lookTab = edit->lookOf(ReLook::FG_GREY_LIGHT,
- ReLook::BG_STANDARD);
+ ReLook::BG_STANDARD);
paragraph.m_columns = 0;
int ixTab;
ReEditText* part;
* Constructor.
*/
ReMouseCatcher::ReMouseCatcher() :
- m_clickObjects(),
- m_vScrollBar(new ClickPosition(CO_VSCROLLBAR)),
- m_hScrollBar(new ClickPosition(CO_HSCROLLBAR)),
- m_hSlider(new ClickPosition(CO_HSLIDER)),
- m_vSlider(new ClickPosition(CO_VSLIDER)),
- m_lastMousePosition(),
- m_lastTopVSlider(0),
- m_lastLeftHSlider(0) {
+ m_clickObjects(),
+ m_vScrollBar(new ClickPosition(CO_VSCROLLBAR)),
+ m_hScrollBar(new ClickPosition(CO_HSCROLLBAR)),
+ m_hSlider(new ClickPosition(CO_HSLIDER)),
+ m_vSlider(new ClickPosition(CO_VSLIDER)),
+ m_lastMousePosition(),
+ m_lastTopVSlider(0),
+ m_lastLeftHSlider(0) {
}
/**
* @return <code>true</code>: the mouse click is inside the horizontal sb
*/
bool ReMouseCatcher::handleHScrollBar(QMouseEvent* event, bool isDragged,
- ReEdit* edit) {
+ ReEdit* edit) {
QPoint pos = event->pos();
bool rc = rectContains(*m_hScrollBar, pos, "hScrollBar")
- || (isDragged && m_hScrollBar->contains(m_lastMousePosition));
+ || (isDragged && m_hScrollBar->contains(m_lastMousePosition));
if (rc) {
if (isDragged) {
int distance = pos.x() - m_lastMousePosition.x();
int moveGap = m_hScrollBar->width() - m_hSlider->width();
double position = moveGap == 0 ? 0.0 : double(sliderPos) / moveGap;
int col = roundInt(
- (edit->m_maxCols - edit->m_screenWidth)
- * max(0.0, min(position, 1.0)));
+ (edit->m_maxCols - edit->m_screenWidth)
+ * max(0.0, min(position, 1.0)));
//ReLogger::globalLogger()->logv(LOG_INFO, 4,
// "x: %d dist: %d last: %d slPos: %d pos: %.2f gap: %d col: %d / %d scw: %d",
// pos.x(), distance, m_lastLeftHSlider, sliderPos, position, moveGap,
* @return <code>true</code>: the mouse click is inside the vertical sb
*/
bool ReMouseCatcher::handleVScrollBar(QMouseEvent* event, bool isDragged,
- ReEdit* edit) {
+ ReEdit* edit) {
QPoint pos = event->pos();
bool rc = rectContains(*m_vScrollBar, pos, "vScrollBar")
- || (isDragged && m_vScrollBar->contains(m_lastMousePosition));
+ || (isDragged && m_vScrollBar->contains(m_lastMousePosition));
if (rc) {
if (isDragged) {
int distance = pos.y() - m_lastMousePosition.y();
int moveGap = m_vScrollBar->height() - m_vSlider->height();
double position = moveGap == 0 ? 0.0 : double(sliderPos) / moveGap;
int line = roundInt(
- (edit->lines().lineCount() - edit->pageSize())
- * max(0.0, min(position, 1.0)));
+ (edit->lines().lineCount() - edit->pageSize())
+ * max(0.0, min(position, 1.0)));
edit->reposition(line, edit->m_cursorCol);
} else {
if (pos.y() < m_vSlider->top())
* @param source source to copy
*/
inline ReEditText(const ReEditText& source) :
- m_text(source.m_text),
- m_look(source.m_look) {
+ m_text(source.m_text),
+ m_look(source.m_look) {
}
/** Assignment operator.
* @param source source to copy
class ReParagraphBuilder {
public:
virtual void buildParagraph(ReParagraph& paragraph, int lineNo,
- ReEdit* edit);
+ ReEdit* edit);
};
class ReCursortLineBuilder: public ReParagraphBuilder {
// ReParagraphBuilder interface
public:
virtual void buildParagraph(ReParagraph& paragraph, int lineNo,
- ReEdit* edit);
+ ReEdit* edit);
};
/**
class ClickPosition: public QRect {
public:
ClickPosition(ClickObjType type) :
- QRect(0, 0, 0, 0),
- m_type(type),
- m_title(),
- m_object(NULL) {
+ QRect(0, 0, 0, 0),
+ m_type(type),
+ m_title(),
+ m_object(NULL) {
}
public:
bool operator <(const ClickPosition& op) {
};
public:
explicit ReEdit(QWidget *parent = 0);
+ virtual ~ReEdit();
public:
void assignColorsStandard();
void assignKeysStandard();
}
ReLines& lines();
ReLook* lookOf(ReLook::ForeGround foreground,
- ReLook::BackGround background);
+ ReLook::BackGround background);
/** Returns the current page size.
* return number of visible lines in the edit field
*/
protected:
QBrush* createBrush(ReLook::BackGround background);
void drawScrollbars(QPainter& painter, const QRect& rect,
- double sizeVertical, double posVertical, double sizeHorizontal,
- double posHorizontal);
+ double sizeVertical, double posVertical, double sizeHorizontal,
+ double posHorizontal);
void ensureCursorVisible();protected slots:
void keyPressEvent(QKeyEvent* event);
void paintEvent(QPaintEvent *);
setPath(path);
}
+/**
+ * Destructor.
+ */
+ReSettings::~ReSettings()
+{
+
+}
+
/*
* Adds an entry to a history item at the first position.
*
ReLogger* m_logger;
};
+typedef QMap<QByteArray, ReProperty*> RePropertyMap;
+typedef QMap<QByteArray, QList<ReProperty*>*> ReChapterMap;
+
class ReSettings {
public:
static QString TRUE;
static QString FALSE;
public:
ReSettings(const QString& path, const QString& prefix, ReLogger* logger);
+ ~ReSettings();
public:
void addHistoryEntry(const char* key, const QString& value, char separator,
int maxEntries);
QString m_path;
QString m_fileHistory;
QString m_fileSettings;
- QMap<QByteArray, ReProperty*> m_settings;
- QMap<QByteArray, QList<ReProperty*>*> m_chapters;
+ RePropertyMap m_settings;
+ ReChapterMap m_chapters;
ReLogger* m_logger;
};
#include "base/rebase.hpp"
#include "os/reos.hpp"
+enum {
+ LOC_READ_1 = LOC_FIRST_OF(LOC_FILESYSTEM), // 12001
+ LOC_WRITE_1, // 12002
+ LOC_WRITE_2, // 12003
+ LOC_WRITE_3, // 12004
+ LOC_WRITE_4, // 12005
+ LOC_READ_2, // 12006
+ LOC_MAKE_DIR_1, // 12007
+ LOC_MAKE_DIR_2, // 12008
+ LOC_MAKE_DIR_3, // 12009
+ LOC_SET_PROPERTIES_1, // 12010
+ LOC_SET_PROPERTIES_2, // 12011
+ LOC_SET_PROPERTIES_3, // 12012
+ LOC_REMOVE_1, // 12013
+ LOC_REMOVE_2, // 12014
+ LOC_REMOVE_3, // 12015
+};
/**
* Constructor.
*
* @param name the name of the filesystem
*/
-ReFileSystem::ReFileSystem(const QString& name) :
- m_name(name), m_writeable(false)
+ReFileSystem::ReFileSystem(const QString& name, ReLogger* logger) :
+ m_name(name), m_writeable(false), m_logger(logger), m_buffer(),
+ m_blocksize(4*1024*1024), m_undefinedTime()
{
}
*/
ReFileSystem::~ReFileSystem()
{
+}
+/**
+ * Copy a file from a source filesystem to the current directory of the instance.
+ *
+ * @param source meta data of the source file (in current directory)
+ * @param sourceFS the filesystem containing the source
+ * @return EC_SUCCESS: success<br>
+ *
+ */
+ReFileSystem::ErrorCode ReFileSystem::copy(ReFileMetaData& source,
+ ReFileSystem& sourceFS)
+{
+ int blocksize = min(m_blocksize, sourceFS.blocksize());
+ ErrorCode rc = EC_SUCCESS;
+ ErrorCode rc2;
+ int64_t size = 0;
+ while(rc == EC_SUCCESS && size < source.m_size){
+ if ( (rc2 = sourceFS.read(source, size, blocksize, m_buffer)) != EC_SUCCESS)
+ rc = rc2;
+ else if ( (rc2 = write(source.m_node, size, m_buffer)) != EC_SUCCESS)
+ rc = rc2;
+ size += blocksize;
+ }
+ close();
+ sourceFS.close();
+ return rc;
}
/**
{
m_writeable = writeable;
}
+/**
+ * Returns the current blocksize (for copy operations).
+ *
+ * @return the current blocksize
+ */
+int ReFileSystem::blocksize() const
+{
+ return m_blocksize;
+}
+
+/**
+ * Finds the first file given by a pattern.
+ *
+ * @param pattern pattern to find
+ * @param file OUT: the found file (valid only if return code is <code>true</code>
+ * @return <code>true</code>: at least one file found<br>
+ * <code>false</code>: no file found
+ */
+bool ReFileSystem::first(const QString& pattern, ReFileMetaData& file)
+{
+ ReFileMetaDataList list;
+ QStringList names;
+ names.append(pattern);
+ ReIncludeExcludeMatcher matcher(names,
+ ReQStringUtils::m_emptyList, Qt::CaseInsensitive, true);
+ listInfos(matcher, list);
+ bool rc = list.size() > 0;
+ if (rc)
+ file = list.at(0);
+ return rc;
+}
+
+/**
+ * Sets the size of the internal buffer for copy operations.
+ *
+ * @param blocksize the new blocksize
+ */
+void ReFileSystem::setBlocksize(int blocksize)
+{
+ m_blocksize = blocksize;
+}
+
/**
* Constructor.
+ *
+ * @param basePath the root directory of the filesystem<br>
+ * Windows: e.g. "c:\" or "\\server\data"<br>
+ * Linux: Mount point, e.g. "/" or "/media/data"
+ * @param logger
*/
-ReLocalFileSytem::ReLocalFileSytem(const QString& basePath) :
- ReFileSystem("localfs"),
+ReLocalFileSytem::ReLocalFileSytem(const QString& basePath, ReLogger* logger) :
+ ReFileSystem("localfs", logger),
m_basePath(basePath),
m_currentPath(basePath),
- m_dir(basePath)
+ m_dir(basePath),
+ m_readFile(NULL),
+ m_writeFile(NULL)
{
-
+ setWriteable(true);
}
/**
return m_basePath;
}
+/**
+ * Closes the open files.
+ */
+void ReLocalFileSytem::close()
+{
+ if (m_readFile != NULL){
+ fclose(m_readFile);
+ m_readFile = NULL;
+ }
+ if (m_writeFile != NULL){
+ fclose(m_writeFile);
+ m_writeFile = NULL;
+ }
+}
+
/**
* Returns the name of the current directory.
*
* @return the count of the found entries (<code>list.size()</code>)
*/
int ReLocalFileSytem::listInfos(const ReIncludeExcludeMatcher& matcher,
- QList<ReFileMetaData*>& list)
+ ReFileMetaDataList& list)
{
list.clear();
const QStringList& patterns = matcher.includes().patterns();
full.resize(pathLength);
full.append(node.toUtf8());
if (stat(full.constData(), &info) == 0){
- ReFileMetaData* meta = new ReFileMetaData(node,
- QDateTime::fromTime_t(info.st_mtime),
- QDateTime::fromTime_t(info.st_ctime),
- info.st_uid, info.st_gid, info.st_mode);
- list.append(meta);
+ list.append(ReFileMetaData(node,
+ QDateTime::fromTime_t(info.st_mtime),
+ QDateTime::fromTime_t(info.st_ctime),
+ info.st_uid, info.st_gid, info.st_mode, info.st_size));
}
}
return list.size();
}
+/** Creates a directory.
+ * @param node the name without path (in the current directory)
+ * @return EC_SUCCESS: successful<br>
+ * EC_FS_READ_ONLY: the filesystem is readonly<br>
+ * EC_ALREADY_EXISTS: a file with this name exists<br>
+ * EC_NOT_ACCESSIBLE: creation failed
+ */
+ReFileSystem::ErrorCode ReLocalFileSytem::makeDir(const QString& node)
+{
+ ErrorCode rc = EC_SUCCESS;
+ if (! m_writeable){
+ m_logger->log(LOG_ERROR, LOC_MAKE_DIR_1,
+ "filesystem is readonly");
+ rc = EC_FS_READ_ONLY;
+ } else if (m_dir.exists(node)) {
+ m_logger->logv(LOG_ERROR, LOC_MAKE_DIR_2,
+ "node exists already: %s", fullNameAsUTF8(node).constData());
+ rc = EC_ALREADY_EXISTS;
+ } else if (! m_dir.mkdir(node)){
+ m_logger->logv(LOG_ERROR, LOC_MAKE_DIR_2,
+ "cannot create directory: %s", fullNameAsUTF8(node).constData());
+ rc = EC_NOT_ACCESSIBLE;
+ }
+ return rc;
+}
+
/**
* Changes the current directory of the filesystem.
*
return rc;
}
+/**
+ * Reads a part of a file into a buffer.
+ *
+ * @param source the file to move
+ * @param offset first position to read
+ * @param size number of bytes to read
+ * @param buffer OUT: content of the file
+ * @return EC_SUCCESS: success<br>
+ * EC_NOT_READABLE: file can't be opened<br>
+ * EC_READ: error while reading
+ */
+ReFileSystem::ErrorCode ReLocalFileSytem::read(const ReFileMetaData& source,
+ int64_t offset, int size, QByteArray& buffer)
+{
+ ErrorCode rc = EC_SUCCESS;
+ if (offset == 0){
+ if (m_readFile != NULL)
+ fclose(m_readFile);
+ QString fn = m_currentPath + source.m_node;
+ if ( (m_readFile = fopen(fn.toUtf8().constData(), "rb")) == NULL){
+ m_logger->logv(LOG_ERROR, LOC_READ_1,
+ "cannot open for reading (%d): %s",
+ errno, fn.toUtf8().constData());
+ rc = EC_NOT_READABLE;
+ }
+ }
+ if (m_readFile != NULL){
+ ReFileUtils::seek(m_readFile, offset, SEEK_SET);
+ buffer.reserve(size);
+ int nRead = fread(buffer.data(), 1, size, m_readFile);
+ if (nRead < 0){
+ m_logger->logv(LOG_ERROR, LOC_READ_2,
+ "cannot read (%d): %s",
+ errno, source.m_node.toUtf8().constData());
+ nRead = 0;
+ rc = EC_READ;
+ }
+ buffer.resize(nRead);
+ if (feof(m_readFile)){
+ fclose(m_readFile);
+ m_readFile = NULL;
+ } else {
+ fflush(m_readFile);
+ }
+ }
+ return rc;
+}
+
+/**
+ * Sets the properties of a file in the current directory.
+ *
+ * @param source the properties to copy
+ * @param target the properties of the file to change
+ * @return EC_SUCCESS: successful<br>
+ * EC_FS_READ_ONLY: filesystem is readonly<br>
+ * EC_ALREADY_EXISTS: renaming failed: target node exists already<br>
+ * EC_RENAME: renaming failed
+ *
+ */
+ReFileSystem::ErrorCode ReLocalFileSytem::setProperties(
+ const ReFileMetaData& source, const ReFileMetaData& target)
+{
+ ErrorCode rc = EC_SUCCESS;
+ if (! m_writeable){
+ m_logger->log(LOG_ERROR, LOC_SET_PROPERTIES_1,
+ "filesystem is readonly");
+ rc = EC_FS_READ_ONLY;
+ } else {
+ if (target.m_node != source.m_node){
+ if (m_dir.exists(source.m_node)){
+ rc = EC_ALREADY_EXISTS;
+ m_logger->logv(LOG_ERROR, LOC_SET_PROPERTIES_2,
+ "renaming impossible: node exists: %s",
+ fullNameAsUTF8(target.m_node).constData());
+ } else if (! m_dir.rename(target.m_node, source.m_node)){
+ rc = EC_RENAME;
+ m_logger->logv(LOG_ERROR, LOC_SET_PROPERTIES_3,
+ "renaming impossible: %s -> %s",
+ source.m_node.toUtf8().constData(),
+ fullNameAsUTF8(target.m_node).constData());
+ }
+ }
+ if (rc == EC_SUCCESS && source.m_modified != target.m_modified
+ && source.m_modified != m_undefinedTime){
+ }
+ if (rc == EC_SUCCESS && source.m_created != target.m_created
+ && source.m_created != m_undefinedTime){
+ }
+ if (rc == EC_SUCCESS && source.m_mode != target.m_mode
+ && source.m_mode != (mode_t) -1){
+ }
+ if (rc == EC_SUCCESS && source.m_owner != target.m_owner
+ && source.m_owner != -1){
+ }
+ if (rc == EC_SUCCESS && source.m_group != target.m_group
+ && source.m_group != -1){
+ }
+ }
+ return rc;
+}
+
+/**
+ * Removes a file or directory.
+ *
+ * @param node the properties ot the node (in the current directory)
+ * @return EC_SUCCESS: successful<br>
+ * EC_FS_READ_ONLY: filesystem is readonly<br>
+ * EC_NOT_EXISTS: the node does not exist
+ * EC_NOT_ACCESSIBLE: removing failed
+ *
+ */
+ReFileSystem::ErrorCode ReLocalFileSytem::remove(const ReFileMetaData& node)
+{
+ ErrorCode rc = EC_SUCCESS;
+ if (! m_writeable){
+ m_logger->log(LOG_ERROR, LOC_REMOVE_1,
+ "filesystem is readonly");
+ rc = EC_FS_READ_ONLY;
+ } else if (! m_dir.exists(node.m_node)) {
+ m_logger->logv(LOG_ERROR, LOC_REMOVE_2,
+ "node does not exists: %s", fullNameAsUTF8(node.m_node).constData());
+ rc = EC_NOT_EXISTS;
+ } else {
+ if (S_ISDIR(node.m_mode)){
+ if (! m_dir.rmdir(node.m_node)){
+ m_logger->logv(LOG_ERROR, LOC_REMOVE_3,
+ "cannot remove directory: %s", fullNameAsUTF8(node.m_node).constData());
+ rc = EC_NOT_ACCESSIBLE;
+ }
+ } else {
+ if (! m_dir.remove(node.m_node)){
+ m_logger->logv(LOG_ERROR, LOC_REMOVE_3,
+ "cannot remove file: %s", fullNameAsUTF8(node.m_node).constData());
+ rc = EC_NOT_ACCESSIBLE;
+ }
+ }
+ }
+ return rc;
+}
+
+/**
+ * Writes a buffer to a file.
+ *
+ * @param node the file to write (without path, inside the current directory)
+ * @param offset first position to write
+ * @param buffer content to write
+ * @return EC_SUCCESS: successful<br>
+ * EC_FS_READ_ONLY: filesystem is readonly<br>
+ * EC_NOT_WRITEABLE: open for writing failed
+ * EC_POSITION: file position not equals to <code>offset</code>
+ * EC_WRITE: writing failed
+ *
+ */
+ReFileSystem::ErrorCode ReLocalFileSytem::write(const QString& node,
+ int64_t offset, const QByteArray& buffer)
+{
+ ErrorCode rc = EC_SUCCESS;
+ if (! writeable()){
+ m_logger->log(LOG_ERROR, LOC_WRITE_1,
+ "filesystem is readonly");
+ rc = EC_FS_READ_ONLY;
+ } else {
+ if (offset == 0){
+ if (m_writeFile != NULL)
+ fclose(m_writeFile);
+ QString fn = m_currentPath + node;
+ if ( (m_writeFile = fopen(fn.toUtf8().constData(), "wb")) == NULL){
+ m_logger->logv(LOG_ERROR, LOC_WRITE_2,
+ "cannot open for writing (%d): %s",
+ errno, fn.toUtf8().constData());
+ rc = EC_NOT_WRITEABLE;
+ }
+ }
+ if (m_writeFile != NULL){
+ int64_t position = ReFileUtils::tell(m_writeFile);
+ if (position != offset){
+ rc = EC_POSITION;
+ m_logger->logv(LOG_ERROR, LOC_WRITE_4,
+ "wrong file position: %lld/%lld",
+ offset, position);
+ } else {
+ int nWritten = fwrite(buffer.constData(),
+ 1, buffer.length(), m_writeFile);
+ if (nWritten != buffer.length()){
+ m_logger->logv(LOG_ERROR, LOC_WRITE_3,
+ "cannot write (%d): %s written: %d/%d",
+ errno, node.toUtf8().constData(),
+ nWritten, buffer.length());
+ rc = EC_WRITE;
+ }
+ fflush(m_writeFile);
+ }
+ }
+ }
+ return rc;
+}
+
+
+/**
+ * Constructor.
+ */
+ReFileMetaData::ReFileMetaData() : m_node(), m_modified(), m_created(),
+ m_owner(0), m_group(0), m_mode(0), m_size(-1){
+
+}
/**
* Constructor.
* @param owner the owner of the file (UID)
* @param group the group of the file (GID)
* @param mode rights and attributs of the file
+ * @param size the filesize (0 for directories)
*/
ReFileMetaData::ReFileMetaData(const QString& node, const QDateTime& modified,
- const QDateTime& created, int owner, int group, mode_t mode) :
+ const QDateTime& created, int owner, int group, mode_t mode,
+ int64_t size) :
m_node(node),
m_modified(modified),
m_created(created),
m_owner(owner),
m_group(group),
- m_mode(mode)
+ m_mode(mode),
+ m_size(size)
{
}
{
}
+/**
+ * Copy constructor.
+ *
+ * @param source source to copy
+ */
+ReFileMetaData::ReFileMetaData(const ReFileMetaData& source) :
+ m_node(source.m_node),
+ m_modified(source.m_modified),
+ m_created(source.m_created),
+ m_owner(source.m_owner),
+ m_group(source.m_group),
+ m_mode(source.m_mode),
+ m_size(source.m_size)
+{
+
+}
+
+/**
+ * Assign operator.
+ *
+ * @param source source to copy
+ * @return the instance itself
+ */
+ReFileMetaData&ReFileMetaData::operator =(const ReFileMetaData& source)
+{
+ m_node = source.m_node;
+ m_modified = source.m_modified;
+ m_created = source.m_created;
+ m_owner = source.m_owner;
+ m_group = source.m_group;
+ m_mode = source.m_mode;
+ m_size = source.m_size;
+ return *this;
+}
class ReFileMetaData {
public:
+ ReFileMetaData();
ReFileMetaData(const QString& node, const QDateTime& modified,
const QDateTime& created,
- int owner, int group, mode_t mode);
+ int owner, int group, mode_t mode, int64_t size);
virtual ~ReFileMetaData();
+ ReFileMetaData(const ReFileMetaData& source);
+ ReFileMetaData& operator =(const ReFileMetaData& source);
public:
QString m_node;
QDateTime m_modified;
int16_t m_owner;
int16_t m_group;
mode_t m_mode;
+ int64_t m_size;
};
+typedef QList<ReFileMetaData> ReFileMetaDataList;
class ReFileSystem {
public:
EC_SUCCESS,
EC_PATH_NOT_FOUND,
EC_NOT_ACCESSIBLE,
+ EC_NOT_READABLE,
+ EC_READ,
+ EC_FS_READ_ONLY,
+ EC_NOT_WRITEABLE,
+ EC_WRITE,
+ EC_POSITION,
+ EC_ALREADY_EXISTS,
+ EC_NOT_EXISTS,
+ EC_RENAME,
};
public:
- ReFileSystem(const QString& name);
+ ReFileSystem(const QString& name, ReLogger* logger);
virtual ~ReFileSystem();
public:
- /** Changes the current directory of the filesystem.
- * @param path the new current directory
- * @return 0: success<br>
- * EC_PATH_NOT_FOUND directory does not exist<br>
- * EC_NOT_ACCESSIBLE parent not readable
+ /** Frees resources like open files.
*/
- virtual ErrorCode setDirectory(const QString& path) = 0;
+ virtual void close() = 0;
/** Returns the name of the current directory.
* @return the name of the current directory
*/
* @return the count of the found entries (<code>list.size()</code>)
*/
virtual int listInfos(const ReIncludeExcludeMatcher& matcher,
- QList<ReFileMetaData*>& list) = 0;
+ ReFileMetaDataList& list) = 0;
+ /** Creates a directory.
+ * @param node the name without path (in the current directory)
+ * @return EC_SUCCESS or error code
+ */
+ virtual ErrorCode makeDir(const QString& node) = 0;
+ /** Reads a part of a file into a buffer.
+ * @param source the file to read (inside the current directory)
+ * @param offset first position to read
+ * @param size number of bytes to read
+ * @param buffer OUT: content of the file
+ * @return EC_SUCCESS or error code
+ */
+ virtual ErrorCode read(const ReFileMetaData& source,
+ int64_t offset, int size,
+ QByteArray& buffer) = 0;
+ /** Removes a file or directory.
+ * @param node the properties ot the node (in the current directory)
+ * @return EC_SUCCESS or error code
+ */
+ virtual ErrorCode remove(const ReFileMetaData& node) = 0;
+ /** Sets the current directory.
+ * @param path relative or absolute path. If absolute it must be part of the
+ * base path
+ * @return EC_SUCCESS or error code
+ */
+ virtual ErrorCode setDirectory(const QString& path) = 0;
+ /** Sets the properties of a file in the current directory.
+ * @param source the properties to copy
+ * @param target the properties of the file to change
+ * @return EC_SUCCESS or error code
+ */
+ virtual ErrorCode setProperties(const ReFileMetaData& source,
+ const ReFileMetaData& target) = 0;
+ /** Writes a buffer to a file.
+ * @param node the file to write (without path, inside the current directory)
+ * @param offset first position to write
+ * @param buffer content to write
+ * @return EC_SUCCESS or error code
+ */
+ virtual ErrorCode write(const QString& target,
+ int64_t offset, const QByteArray& buffer) = 0;
public:
- bool writeable() const;
+ virtual ErrorCode copy(ReFileMetaData& source, ReFileSystem& sourceFS);
+public:
+ int blocksize() const;
+ bool first(const QString& pattern, ReFileMetaData& file);
+ /** Returns the full name (with path).
+ * @param node the name without path
+ * @return the full filename
+ */
+ inline QString fullName(const QString& node) const{
+ return m_directory + node;
+ }
+ /** Returns the full name (with path) as UTF-8 string.
+ * @param node the name without path
+ * @return the full filename
+ */
+ QByteArray fullNameAsUTF8(const QString& node) const{
+ return (m_directory + node).toUtf8();
+ }
void setWriteable(bool writeable);
+ void setBlocksize(int blocksize);
+ bool writeable() const;
+
protected:
QString m_name;
QString m_directory;
bool m_writeable;
+ ReLogger* m_logger;
+ QByteArray m_buffer;
+ int m_blocksize;
+ QDateTime m_undefinedTime;
};
class ReLocalFileSytem : public ReFileSystem {
public:
- ReLocalFileSytem(const QString& basePath);
+ ReLocalFileSytem(const QString& basePath, ReLogger* logger);
virtual ~ReLocalFileSytem();
public:
const QString& basePath() const;
const QString& directory() const;
- virtual int listInfos(const ReIncludeExcludeMatcher& matcher,
- QList<ReFileMetaData*>& list);
ErrorCode setDirectory(const QString& path);
+public:
+ // ReFileSystem interface
+ virtual void close();
+ virtual int listInfos(const ReIncludeExcludeMatcher& matcher,
+ ReFileMetaDataList& list);
+ ErrorCode makeDir(const QString& node);
+ virtual ErrorCode read(const ReFileMetaData& source, int64_t offset,
+ int size, QByteArray& buffer);
+ ErrorCode remove(const ReFileMetaData& node);
+ ErrorCode setProperties(const ReFileMetaData& source, const ReFileMetaData& target);
+ virtual ErrorCode write(const QString& target, int64_t offset,
+ const QByteArray& buffer);
+
protected:
QString m_basePath;
QString m_currentPath;
QDir m_dir;
+
+ FILE* m_readFile;
+ FILE* m_writeFile;
+
};
#endif /* OS_REFILESYSTEM_HPP_ */
LOC_FILE,
LOC_FILETREE,
LOC_STATESTORAGE, // 120
+ LOC_FILESYSTEM,
};
#define LOC_FIRST_OF(moduleNo) (moduleNo*100+1)
class RplModules {