#include "../include/dchat/IncomingMessage.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 parseIncomingMessage(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(IncomingMessagePart { IncomingMessagePart::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(IncomingMessagePart { IncomingMessagePart::Type::EMOJI, tokenizer.typeDataRange }); } else { Range typeToTextRange = { tokenizer.typeRange.start - 1, tokenizer.typeDataRange.end + 1 }; callbackFunc(IncomingMessagePart{ IncomingMessagePart::Type::TEXT, typeToTextRange }); } token = tokenizer.next(); } } } }