Skip to content

Commit

Permalink
libdeng2: Added EscapeParser
Browse files Browse the repository at this point in the history
Utility for parsing a text string with ASCII Esc (0x1b) escape
sequences, used for rich text formatting in libdeng2.
  • Loading branch information
skyjake committed Jun 7, 2013
1 parent b29998c commit e6373b9
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 0 deletions.
3 changes: 3 additions & 0 deletions doomsday/libdeng2/data.pri
Expand Up @@ -16,6 +16,7 @@ HEADERS += \
include/de/Date \
include/de/DictionaryValue \
include/de/DotPath \
include/de/EscapeParser \
include/de/FIFO \
include/de/FixedByteArray \
include/de/IBlock \
Expand Down Expand Up @@ -64,6 +65,7 @@ HEADERS += \
include/de/data/counted.h \
include/de/data/date.h \
include/de/data/dictionaryvalue.h \
include/de/data/escapeparser.h \
include/de/data/fifo.h \
include/de/data/fixedbytearray.h \
include/de/data/huffman.h \
Expand Down Expand Up @@ -114,6 +116,7 @@ SOURCES += \
src/data/counted.cpp \
src/data/date.cpp \
src/data/dictionaryvalue.cpp \
src/data/escapeparser.cpp \
src/data/fixedbytearray.cpp \
src/data/huffman.cpp \
src/data/info.cpp \
Expand Down
1 change: 1 addition & 0 deletions doomsday/libdeng2/include/de/EscapeParser
@@ -0,0 +1 @@
#include "data/escapeparser.h"
72 changes: 72 additions & 0 deletions doomsday/libdeng2/include/de/data/escapeparser.h
@@ -0,0 +1,72 @@
/** @file escapeparser.h Text escape sequence parser.
*
* @authors Copyright (c) 2013 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
*
* <small>This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. This program is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details. You should have received a copy of the GNU
* General Public License along with this program; if not, see:
* http://www.gnu.org/licenses</small>
*/

#ifndef LIBDENG2_ESCAPEPARSER_H
#define LIBDENG2_ESCAPEPARSER_H

#include <de/libdeng2.h>
#include <de/String>
#include <de/Observers>

namespace de {

/**
* Escape sequence parser for text strings.
*
* @see DENG2_ESC() macro
*/
class DENG2_PUBLIC EscapeParser
{
public:
/**
* Called during parsing when a plain text range has been parsed.
*
* @param range Range in the original text.
*/
DENG2_DEFINE_AUDIENCE(PlainText, void handlePlainText(Rangei const &range))

/**
* Called during parsing when an escape sequence has been parsed.
* Does not include the Esc (0x1b) in the beginning.
*
* @param range Range in the original text.
*/
DENG2_DEFINE_AUDIENCE(EscapeSequence, void handleEscapeSequence(Rangei const &range))

public:
EscapeParser();

void parse(String const &textWithEscapes);

/**
* Returns the original string that was parsed.
*/
String originalText() const;

/**
* Returns the plain text string. Available after parsing.
*/
String plainText() const;

private:
DENG2_PRIVATE(d)
};

} // namespace de

#endif // LIBDENG2_ESCAPEPARSER_H
115 changes: 115 additions & 0 deletions doomsday/libdeng2/src/data/escapeparser.cpp
@@ -0,0 +1,115 @@
/** @file escapeparser.cpp
*
* @authors Copyright (c) 2013 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
*
* <small>This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. This program is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details. You should have received a copy of the GNU
* General Public License along with this program; if not, see:
* http://www.gnu.org/licenses</small>
*/

#include "de/EscapeParser"

namespace de {

DENG2_PIMPL_NOREF(EscapeParser)
{
String original;
String plain;
};

EscapeParser::EscapeParser() : d(new Instance)
{}

void EscapeParser::parse(String const &textWithEscapes)
{
d->original = textWithEscapes;
d->plain.clear();

Rangei range;

forever
{
range.end = d->original.indexOf(QChar('\x1b'), range.start);
if(range.end >= 0)
{
// Empty ranges are ignored.
if(range.size() > 0)
{
DENG2_FOR_AUDIENCE(PlainText, i)
{
i->handlePlainText(range);
}

// Update the plain text.
d->plain += d->original.substr(range);
}

// Check the escape sequences.
int escLen = 2;
char ch = d->original[range.end + 1].toLatin1();
switch(ch)
{
case '(':
case '[':
case '{':
case '<': {
// Find the matching end.
int end = d->original.indexOf(ch == '('? ')' : ch == '['? ']' :
ch == '{'? '}' : '>', range.end + 1);
if(end < 0) end = d->original.size() - 1;
escLen = end - range.end + 1;
break; }

case 'T':
escLen = 3;
break;

default:
break;
}

DENG2_FOR_AUDIENCE(EscapeSequence, i)
{
i->handleEscapeSequence(Rangei(range.end + 1, range.end + escLen));
}

// Advance the scanner.
range.start = range.end + escLen;
}
else
{
// Final plain text range.
range.end = d->original.size();
if(range.size() > 0)
{
DENG2_FOR_AUDIENCE(PlainText, i)
{
i->handlePlainText(range);
}
d->plain += d->original.substr(range);
}
break;
}
}
}

String EscapeParser::originalText() const
{
return d->original;
}

String EscapeParser::plainText() const
{
return d->plain;
}

} // namespace de

0 comments on commit e6373b9

Please sign in to comment.