blob: d889a765624dde793eeffa9932c4f74ae77d1431 [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
Alexander Afanasyev3898e1b2013-07-27 12:03:17 -070011#if __clang__
12#pragma clang diagnostic push
13#pragma clang diagnostic ignored "-Wreorder"
Alexander Afanasyev46992422013-08-03 17:21:15 -070014#elif __GNUC__
15#pragma GCC diagnostic ignored "-Wreorder"
Alexander Afanasyev3898e1b2013-07-27 12:03:17 -070016#endif
17
Alexander Afanasyev92136012013-07-16 20:36:30 -070018#include "name-component.h"
19
20#include "detail/error.h"
21#include "detail/uri.h"
22
23NDN_NAMESPACE_BEGIN
24
25namespace name {
Alexander Afanasyev38c215d2014-07-11 14:20:58 -070026
Alexander Afanasyev92136012013-07-16 20:36:30 -070027Component::Component ()
28{
29}
30
31Component::Component (const std::string &uri)
32{
Alexander Afanasyevf23a7b62013-07-17 13:22:25 -070033 copy (uri.begin (), uri.end (), std::back_inserter (*this));
Alexander Afanasyev157c9e62013-07-16 20:58:04 -070034}
35
36Component::Component (std::string::const_iterator begin, std::string::const_iterator end)
37{
Alexander Afanasyevf23a7b62013-07-17 13:22:25 -070038 copy (begin, end, std::back_inserter (*this));
Alexander Afanasyev157c9e62013-07-16 20:58:04 -070039}
40
41Component::Component (const void *buf, size_t length)
42{
43 copy (static_cast<const char*> (buf),
44 static_cast<const char*> (buf)+length,
Alexander Afanasyevf23a7b62013-07-17 13:22:25 -070045 std::back_inserter (*this));
Alexander Afanasyev157c9e62013-07-16 20:58:04 -070046}
47
48Component &
49Component::fromUri (const std::string &uri)
50{
Alexander Afanasyev92136012013-07-16 20:36:30 -070051 try
52 {
Alexander Afanasyevf23a7b62013-07-17 13:22:25 -070053 Uri::fromEscaped (uri.begin (), uri.end (), std::back_inserter (*this));
Alexander Afanasyev92136012013-07-16 20:36:30 -070054 }
55 catch (error::Uri &err)
56 {
57 // re-throwing different exception
58 BOOST_THROW_EXCEPTION (error::name::Component ()
59 << error::msg (uri)
60 << error::pos (error::get_pos (err)));
61 }
Alexander Afanasyev157c9e62013-07-16 20:58:04 -070062
63 return *this;
Alexander Afanasyev92136012013-07-16 20:36:30 -070064}
65
Alexander Afanasyev157c9e62013-07-16 20:58:04 -070066Component &
67Component::fromUri (std::string::const_iterator begin, std::string::const_iterator end)
Alexander Afanasyev92136012013-07-16 20:36:30 -070068{
69 try
70 {
Alexander Afanasyevf23a7b62013-07-17 13:22:25 -070071 Uri::fromEscaped (begin, end, std::back_inserter (*this));
Alexander Afanasyev92136012013-07-16 20:36:30 -070072 }
73 catch (error::Uri &err)
74 {
75 // re-throwing different exception
76 BOOST_THROW_EXCEPTION (error::name::Component ()
77 << error::msg (std::string (begin, end))
78 << error::pos (error::get_pos (err)));
79 }
Alexander Afanasyev157c9e62013-07-16 20:58:04 -070080 return *this;
Alexander Afanasyev92136012013-07-16 20:36:30 -070081}
82
83int
84Component::compare (const Component &other) const
85{
86 if (size () < other.size ())
87 return -1;
88
89 if (size () > other.size ())
90 return +1;
91
92 // now we know that sizes are equal
93
94 std::pair<const_iterator, const_iterator> diff = mismatch (begin (), end (), other.begin ());
95 if (diff.first == end ()) // components are actually equal
96 return 0;
97
Alexander Afanasyev38c215d2014-07-11 14:20:58 -070098 return (std::lexicographical_compare (diff.first, end (), diff.second, other.end ())) ? -1 : +1;
Alexander Afanasyev92136012013-07-16 20:36:30 -070099}
100
Alexander Afanasyev157c9e62013-07-16 20:58:04 -0700101Component &
Alexander Afanasyev92136012013-07-16 20:36:30 -0700102Component::fromNumber (uint64_t number)
103{
Alexander Afanasyev92136012013-07-16 20:36:30 -0700104 while (number > 0)
105 {
Alexander Afanasyev157c9e62013-07-16 20:58:04 -0700106 this->push_back (static_cast<unsigned char> (number & 0xFF));
Alexander Afanasyev92136012013-07-16 20:36:30 -0700107 number >>= 8;
108 }
Alexander Afanasyev157c9e62013-07-16 20:58:04 -0700109 std::reverse (this->begin (), this->end ());
110 return *this;
Alexander Afanasyev92136012013-07-16 20:36:30 -0700111}
112
Alexander Afanasyev157c9e62013-07-16 20:58:04 -0700113Component &
Alexander Afanasyev92136012013-07-16 20:36:30 -0700114Component::fromNumberWithMarker (uint64_t number, unsigned char marker)
115{
Alexander Afanasyev157c9e62013-07-16 20:58:04 -0700116 this->push_back (marker);
Alexander Afanasyev92136012013-07-16 20:36:30 -0700117
118 while (number > 0)
119 {
Alexander Afanasyev157c9e62013-07-16 20:58:04 -0700120 this->push_back (static_cast<unsigned char> (number & 0xFF));
Alexander Afanasyev92136012013-07-16 20:36:30 -0700121 number >>= 8;
122 }
123
Alexander Afanasyev157c9e62013-07-16 20:58:04 -0700124 std::reverse (this->begin () + 1, this->end ());
125 return *this;
Alexander Afanasyev92136012013-07-16 20:36:30 -0700126}
127
128std::string
129Component::toBlob () const
130{
131 return std::string (begin (), end ());
132}
133
134void
135Component::toBlob (std::ostream &os) const
136{
137 os.write (buf (), size ());
138}
139
140std::string
141Component::toUri () const
142{
143 std::ostringstream os;
144 toUri (os);
Alexander Afanasyev38c215d2014-07-11 14:20:58 -0700145 return os.str ();
Alexander Afanasyev92136012013-07-16 20:36:30 -0700146}
147
148void
149Component::toUri (std::ostream &os) const
150{
Alexander Afanasyev38c215d2014-07-11 14:20:58 -0700151 const uint8_t* valuePtr = reinterpret_cast<const uint8_t*>(buf());
152 size_t valueSize = size();
153
154 bool gotNonDot = false;
155 for (unsigned i = 0; i < valueSize; ++i) {
156 if (valuePtr[i] != 0x2e) {
157 gotNonDot = true;
158 break;
159 }
160 }
161 if (!gotNonDot) {
162 // Special case for component of zero or more periods. Add 3 periods.
163 os << "...";
164 for (size_t i = 0; i < valueSize; ++i)
165 os << '.';
166 }
167 else {
168 // In case we need to escape, set to upper case hex and save the previous flags.
169 std::ios::fmtflags saveFlags = os.flags(std::ios::hex | std::ios::uppercase);
170
171 for (size_t i = 0; i < valueSize; ++i) {
172 uint8_t x = valuePtr[i];
173 // Check for 0-9, A-Z, a-z, (+), (-), (.), (_)
174 if ((x >= 0x30 && x <= 0x39) || (x >= 0x41 && x <= 0x5a) ||
175 (x >= 0x61 && x <= 0x7a) || x == 0x2b || x == 0x2d ||
176 x == 0x2e || x == 0x5f)
177 os << x;
178 else {
179 os << '%';
180 if (x < 16)
181 os << '0';
182 os << static_cast<unsigned int>(x);
183 }
184 }
185
186 // Restore.
187 os.flags(saveFlags);
188 }
Alexander Afanasyev92136012013-07-16 20:36:30 -0700189}
190
191uint64_t
192Component::toNumber () const
193{
194 uint64_t ret = 0;
195 for (const_iterator i = begin (); i != end (); i++)
196 {
197 ret <<= 8;
198 ret |= static_cast<unsigned char> (*i);
199 }
200 return ret;
201}
202
203uint64_t
204Component::toNumberWithMarker (unsigned char marker) const
205{
206 if (empty () ||
207 static_cast<unsigned char> (*(begin ())) != marker)
208 {
209 BOOST_THROW_EXCEPTION (error::name::Component ()
210 << error::msg ("Name component does not have required marker [" + toUri () + "]"));
211 }
212
213 uint64_t ret = 0;
214 for (const_iterator i = begin () + 1; i != end (); i++)
215 {
216 ret <<= 8;
217 ret |= static_cast<unsigned char> (*i);
218 }
219 return ret;
220}
221
222} // name
223
224NDN_NAMESPACE_END