aboutsummaryrefslogtreecommitdiff
path: root/src/OutgoingMessage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/OutgoingMessage.cpp')
-rw-r--r--src/OutgoingMessage.cpp136
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