aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/IsCharacterInSet.cpp35
-rw-r--r--src/IsCharacterInSet.hpp37
-rw-r--r--src/PercentEncodedCharacterDecoder.cpp78
-rw-r--r--src/PercentEncodedCharacterDecoder.hpp85
-rw-r--r--src/Uri.cpp141
5 files changed, 246 insertions, 130 deletions
diff --git a/src/IsCharacterInSet.cpp b/src/IsCharacterInSet.cpp
new file mode 100644
index 0000000..82625e9
--- /dev/null
+++ b/src/IsCharacterInSet.cpp
@@ -0,0 +1,35 @@
+/**
+ * @file IsCharacterInSet.cpp
+ *
+ * This module contains the implementation of the
+ * Uri::IsCharacterInSet function.
+ *
+ * © 2018 by Richard Walters
+ */
+
+#include "IsCharacterInSet.hpp"
+
+namespace Uri {
+
+ bool IsCharacterInSet(
+ char c,
+ std::initializer_list< char > characterSet
+ ) {
+ for (
+ auto charInSet = characterSet.begin();
+ charInSet != characterSet.end();
+ ++charInSet
+ ) {
+ const auto first = *charInSet++;
+ const auto last = *charInSet;
+ if (
+ (c >= first)
+ && (c <= last)
+ ) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/src/IsCharacterInSet.hpp b/src/IsCharacterInSet.hpp
new file mode 100644
index 0000000..f17460c
--- /dev/null
+++ b/src/IsCharacterInSet.hpp
@@ -0,0 +1,37 @@
+#ifndef URI_IS_CHARACTER_IN_SET_HPP
+#define URI_IS_CHARACTER_IN_SET_HPP
+
+/**
+ * @file IsCharacterInSet.hpp
+ *
+ * This module declares the Uri::IsCharacterInSet class.
+ *
+ * © 2018 by Richard Walters
+ */
+
+#include <initializer_list>
+
+namespace Uri {
+
+ /**
+ * This function determines whether or not the given character
+ * is in the given character set.
+ *
+ * @param[in] c
+ * This is the character to check.
+ *
+ * @param[in] characterSet
+ * This is the set of characters that are allowed.
+ *
+ * @return
+ * An indication of whether or not the given character
+ * is in the given character set is returned.
+ */
+ bool IsCharacterInSet(
+ char c,
+ std::initializer_list< char > characterSet
+ );
+
+}
+
+#endif /* URI_IS_CHARACTER_IN_SET_HPP */
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;
+ }
+
+}
diff --git a/src/PercentEncodedCharacterDecoder.hpp b/src/PercentEncodedCharacterDecoder.hpp
new file mode 100644
index 0000000..b3e207d
--- /dev/null
+++ b/src/PercentEncodedCharacterDecoder.hpp
@@ -0,0 +1,85 @@
+#ifndef URI_PERCENT_ENCODED_CHARACTER_DECODER_HPP
+#define URI_PERCENT_ENCODED_CHARACTER_DECODER_HPP
+
+/**
+ * @file PercentEncodedCharacterDecoder.hpp
+ *
+ * This module declares the Uri::PercentEncodedCharacterDecoder class.
+ *
+ * © 2018 by Richard Walters
+ */
+
+#include <memory>
+#include <stddef.h>
+
+namespace Uri {
+
+ /**
+ * This class can take in a percent-encoded character,
+ * decode it, and also detect if there are any problems in the encoding.
+ */
+ class PercentEncodedCharacterDecoder {
+ // Lifecycle management
+ public:
+ ~PercentEncodedCharacterDecoder();
+ PercentEncodedCharacterDecoder(const PercentEncodedCharacterDecoder&) = delete;
+ PercentEncodedCharacterDecoder(PercentEncodedCharacterDecoder&&);
+ PercentEncodedCharacterDecoder& operator=(const PercentEncodedCharacterDecoder&) = delete;
+ PercentEncodedCharacterDecoder& operator=(PercentEncodedCharacterDecoder&&);
+
+ // Methods
+ public:
+ /**
+ * This is the default constructor.
+ */
+ PercentEncodedCharacterDecoder();
+
+ /**
+ * This method inputs the next encoded character.
+ *
+ * @param[in] c
+ * This is the next encoded character to give to the decoder.
+ *
+ * @return
+ * An indication of whether or not the encoded character
+ * was accepted is returned.
+ */
+ bool NextEncodedCharacter(char c);
+
+ /**
+ * This method checks to see if the decoder is done
+ * and has decoded the encoded character.
+ *
+ * @return
+ * An indication of whether or not the decoder is done
+ * and has decoded the encoded character is returned.
+ */
+ bool Done() const;
+
+ /**
+ * This method returns the decoded character, once
+ * the decoder is done.
+ *
+ * @return
+ * The decoded character is returned.
+ */
+ char GetDecodedCharacter() const;
+
+ // Properties
+ private:
+ /**
+ * This is the type of structure that contains the private
+ * properties of the instance. It is defined in the implementation
+ * and declared here to ensure that it is scoped inside the class.
+ */
+ struct Impl;
+
+ /**
+ * This contains the private properties of the instance.
+ */
+ std::unique_ptr< struct Impl > impl_;
+ };
+
+}
+
+#endif /* URI_PERCENT_ENCODED_CHARACTER_DECODER_HPP */
diff --git a/src/Uri.cpp b/src/Uri.cpp
index f122c0a..208297d 100644
--- a/src/Uri.cpp
+++ b/src/Uri.cpp
@@ -6,6 +6,9 @@
* © 2018 by Richard Walters
*/
+#include "IsCharacterInSet.hpp"
+#include "PercentEncodedCharacterDecoder.hpp"
+
#include <functional>
#include <inttypes.h>
#include <memory>
@@ -81,41 +84,6 @@ namespace {
}
/**
- * This function determines whether or not the given character
- * is in the given character set.
- *
- * @param[in] c
- * This is the character to check.
- *
- * @param[in] characterSet
- * This is the set of characters that are allowed.
- *
- * @return
- * An indication of whether or not the given character
- * is in the given character set is returned.
- */
- bool IsCharacterInSet(
- char c,
- std::initializer_list< char > characterSet
- ) {
- for (
- auto charInSet = characterSet.begin();
- charInSet != characterSet.end();
- ++charInSet
- ) {
- const auto first = *charInSet++;
- const auto last = *charInSet;
- if (
- (c >= first)
- && (c <= last)
- ) {
- return true;
- }
- }
- return false;
- }
-
- /**
* This function returns a strategy function that
* may be used with the FailsMatch function to test a scheme
* to make sure it is legal according to the standard.
@@ -133,9 +101,9 @@ namespace {
} else {
bool check;
if (*isFirstCharacter) {
- check = IsCharacterInSet(c, { 'a','z', 'A','Z' });
+ check = Uri::IsCharacterInSet(c, { 'a','z', 'A','Z' });
} else {
- check = IsCharacterInSet(c, { 'a','z', 'A','Z', '0','9', '+','+', '-','-', '.','.' });
+ check = Uri::IsCharacterInSet(c, { 'a','z', 'A','Z', '0','9', '+','+', '-','-', '.','.' });
}
*isFirstCharacter = false;
return check;
@@ -144,93 +112,6 @@ namespace {
}
/**
- * This class can take in a percent-encoded character,
- * decode it, and also detect if there are any problems in the encoding.
- */
- class PercentEncodedCharacterDecoder {
- // Methods
- public:
- /**
- * This method inputs the next encoded character.
- *
- * @param[in] c
- * This is the next encoded character to give to the decoder.
- *
- * @return
- * An indication of whether or not the encoded character
- * was accepted is returned.
- */
- bool NextEncodedCharacter(char c) {
- switch(decoderState_) {
- case 0: { // % ...
- decoderState_ = 1;
- decodedCharacter_ <<= 4;
- if (IsCharacterInSet(c, {'0','9'})) {
- decodedCharacter_ += (int)(c - '0');
- } else if (IsCharacterInSet(c, {'A','F'})) {
- decodedCharacter_ += (int)(c - 'A') + 10;
- } else {
- return false;
- }
- } break;
-
- case 1: { // %[0-9A-F] ...
- decoderState_ = 2;
- decodedCharacter_ <<= 4;
- if (IsCharacterInSet(c, {'0','9'})) {
- decodedCharacter_ += (int)(c - '0');
- } else if (IsCharacterInSet(c, {'A','F'})) {
- decodedCharacter_ += (int)(c - 'A') + 10;
- } else {
- return false;
- }
- } break;
-
- default: break;
- }
- return true;
- }
-
- /**
- * This method checks to see if the decoder is done
- * and has decoded the encoded character.
- *
- * @return
- * An indication of whether or not the decoder is done
- * and has decoded the encoded character is returned.
- */
- bool Done() const {
- return (decoderState_ == 2);
- }
-
- /**
- * This method returns the decoded character, once
- * the decoder is done.
- *
- * @return
- * The decoded character is returned.
- */
- char GetDecodedCharacter() const {
- return (char)decodedCharacter_;
- }
-
- // Properties
- private:
- /**
- * 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;
- };
-
- /**
* This method checks and decodes the given path segment.
*
* @param[in,out] segment
@@ -246,16 +127,16 @@ namespace {
segment.clear();
size_t decoderState = 0;
int decodedCharacter = 0;
- PercentEncodedCharacterDecoder pecDecoder;
+ Uri::PercentEncodedCharacterDecoder pecDecoder;
for (const auto c: originalSegment) {
switch(decoderState) {
case 0: { // default
if (c == '%') {
- pecDecoder = PercentEncodedCharacterDecoder();
+ pecDecoder = Uri::PercentEncodedCharacterDecoder();
decoderState = 1;
} else {
if (
- IsCharacterInSet(
+ Uri::IsCharacterInSet(
c,
{
// unreserved
@@ -309,16 +190,16 @@ namespace {
queryOrFragment.clear();
size_t decoderState = 0;
int decodedCharacter = 0;
- PercentEncodedCharacterDecoder pecDecoder;
+ Uri::PercentEncodedCharacterDecoder pecDecoder;
for (const auto c: originalQueryOrFragment) {
switch(decoderState) {
case 0: { // default
if (c == '%') {
- pecDecoder = PercentEncodedCharacterDecoder();
+ pecDecoder = Uri::PercentEncodedCharacterDecoder();
decoderState = 1;
} else {
if (
- IsCharacterInSet(
+ Uri::IsCharacterInSet(
c,
{
// unreserved