diff options
Diffstat (limited to 'src/OutgoingMessage.cpp')
-rw-r--r-- | src/OutgoingMessage.cpp | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/src/OutgoingMessage.cpp b/src/OutgoingMessage.cpp new file mode 100644 index 0000000..e774940 --- /dev/null +++ b/src/OutgoingMessage.cpp @@ -0,0 +1,136 @@ +#include "../include/dchat/OutgoingMessage.hpp" +#include <assert.h> + +namespace dchat +{ + namespace OutgoingMessage + { + enum class Token + { + NONE, + END_OF_FILE, + + TEXT, + BIND + }; + + struct Tokenizer + { + Tokenizer(const char *_text, usize _size, const EmojiBindMap *_emojiBindMap) + { + assert(_text); + assert(_emojiBindMap); + text = _text; + size = _size; + index = 0; + emoji = nullptr; + emojiBindMap = _emojiBindMap; + textRange = { 0, 0 }; + } + + // returns -1 if character can't be found in the string + usize find(const char *str, usize size, char c) const + { + for(usize i = 0; i < size; ++i) + { + if(str[i] == c) + return i; + } + return -1; + } + + // Return nullptr if bind is not found + const std::string* getBindEmoji(const char *text, usize size) const + { + // TODO: unecessary conversion to string, convert emojibindmap to const char* and uses custom hasher + auto it = emojiBindMap->find(std::string(text, size)); + if(it != emojiBindMap->end()) + return &it->second; + return nullptr; + } + + Token next() + { + if(index >= size) + return Token::END_OF_FILE; + + char c = getChar(); + usize start = index; + ++index; + if(c == ':') + { + while(index < size) + { + c = getChar(); + ++index; + if(c == ':') + { + usize end = index - 1; + const std::string *_emoji = getBindEmoji(text + start + 1, end - (start + 1)); + if(_emoji) + { + emoji = _emoji; + return Token::BIND; + } + break; + } + } + + textRange.start = start; + textRange.end = index; + return Token::TEXT; + } + else + { + while(index < size) + { + c = getChar(); + if(c == ':') + break; + ++index; + } + + textRange.start = start; + textRange.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; + const std::string *emoji; + const EmojiBindMap *emojiBindMap; + + Range textRange; + }; + } + + void parseOutgoingMessage(const char *text, usize size, const EmojiBindMap &emojiBindMap, std::function<void(OutgoingMessagePart)> callbackFunc) + { + OutgoingMessage::Tokenizer tokenizer(text, size, &emojiBindMap); + OutgoingMessage::Token token = tokenizer.next(); + while(token != OutgoingMessage::Token::END_OF_FILE) + { + if(token == OutgoingMessage::Token::TEXT) + { + callbackFunc(OutgoingMessagePart { OutgoingMessagePart::Type::TEXT, tokenizer.textRange }); + token = tokenizer.next(); + } + else if(token == OutgoingMessage::Token::BIND) + { + callbackFunc(OutgoingMessagePart { OutgoingMessagePart::Type::EMOJI, tokenizer.emoji }); + token = tokenizer.next(); + } + } + } +}
\ No newline at end of file |