App/Toponaming: Add supporting code

Support for reading and writing binary data, and a small tweak to bitmask.
This commit is contained in:
Chris Hennes
2023-03-30 21:19:58 -05:00
committed by Chris Hennes
parent d9e171e5d0
commit 1c0cf32b22
5 changed files with 195 additions and 0 deletions

View File

@@ -34,11 +34,43 @@
#include "Stream.h"
#include "Tools.h"
#include <boost/iostreams/filtering_stream.hpp>
#include <memory>
using namespace Base;
using namespace std;
using namespace zipios;
// boost iostream filter to escape ']]>' in text file saved into CDATA section.
// It does not check if the character is valid utf8 or not.
struct cdata_filter {
typedef char char_type;
typedef boost::iostreams::output_filter_tag category;
template<typename Device>
inline bool put(Device& dev, char c) {
switch(state) {
case 0:
case 1:
if(c == ']')
++state;
else
state = 0;
break;
case 2:
if(c == '>') {
static const char escape[] = "]]><![CDATA[";
boost::iostreams::write(dev,escape,sizeof(escape)-1);
}
state = 0;
break;
}
return boost::iostreams::put(dev,c);
}
int state = 0;
};
// ---------------------------------------------------------------------------
// Writer: Constructors and Destructor
@@ -55,6 +87,38 @@ Writer::Writer()
Writer::~Writer() = default;
std::ostream &Writer::beginCharStream() {
if(CharStream) {
throw Base::RuntimeError("Writer::beginCharStream(): invalid state");
}
Stream() << "<![CDATA[";
CharStream = std::make_unique<boost::iostreams::filtering_ostream>();
auto f = dynamic_cast<boost::iostreams::filtering_ostream*>(CharStream.get());
f->push(cdata_filter());
f->push(Stream());
*f << std::setprecision(std::numeric_limits<double>::digits10 + 1);
return *CharStream;
}
std::ostream &Writer::endCharStream() {
if(CharStream) {
CharStream.reset();
}
return Stream();
}
std::ostream &Writer::charStream() {
if(!CharStream)
throw Base::RuntimeError("Writer::endCharStream(): no current character stream");
return *CharStream;
}
void Writer::insertText(const std::string &s) {
beginCharStream() << s;
endCharStream();
}
void Writer::insertAsciiFile(const char* FileName)
{
Base::FileInfo fi(FileName);