GY-63_MS5611/libraries/XMLWriter/XMLWriter.cpp

408 lines
7.5 KiB
C++
Raw Normal View History

//
// FILE: XMLWriter.cpp
// AUTHOR: Rob Tillaart
2022-11-27 06:54:57 -05:00
// VERSION: 0.3.3
// DATE: 2013-11-06
2022-11-27 06:54:57 -05:00
// PURPOSE: Arduino library for creating XML
2021-01-29 06:31:58 -05:00
#include "XMLWriter.h"
2021-11-11 14:36:58 -05:00
XMLWriter::XMLWriter(Print* stream, uint8_t bufferSize)
{
2021-11-11 14:36:58 -05:00
_bufferSize = constrain(bufferSize, 2, 250);
_buffer = (char *) malloc(_bufferSize);
_stream = stream;
reset();
}
2021-01-29 06:31:58 -05:00
2020-05-25 03:58:04 -04:00
XMLWriter::~XMLWriter()
{
if (_buffer != NULL) free(_buffer);
}
2021-01-29 06:31:58 -05:00
void XMLWriter::reset()
{
2021-11-11 14:36:58 -05:00
_indent = 0;
_indentStep = 2;
_tagIndex = 0;
_bufferIndex = 0;
_config = XMLWRITER_COMMENT | XMLWRITER_INDENT | XMLWRITER_NEWLINE;
_bytesOut = 0;
}
2021-01-29 06:31:58 -05:00
void XMLWriter::header()
{
2020-05-25 03:58:04 -04:00
print(F("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"));
}
2021-01-29 06:31:58 -05:00
void XMLWriter::version()
{
print(F("<!-- "));
print(F(" XMLWRITER_VERSION: "));
print(XMLWRITER_VERSION);
print(F(" -->\n"));
}
void XMLWriter::debug()
{
print(F("<!-- "));
print('\n');
print(F(" VERSION: "));
println(XMLWRITER_VERSION);
print(F("MAXLEVEL: "));
println(XMLWRITER_MAXLEVEL);
print(F(" TAGSIZE: "));
println(XMLWRITER_MAXTAGSIZE);
print(F(" CONFIG: "));
println(_config, HEX);
print(F(" INDENT: "));
println(_indent);
print(F(" BUFSIZE: "));
2021-11-11 14:36:58 -05:00
println(_bufferSize);
2021-01-29 06:31:58 -05:00
print(F(" -->\n"));
}
2020-11-27 05:33:55 -05:00
void XMLWriter::comment(const char* text, const bool multiLine)
{
2020-05-25 03:58:04 -04:00
if (_config & XMLWRITER_COMMENT)
{
print('\n');
if (!multiLine) indent();
print(F("<!-- "));
if (multiLine) print('\n');
print(text);
if (multiLine) print('\n');
print(F(" -->\n"));
}
}
2021-01-29 06:31:58 -05:00
2020-05-25 03:58:04 -04:00
void XMLWriter::newLine(uint8_t n)
{
if (_config & XMLWRITER_NEWLINE)
{
while(n--) print('\n');
}
}
2021-01-29 06:31:58 -05:00
void XMLWriter::tagOpen(const char* tag, const bool newline)
{
tagOpen(tag, "", newline);
}
2021-11-11 14:36:58 -05:00
void XMLWriter::tagOpen(const char* tag, const char* name, const bool newline)
{
2021-11-11 14:36:58 -05:00
if (_tagIndex > XMLWRITER_MAXLEVEL)
2020-05-25 03:58:04 -04:00
{
2020-11-27 05:33:55 -05:00
comment("MAXLEVEL exceeded.");
2020-05-25 03:58:04 -04:00
comment(tag);
comment(name);
2020-11-27 05:33:55 -05:00
flush();
2020-05-25 03:58:04 -04:00
return;
}
2020-11-27 05:33:55 -05:00
if (strlen(tag) > XMLWRITER_MAXTAGSIZE)
{
comment("MAXTAGSIZE exceeded.");
comment(tag);
flush();
return;
}
2021-11-11 14:36:58 -05:00
strcpy(_tagStack[_tagIndex++], tag);
tagStart(tag);
if (name[0] != 0) tagField("name", name);
tagEnd(newline, NOSLASH);
_indent += _indentStep;
}
2021-11-11 14:36:58 -05:00
void XMLWriter::tagClose(const bool ind)
{
_indent -= _indentStep;
if (ind) indent();
2020-05-25 03:58:04 -04:00
print("</");
2021-11-11 14:36:58 -05:00
print(_tagStack[--_tagIndex]);
2020-05-25 03:58:04 -04:00
print(">\n");
}
2021-11-11 14:36:58 -05:00
void XMLWriter::tagStart(const char *tag)
{
indent();
2020-05-25 03:58:04 -04:00
print('<');
print(tag);
}
2021-11-11 14:36:58 -05:00
void XMLWriter::tagField(const char *field, const char* str)
{
2020-05-25 03:58:04 -04:00
print(' ');
print(field);
print("=\"");
#ifdef XMLWRITER_ESCAPE_SUPPORT
escape(str);
#else
2020-05-25 03:58:04 -04:00
print(str);
#endif
2020-05-25 03:58:04 -04:00
print('"');
}
2021-11-11 14:36:58 -05:00
void XMLWriter::tagEnd(const bool newline, const bool addSlash)
{
2020-05-25 03:58:04 -04:00
if (addSlash) print("/>");
else print('>');
if (newline) print('\n');
}
2021-11-11 14:36:58 -05:00
void XMLWriter::writeNode(const char* tag, const char* str)
{
tagOpen(tag, "", NONEWLINE);
#ifdef XMLWRITER_ESCAPE_SUPPORT
escape(str);
#else
2020-05-25 03:58:04 -04:00
print(str);
#endif
tagClose(NOINDENT);
}
2021-01-29 06:31:58 -05:00
///////////////////////////////////////////////////////////////
//
2022-11-27 06:54:57 -05:00
// TAGFIELD
2021-01-29 06:31:58 -05:00
//
void XMLWriter::tagField(const char *field, const uint8_t value, const uint8_t base)
{
tagField(field, (uint32_t) value, base);
}
2021-11-11 14:36:58 -05:00
void XMLWriter::tagField(const char *field, const uint16_t value, const uint8_t base)
{
tagField(field, (uint32_t) value, base);
}
2021-11-11 14:36:58 -05:00
void XMLWriter::tagField(const char *field, const uint32_t value, const uint8_t base)
{
2020-05-25 03:58:04 -04:00
print(' ');
print(field);
print("=\"");
print(value, base);
print('"');
}
2021-11-11 14:36:58 -05:00
void XMLWriter::tagField(const char *field, const int8_t value, const uint8_t base)
{
tagField(field, (int32_t) value, base);
}
2021-11-11 14:36:58 -05:00
void XMLWriter::tagField(const char *field, const int16_t value, const uint8_t base)
{
tagField(field, (int32_t) value, base);
}
2021-11-11 14:36:58 -05:00
2021-01-29 06:31:58 -05:00
void XMLWriter::tagField(const char *field, const int value, const int base)
{
tagField(field, (int32_t) value, (uint8_t) base);
}
2021-11-11 14:36:58 -05:00
void XMLWriter::tagField(const char *field, const int32_t value, const uint8_t base)
{
2020-05-25 03:58:04 -04:00
print(' ');
print(field);
print("=\"");
print(value, base);
print('"');
}
2021-11-11 14:36:58 -05:00
void XMLWriter::tagField(const char *field, const bool value)
{
2020-05-25 03:58:04 -04:00
print(' ');
print(field);
2022-11-27 06:54:57 -05:00
// F() is slower & uses less RAM but 15 bytes saved
2020-05-25 03:58:04 -04:00
print(value ? F("=\"true\"") : F("=\"false\""));
}
2021-11-11 14:36:58 -05:00
void XMLWriter::tagField(const char *field, const double value, const uint8_t decimals)
{
2020-05-25 03:58:04 -04:00
print(' ');
print(field);
print(F("=\""));
print(value, decimals);
print('"');
}
2021-11-11 14:36:58 -05:00
2021-01-29 06:31:58 -05:00
///////////////////////////////////////////////////////////////
//
2022-11-27 06:54:57 -05:00
// WRITENODE
2021-01-29 06:31:58 -05:00
//
void XMLWriter::writeNode(const char* tag, const uint8_t value, const uint8_t base)
{
writeNode(tag, (uint32_t) value, base);
}
2021-11-11 14:36:58 -05:00
void XMLWriter::writeNode(const char* tag, const uint16_t value, const uint8_t base)
{
writeNode(tag, (uint32_t) value, base);
}
2021-11-11 14:36:58 -05:00
void XMLWriter::writeNode(const char* tag, const uint32_t value, const uint8_t base)
{
tagOpen(tag, "", NONEWLINE);
2020-05-25 03:58:04 -04:00
print(value, base);
tagClose(NOINDENT);
}
2021-11-11 14:36:58 -05:00
void XMLWriter::writeNode(const char* tag, const int8_t value, const uint8_t base)
{
writeNode(tag, (int32_t) value, base);
}
2021-11-11 14:36:58 -05:00
void XMLWriter::writeNode(const char* tag, const int16_t value, const uint8_t base)
{
writeNode(tag, (int32_t) value, base);
}
2021-11-11 14:36:58 -05:00
2021-01-29 06:31:58 -05:00
void XMLWriter::writeNode(const char* tag, const int value, const int base)
{
writeNode(tag, (int32_t) value, (uint8_t) base);
}
2021-11-11 14:36:58 -05:00
void XMLWriter::writeNode(const char* tag, const int32_t value, const uint8_t base)
{
tagOpen(tag, "", NONEWLINE);
2020-05-25 03:58:04 -04:00
print(value, base);
tagClose(NOINDENT);
}
2021-11-11 14:36:58 -05:00
void XMLWriter::writeNode(const char* tag, const bool value)
{
tagOpen(tag, "", NONEWLINE);
2022-11-27 06:54:57 -05:00
// F() is slower & uses less RAM but saves 9 bytes
2020-05-25 03:58:04 -04:00
print(value ? F("true") : F("false"));
tagClose(NOINDENT);
}
2021-11-11 14:36:58 -05:00
void XMLWriter::writeNode(const char* tag, const double value, const uint8_t decimals)
{
tagOpen(tag, "", NONEWLINE);
2020-05-25 03:58:04 -04:00
print(value, decimals);
tagClose(NOINDENT);
}
2021-11-11 14:36:58 -05:00
void XMLWriter::indent()
{
2020-05-25 03:58:04 -04:00
if (_config & XMLWRITER_INDENT)
{
2022-11-27 06:54:57 -05:00
// as indentation is a multiple of 2
// this is nice balance between speed and RAM.
2020-05-25 03:58:04 -04:00
for (uint8_t i = _indent; i > 0; i-= 2) print(" ");
}
}
2021-11-11 14:36:58 -05:00
2020-05-25 03:58:04 -04:00
size_t XMLWriter::write(uint8_t c)
{
2021-11-11 14:36:58 -05:00
_buffer[_bufferIndex++] = c;
if (_bufferIndex == (_bufferSize - 1)) flush();
2020-05-25 03:58:04 -04:00
return 1;
};
2021-11-11 14:36:58 -05:00
2020-05-25 03:58:04 -04:00
void XMLWriter::flush()
{
2021-11-11 14:36:58 -05:00
_bytesOut += _bufferIndex;
if (_bufferIndex > 0)
2020-05-25 03:58:04 -04:00
{
2021-11-11 14:36:58 -05:00
_buffer[_bufferIndex] = 0;
2022-11-27 06:54:57 -05:00
_stream->write(_buffer, _bufferIndex); // saves ~40 bytes on UNO.
// _stream->print(_buffer);
2021-11-11 14:36:58 -05:00
_bufferIndex = 0;
2020-05-25 03:58:04 -04:00
}
};
////////////////////////////////////////////////////////////////////
2020-05-25 03:58:04 -04:00
//
2022-11-27 06:54:57 -05:00
// ESCAPE
2020-05-25 03:58:04 -04:00
//
#ifdef XMLWRITER_ESCAPE_SUPPORT
2020-05-25 03:58:04 -04:00
static char c[6] = "\"\'<>&";
#ifdef __PROGMEM__
PROGMEM const char quote[] = "&quot;";
PROGMEM const char apostrophe[] = "&apos;";
PROGMEM const char lessthen[] = "&lt;";
PROGMEM const char greaterthen[] = "&gt;";
PROGMEM const char ampersand[] = "&amp;";
PROGMEM const char* const expanded[] =
{
quote, apostrophe, lessthen, greaterthen, ampersand
};
#else
2022-11-27 06:54:57 -05:00
// NOTE: & and ; are handled in code. // 25 bytes RAM
2020-05-25 03:58:04 -04:00
static char expanded[][5] = { "quot", "apos","lt","gt","amp"};
#endif
void XMLWriter::escape(const char* str)
{
char* p = (char *)str;
2020-05-25 03:58:04 -04:00
while (*p != 0)
{
char* q = strchr(c, *p);
2020-05-25 03:58:04 -04:00
if (q == NULL) print(*p);
#ifdef __PROGMEM__
2022-11-27 06:54:57 -05:00
else
2020-05-25 03:58:04 -04:00
{
char buf[8];
strcpy_P(buf, (char*)pgm_read_word(&(expanded[q - c])));
print(buf);
}
#else
else
{
print('&');
2022-11-27 06:54:57 -05:00
print(expanded[q - c]); // uint8_t idx = q-c;
2020-05-25 03:58:04 -04:00
print(';');
}
#endif
p++;
}
}
#endif
2020-05-25 03:58:04 -04:00
2022-11-27 06:54:57 -05:00
// -- END OF FILE --
2021-12-29 10:27:03 -05:00