9#include <Atlas/Debug.h>
15static const bool debug_flag =
false;
20 Bach::Bach(std::istream &in, std::ostream &out,
Atlas::Bridge &b)
21 : m_istream(in), m_ostream(out), m_bridge(b), m_comma(false), m_linenum(0) {
22 m_state.push(PARSE_INIT);
25 void Bach::parseInit(
char next) {
26 ATLAS_DEBUG(std::cout <<
"Bach::parseInit" << std::endl;)
29 m_bridge.streamBegin();
30 m_state.push(PARSE_STREAM);
34 void Bach::parseStream(
char next) {
35 ATLAS_DEBUG(std::cout <<
"Bach::parseStream" << std::endl;)
39 m_bridge.streamMessage();
40 m_state.push(PARSE_MAP);
52 void Bach::parseMap(
char next) {
53 ATLAS_DEBUG(std::cout <<
"Bach::parseMap" << std::endl;)
67 m_state.push(PARSE_DATA);
68 m_state.push(PARSE_NAME);
72 if (((next >=
'a') && (next <=
'z')) ||
73 ((next >=
'A') && (next <=
'Z'))) {
74 m_istream.putback(next);
75 m_state.push(PARSE_DATA);
76 m_state.push(PARSE_NAME);
78 std::cerr <<
"Bach::parseMap: unexpected character: " << next << std::endl;
84 void Bach::parseList(
char next) {
85 ATLAS_DEBUG(std::cout <<
"Bach::parseList" << std::endl;)
94 m_bridge.listMapItem();
95 m_state.push(PARSE_MAP);
99 m_bridge.listListItem();
100 m_state.push(PARSE_LIST);
119 m_state.push(PARSE_INT);
120 m_istream.putback(next);
124 m_state.push(PARSE_STRING);
128 std::cerr <<
"Bach::parseMap: unexpected character: " << next << std::endl;
133 void Bach::parseInt(
char next) {
134 ATLAS_DEBUG(std::cout <<
"Bach::parseInt" << std::endl;)
142 m_istream.putback(next);
144 if (m_state.top() == PARSE_MAP) {
145 ATLAS_DEBUG(std::cout <<
"Int: " << m_name <<
": " << m_data << std::endl;)
147 m_bridge.mapIntItem(decodeString(std::move(m_name)), std::stol(m_data));
148 }
else if (m_state.top() == PARSE_LIST) {
149 ATLAS_DEBUG(std::cout <<
"Int: " << m_data << std::endl;)
151 m_bridge.listIntItem(std::stol(m_data));
153 std::cerr <<
"Bach::parseIntt: Error" << std::endl;
178 m_state.push(PARSE_FLOAT);
183 std::cerr <<
"Bach::parseInt: unexpected character: " << next << std::endl;
188 void Bach::parseFloat(
char next) {
189 ATLAS_DEBUG(std::cout <<
"Bach::parseFloat" << std::endl;)
197 m_istream.putback(next);
199 if (m_state.top() == PARSE_MAP) {
200 ATLAS_DEBUG(std::cout <<
"Float: " << m_name <<
": " << m_data << std::endl;)
202 m_bridge.mapFloatItem(decodeString(std::move(m_name)), std::stod(m_data));
203 }
else if (m_state.top() == PARSE_LIST) {
204 ATLAS_DEBUG(std::cout <<
"Float: " << m_data << std::endl;)
206 m_bridge.listFloatItem(std::stod(m_data));
208 std::cerr <<
"Bach::parseFloat: Error" << std::endl;
233 std::cerr <<
"Bach::parseFloat: unexpected character: " << next << std::endl;
238 void Bach::parseString(
char next) {
239 ATLAS_DEBUG(std::cout <<
"Bach::parseString" << std::endl;)
244 if (m_state.top() == PARSE_MAP) {
245 ATLAS_DEBUG(std::cout <<
"String: " << m_name <<
": " << m_data << std::endl;)
247 m_bridge.mapStringItem(decodeString(std::move(m_name)), decodeString(std::move(m_data)));
248 }
else if (m_state.top() == PARSE_LIST) {
249 ATLAS_DEBUG(std::cout <<
"String: " << m_data << std::endl;)
251 m_bridge.listStringItem(decodeString(std::move(m_data)));
253 std::cerr <<
"Bach::parseString: Error" << std::endl;
260 m_state.push(PARSE_LITERAL);
269 void Bach::parseLiteral(
char next) {
274 void Bach::parseData(
char next) {
275 ATLAS_DEBUG(std::cout <<
"Bach::parseData" << std::endl;)
289 m_istream.putback(next);
291 m_state.push(PARSE_INT);
297 switch (m_state.top()) {
299 m_bridge.mapMapItem(decodeString(m_name));
304 m_bridge.listMapItem();
308 std::cerr <<
"Bach::parseData: Error: " << (int) m_state.top() << std::endl;
312 m_state.push(PARSE_MAP);
318 switch (m_state.top()) {
320 m_bridge.mapListItem(decodeString(m_name));
325 m_bridge.listListItem();
329 std::cerr <<
"Bach::parseData: Error: " << (int) m_state.top() << std::endl;
333 m_state.push(PARSE_LIST);
338 m_state.push(PARSE_STRING);
346 std::cerr <<
"Bach::parseData: unexpected character: " << next << std::endl;
351 void Bach::parseName(
char next) {
352 ATLAS_DEBUG(std::cout <<
"Bach::parseName" << std::endl;)
357 ATLAS_DEBUG(std::cout <<
"Name: " << m_name << std::endl;)
363 if (((next >=
'a') && (next <=
'z')) ||
364 ((next >=
'A') && (next <=
'Z')) ||
365 ((next >=
'0') && (next <=
'9')) ||
369 std::cerr <<
"Bach::parseName: unexpected character: " << next << std::endl;
375 void Bach::parseComment(
char next) {
380 bool Bach::stringmode()
const {
381 switch (m_state.top()) {
395 std::streamsize count;
397 while ((count = m_istream.rdbuf()->in_avail()) > 0) {
399 for (std::streamsize i = 0; i < count; ++i) {
401 char next = m_istream.rdbuf()->sbumpc();
409 m_state.push(PARSE_COMMENT);
425 switch (m_state.top()) {
464 std::string Bach::decodeString(std::string toDecode) {
465 std::string::size_type pos = 0;
467 while ((pos = toDecode.find(
"\\\"", pos)) != std::string::npos)
468 toDecode.replace(pos, 2, 1,
'\"');
472 while ((pos = toDecode.find(
"\\\\", pos)) != std::string::npos)
473 toDecode.replace(pos, 2, 1,
'\\');
478 std::string Bach::encodeString(std::string toEncode) {
480 for (
size_t i = 0; i < toEncode.size(); ++i) {
481 if (toEncode[i] ==
'\\' || toEncode[i] ==
'\"') {
484 encoded.reserve(toEncode.size() + (toEncode.size() / 4));
485 encoded.assign(toEncode, 0, i);
487 for (; i < toEncode.size(); ++i) {
488 if (toEncode[i] ==
'\\') {
490 }
else if (toEncode[i] ==
'\"') {
493 encoded += toEncode[i];
503 void Bach::writeIntItem(
const std::string &name, std::int64_t data) {
508 m_ostream << name <<
":";
513 void Bach::writeFloatItem(
const std::string &name,
double data) {
518 m_ostream << name <<
":";
523 void Bach::writeStringItem(
const std::string &name, std::string data) {
528 m_ostream << name <<
":";
530 m_ostream <<
"\"" << encodeString(std::move(data)) <<
"\"";
533 void Bach::writeLine(
const std::string &line,
bool endline,
bool endtag) {
534 if (m_comma && !endtag)
540 void Bach::streamBegin() {
545 void Bach::streamEnd() {
546 writeLine(
"]",
true,
true);
549 void Bach::streamMessage() {
554 void Bach::mapMapItem(std::string name) {
555 writeLine(name +
":{");
559 void Bach::mapListItem(std::string name) {
560 writeLine(name +
":[");
564 void Bach::mapIntItem(std::string name, std::int64_t data) {
565 writeIntItem(name, data);
569 void Bach::mapFloatItem(std::string name,
double data) {
570 writeFloatItem(name, data);
574 void Bach::mapStringItem(std::string name, std::string data) {
575 writeStringItem(name, std::move(data));
579 void Bach::mapNoneItem(std::string name) {
583 m_ostream << name <<
":";
586 void Bach::mapEnd() {
587 writeLine(
"}",
true,
true);
591 void Bach::listMapItem() {
596 void Bach::listListItem() {
601 void Bach::listIntItem(std::int64_t data) {
602 writeIntItem(
"", data);
606 void Bach::listFloatItem(
double data) {
607 writeFloatItem(
"", data);
611 void Bach::listStringItem(std::string data) {
612 writeStringItem(
"", std::move(data));
616 void Bach::listNoneItem() {
622 void Bach::listEnd() {
623 writeLine(
"]",
true,
true);