diff options
Diffstat (limited to 'cpp/src/IceUtil/OutputUtil.cpp')
-rw-r--r-- | cpp/src/IceUtil/OutputUtil.cpp | 594 |
1 files changed, 594 insertions, 0 deletions
diff --git a/cpp/src/IceUtil/OutputUtil.cpp b/cpp/src/IceUtil/OutputUtil.cpp new file mode 100644 index 00000000000..e65d416efd7 --- /dev/null +++ b/cpp/src/IceUtil/OutputUtil.cpp @@ -0,0 +1,594 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <IceUtil/OutputUtil.h> +#include <IceUtil/FileUtil.h> +#include <cstring> + +using namespace std; +using namespace IceUtil; +using namespace IceUtilInternal; + +namespace IceUtilInternal +{ + +NextLine nl; +StartBlock sb; +EndBlock eb; +StartPar spar; +EndPar epar; +Separator sp; +EndElement ee; +StartEscapes startEscapes; +EndEscapes endEscapes; + +} + +string +IceUtilInternal::int64ToString(Int64 val) +{ + char buf[64]; +#ifdef _WIN32 +#if defined(_MSC_VER) && (_MSC_VER >= 1400) + sprintf_s(buf, sizeof(buf), "%I64d", val); +#else + sprintf(buf, "%I64d", val); +#endif +#elif defined(ICE_64) + sprintf(buf, "%ld", val); // Avoids a format warning from GCC. +#else + sprintf(buf, "%lld", val); +#endif + return string(buf); +} + +// ---------------------------------------------------------------------- +// OutputBase +// ---------------------------------------------------------------------- + +IceUtilInternal::OutputBase::OutputBase() : + _out(_fout), + _pos(0), + _indent(0), + _indentSize(4), + _useTab(false), + _separator(true) +{ +} + +IceUtilInternal::OutputBase::OutputBase(ostream& os) : + _out(os), + _pos(0), + _indent(0), + _indentSize(4), + _useTab(false), + _separator(true) +{ +} + + +IceUtilInternal::OutputBase::OutputBase(const char* s) : + _out(_fout), + _pos(0), + _indent(0), + _indentSize(4), + _useTab(false), + _separator(true) +{ + open(s); +} + +IceUtilInternal::OutputBase::~OutputBase() +{ +} + +void +IceUtilInternal::OutputBase::open(const char* s) +{ + // + // Remove any existing file first. This prevents file name + // mismatches on case-insensitive OSs. + // + IceUtilInternal::unlink(s); + _fout.open(s); +} + +void +IceUtilInternal::OutputBase::close() +{ + if(_fout.is_open()) + { + _fout.close(); + } +} + +bool +IceUtilInternal::OutputBase::isOpen() +{ + return _fout.is_open(); +} + +void +IceUtilInternal::OutputBase::print(const char* s) +{ + for(unsigned int i = 0; i < strlen(s); ++i) + { + if(s[i] == '\n') + { + _pos = 0; + } + else + { + ++_pos; + } + } + + _out << s; +} + +void +IceUtilInternal::OutputBase::inc() +{ + _indent += _indentSize; +} + +void +IceUtilInternal::OutputBase::dec() +{ + assert(_indent >= _indentSize); + _indent -= _indentSize; +} + +void +IceUtilInternal::OutputBase::useCurrentPosAsIndent() +{ + _indentSave.push(_indent); + _indent = _pos; +} + +void +IceUtilInternal::OutputBase::zeroIndent() +{ + _indentSave.push(_indent); + _indent = 0; +} + +void +IceUtilInternal::OutputBase::restoreIndent() +{ + assert(!_indentSave.empty()); + _indent = _indentSave.top(); + _indentSave.pop(); +} + +int +IceUtilInternal::OutputBase::currIndent() +{ + return _indent; +} + +void +IceUtilInternal::OutputBase::setIndent(int indentSize) +{ + _indentSize = indentSize; +} + +void +IceUtilInternal::OutputBase::setUseTab(bool useTab) +{ + _useTab = useTab; +} + +void +IceUtilInternal::OutputBase::newline() +{ + _out << '\n'; + _pos = 0; + _separator = true; + + int indent = _indent; + + if(_useTab) + { + while(indent >= 8) + { + indent -= 8; + _out << '\t'; + _pos += 8; + } + } + else + { + while(indent >= _indentSize) + { + indent -= _indentSize; + _out << " "; + _pos += _indentSize; + } + } + + while(indent > 0) + { + --indent; + _out << ' '; + ++_pos; + } + + _out.flush(); +} + +void +IceUtilInternal::OutputBase::separator() +{ + if(_separator) + { + _out << '\n'; + } +} + +bool +IceUtilInternal::OutputBase::operator!() const +{ + return !_out; +} + +// ---------------------------------------------------------------------- +// Output +// ---------------------------------------------------------------------- + +IceUtilInternal::Output::Output() : + OutputBase(), + _blockStart("{"), + _blockEnd("}"), + _par(-1) +{ +} + +IceUtilInternal::Output::Output(ostream& os) : + OutputBase(os), + _blockStart("{"), + _blockEnd("}"), + _par(-1) +{ +} + +IceUtilInternal::Output::Output(const char* s) : + OutputBase(s), + _blockStart("{"), + _blockEnd("}"), + _par(-1) +{ +} + +void +IceUtilInternal::Output::print(const char* s) +{ + if(_par >= 0) + { + if(++_par > 1) // No comma for the first parameter. + { + _out << ", "; + } + } + OutputBase::print(s); +} + +void +IceUtilInternal::Output::setBeginBlock(const char *bb) +{ + _blockStart = bb; +} + +void +IceUtilInternal::Output::setEndBlock(const char *eb) +{ + _blockEnd = eb; +} + +void +IceUtilInternal::Output::sb() +{ + if(_blockStart.length()) + { + newline(); + _out << _blockStart; + } + ++_pos; + inc(); + _separator = false; +} + +void +IceUtilInternal::Output::eb() +{ + dec(); + if(_blockEnd.length()) + { + newline(); + _out << _blockEnd; + } + --_pos; +} + +void +IceUtilInternal::Output::spar() +{ + _out << '('; + _par = 0; +} + +void +IceUtilInternal::Output::epar() +{ + _par = -1; + _out << ')'; +} + +Output& +IceUtilInternal::operator<<(Output& out, ios_base& (*val)(ios_base&)) +{ + ostringstream s; + s << val; + out.print(s.str().c_str()); + return out; +} + +// ---------------------------------------------------------------------- +// XMLOutput +// ---------------------------------------------------------------------- + +IceUtilInternal::XMLOutput::XMLOutput() : + OutputBase(), + _se(false), + _text(false), + _escape(false) +{ +} + +IceUtilInternal::XMLOutput::XMLOutput(ostream& os) : + OutputBase(os), + _se(false), + _text(false), + _escape(false) +{ +} + +IceUtilInternal::XMLOutput::XMLOutput(const char* s) : + OutputBase(s), + _se(false), + _text(false), + _escape(false) +{ +} + +void +IceUtilInternal::XMLOutput::print(const char* s) +{ + if(_se) + { + _out << '>'; + _se = false; + } + _text = true; + + if(_escape) + { + string escaped = escape(s); + OutputBase::print(escaped.c_str()); + } + else + { + OutputBase::print(s); + } +} + +void +IceUtilInternal::XMLOutput::newline() +{ + if(_se) + { + _se = false; + _out << '>'; + } + OutputBase::newline(); +} + +void +IceUtilInternal::XMLOutput::startElement(const string& element) +{ + newline(); + + // + // If we're not in SGML mode the output of the '>' character is + // deferred until either the //end-element (in which case a /> is + // emitted) or until something //is displayed. + // + if(_escape) + { + _out << '<' << escape(element); + } + else + { + _out << '<' << element; + } + _se = true; + _text = false; + + string::size_type pos = element.find_first_of(" \t"); + if(pos == string::npos) + { + _elementStack.push(element); + } + else + { + _elementStack.push(element.substr(0, pos)); + } + + ++_pos; // TODO: ??? + inc(); + _separator = false; +} + +void +IceUtilInternal::XMLOutput::endElement() +{ + string element = _elementStack.top(); + _elementStack.pop(); + + dec(); + if(_se) + { + _out << "></" << element << '>'; + } + else + { + if(!_text) + { + newline(); + } + _out << "</" << element << '>'; + } + --_pos; // TODO: ??? + + _se = false; + _text = false; +} + +void +IceUtilInternal::XMLOutput::attr(const string& name, const string& value) +{ + // + // Precondition: Attributes can only be attached to elements. + // + assert(_se); + _out << " " << name << "=\"" << escape(value) << '"'; +} + +void +IceUtilInternal::XMLOutput::startEscapes() +{ + _escape = true; +} + +void +IceUtilInternal::XMLOutput::endEscapes() +{ + _escape = false; +} + +string +IceUtilInternal::XMLOutput::currentElement() const +{ + if(_elementStack.size() > 0) + { + return _elementStack.top(); + } + else + { + return string(); + } +} + +string +IceUtilInternal::XMLOutput::escape(const string& input) const +{ + string v = input; + + // + // Find out whether there is a reserved character to avoid + // conversion if not necessary. + // + const string allReserved = "<>'\"&"; + if(v.find_first_of(allReserved) != string::npos) + { + // + // First convert all & to & + // + size_t pos = 0; + while((pos = v.find_first_of('&', pos)) != string::npos) + { + v.insert(pos+1, "amp;"); + pos += 4; + } + + // + // Next convert remaining reserved characters. + // + const string reserved = "<>'\""; + pos = 0; + while((pos = v.find_first_of(reserved, pos)) != string::npos) + { + string replace; + switch(v[pos]) + { + case '>': + replace = ">"; + break; + + case '<': + replace = "<"; + break; + + case '\'': + replace = "'"; + break; + + case '"': + replace = """; + break; + + default: + assert(false); + } + + v.erase(pos, 1); + v.insert(pos, replace); + pos += replace.size(); + } + } + return v; +} + +XMLOutput& +IceUtilInternal::operator<<(XMLOutput& out, ios_base& (*val)(ios_base&)) +{ + ostringstream s; + s << val; + out.print(s.str().c_str()); + return out; +} + +IceUtilInternal::StartElement::StartElement(const string& name) : + _name(name) +{ +} + +const string& +IceUtilInternal::StartElement::getName() const +{ + return _name; +} + +IceUtilInternal::Attribute::Attribute(const string& name, const string& value) : + _name(name), + _value(value) +{ +} + +const string& +IceUtilInternal::Attribute::getName() const +{ + return _name; +} + +const string& +IceUtilInternal::Attribute::getValue() const +{ + return _value; +} |