diff options
author | Richard Walters <rwalters@digitalstirling.com> | 2018-07-01 16:08:20 -0700 |
---|---|---|
committer | Richard Walters <rwalters@digitalstirling.com> | 2018-07-01 16:08:20 -0700 |
commit | cdc3f449812d0d45a3ea271636d669eb05ba3751 (patch) | |
tree | 1f46bea16d444b84a84843aed8bc9a0ebcadced5 | |
parent | 0a991ade05f2e98b412301cb47cb6112a374ee8c (diff) |
Refactoring
* Extract IsCharacterInSet to its own module.
* Extract PercentEncodedCharacterDecoder to its own module.
-rw-r--r-- | CMakeLists.txt | 4 | ||||
-rw-r--r-- | src/IsCharacterInSet.cpp | 35 | ||||
-rw-r--r-- | src/IsCharacterInSet.hpp | 37 | ||||
-rw-r--r-- | src/PercentEncodedCharacterDecoder.cpp | 78 | ||||
-rw-r--r-- | src/PercentEncodedCharacterDecoder.hpp | 85 | ||||
-rw-r--r-- | src/Uri.cpp | 141 |
6 files changed, 250 insertions, 130 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index bfd19d7..ab5ca79 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,9 +7,13 @@ set(This Uri) set(Headers include/Uri/Uri.hpp + src/IsCharacterInSet.hpp + src/PercentEncodedCharacterDecoder.hpp ) set(Sources + src/IsCharacterInSet.cpp + src/PercentEncodedCharacterDecoder.cpp src/Uri.cpp ) 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 |