mxwcore-wotlk/deps/g3dlite/include/G3D/TextOutput.h

263 lines
8.5 KiB
C
Raw Normal View History

2023-11-07 05:04:30 -05:00
/**
\file G3D/TextOutput.h
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
\created 2004-06-21
\edited 2011-05-24
Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
#ifndef G3D_TextOutput_h
#define G3D_TextOutput_h
#include "G3D/platform.h"
#include "G3D/Array.h"
#include <string>
namespace G3D {
/**
Convenient formatting of ASCII text written to a file.
<P>
The core writeString, writeNumber, and writeSymbol methods map to TextInput's
methods. Number and Symbol each print an additional space that is used to
separate adjacent tokens.
TextOutput::printf allows arbitrary text to be conveniently dumped
en-masse. Use [de]serialize(bool, TextOutput) and other overloads to read/write
primitive types in a standardized manner and
<P>
When a word-wrap line break occurs, all whitespace between words is replaced
with a single newline (the newline may be two characters-- see
G3D::TextOutput::Options::NewlineStyle). Word wrapping occurs against
the number of columns specified by Options::numColumns, <I>minus</I> the current
indent level.
Indenting adds the specified number of spaces immediately after a newline.
If a newline was followed by spaces in the original string, these are added
to the indent spaces. Indenting <B>will</B> indent blank lines and will leave
indents after the last newline of a file (if the indent level is non-zero at the end).
<P><B>Serialization/Marshalling</B>
<DT>Text serialization is accomplished using TextOutput by defining the pair of
methods:
<PRE>
void serialize(TextOutput& to) const;
void deserialize(TextInput& ti);
</PRE>
See also G3D::TextInput.
<P>
<B>BETA API</B>
<DT>This API is subject to change in future versions.
*/
class TextOutput {
public:
class Settings {
public:
/**
WRAP_NONE Word wrapping is disabled
WRAP_WITHOUT_BREAKING Word-wrap, but don't break continuous lines that
are longer than numColumns (default)
WRAP_ALWAYS Wrap even if it means breaking a continuous line or
a quoted string.
Word wrapping is only allowed at whitespaces ('\\n', '\\r', '\\t', ' '); it
will not occur after commas, punctuation, minus signs, or any other characters
*/
enum WordWrapMode {WRAP_NONE, WRAP_WITHOUT_BREAKING, WRAP_ALWAYS};
/** Defaults to WRAP_WITHOUT_BREAKING */
WordWrapMode wordWrap;
/** Is word-wrapping allowed to insert newlines inside double quotes?
Default: false */
bool allowWordWrapInsideDoubleQuotes;
/** Number of columns for word wrapping. Default: 8 */
int numColumns;
/** Number of spaces in each indent. Default: 4 */
int spacesPerIndent;
/** Style of newline used by word wrapping and by (optional) conversion.
default: Windows: NEWLINE_WINDOWS, Linux, OS X: NEWLINE_UNIX.
*/
enum NewlineStyle {NEWLINE_WINDOWS, NEWLINE_UNIX};
NewlineStyle newlineStyle;
/** If true, all newlines are converted to NewlineStyle regardless of
how they start out. Default: true. */
bool convertNewlines;
/** Used by writeBoolean */
std::string trueSymbol;
/** Used by writeBoolean */
std::string falseSymbol;
Settings() :
wordWrap(WRAP_WITHOUT_BREAKING),
allowWordWrapInsideDoubleQuotes(false),
numColumns(80),
spacesPerIndent(4),
convertNewlines(true),
trueSymbol("true"),
falseSymbol("false") {
#ifdef G3D_WINDOWS
newlineStyle = NEWLINE_WINDOWS;
#else
newlineStyle = NEWLINE_UNIX;
#endif
}
};
private:
/** Used by indentAndAppend to tell when we are writing the
first character of a new line.
So that push/popIndent work correctly, we cannot indent
immediately after writing a newline. Instead we must
indent on writing the first character <B>after</B> that
newline.
*/
bool startingNewLine;
/** Number of characters at the end of the buffer since the last newline */
int currentColumn;
/** True if we have seen an open " and no close ".*/
bool inDQuote;
/** Empty if there is none */
std::string filename;
Array<char> data;
Settings option;
/** Number of indents to prepend before each line. Always set using setIndentLevel.*/
int indentLevel;
void setIndentLevel(int i);
/** Actual number of spaces to indent. */
int indentSpaces;
/** the newline character(s) */
std::string newline;
/** Starts at 1 */
int m_currentLine;
void setOptions(const Settings& _opt);
/** Converts to the desired newlines. Called from vprintf */
void convertNewlines(const std::string& in, std::string& out);
/** Called from vprintf */
void wordWrapIndentAppend(const std::string& str);
/** Appends the character to data, indenting whenever a newline is encountered.
Called from wordWrapIndentAppend */
void indentAppend(char c);
public:
explicit TextOutput(const std::string& filename, const Settings& options = Settings());
/** Constructs a text output that can later be commited to a string instead of a file.*/
explicit TextOutput(const Settings& options = Settings());
/** Returns one plus the number of newlines written since the output was created. */
int line() const {
return m_currentLine;
}
/** Commit to the filename specified on the constructor.
<B>Not</B> called from the destructor; you must call
it yourself.
@param flush If true (default) the file is ready for reading when the method returns, otherwise
the method returns immediately and writes the file in the background.*/
void commit(bool flush = true);
/** Commits to this string */
void commitString(std::string& string);
/** Increase indent level by 1 */
void pushIndent();
void popIndent();
/** Produces a new string that contains the output */
std::string commitString();
/** Writes a quoted string. Special characters in the string (e.g., \\, \\t, \\n) are escaped so that
TextInput will produce the identical string on reading.*/
void writeString(const std::string& string);
void writeBoolean(bool b);
void writeNumber(double n);
void writeNumber(int n);
void writeNewline();
void writeNewlines(int numLines);
/** If the most recently written character was a space, remove it and return true. Can be called repeatedly to back up over multiple spaces. */
bool deleteSpace();
/** The symbol is written without quotes. Symbols are required to begin with a
letter or underscore and contain only letters, underscores, and numbers
or be a C++ symbol (e.g. "{", "(", "++", etc.)
so that they may be properly parsed by TextInput::readSymbol. Symbols are
printed with a trailing space.*/
void writeSymbol(const std::string& string);
void writeSymbol(char s);
/** Convenient idiom for writing multiple symbols in a row, e.g.
writeSymbols("name", "="); The empty symbols are not written.
*/
void writeSymbols(
const std::string& a,
const std::string& b = "",
const std::string& c = "",
const std::string& d = "",
const std::string& e = "",
const std::string& f = "");
/** Normal printf conventions. Note that the output will be reformatted
for word-wrapping and newlines */
void __cdecl printf(const char* fmt, ...)
G3D_CHECK_PRINTF_METHOD_ARGS;
// Can't pass by reference because that confuses va_start
void __cdecl printf(const std::string fmt, ...);
void __cdecl vprintf(const char* fmt, va_list argPtr)
G3D_CHECK_VPRINTF_METHOD_ARGS;
};
// Primitive serializers
void serialize(const bool& b, TextOutput& to);
void serialize(const int& b, TextOutput& to);
void serialize(const uint8& b, TextOutput& to);
void serialize(const double& b, TextOutput& to);
void serialize(const float& b, TextOutput& to);
void serialize(const std::string& b, TextOutput& to);
void serialize(const char* b, TextOutput& to);
}
#endif