From 3ee98f3bac24fd1c70a9de3e0fbe774e762c25b3 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Fri, 26 Jun 2009 15:31:34 +0000 Subject: Add lots of comments, and some code fixes discovered in the process. --- libdimensionxx/cookie-fopencookie.cpp | 52 +++++++++++++++++++-- libdimensionxx/cookie-tmpfile.cpp | 83 +++++++++++++++++++++++++++------ libdimensionxx/dimensionxx/array.hpp | 7 ++- libdimensionxx/dimensionxx/canvas.hpp | 4 +- libdimensionxx/dimensionxx/color.hpp | 4 +- libdimensionxx/dimensionxx/cookie.hpp | 4 +- libdimensionxx/dimensionxx/error.hpp | 6 +-- libdimensionxx/dimensionxx/geometry.hpp | 55 +++++++++++++++++++++- libdimensionxx/dimensionxx/object.hpp | 4 +- libdimensionxx/dimensionxx/png.hpp | 4 +- libdimensionxx/dimensionxx/progress.hpp | 4 +- libdimensionxx/progress.cpp | 25 ++++++++-- 12 files changed, 208 insertions(+), 44 deletions(-) (limited to 'libdimensionxx') diff --git a/libdimensionxx/cookie-fopencookie.cpp b/libdimensionxx/cookie-fopencookie.cpp index 78b6e8b..070b038 100644 --- a/libdimensionxx/cookie-fopencookie.cpp +++ b/libdimensionxx/cookie-fopencookie.cpp @@ -21,6 +21,7 @@ #include "dimensionxx.hpp" #ifndef _GNU_SOURCE +// For fopencookie() # define _GNU_SOURCE #endif #include @@ -99,7 +100,7 @@ namespace Dimension } if (streams->is_output()) { - // If we have an output stream, seek it too + // If we have an output stream, seek it switch (whence) { case SEEK_SET: streams->ostr().seekp(*offset, std::ios::beg); @@ -164,14 +165,55 @@ namespace Dimension // Close the file FILE_Cookie::~FILE_Cookie() { std::fclose(m_file); } + // Get the FILE* FILE* FILE_Cookie::file() { return m_file; } const FILE* FILE_Cookie::file() const { return m_file; } bool FILE_Cookie::is_input() const { return m_istr; } bool FILE_Cookie::is_output() const { return m_ostr; } - std::istream& FILE_Cookie::istr() { return *m_istr; } - const std::istream& FILE_Cookie::istr() const { return *m_istr; } - std::ostream& FILE_Cookie::ostr() { return *m_ostr; } - const std::ostream& FILE_Cookie::ostr() const { return *m_ostr; } + // Get the C++ streams + + std::istream& + FILE_Cookie::istr() + { + if (is_input()) { + return *m_istr; + } else { + throw Dimension_Error("Attempted to get input stream from non-input" + " FILE_Cookie."); + } + } + + const std::istream& + FILE_Cookie::istr() const + { + if (is_input()) { + return *m_istr; + } else { + throw Dimension_Error("Attempted to get input stream from non-input" + " FILE_Cookie."); + } + } + + std::ostream& + FILE_Cookie::ostr() + { + if (is_output()) { + return *m_ostr; + } else { + throw Dimension_Error("Attempted to get output stream from non-input" + " FILE_Cookie."); + } + } + + const std::ostream& FILE_Cookie::ostr() const + { + if (is_output()) { + return *m_ostr; + } else { + throw Dimension_Error("Attempted to get output stream from non-input" + " FILE_Cookie."); + } + } } diff --git a/libdimensionxx/cookie-tmpfile.cpp b/libdimensionxx/cookie-tmpfile.cpp index ec320d8..6a41f09 100644 --- a/libdimensionxx/cookie-tmpfile.cpp +++ b/libdimensionxx/cookie-tmpfile.cpp @@ -27,74 +27,85 @@ namespace Dimension { namespace { + // Write an input stream completely to a FILE*; this works poorly for + // console input, which may not have an EOF in the near future void write_cookie(FILE* file, std::istream& istr) { + const unsigned int bs = 8192; // Bytes to read at once unsigned int count, pos; - const unsigned int bs = 8192; char buffer[bs]; - pos = istr.tellg(); - istr.seekg(0); + pos = istr.tellg(); // Get the stream's current position + istr.seekg(0); // Seek to the beginning while (true) { + // Read the whole stream into `file', `bs' bytes at a time istr.read(buffer, bs); count = istr.gcount(); if (count != bs) { if (istr.eof()) { + // We reached EOF; write the last count bytes fwrite(buffer, 1, count, file); break; } else { + // Some other error throw Dimension_Error("Error reading from input stream."); } } + // Write the next `bs' bytes fwrite(buffer, 1, bs, file); } - fseek(file, pos, SEEK_SET); + fseek(file, pos, SEEK_SET); // Seek to the stream's initial position } + // Read a C++ stream completely from a file void read_cookie(std::ostream& ostr, FILE* file) { + const unsigned int bs = 8192; // Bytes to read at a time unsigned int count, pos; - const unsigned int bs = 8192; char buffer[bs]; - pos = ftell(file); - rewind(file); + pos = ftell(file); // Get the initial position + rewind(file); // Seek to the beginning while (true) { count = fread(buffer, 1, bs, file); if (count != bs) { if (feof(file)) { + // Reached EOF, write the last `count' bytes ostr.write(buffer, count); break; } else { + // Some other error throw Dimension_Error("Error reading from temporary file."); } } + // Write the next `bs' bytes ostr.write(buffer, bs); } - ostr.seekp(pos); + ostr.seekp(pos); // Seek to the initial position of `file' } } // Make an input FILE_Cookie FILE_Cookie::FILE_Cookie(std::istream& istr) - : m_file(tmpfile()), m_istr(&istr), m_ostr(0) + : m_file(std::tmpfile()), m_istr(&istr), m_ostr(0) { if (!m_file) { throw Dimension_Error("Error opening temporary file for C++/C I/O" " interface."); } + // Write the input stream to the temporary file write_cookie(m_file, *m_istr); } // Make an output FILE_Cookie FILE_Cookie::FILE_Cookie(std::ostream& ostr) - : m_file(tmpfile()), m_istr(0), m_ostr(&ostr) + : m_file(std::tmpfile()), m_istr(0), m_ostr(&ostr) { if (!m_file) { throw Dimension_Error("Error opening temporary file for C++/C I/O" @@ -104,13 +115,14 @@ namespace Dimension // Make an I/O FILE_Cookie FILE_Cookie::FILE_Cookie(std::iostream& iostr) - : m_file(tmpfile()), m_istr(&iostr), m_ostr(&iostr) + : m_file(std::tmpfile()), m_istr(&iostr), m_ostr(&iostr) { if (!m_file) { throw Dimension_Error("Error opening temporary file for C++/C I/O" " interface."); } + // Write the input stream to the temporary file write_cookie(m_file, *m_istr); } @@ -123,14 +135,55 @@ namespace Dimension std::fclose(m_file); } + // Get the FILE* FILE* FILE_Cookie::file() { return m_file; } const FILE* FILE_Cookie::file() const { return m_file; } bool FILE_Cookie::is_input() const { return m_istr; } bool FILE_Cookie::is_output() const { return m_ostr; } - std::istream& FILE_Cookie::istr() { return *m_istr; } - const std::istream& FILE_Cookie::istr() const { return *m_istr; } - std::ostream& FILE_Cookie::ostr() { return *m_ostr; } - const std::ostream& FILE_Cookie::ostr() const { return *m_ostr; } + // Get the C++ streams + + std::istream& + FILE_Cookie::istr() + { + if (is_input()) { + return *m_istr; + } else { + throw Dimension_Error("Attempted to get input stream from non-input" + " FILE_Cookie."); + } + } + + const std::istream& + FILE_Cookie::istr() const + { + if (is_input()) { + return *m_istr; + } else { + throw Dimension_Error("Attempted to get input stream from non-input" + " FILE_Cookie."); + } + } + + std::ostream& + FILE_Cookie::ostr() + { + if (is_output()) { + return *m_ostr; + } else { + throw Dimension_Error("Attempted to get output stream from non-input" + " FILE_Cookie."); + } + } + + const std::ostream& FILE_Cookie::ostr() const + { + if (is_output()) { + return *m_ostr; + } else { + throw Dimension_Error("Attempted to get output stream from non-input" + " FILE_Cookie."); + } + } } diff --git a/libdimensionxx/dimensionxx/array.hpp b/libdimensionxx/dimensionxx/array.hpp index dfbf1c8..735e17a 100644 --- a/libdimensionxx/dimensionxx/array.hpp +++ b/libdimensionxx/dimensionxx/array.hpp @@ -18,14 +18,14 @@ * . * *************************************************************************/ +// dmnsn_array* wrapper. + #ifndef DIMENSIONXX_ARRAY_HPP #define DIMENSIONXX_ARRAY_HPP #include // For tr1::shared_ptr #include // For size_t -// dmnsn_array* wrapper. - namespace Dimension { // RAII scoped read-lock @@ -148,6 +148,8 @@ namespace Dimension return ret; } + // Access the underlying dmnsn_array* + template dmnsn_array* Array::dmnsn() @@ -170,6 +172,7 @@ namespace Dimension return *m_array; } + // Release the dmnsn_array*, if we are the only Array holding it template dmnsn_array* Array::release() diff --git a/libdimensionxx/dimensionxx/canvas.hpp b/libdimensionxx/dimensionxx/canvas.hpp index eda9ad3..f9e77e5 100644 --- a/libdimensionxx/dimensionxx/canvas.hpp +++ b/libdimensionxx/dimensionxx/canvas.hpp @@ -18,11 +18,11 @@ * . * *************************************************************************/ +// dmnsn_canvas* wrapper. + #ifndef DIMENSIONXX_CANVAS_HPP #define DIMENSIONXX_CANVAS_HPP -// dmnsn_canvas* wrapper. - namespace Dimension { // Base canvas class. Wraps a dmnsn_canvas*. diff --git a/libdimensionxx/dimensionxx/color.hpp b/libdimensionxx/dimensionxx/color.hpp index c79f86b..9289479 100644 --- a/libdimensionxx/dimensionxx/color.hpp +++ b/libdimensionxx/dimensionxx/color.hpp @@ -18,11 +18,11 @@ * . * *************************************************************************/ +// Wrappers for libdimension colors. + #ifndef DIMENSIONXX_COLOR_HPP #define DIMENSIONXX_COLOR_HPP -// Wrappers for libdimension colors. - namespace Dimension { // Forward declarations diff --git a/libdimensionxx/dimensionxx/cookie.hpp b/libdimensionxx/dimensionxx/cookie.hpp index df26b93..0d8b4da 100644 --- a/libdimensionxx/dimensionxx/cookie.hpp +++ b/libdimensionxx/dimensionxx/cookie.hpp @@ -18,11 +18,11 @@ * . * *************************************************************************/ +// Some internal magic to use C FILE* I/O with C++ streams. + #ifndef DIMENSIONXX_COOKIE_HPP #define DIMENSIONXX_COOKIE_HPP -// Some internal magic to use C FILE* I/O with C++ streams. - #include #include #include diff --git a/libdimensionxx/dimensionxx/error.hpp b/libdimensionxx/dimensionxx/error.hpp index 99670cb..7fb0e53 100644 --- a/libdimensionxx/dimensionxx/error.hpp +++ b/libdimensionxx/dimensionxx/error.hpp @@ -18,14 +18,14 @@ * . * *************************************************************************/ -#ifndef DIMENSIONXX_ERROR_HPP -#define DIMENSIONXX_ERROR_HPP - // Wrappers for libdimension error handling, and an exception class. // dmnsn_error is still used by libdimensionxx whenever an exception shouldn't // be thrown, like in destructors, and whenever libdimension or libdimension-* // use it internally. Exceptions are thrown otherwise to report errors. +#ifndef DIMENSIONXX_ERROR_HPP +#define DIMENSIONXX_ERROR_HPP + #include #include #include diff --git a/libdimensionxx/dimensionxx/geometry.hpp b/libdimensionxx/dimensionxx/geometry.hpp index f623eda..606f83a 100644 --- a/libdimensionxx/dimensionxx/geometry.hpp +++ b/libdimensionxx/dimensionxx/geometry.hpp @@ -18,15 +18,17 @@ * . * *************************************************************************/ +// Wrappers for geometric types (Vectors, Matricies, Lines (rays)). + #ifndef DIMENSIONXX_GEOMETRY_HPP #define DIMENSIONXX_GEOMETRY_HPP -// Wrappers for geometric types (Vectors, Matricies, Lines (rays)). - #include namespace Dimension { + class Vector; + // Wrapper for dmnsn_matrix class Matrix { @@ -56,6 +58,12 @@ namespace Dimension // Get the wrapped matrix dmnsn_matrix dmnsn() const { return m_matrix; } + // Special constructors + static inline Matrix identity(); + static inline Matrix scale(const Vector& factor); + static inline Matrix translation(const Vector& d); + static inline Matrix rotation(const Vector& theta); + private: dmnsn_matrix m_matrix; }; @@ -126,6 +134,49 @@ namespace Dimension dmnsn_line m_line; }; + // Matrix operators + + inline Matrix + operator*(const Matrix& lhs, const Matrix& rhs) + { + // This order is important! + Matrix r = rhs; + r *= lhs; + return r; + } + + inline Matrix + inverse(const Matrix& M) + { + return Matrix(dmnsn_matrix_inverse(M.dmnsn())); + } + + // Special Matrix constructors + + inline Matrix + Matrix::identity() + { + return Matrix(dmnsn_identity_matrix()); + } + + inline Matrix + Matrix::scale(const Vector& factor) + { + return Matrix(dmnsn_scale_matrix(factor.dmnsn())); + } + + inline Matrix + Matrix::translation(const Vector& d) + { + return Matrix(dmnsn_translation_matrix(d.dmnsn())); + } + + inline Matrix + Matrix::rotation(const Vector& theta) + { + return Matrix(dmnsn_rotation_matrix(theta.dmnsn())); + } + // Vector operators inline Vector diff --git a/libdimensionxx/dimensionxx/object.hpp b/libdimensionxx/dimensionxx/object.hpp index 3b2c6c1..40dcb25 100644 --- a/libdimensionxx/dimensionxx/object.hpp +++ b/libdimensionxx/dimensionxx/object.hpp @@ -18,11 +18,11 @@ * . * *************************************************************************/ +// dmnsn_object* wrapper. + #ifndef DIMENSIONXX_OBJECT_HPP #define DIMENSIONXX_OBJECT_HPP -// dmnsn_object* wrapper. - namespace Dimension { // Abstract base object class. Wraps a dmnsn_object*. diff --git a/libdimensionxx/dimensionxx/png.hpp b/libdimensionxx/dimensionxx/png.hpp index d768287..980840c 100644 --- a/libdimensionxx/dimensionxx/png.hpp +++ b/libdimensionxx/dimensionxx/png.hpp @@ -18,11 +18,11 @@ * . * *************************************************************************/ +// C++ wrapper for libdimension PNG support. PNG_Canvas derives from Canvas. + #ifndef DIMENSIONXX_PNG_HPP #define DIMENSIONXX_PNG_HPP -// C++ wrapper for libdimension PNG support. PNG_Canvas derives from Canvas. - #include #include diff --git a/libdimensionxx/dimensionxx/progress.hpp b/libdimensionxx/dimensionxx/progress.hpp index b9df870..3fff1bc 100644 --- a/libdimensionxx/dimensionxx/progress.hpp +++ b/libdimensionxx/dimensionxx/progress.hpp @@ -18,14 +18,14 @@ * . * *************************************************************************/ +// dmnsn_progress* wrapper. + #ifndef DIMENSIONXX_PROGRESS_HPP #define DIMENSIONXX_PROGRESS_HPP #include // For tr1::shared_ptr #include -// dmnsn_canvas* wrapper. - namespace Dimension { // Base class for persisting objects diff --git a/libdimensionxx/progress.cpp b/libdimensionxx/progress.cpp index ca74571..0a32b72 100644 --- a/libdimensionxx/progress.cpp +++ b/libdimensionxx/progress.cpp @@ -25,14 +25,17 @@ namespace Dimension Persist_Base::~Persist_Base() { } + // Construct a dmnsn_progress* wrapper Progress::Progress(dmnsn_progress* progress) : m_progress(new dmnsn_progress*(progress)) { } + // Construct a dmnsn_progress* wrapper, with a known persister Progress::Progress(dmnsn_progress* progress, const Persister& persister) : m_progress(new dmnsn_progress*(progress)), m_persister(persister) { } + // Finish the progress if not yet finished and we are unique Progress::~Progress() { if (m_progress && m_progress.unique()) { @@ -45,45 +48,55 @@ namespace Dimension } } + // Get the current progress double Progress::progress() const { return dmnsn_get_progress(dmnsn()); } + // Wait until progress() >= progress void Progress::wait(double progress) const { dmnsn_wait_progress(dmnsn(), progress); } + // Start a new level of loop nesting void Progress::new_element(unsigned int total) { dmnsn_new_progress_element(dmnsn(), total); } + // Increment the progress void Progress::increment() { dmnsn_increment_progress(dmnsn()); } + // Immediately finish the progress void Progress::done() { - dmnsn_progress_done(dmnsn()); + dmnsn_done_progress(dmnsn()); } + // Wait for progress completion void Progress::finish() { - if (m_progress.unique()) { - dmnsn_finish_progress(dmnsn()); - m_progress.reset(); - } else { + if (!m_progress) { + throw Dimension_Error("Attempt to finish Progress twice."); + } + + if (!m_progress.unique()) { throw Dimension_Error("Attempt to finish non-unique Progress."); } + + dmnsn_finish_progress(dmnsn()); + m_progress.reset(); // Don't try again } // Access the set of persisted objects @@ -93,6 +106,8 @@ namespace Dimension return m_persister; } + // Access the underlying dmnsn_progress* + dmnsn_progress* Progress::dmnsn() { -- cgit v1.2.3