blob: fc0e1a13721eeb4d870b37fb9f700d468df4dd7c [file] [log] [blame]
Alexander Afanasyev8828ca62015-07-02 13:40:09 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2013-2015 Regents of the University of California.
4 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20 */
21
22#include "string-helper.hpp"
23#include "../encoding/buffer-stream.hpp"
24#include "../security/cryptopp.hpp"
25
26#include <sstream>
27#include <iomanip>
28
29#include <boost/algorithm/string/trim.hpp>
30
31namespace ndn {
32
33void
34printHex(std::ostream& os, const uint8_t* buffer, size_t length, bool isUpperCase/* = true*/)
35{
36 if (buffer == nullptr || length == 0)
37 return;
38
39 auto newFlags = std::ios::hex;
40 if (isUpperCase) {
41 newFlags |= std::ios::uppercase;
42 }
43 auto oldFlags = os.flags(newFlags);
44 auto oldFill = os.fill('0');
45 for (size_t i = 0; i < length; ++i) {
46 os << std::setw(2) << static_cast<unsigned int>(buffer[i]);
47 }
48 os.fill(oldFill);
49 os.flags(oldFlags);
50}
51
52void
53printHex(std::ostream& os, const Buffer& buffer, bool isUpperCase/* = true*/)
54{
55 return printHex(os, buffer.buf(), buffer.size(), isUpperCase);
56}
57
58std::string
59toHex(const uint8_t* buffer, size_t length, bool isUpperCase/* = true*/)
60{
61 if (buffer == nullptr || length == 0)
62 return "";
63
64 std::ostringstream result;
65 printHex(result, buffer, length, isUpperCase);
66 return result.str();
67}
68
69std::string
70toHex(const Buffer& buffer, bool isUpperCase/* = true*/)
71{
72 return toHex(buffer.buf(), buffer.size(), isUpperCase);
73}
74
75int
76fromHexChar(uint8_t c)
77{
78 if (c >= '0' && c <= '9')
79 return c - '0';
80 else if (c >= 'A' && c <= 'F')
81 return c - 'A' + 0xA;
82 else if (c >= 'a' && c <= 'f')
83 return c - 'a' + 0xA;
84 else
85 return -1;
86}
87
88shared_ptr<const Buffer>
89fromHex(const std::string& hexString)
90{
91 if (hexString.size() % 2 != 0) {
92 throw StringHelperError("Invalid number of characters in the supplied hex string");
93 }
94
95 using namespace CryptoPP;
96
97 OBufferStream os;
98 StringSource(hexString, true, new HexDecoder(new FileSink(os)));
99 shared_ptr<const Buffer> buffer = os.buf();
100
101 if (buffer->size() * 2 != hexString.size()) {
102 throw StringHelperError("The supplied hex string contains non-hex characters");
103 }
104
105 return buffer;
106}
107
108void
109trimLeft(std::string& str)
110{
111 boost::algorithm::trim_left(str);
112}
113
114void
115trimRight(std::string& str)
116{
117 boost::algorithm::trim_right(str);
118}
119
120void
121trim(std::string& str)
122{
123 boost::algorithm::trim(str);
124}
125
126std::string
127unescape(const std::string& str)
128{
129 std::ostringstream result;
130
131 for (size_t i = 0; i < str.size(); ++i) {
132 if (str[i] == '%' && i + 2 < str.size()) {
133 int hi = fromHexChar(str[i + 1]);
134 int lo = fromHexChar(str[i + 2]);
135
136 if (hi < 0 || lo < 0)
137 // Invalid hex characters, so just keep the escaped string.
138 result << str[i] << str[i + 1] << str[i + 2];
139 else
140 result << static_cast<char>((hi << 4) | lo);
141
142 // Skip ahead past the escaped value.
143 i += 2;
144 }
145 else
146 // Just copy through.
147 result << str[i];
148 }
149
150 return result.str();
151}
152
153} // namespace ndn