Created
May 20, 2014 07:24
-
-
Save mindw/20814408ea03b1736a6c to your computer and use it in GitHub Desktop.
Escape a string for use in any FS using C++11
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <assert.h> | |
| #include <string> | |
| #include <time.h> | |
| #include <stdlib.h> | |
| #include <vector> | |
| std::string UriDecode(const std::string & src) | |
| { | |
| // Note from RFC1630: "Sequences which start with a percent sign | |
| // but are not followed by two hexadecimal characters (0-9, A-F) are reserved | |
| // for future extension" | |
| std::string out; | |
| out.reserve(src.length()); | |
| auto inserter = std::back_insert_iterator<std::string>(out); | |
| for (auto iter = src.begin(); iter != src.end(); ++iter) | |
| { | |
| if (*iter == '%') | |
| { | |
| ++iter; | |
| std::string charCode(iter , iter + 2); | |
| char ret = std::stoi(charCode, NULL, 16); | |
| inserter = ret; | |
| iter += 1; | |
| } | |
| else | |
| { | |
| inserter = *iter; | |
| } | |
| } | |
| return out; | |
| } | |
| // Only alphanum is safe. | |
| static const char SAFE[256] = | |
| { | |
| /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ | |
| /* 0 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, | |
| /* 1 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, | |
| /* 2 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, | |
| /* 3 */ 1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0, | |
| /* 4 */ 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, | |
| /* 5 */ 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, | |
| /* 6 */ 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, | |
| /* 7 */ 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, | |
| /* 8 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, | |
| /* 9 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, | |
| /* A */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, | |
| /* B */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, | |
| /* C */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, | |
| /* D */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, | |
| /* E */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, | |
| /* F */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 | |
| }; | |
| #include <iterator> | |
| std::string UriEncode(const std::string & src) | |
| { | |
| static const char DEC2HEX[] = "0123456789ABCDEF"; | |
| std::string out; | |
| out.reserve(src.length()); | |
| auto inserter = std::back_insert_iterator<std::string>(out); | |
| for (auto iter = src.begin(); iter != src.end(); ++iter) | |
| { | |
| if (SAFE[*iter]) | |
| { | |
| inserter = *iter; | |
| } | |
| else | |
| { | |
| inserter = '%'; | |
| inserter = DEC2HEX[(*iter >> 4) & 0xF]; | |
| inserter = DEC2HEX[*iter & 0xF]; | |
| } | |
| } | |
| return out; | |
| } | |
| void encodeDecodeTest(void) | |
| { | |
| TEST_ASSERT_EQUAL_STRING(UriEncode("ABC").c_str(), "ABC"); | |
| std::vector<char> v = {0, 1, 2}; | |
| const std::string ORG(v.begin(), v.end()); | |
| const std::string ENC("%00%01%02"); | |
| TEST_ASSERT_EQUAL_STRING(UriEncode(ORG).c_str(), ENC.c_str()); | |
| TEST_ASSERT_EQUAL_STRING(UriDecode(ENC).c_str(), ORG.c_str()); | |
| TEST_ASSERT_EQUAL_STRING(UriEncode("\xFF").c_str(), "%FF"); | |
| TEST_ASSERT_EQUAL_STRING(UriDecode("%FF").c_str(), "\xFF"); | |
| TEST_ASSERT_EQUAL_STRING(UriDecode("%ff").c_str(), "\xFF"); | |
| // unsafe chars test, RFC1738 | |
| const std::string UNSAFE(" <>#{}|\\^~[]`"); | |
| std::string sUnsafeEnc = UriEncode(UNSAFE); | |
| TEST_ASSERT_EQUAL(std::string::npos, sUnsafeEnc.find_first_of(UNSAFE)); | |
| TEST_ASSERT_EQUAL_STRING(UriDecode(sUnsafeEnc).c_str(), UNSAFE.c_str()); | |
| // random test | |
| const int MAX_LEN = 128; | |
| char a[MAX_LEN]; | |
| srand((unsigned)time(NULL)); | |
| for (int i = 0; i < 100; i++) | |
| { | |
| for (int j = 0; j < MAX_LEN; j++) | |
| a[j] = rand() % (1 << 8); | |
| int nLen = rand() % MAX_LEN; | |
| std::string sOrg(a, nLen); | |
| std::string sEnc = UriEncode(sOrg); | |
| TEST_ASSERT_EQUAL_STRING(sOrg.c_str(), UriDecode(sEnc).c_str()); | |
| } | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment