decode.ipp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. //
  2. // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // Official repository: https://github.com/boostorg/url
  8. //
  9. #ifndef BOOST_URL_DETAIL_IMPL_DECODE_IPP
  10. #define BOOST_URL_DETAIL_IMPL_DECODE_IPP
  11. #include <boost/url/detail/decode.hpp>
  12. #include <boost/url/grammar/charset.hpp>
  13. #include <memory>
  14. namespace boost {
  15. namespace urls {
  16. namespace detail {
  17. char
  18. decode_one(
  19. char const* const it) noexcept
  20. {
  21. auto d0 = grammar::hexdig_value(it[0]);
  22. auto d1 = grammar::hexdig_value(it[1]);
  23. return static_cast<char>(
  24. ((static_cast<
  25. unsigned char>(d0) << 4) +
  26. (static_cast<
  27. unsigned char>(d1))));
  28. }
  29. std::size_t
  30. decode_bytes_unsafe(
  31. string_view s) noexcept
  32. {
  33. auto p = s.begin();
  34. auto const end = s.end();
  35. std::size_t dn = 0;
  36. if(s.size() >= 3)
  37. {
  38. auto const safe_end = end - 2;
  39. while(p < safe_end)
  40. {
  41. if(*p != '%')
  42. p += 1;
  43. else
  44. p += 3;
  45. ++dn;
  46. }
  47. }
  48. dn += end - p;
  49. return dn;
  50. }
  51. std::size_t
  52. decode_unsafe(
  53. char* const dest0,
  54. char const* end,
  55. string_view s,
  56. encoding_opts opt) noexcept
  57. {
  58. auto it = s.data();
  59. auto const last = it + s.size();
  60. auto dest = dest0;
  61. if(opt.space_as_plus)
  62. {
  63. while(it != last)
  64. {
  65. if(dest == end)
  66. {
  67. // dest too small
  68. return dest - dest0;
  69. }
  70. if(*it == '+')
  71. {
  72. // plus to space
  73. *dest++ = ' ';
  74. ++it;
  75. continue;
  76. }
  77. if(*it == '%')
  78. {
  79. // escaped
  80. ++it;
  81. if(last - it < 2)
  82. {
  83. // missing input,
  84. // initialize output
  85. std::memset(dest,
  86. 0, end - dest);
  87. return dest - dest0;
  88. }
  89. *dest++ = decode_one(it);
  90. it += 2;
  91. continue;
  92. }
  93. // unescaped
  94. *dest++ = *it++;
  95. }
  96. return dest - dest0;
  97. }
  98. while(it != last)
  99. {
  100. if(dest == end)
  101. {
  102. // dest too small
  103. return dest - dest0;
  104. }
  105. if(*it == '%')
  106. {
  107. // escaped
  108. ++it;
  109. if(last - it < 2)
  110. {
  111. // missing input,
  112. // initialize output
  113. std::memset(dest,
  114. 0, end - dest);
  115. return dest - dest0;
  116. }
  117. *dest++ = decode_one(it);
  118. it += 2;
  119. continue;
  120. }
  121. // unescaped
  122. *dest++ = *it++;
  123. }
  124. return dest - dest0;
  125. }
  126. } // detail
  127. } // urls
  128. } // boost
  129. #endif