예제 #1
0
static void
WriteXMLChar(BufferedOutputStream &os, TCHAR ch)
{
  switch (ch) {
  case '<':
    os.Write("&lt;");
    break;
  case '>':
    os.Write("&gt;");
    break;
  case '&':
    os.Write("&amp;");
    break;
  case '\'':
    os.Write("&apos;");
    break;
  case '"':
    os.Write("&quot;");
    break;
  default:
    if (IsWhitespaceOrNull(ch))
      ch = ' ';

    os.Write(ch);
    break;
  }
}
예제 #2
0
void
PortLineSplitter::DataReceived(const void *_data, size_t length)
{
  assert(_data != NULL);
  assert(length > 0);

  const char *data = (const char *)_data, *end = data + length;

  do {
    /* append new data to buffer, as much as fits there */
    auto range = buffer.Write();
    if (range.IsEmpty()) {
      /* overflow: reset buffer to recover quickly */
      buffer.Clear();
      continue;
    }

    size_t nbytes = std::min(size_t(range.size), size_t(end - data));
    memcpy(range.data, data, nbytes);
    data += nbytes;
    buffer.Append(nbytes);

    while (true) {
      /* read data from the buffer, to see if there's a newline
         character */
      range = buffer.Read();
      if (range.IsEmpty())
        break;

      char *newline = (char *)memchr(range.data, '\n', range.size);
      if (newline == NULL)
        /* no newline here: wait for more data */
        break;

      /* remove trailing whitespace, such as '\r' */
      char *end = newline;
      while (end > range.data && IsWhitespaceOrNull(end[-1]))
        --end;

      *end = '\0';

      SanitiseLine(range.data, end);

      const char *line = range.data;

      /* if there are NUL bytes in the line, skip to after the last
         one, to avoid conflicts with NUL terminated C strings due to
         binary garbage */
      const void *nul;
      while ((nul = memchr(line, 0, end - line)) != NULL)
        line = (const char *)nul + 1;

      LineReceived(line);

      buffer.Consume(newline - range.data + 1);
    }
  } while (data < end);
}
예제 #3
0
파일: Parser.cpp 프로젝트: Advi42/XCSoar
/**
 * Find next non-white space character.
 */
static TCHAR
FindNonWhiteSpace(XML::Parser *pXML)
{
  assert(pXML);

    // Iterate through characters in the string until we find a NULL or a
  // non-white space character
  TCHAR ch;
  while ((ch = GetNextChar(pXML)) != 0) {
    if (!IsWhitespaceOrNull(ch))
      return ch;
  }
  return 0;
}
예제 #4
0
/**
 * Trim the end of the text to remove white space characters.
 */
gcc_pure
static size_t
FindEndOfText(const TCHAR *token, size_t length)
{
  assert(token != NULL);

  --length;
  while (1) {
    if (IsWhitespaceOrNull(token[length]))
      return length + 1;

    --length;
  }
}
예제 #5
0
파일: Parser.cpp 프로젝트: Advi42/XCSoar
gcc_pure
static bool
CompareTagName(const TCHAR *cclose, const TCHAR *copen)
{
  assert(cclose != nullptr);
  assert(copen != nullptr);

  size_t l = _tcslen(cclose);
  if (!StringIsEqualIgnoreCase(cclose, copen, l))
    return false;

  const TCHAR c = copen[l];
  if (IsWhitespaceOrNull(c) ||
      (c == _T('/')) ||
      (c == _T('<')) ||
      (c == _T('>')) ||
      (c == _T('=')))
    return true;

  return false;
}
예제 #6
0
/**
 * Reads next FlarmNet.org file entry and returns the pointer to
 * a new FlarmNetRecord instance or NULL on error.
 *
 * The caller is responsible for deleting the object again!
 */
static bool
LoadRecord(FlarmRecord &record, const char *line)
{
  if (strlen(line) < 172)
    return false;

  LoadString(line, 6, record.id);
  LoadString(line + 12, 21, record.pilot);
  LoadString(line + 54, 21, record.airfield);
  LoadString(line + 96, 21, record.plane_type);
  LoadString(line + 138, 7, record.registration);
  LoadString(line + 152, 3, record.callsign);
  LoadString(line + 158, 7, record.frequency);

  // Terminate callsign string on first whitespace
  for (TCHAR *i = record.callsign.buffer(); *i != _T('\0'); ++i)
    if (IsWhitespaceOrNull(*i))
      *i = _T('\0');

  return true;
}
예제 #7
0
/**
 * Reads next FlarmNet.org file entry and returns the pointer to
 * a new FlarmNetRecord instance or NULL on error.
 *
 * The caller is responsible for deleting the object again!
 */
