Fri, 14 Jun 2013 19:34:30 +0300
Added a File type that wraps around QFile and provides stuff like a null file and range-for-iterating
src/common.h | file | annotate | diff | comparison | revisions | |
src/config.cpp | file | annotate | diff | comparison | revisions | |
src/main.cpp | file | annotate | diff | comparison | revisions | |
src/types.cpp | file | annotate | diff | comparison | revisions | |
src/types.h | file | annotate | diff | comparison | revisions |
--- a/src/common.h Fri Jun 14 16:00:54 2013 +0300 +++ b/src/common.h Fri Jun 14 19:34:30 2013 +0300 @@ -59,9 +59,8 @@ # define devf(...) #endif // RELEASE -class QFile; -extern QFile g_file_stdout; -extern QFile g_file_stderr; +extern File g_file_stdout; +extern File g_file_stderr; void doDevf (const char* func, const char* fmtstr, ...); @@ -149,10 +148,10 @@ #define fprint(F, ...) doPrint (F, {__VA_ARGS__}) #else void print (const char* fmtstr, ...); -void fprint (QFile& f, const char* fmtstr, ...); +void fprint (File& f, const char* fmtstr, ...); #endif -void doPrint (QFile& f, initlist<StringFormatArg> args); -void doPrint (FILE* f, initlist<StringFormatArg> args); +void doPrint (File& f, initlist<StringFormatArg> args); +void doPrint (FILE* f, initlist<StringFormatArg> args); // heh // Replace assert with a version that shows a GUI dialog if possible #ifdef assert @@ -168,9 +167,6 @@ #define fatal(MSG) \ fatalError (__FILE__, __LINE__, FUNCNAME, MSG) -// Null pointer -static const std::nullptr_t null = nullptr; - // Main and edge color identifiers static const short maincolor = 16; static const short edgecolor = 24;
--- a/src/config.cpp Fri Jun 14 16:00:54 2013 +0300 +++ b/src/config.cpp Fri Jun 14 19:34:30 2013 +0300 @@ -46,16 +46,14 @@ // Locale must be disabled for atof setlocale (LC_NUMERIC, "C"); - QFile f (filepath ()); - if (!f.open (QIODevice::ReadOnly)) + File f (filepath (), File::Read); + if (!f) return false; - QTextStream input (&f); size_t ln = 0; // Read the values. - while (!input.atEnd ()) { - str line = input.readLine ().simplified (); + for (str line : f) { ln++; if (line.isEmpty () || line[0] == '#') @@ -141,10 +139,10 @@ } } - QFile f (filepath ()); - print ("writing cfg to %1\n", qchars (filepath ())); + File f (filepath (), File::Write); + print ("writing cfg to %1\n", filepath ()); - if (!f.open (QIODevice::WriteOnly)) { + if (!f) { critical (fmt ("Cannot save configuration, cannot open %1 for writing\n", filepath ())); return false; }
--- a/src/main.cpp Fri Jun 14 16:00:54 2013 +0300 +++ b/src/main.cpp Fri Jun 14 19:34:30 2013 +0300 @@ -20,6 +20,7 @@ #include <QMessageBox> #include <QAbstractButton> #include <qfile.h> +#include <QTextStream> #include "gui.h" #include "file.h" #include "bbox.h" @@ -33,14 +34,15 @@ ForgeWindow* g_win = null; bbox g_BBox; const QApplication* g_app = null; -QFile g_file_stdout, g_file_stderr; +File g_file_stdout (stdout, File::Write); +File g_file_stderr (stderr, File::Write); const vertex g_origin (0.0f, 0.0f, 0.0f); const matrix g_identity ({1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f}); -void doPrint (QFile& f, initlist<StringFormatArg> args) { +void doPrint (File& f, initlist<StringFormatArg> args) { str msg = DoFormat (args); - f.write (msg.toUtf8 (), msg.length ()); + f.write (msg.toUtf8 ()); f.flush (); } @@ -57,12 +59,9 @@ // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= int main (int argc, char* argv[]) { - g_file_stdout.open (stdout, QIODevice::WriteOnly); - g_file_stderr.open (stderr, QIODevice::WriteOnly); - const QApplication app (argc, argv); g_app = &app; - g_curfile = NULL; + g_curfile = null; // Load or create the configuration if (!config::load ()) {
--- a/src/types.cpp Fri Jun 14 16:00:54 2013 +0300 +++ b/src/types.cpp Fri Jun 14 19:34:30 2013 +0300 @@ -18,11 +18,15 @@ #include <QObject> #include <QStringList> +#include <QTextStream> +#include <qfile.h> #include <assert.h> #include "common.h" #include "types.h" #include "misc.h" +const File nullfile (null); + str DoFormat (vector<StringFormatArg> args) { assert (args.size () >= 1); str text = args[0].value (); @@ -269,4 +273,126 @@ StringFormatArg::StringFormatArg (const floatconfig& v) { m_val.number (v.value); +} + +// ============================================================================= +File::File (const std::nullptr_t&) { + // Make a null file + m_file = null; + m_textstream = null; +} + +File::File (str path, OpenType rtype) { + m_file = null; + open (path, rtype); +} + +File::File (FILE* fp, OpenType rtype) { + m_file = null; + open (fp, rtype); +} + +File::~File () { + if (m_file) { + m_file->close (); + delete m_file; + + if (m_textstream) + delete m_textstream; + } +} + +bool File::open (FILE* fp, OpenType rtype) { + return open ("", rtype, fp); +} + +bool File::open (str path, OpenType rtype, FILE* fp) { + close (); + + if (!m_file) + m_file = new QFile; + + m_file->setFileName (path); + + bool result; + + QIODevice::OpenMode mode = + (rtype == Read) ? QIODevice::ReadOnly : + (rtype == Write) ? QIODevice::WriteOnly : + QIODevice::Append; + + if (fp) + result = m_file->open (fp, mode); + else + result = m_file->open (mode); + + if (result) { + m_textstream = new QTextStream (m_file); + return true; + } + + delete m_file; + m_file = null; + return false; +} + +File::iterator File::begin() { + return iterator (this); +} + +File::iterator& File::end () { + return m_endIterator; +} + +void File::write (str msg) { + m_file->write (msg.toUtf8 (), msg.length ()); +} + +str File::readLine () { + return m_textstream->readLine (); +} + +bool File::atEnd () const { + return m_textstream->atEnd (); +} + +bool File::isNull () const { + return m_file == null; +} + +bool File::operator!() const { + return isNull (); +} + +void File::close () { + if (!m_file) + return; + + delete m_file; + m_file = null; + + if (m_textstream) { + delete m_textstream; + m_textstream = null; + } +} + +bool File::flush () { + return m_file->flush (); +} + +void File::iterator::operator++() { + m_text = m_file->readLine (); +} + +str File::iterator::operator*() { + return m_text; +} + +bool File::iterator::operator== (File::iterator& other) { + return (other.m_file == null && m_file->atEnd ()); +} + +bool File::iterator::operator!= (File::iterator& other) { + return !operator== (other); } \ No newline at end of file
--- a/src/types.h Fri Jun 14 16:00:54 2013 +0300 +++ b/src/types.h Fri Jun 14 19:34:30 2013 +0300 @@ -23,6 +23,9 @@ #include <vector> #include "common.h" +// Null pointer +static const std::nullptr_t null = nullptr; + typedef QChar qchar; typedef QString str; template<class T> class ConstVectorReverser; @@ -30,6 +33,8 @@ class strconfig; class intconfig; class floatconfig; +class QFile; +class QTextStream; typedef unsigned int uint; typedef unsigned short ushort; @@ -125,13 +130,12 @@ double m_coords[3]; }; - // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= // vector // -// Array class that wraps around vector +// Array class that wraps around std::vector // ============================================================================= template<class T> class vector { public: @@ -277,6 +281,13 @@ std::vector<T> m_vect; }; +// ============================================================================= +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// ============================================================================= +// VectorReverser (aka rev) +// +// Helper class used to reverse-iterate vectors in range-for-loops. +// ============================================================================= template<class T> class VectorReverser { public: typedef typename vector<T>::r_it it; @@ -297,6 +308,13 @@ vector<T>* m_vect; }; +// ============================================================================= +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// ============================================================================= +// ConstVectorReverser (aka c_rev) +// +// Like VectorReverser, except works on const vectors. +// ============================================================================= template<class T> class ConstVectorReverser { public: typedef typename vector<T>::cr_it it; @@ -321,6 +339,13 @@ template<class T> using c_rev = ConstVectorReverser<T>; // ============================================================================= +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// ============================================================================= +// StringFormatArg +// +// Converts a given value into a string that can be retrieved with ::value (). +// Used as the argument type to the formatting functions, hence its name. +// ============================================================================= class StringFormatArg { public: StringFormatArg (const str& v); @@ -356,11 +381,68 @@ str m_val; }; -str DoFormat (vector< StringFormatArg > args); +// Formatter function +str DoFormat (vector<StringFormatArg> args); #ifndef IN_IDE_PARSER #define fmt(...) DoFormat ({__VA_ARGS__}) #else str fmt (const char* fmtstr, ...); #endif +// ============================================================================= +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// ============================================================================= +// File +// +// A file interface with simple interface and support for range-for-loops. +// ============================================================================= +class File { +public: + // Iterator class to enable range-for-loop support. Rough hack.. don't use directly! + class iterator { + public: + iterator () : m_file (null) {} // end iterator has m_file == null + iterator (File* f) : m_file (f), m_text (m_file->readLine ()) {} + void operator++ (); + str operator* (); + bool operator== (iterator& other); + bool operator!= (iterator& other); + + private: + File* m_file; + str m_text; + }; + + enum OpenType { + Read, + Write, + Append + }; + + File (const std::nullptr_t&); + File (str path, File::OpenType rtype); + File (FILE* fp, File::OpenType rtype); + ~File (); + + bool atEnd () const; + iterator begin (); + void close (); + iterator& end (); + bool flush (); + bool isNull () const; + str readLine (); + bool open (FILE* fp, OpenType rtype); + bool open (str path, OpenType rtype, FILE* fp = null); + bool operator! () const; + void write (str msg); + +private: + QFile* m_file; + QTextStream* m_textstream; + iterator m_endIterator; +}; + +// Null-file, equivalent to a null FILE* +extern const File nullfile; + #endif // TYPES_H \ No newline at end of file