blob: 16064b0f50bbe4b41ad3390d9660090ae66512f7 [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) {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -070092 BOOST_THROW_EXCEPTION(StringHelperError("Invalid number of characters in the supplied hex "
93 "string"));
Alexander Afanasyev8828ca62015-07-02 13:40:09 -070094 }
95
96 using namespace CryptoPP;
97
98 OBufferStream os;
99 StringSource(hexString, true, new HexDecoder(new FileSink(os)));
100 shared_ptr<const Buffer> buffer = os.buf();
101
102 if (buffer->size() * 2 != hexString.size()) {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700103 BOOST_THROW_EXCEPTION(StringHelperError("The supplied hex string contains non-hex characters"));
Alexander Afanasyev8828ca62015-07-02 13:40:09 -0700104 }
105
106 return buffer;
107}
108
109void
110trimLeft(std::string& str)
111{
112 boost::algorithm::trim_left(str);
113}
114
115void
116trimRight(std::string& str)
117{
118 boost::algorithm::trim_right(str);
119}
120
121void
122trim(std::string& str)
123{
124 boost::algorithm::trim(str);
125}
126
127std::string
128unescape(const std::string& str)
129{
130 std::ostringstream result;
131
132 for (size_t i = 0; i < str.size(); ++i) {
133 if (str[i] == '%' && i + 2 < str.size()) {
134 int hi = fromHexChar(str[i + 1]);
135 int lo = fromHexChar(str[i + 2]);
136
137 if (hi < 0 || lo < 0)
138 // Invalid hex characters, so just keep the escaped string.
139 result << str[i] << str[i + 1] << str[i + 2];
140 else
141 result << static_cast<char>((hi << 4) | lo);
142
143 // Skip ahead past the escaped value.
144 i += 2;
145 }
146 else
147 // Just copy through.
148 result << str[i];
149 }
150
151 return result.str();
152}
153
154} // namespace ndn