static bool
LoadRecord(FlarmRecord &record, const char *line)
{
  if (strlen(line) < 172)
    return false;

  LoadString(line, 6, record.id);
  LoadString(line + 12, 21, record.pilot);
  LoadString(line + 54, 21, record.airfield);
  LoadString(line + 96, 21, record.plane_type);
  LoadString(line + 138, 7, record.registration);
  LoadString(line + 152, 3, record.callsign);
  LoadString(line + 158, 7, record.frequency);

  // Terminate callsign string on first whitespace
  int maxSize = sizeof(record.callsign) / sizeof(TCHAR);
  for (int i = 0; record.callsign[i] != 0 && i < maxSize; i++)
    if (IsWhitespaceOrNull(record.callsign[i]))
      record.callsign[i] = 0;

  return true;
}
예제 #8
0
파일: Parser.cpp 프로젝트: DRIZO/xcsoar
static const char *
ParseLine(char *line)
{
  char *separator = strchr(line, '=');
  if (separator == NULL)
    /* malformed line */
    return NULL;

  char *p = separator;
  while (p > separator && IsWhitespaceOrNull(p[-1]))
    --p;

  if (p == line)
    /* empty name */
    return NULL;

  *p = 0;

  char *value = const_cast<char *>(TrimLeft(separator + 1));
  TrimRight(value);
  return value;
}
예제 #9
0
파일: CharUtil.hpp 프로젝트: Advi42/XCSoar
/**
 * Is the given character whitespace?  This calls the faster one of
 * IsWhitespaceOrNull() or IsWhitespaceNotNull().  Use this if you
 * want the fastest implementation, and you don't care if a null byte
 * matches.
 */
constexpr
static inline bool
IsWhitespaceFast(const char ch)
{
  return IsWhitespaceOrNull(ch);
}
예제 #10
0
파일: Parser.cpp 프로젝트: Advi42/XCSoar
/**
 * Find the next token in a string.
 */
