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