blob: 3fbda7c364d1ff5fcf4e31d2fe679654fb19b79f [file] [log] [blame]
Jeff Thompsonfa306642013-06-17 15:06:57 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2013, Regents of the University of California
4 * Alexander Afanasyev
5 *
6 * BSD license, See the LICENSE file for more information
7 *
8 * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
9 */
10
11#ifndef NDN_DETAIL_URI_H
12#define NDN_DETAIL_URI_H
13
14#include "ndn-cpp/error.h"
15
16#include <boost/archive/iterators/transform_width.hpp>
17#include <boost/iterator/transform_iterator.hpp>
18
19namespace ndn
20{
21
22namespace detail
23{
24
25static const bool ESCAPE_CHARACTER [256] = {
26 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 26
27 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 53
28 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80
29 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 107
30 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 134
31 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 161
32 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 188
33 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 215
34 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 242
35 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 255
36};
37
38/// @cond include_hidden
39template<class CharType>
40struct hex_from_4_bit
41{
42 typedef CharType result_type;
43 CharType operator () (CharType ch) const
44 {
45 const char lookup_table [16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
46 // cout << "New character: " << (int) ch << " (" << (char) ch << ")" << "\n";
47 BOOST_ASSERT (ch < 16);
48 return lookup_table[static_cast<size_t>(ch)];
49 }
50};
51
52typedef boost::transform_iterator<hex_from_4_bit<std::string::const_iterator::value_type>,
53 boost::archive::iterators::transform_width<std::string::const_iterator, 4, 8, std::string::const_iterator::value_type> > string_from_binary;
54
55
56
57template<class CharType>
58struct hex_to_4_bit
59{
60 typedef CharType result_type;
61 CharType operator () (CharType ch) const
62 {
63 const signed char lookup_table [] = {
64 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
65 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
66 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
67 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
68 -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,
69 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
70 -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,
71 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
72 };
73
74 signed char value = -1;
75 if ((unsigned)ch < 128)
76 value = lookup_table [(unsigned)ch];
77 if (value == -1)
78 boost::throw_exception (error::StringTransform ());
79
80 return value;
81 }
82};
83
84typedef boost::archive::iterators::transform_width<boost::transform_iterator<hex_to_4_bit<std::string::const_iterator::value_type>, std::string::const_iterator>, 8, 4> string_to_binary;
85/// @endcond
86
87} // detail
88
89/**
90 * @brief A helper class to convert to/from URI
91 */
92class Uri
93{
94public:
95 template<class Iterator1, class Iterator2>
96 inline static void
97 fromEscaped (Iterator1 begin, Iterator1 end, Iterator2 inserter)
98 {
99 Iterator1 i = begin;
100 while (i != end)
101 {
102 if (*i == '%')
103 {
104 try
105 {
106 ++i;
107 Iterator1 j = i;
108 advance (i, 2);
109
110 std::copy (detail::string_to_binary (j), detail::string_to_binary (i), inserter);
111 }
112 catch (ndn::error::StringTransform &e)
113 {
114 BOOST_THROW_EXCEPTION (error::Uri ()
115 << error::pos (std::distance (i, begin)));
116 }
117 }
118 else if (!detail::ESCAPE_CHARACTER[static_cast<unsigned char> (*i)])
119 {
120 *inserter = *i;
121 ++inserter; ++i;
122 }
123 else
124 {
125 BOOST_THROW_EXCEPTION (error::Uri ()
126 << error::pos (std::distance (i, begin)));
127 }
128 }
129 }
130
131 template<class Iterator1, class Iterator2>
132 inline static void
133 toEscaped (Iterator1 begin, Iterator1 end, Iterator2 inserter)
134 {
135 const char lookup_table [16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
136
137 for (Iterator1 i = begin; i != end; i++)
138 {
139 if (detail::ESCAPE_CHARACTER[static_cast<unsigned char> (*i)])
140 {
141 *inserter = '%'; ++inserter;
142 *inserter = lookup_table [(*i >> 4) & 0x0F]; ++inserter;
143 *inserter = lookup_table [(*i & 0x0F)]; ++inserter;
144 }
145 else
146 {
147 *inserter = *i; ++inserter;
148 }
149 }
150 }
151};
152
153} // ndn
154
155#endif // NDN_DETAIL_URI_H