static XML::NextToken
XML::GetNextToken(Parser *pXML)
{
  XML::NextToken result;
  const TCHAR *lpXML;
  TCHAR ch;
  TCHAR temp_ch;
  size_t size;
  unsigned n;
  bool found_match;
  bool is_text = false;

  // Find next non-white space character
  ch = FindNonWhiteSpace(pXML);
  if (gcc_unlikely(ch == 0)) {
    // If we failed to obtain a valid character
    return { nullptr, 0, eTokenError };
  }

  // Cache the current string pointer
  lpXML = pXML->lpXML;
  result.pStr = &lpXML[pXML->nIndex - 1];

  switch (ch) {
    // Check for quotes
  case _T('\''):
  case _T('\"'):
    // Type of token
    result.type = eTokenQuotedText;
    temp_ch = ch;
    n = pXML->nIndex;

    // Set the size
    size = 1;
    found_match = false;

    // Search through the string to find a matching quote
    while (((ch = GetNextChar(pXML))) != 0) {
      size++;
      if (ch == temp_ch) {
        found_match = true;
        break;
      }
      if (ch == _T('<'))
        break;
    }

    // If we failed to find a matching quote
    if (!found_match) {
      pXML->nIndex = n;
      is_text = true;
      break;
    }

    //  4.02.2002
    if (FindNonWhiteSpace(pXML)) {
      pXML->nIndex--;
    }

    break;

    // Equals (used with attribute values)
  case _T('='):
    size = 1;
    result.type = eTokenEquals;
    break;

    // Close tag
  case _T('>'):
    size = 1;
    result.type = eTokenCloseTag;
    break;

    // Check for tag start and tag end
  case _T('<'):

    // Peek at the next character to see if we have an end tag '</',
    // or an xml declaration '<?'
    temp_ch = pXML->lpXML[pXML->nIndex];

    // If we have a tag end...
    if (temp_ch == _T('/')) {
      // Set the type and ensure we point at the next character
      GetNextChar(pXML);
      result.type = eTokenTagEnd;
      size = 2;
    }

    // If we have an XML declaration tag
    else if (temp_ch == _T('?')) {

      // Set the type and ensure we point at the next character
      GetNextChar(pXML);
      result.type = eTokenDeclaration;
      size = 2;
    }

    // Otherwise we must have a start tag
    else {
      result.type = eTokenTagStart;
      size = 1;
    }
    break;

    // Check to see if we have a short hand type end tag ('/>').
  case _T('/'):

    // Peek at the next character to see if we have a short end tag '/>'
    temp_ch = pXML->lpXML[pXML->nIndex];

    // If we have a short hand end tag...
    if (temp_ch == _T('>')) {
      // Set the type and ensure we point at the next character
      GetNextChar(pXML);
      result.type = eTokenShortHandClose;
      size = 2;
      break;
    }

    // If we haven't found a short hand closing tag then drop into the
    // text process

#if GCC_CHECK_VERSION(7,0)
    [[fallthrough]];
#endif

    // Other characters
  default:
    is_text = true;
  }

  // If this is a TEXT node
  if (is_text) {
    // Indicate we are dealing with text
    result.type = eTokenText;
    size = 1;
    bool nExit = false;

    while (!nExit && ((ch = GetNextChar(pXML)) != 0)) {
      if (IsWhitespaceOrNull(ch))
        // Break when we find white space
        break;

      switch (ch) {
      // If we find a slash then this maybe text or a short hand end tag.
      case _T('/'):

        // Peek at the next character to see it we have short hand end tag
        temp_ch = pXML->lpXML[pXML->nIndex];

        // If we found a short hand end tag then we need to exit the loop
        if (temp_ch == _T('>')) {
          pXML->nIndex--; //  03.02.2002
          nExit = true;
        } else {
          size++;
        }
        break;

        // Break when we find a terminator and decrement the index and
        // column count so that we are pointing at the right character
        // the next time we are called.
      case _T('<'):
      case _T('>'):
      case _T('='):
        pXML->nIndex--;
      nExit = true;
      break;

      case 0:
        nExit = true;
        break;

      default:
        size++;
      }
    }
  }
  result.length = size;

  return result;
}
예제 #11
0
ButtonLabel::Expanded
ButtonLabel::Expand(const TCHAR *text, TCHAR *buffer, size_t size)
{
  Expanded expanded;
  const TCHAR *dollar;

  if ((text == NULL) || (*text == _T('\0')) || (*text == _T(' '))) {
    expanded.visible = false;
    return expanded;
  } else if ((dollar = _tcschr(text, '$')) == NULL) {
    /* no macro, we can just translate the text */
    expanded.visible = true;
    expanded.enabled = true;
    const TCHAR *nl;
    if (((nl = _tcschr(text, '\n')) != NULL) && OnlyDigitsAndPunctuation(nl+1)) {
      /* Quick hack for skipping the translation for second line of a two line
         label with only digits and punctuation in the second line, e.g.
         for menu labels like "Config\n2/3" */

      /* copy the text up to the '\n' to a new buffer and translate it */
      TCHAR translatable[256];
      std::copy(text, nl, translatable);
      translatable[nl - text] = _T('\0');

      const TCHAR *translated = StringIsEmpty(translatable)
        ? _T("") : gettext(translatable);

      /* concatenate the translated text and the part starting with '\n' */
      _tcscpy(buffer, translated);
      _tcscat(buffer, nl);

      expanded.text = buffer;
    } else
      expanded.text = gettext(text);
    return expanded;
  } else {
    const TCHAR *macros = dollar;
    /* backtrack until the first non-whitespace character, because we
       don't want to translate whitespace between the text and the
       macro */
    while (macros > text && IsWhitespaceOrNull(macros[-1]))
      --macros;

    TCHAR s[100];
    expanded.enabled = !ExpandMacros(text, s, ARRAY_SIZE(s));
    if (s[0] == _T('\0') || s[0] == _T(' ')) {
      expanded.visible = false;
      return expanded;
    }

    /* copy the text (without trailing whitespace) to a new buffer and
       translate it */
    TCHAR translatable[256];
    std::copy(text, macros, translatable);
    translatable[macros - text] = _T('\0');

    const TCHAR *translated = StringIsEmpty(translatable)
      ? _T("") : gettext(translatable);

    /* concatenate the translated text and the macro output */
    _tcscpy(buffer, translated);
    _tcscat(buffer, s + (macros - text));

    expanded.visible = true;
    expanded.text = buffer;
    return expanded;
  }
}