From 2446736bc775b22cf5aaae88c2c69c9504e5eb17 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Thu, 24 Jan 2019 23:10:59 +0100 Subject: Move message composer from dchat_gtk to dchat_core --- src/MessageComposer.cpp | 160 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 src/MessageComposer.cpp (limited to 'src') diff --git a/src/MessageComposer.cpp b/src/MessageComposer.cpp new file mode 100644 index 0000000..71fa62e --- /dev/null +++ b/src/MessageComposer.cpp @@ -0,0 +1,160 @@ +#include "../include/dchat/MessageComposer.hpp" +#include +#include + +namespace dchat +{ + enum class Token + { + NONE, + END_OF_FILE, + + TEXT, + TYPE + }; + + struct Tokenizer + { + Tokenizer(const char *_text, usize _size) + { + assert(_text); + text = _text; + size = _size; + index = 0; + identifierRange = { 0, 0 }; + typeRange = { 0, 0 }; + typeDataRange = { 0, 0 }; + } + + enum class EnclosedType + { + TEXT, + DATA + }; + + EnclosedType parseEnclosedData(char endSymbol) + { + bool foundEndOfType = false; + + while(index < size) + { + char c = getChar(); + ++index; + if(c == endSymbol) + { + foundEndOfType = true; + break; + } + } + + if(!foundEndOfType) + return EnclosedType::TEXT; + + return EnclosedType::DATA; + } + + Token next() + { + if(index >= size) + return Token::END_OF_FILE; + + char c = getChar(); + if(c == '[') + { + usize start = index; + ++index; + if(parseEnclosedData(']') == EnclosedType::TEXT) + { + identifierRange.start = start; + identifierRange.end = index; + return Token::TEXT; + } + + if(index == size || getChar() != '(') + { + identifierRange.start = start; + identifierRange.end = index; + return Token::TEXT; + } + + typeRange.start = start + 1; + typeRange.end = index - 1; + typeDataRange.start = index + 1; + + ++index; + switch(parseEnclosedData(')')) + { + case EnclosedType::TEXT: + { + identifierRange.start = start; + identifierRange.end = index; + return Token::TEXT; + } + case EnclosedType::DATA: + { + typeDataRange.end = index - 1; + return Token::TYPE; + } + } + } + else + { + identifierRange.start = index; + ++index; + while(index < size) + { + c = getChar(); + if(c == '[') + break; + ++index; + } + identifierRange.end = index; + return Token::TEXT; + } + + assert(false); + return Token::NONE; + } + + char getChar() const + { + assert(index < size); + return text[index]; + } + + const char *text; + usize size; + usize index; + + Range identifierRange; + Range typeRange; + Range typeDataRange; + }; + + void compose(const char *text, usize size, std::function callbackFunc) + { + Tokenizer tokenizer(text, size); + Token token = tokenizer.next(); + while(token != Token::END_OF_FILE) + { + if(token == Token::TEXT) + { + callbackFunc(MessagePart { MessagePart::Type::TEXT, tokenizer.identifierRange }); + token = tokenizer.next(); + } + else if(token == Token::TYPE) + { + if(tokenizer.typeRange.length() == 5 && memcmp(text + tokenizer.typeRange.start, "emoji", 5) == 0) + { + callbackFunc(MessagePart { MessagePart::Type::EMOJI, tokenizer.typeDataRange }); + } + else + { + Range typeToTextRange = { tokenizer.typeRange.start - 1, tokenizer.typeDataRange.end + 1 }; + callbackFunc(MessagePart{ MessagePart::Type::TEXT, typeToTextRange }); + } + token = tokenizer.next(); + } + } + } +} \ No newline at end of file -- cgit v1.2.3