Beispiel #1
0
void XMLWriter::writeNode(const char* tag, const char* str)
{
    tagOpen(tag, "", NONEWLINE);
#ifdef XMLWRITER_ESCAPE_SUPPORT
    escape(str);
#else
    _stream->print(str);
#endif
    tagClose(NOINDENT);
}
Beispiel #2
0
//--------------------------------------------------------------
// parse a char buffer.  Characters are assumed UTF-8, but this
// is passed through to content and attributes.  All we care
// about is xml characters (<, >, =", etc.)
void mgXMLScanner::parse(
  int len,
  const char* buffer)
{
  int posn = 0;
  while (true)
  {
    // read a char, possibly pushed back
    char c;
    if (m_lastChar != '\0')
    {
      c = m_lastChar;
      m_lastChar = '\0';
    }
    else
    {
      // if buffer empty
      if (posn >= len)
        break;
      c = buffer[posn++];

      // track line and col nums for error messages
      if (c == '\n')
      {
        m_lineNum++;
        m_colNum = 0;
      }
      else if (c != '\r')
        m_colNum++;
    }

    // process against state machine
    switch (m_state)
    {
      case START_STATE:
        if (c == '<')
        {
          if (m_token.length() > 0)
          {
            content(m_token, m_token.length());
            m_token.empty();
          }
          m_state = OPEN_STATE;
        }
        else if (c == '&')
        {
          if (m_token.length() > 0)
          {
            content(m_token, m_token.length());
            m_token.empty();
          }
          m_state = AMPER_STATE;
        }
        else 
        {
          if (m_token.length() > CONTENT_CHUNK_MAX)
          {
            content(m_token, m_token.length());
            m_token.empty();
          }
          m_token += c;
        }
        break;

      case OPEN_STATE:     // '<' seen
        if (c == '?')
          m_state = PROCESS_STATE;
        else if (c == '!')
          m_state = TAGEXP_STATE;
        else if (c == '/')  
          m_state = TAGCLOSE_STATE;
        else 
        {
          m_state = TAGOPEN_STATE;
          m_lastChar = c;
        }
        break;

      case PROCESS_STATE:   // <? seen
        if (c == '?')
          m_state = PROCESS_END_STATE;
        else m_token += c;
        break;
      
      case PROCESS_END_STATE:  // <? ... ? seen
        if (c == '>')
        {
          processingInstruction(m_token);
          m_token.empty();
          m_state = START_STATE;
        }
        else 
        {
          m_token += '?';
          m_lastChar = c;
          m_state = PROCESS_STATE;
        }
        break;

      case TAGEXP_STATE:    // <! seen
        if (c == '-')
          m_state = TAGEXP_DASH_STATE;
        else if (c == '[')
          m_state = CDATA_OPEN_STATE;
        else errorMsg("xmlBadString", "string", "<!%c", c);
        break;

      case TAGEXP_DASH_STATE:  // <!- seen 
        if (c == '-')
          m_state = COMMENT_STATE;
        else errorMsg("xmlBadString", "string", "<!-%c", c);
        break;

      case COMMENT_STATE:   // <!-- seen
        if (c == '-')
          m_state = COMMENT_END_STATE;
        else m_token += c;
        break;
      
      case COMMENT_END_STATE: // <!-- ... - seen
        if (c == '-')
          m_state = COMMENT_END2_STATE;
        else 
        {
          m_token += '-';
          m_lastChar = c;
          m_state = COMMENT_STATE;
        }
        break;

      case COMMENT_END2_STATE:  // <!-- ... -- seen
        if (c == '>')
        {
          comment(m_token);
          m_token.empty();
          m_state = START_STATE;
        }
        else 
        {
          m_token += "--";
          m_lastChar = c;
          m_state = COMMENT_STATE;
        }
        break;

      case CDATA_OPEN_STATE:   // <![ seen
        if (c == 'C')
          m_state = CDATA_OPEN2_STATE;
        else errorMsg("xmlBadString", "string", "<![%c", c);
        break;

      case CDATA_OPEN2_STATE: // <![C seen
        if (c == 'D')
          m_state = CDATA_OPEN3_STATE;
        else errorMsg("xmlBadString", "string", "<![C%c", c);
        break;

      case CDATA_OPEN3_STATE: // <![CD seen
        if (c == 'A')
          m_state = CDATA_OPEN4_STATE;
        else errorMsg("xmlBadString", "string", "<![CD%c", c);
        break;

      case CDATA_OPEN4_STATE: // <![CDA seen
        if (c == 'T')
          m_state = CDATA_OPEN5_STATE;
        else errorMsg("xmlBadString", "string", "<![CDA%c", c);
        break;

      case CDATA_OPEN5_STATE: // <![CDAT seen
        if (c == 'A')
          m_state = CDATA_OPEN6_STATE;
        else errorMsg("xmlBadString", "string", "<![CDAT%c", c);
        break;

      case CDATA_OPEN6_STATE: // <![CDATA seen
        if (c == '[')
          m_state = CDATA_STATE;
        else errorMsg("xmlBadString", "string", "<![CDATA%c", c);
        break;

      case CDATA_STATE:  // <![CDATA[ ... seen
        if (c == ']')
          m_state = CDATA_END_STATE;
        else 
        {
          // break this into chunks
          if (m_token.length() > CONTENT_CHUNK_MAX)
          {
            CDATAContent(m_token, m_token.length());
            m_token.empty();
          }
          m_token += c;
        }
        break;

      case CDATA_END_STATE:  // <![CDATA[ ... ] seen
        if (c == ']')
          m_state = CDATA_END2_STATE;
        else
        {
          m_state = CDATA_STATE;
          m_token += ']';
          m_lastChar = c;
        }
        break;

      case CDATA_END2_STATE:  // <![CDATA[ ... ]] seen
        if (c == '>')
        {
          CDATAContent(m_token, m_token.length());
          m_token.empty();
          m_state = START_STATE;
        }
        else
        {
          m_state = CDATA_STATE;
          m_token += "]]";
          m_lastChar = c;
        }
        break;

      case TAGOPEN_STATE:   // <x... seen
        if (c == '>')
        {
          tagOpen(m_token);
          endAttrs();
          m_token.empty();
          m_state = START_STATE;
        }
        else if (c == '/')
        {
          tagOpen(m_token);
          m_token.empty();
          endAttrs();
          tagNoContent();
          m_state = TAGCLOSE_BLANK_STATE;
        }
        else if (isspace(c))
        {
          tagOpen(m_token);
          m_token.empty();
          m_state = ATTR_START_STATE;
        }
        else m_token += c;
        break;

      case TAGCLOSE_STATE:  // </ seen
        if (c == '>')
        {
          tagClose(m_token);
          m_token.empty();
          m_state = START_STATE;
        }
        else if (isspace(c))
        {
          tagClose(m_token);
          m_token.empty();
          m_state = TAGCLOSE_BLANK_STATE;
        }
        else m_token += c;
        break;

      case TAGCLOSE_BLANK_STATE:  // </tag ' ' seen
        if (c == '>')
          m_state = START_STATE;

        else if (!isspace(c))
          errorMsg("xmlBadClose", "", "");
        break;

      case ATTR_START_STATE: // <tag ' ' seen, or attr=value seen
        if (c == '>')
        {
          if (m_token.length() > 0)
          {
            tagOpen(m_token);
            m_token.empty();
          }
          endAttrs();
          m_state = START_STATE;
        }
        else if (c == '/')
        {
          if (m_token.length() > 0)
          {
            tagOpen(m_token);
            m_token.empty();
          }
          endAttrs();
          tagNoContent();
          m_state = TAGCLOSE_BLANK_STATE;
        }
        else if (!isspace(c))
        {
          m_state = ATTR_NAME_STATE;
          m_lastChar = c;
        }
        break;

      case ATTR_NAME_STATE: // <tag ... 'letter' a seen
        if (iswalnum(c) || c == '_' || c == '.' || c == '-')
          m_token += c;
        else if (c == '=')
        {
          attrName(m_token);
          m_token.empty();
          m_state = VALUE_START_STATE;
        }
        else if (isspace(c))
        {
          attrName(m_token);
          m_token.empty();
          m_state = EQUAL_START_STATE;
        }

        else errorMsg("xmlMissingEquals", "", "");
        break;

      case EQUAL_START_STATE:
        if (c == '=')
          m_state = VALUE_START_STATE;
        else if (!isspace(c))
          errorMsg("xmlMissingEquals", "", "");
        break;

      case VALUE_START_STATE:
        if (c == '"')
        {
          m_state = VALUE_STATE;
          m_valueDelim = '"';
        }
        else if (c == '\'')
        {
          m_state = VALUE_STATE;
          m_valueDelim = '\'';
        }
        else if (!isspace(c))
          errorMsg("xmlMissingQuote", "", "");
        break;

      case VALUE_STATE:
        if (c == m_valueDelim)
        {
          attrValue(m_token);
          m_token.empty();
          m_state = ATTR_START_STATE;
        }
        else if (c == '&')
          m_state = VALUE_AMPER_STATE;
        else m_token += c;
        break;

      case VALUE_AMPER_STATE:  // & seen in attribute value
        if (c == ';')
        {
          mgString value;
          entityRef(m_entityRef, value);
          m_token += value;
          m_entityRef.empty();
          m_state = VALUE_STATE;
        }
        else if (isspace(c))
          errorMsg("xmlMissingSemi", "", "");

        else m_entityRef += c;
        break;

      case AMPER_STATE: // & seen in content
        if (c == ';')
        {
          mgString value;
          entityRef(m_entityRef, value);
          m_token += value;
          m_entityRef.empty();
          m_state = START_STATE;
        }
        else if (isspace(c))
          errorMsg("xmlMissingSemi", "", "");

        else m_entityRef += c;
        break;
    }
  }
}
Beispiel #3
0
void XMLWriter::tagOpen(const char* tag, const bool newline)
{
    tagOpen(tag, "", newline);
}
Beispiel #4
0
void XMLWriter::writeNode(const char* tag, const double value, const uint8_t decimals)
{
    tagOpen(tag, "", NONEWLINE);
    _stream->print(value, decimals);
    tagClose(NOINDENT);
}
Beispiel #5
0
void XMLWriter::writeNode(const char* tag, const bool value)
{
    tagOpen(tag, "", NONEWLINE);
    _stream->print(value?F("true"):F("false"));
    tagClose(NOINDENT);
}
Beispiel #6
0
void XMLWriter::writeNode(const char* tag, const int32_t value, const uint8_t base)
{
    tagOpen(tag, "", NONEWLINE);
    _stream->print(value, base);  // todo: leading zero's
    tagClose(NOINDENT);
}
Beispiel #7
0
void XMLWriter::tagOpen(char* tag, bool newline)
{
    tagOpen(tag, "", newline);
}