aboutsummaryrefslogtreecommitdiff
path: root/src/PercentEncodedCharacterDecoder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/PercentEncodedCharacterDecoder.cpp')
-rw-r--r--src/PercentEncodedCharacterDecoder.cpp78
1 files changed, 78 insertions, 0 deletions
diff --git a/src/PercentEncodedCharacterDecoder.cpp b/src/PercentEncodedCharacterDecoder.cpp
new file mode 100644
index 0000000..d3bc0d9
--- /dev/null
+++ b/src/PercentEncodedCharacterDecoder.cpp
@@ -0,0 +1,78 @@
+/**
+ * @file PercentEncodedCharacterDecoder.cpp
+ *
+ * This module contains the implementation of the
+ * Uri::PercentEncodedCharacterDecoder class.
+ *
+ * © 2018 by Richard Walters
+ */
+
+#include "IsCharacterInSet.hpp"
+#include "PercentEncodedCharacterDecoder.hpp"
+
+namespace Uri {
+
+ struct PercentEncodedCharacterDecoder::Impl {
+ /**
+ * This is the decoded character.
+ */
+ int decodedCharacter = 0;
+
+ /**
+ * This is the current state of the decoder's state machine.
+ * - 0: we haven't yet received the first hex digit.
+ * - 1: we received the first hex digit but not the second.
+ * - 2: we received both hex digits
+ */
+ size_t decoderState = 0;
+ };
+
+ PercentEncodedCharacterDecoder::~PercentEncodedCharacterDecoder() = default;
+ PercentEncodedCharacterDecoder::PercentEncodedCharacterDecoder(PercentEncodedCharacterDecoder&&) = default;
+ PercentEncodedCharacterDecoder& PercentEncodedCharacterDecoder::operator=(PercentEncodedCharacterDecoder&&) = default;
+
+ PercentEncodedCharacterDecoder::PercentEncodedCharacterDecoder()
+ : impl_(new Impl)
+ {
+ }
+
+ bool PercentEncodedCharacterDecoder::NextEncodedCharacter(char c) {
+ switch(impl_->decoderState) {
+ case 0: { // % ...
+ impl_->decoderState = 1;
+ impl_->decodedCharacter <<= 4;
+ if (IsCharacterInSet(c, {'0','9'})) {
+ impl_->decodedCharacter += (int)(c - '0');
+ } else if (IsCharacterInSet(c, {'A','F'})) {
+ impl_->decodedCharacter += (int)(c - 'A') + 10;
+ } else {
+ return false;
+ }
+ } break;
+
+ case 1: { // %[0-9A-F] ...
+ impl_->decoderState = 2;
+ impl_->decodedCharacter <<= 4;
+ if (IsCharacterInSet(c, {'0','9'})) {
+ impl_->decodedCharacter += (int)(c - '0');
+ } else if (IsCharacterInSet(c, {'A','F'})) {
+ impl_->decodedCharacter += (int)(c - 'A') + 10;
+ } else {
+ return false;
+ }
+ } break;
+
+ default: break;
+ }
+ return true;
+ }
+
+ bool PercentEncodedCharacterDecoder::Done() const {
+ return (impl_->decoderState == 2);
+ }
+
+ char PercentEncodedCharacterDecoder::GetDecodedCharacter() const {
+ return (char)impl_->decodedCharacter;
+ }
+
+}