blob: 7af2a9e0b53d2489b8e18717bb74ef2b5ac320a3 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Yingdi Yuf50098d2014-02-26 14:26:29 -08002/**
Junxiao Shi2d4be252016-08-17 04:29:00 +00003 * Copyright (c) 2013-2016 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * 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.
Yingdi Yuf50098d2014-02-26 14:26:29 -080020 */
21
22#ifndef NDN_UTIL_IO_HPP
23#define NDN_UTIL_IO_HPP
24
Yingdi Yuf50098d2014-02-26 14:26:29 -080025#include "../encoding/block.hpp"
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070026#include "../encoding/buffer-stream.hpp"
Junxiao Shif2515a72016-08-19 02:21:59 +000027#include "../security/transform.hpp"
Yingdi Yuf50098d2014-02-26 14:26:29 -080028
Yingdi Yuf50098d2014-02-26 14:26:29 -080029#include <iostream>
30#include <fstream>
Yingdi Yuf50098d2014-02-26 14:26:29 -080031
Yingdi Yuf50098d2014-02-26 14:26:29 -080032namespace ndn {
33namespace io {
34
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070035class Error : public std::runtime_error
36{
37public:
38 explicit
39 Error(const std::string& what)
40 : std::runtime_error(what)
41 {
42 }
43};
Yingdi Yuf50098d2014-02-26 14:26:29 -080044
Junxiao Shif2515a72016-08-19 02:21:59 +000045/** \brief indicates how a file or stream is encoded
46 */
Yingdi Yuf50098d2014-02-26 14:26:29 -080047enum IoEncoding {
Junxiao Shif2515a72016-08-19 02:21:59 +000048 NO_ENCODING, ///< binary without encoding
49 BASE_64, ///< base64 encoding
50 HEX ///< uppercase hexadecimal encoding
Yingdi Yuf50098d2014-02-26 14:26:29 -080051};
52
Junxiao Shif2515a72016-08-19 02:21:59 +000053/** \brief loads a TLV element from a stream
54 * \tparam T type of TLV element; T must be WireDecodable,
55 * and must have a Error nested type
56 * \return the TLV element, or nullptr if an error occurs
57 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070058template<typename T>
59shared_ptr<T>
Yingdi Yuf50098d2014-02-26 14:26:29 -080060load(std::istream& is, IoEncoding encoding = BASE_64)
61{
Junxiao Shif2515a72016-08-19 02:21:59 +000062 OBufferStream os;
Junxiao Shi2d4be252016-08-17 04:29:00 +000063 try {
Junxiao Shif2515a72016-08-19 02:21:59 +000064 namespace t = ndn::security::transform;
Junxiao Shi2d4be252016-08-17 04:29:00 +000065 switch (encoding) {
Junxiao Shif2515a72016-08-19 02:21:59 +000066 case NO_ENCODING:
67 t::streamSource(is) >> t::streamSink(os);
Junxiao Shi2d4be252016-08-17 04:29:00 +000068 break;
Junxiao Shif2515a72016-08-19 02:21:59 +000069 case BASE_64:
70 t::streamSource(is) >> t::base64Decode() >> t::streamSink(os);
Junxiao Shi2d4be252016-08-17 04:29:00 +000071 break;
Junxiao Shif2515a72016-08-19 02:21:59 +000072 case HEX:
73 t::streamSource(is) >> t::hexDecode() >> t::streamSink(os);
Junxiao Shi2d4be252016-08-17 04:29:00 +000074 break;
Junxiao Shi2d4be252016-08-17 04:29:00 +000075 default:
76 return nullptr;
77 }
Junxiao Shi2d4be252016-08-17 04:29:00 +000078 }
Junxiao Shif2515a72016-08-19 02:21:59 +000079 catch (const ndn::security::transform::Error&) {
Junxiao Shi2d4be252016-08-17 04:29:00 +000080 return nullptr;
81 }
Junxiao Shif2515a72016-08-19 02:21:59 +000082
83 try {
84 auto obj = make_shared<T>();
85 obj->wireDecode(Block(os.buf()));
86 return obj;
87 }
88 catch (const typename T::Error& e) {
Junxiao Shi2d4be252016-08-17 04:29:00 +000089 return nullptr;
90 }
91 catch (const tlv::Error& e) {
92 return nullptr;
93 }
Yingdi Yuf50098d2014-02-26 14:26:29 -080094}
95
Junxiao Shif2515a72016-08-19 02:21:59 +000096/** \brief loads a TLV element from a file
97 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070098template<typename T>
99shared_ptr<T>
Junxiao Shif2515a72016-08-19 02:21:59 +0000100load(const std::string& filename, IoEncoding encoding = BASE_64)
Yingdi Yuf50098d2014-02-26 14:26:29 -0800101{
Junxiao Shif2515a72016-08-19 02:21:59 +0000102 std::ifstream is(filename);
Yingdi Yuf50098d2014-02-26 14:26:29 -0800103 return load<T>(is, encoding);
104}
105
Junxiao Shif2515a72016-08-19 02:21:59 +0000106/** \brief saves a TLV element to a stream
107 * \tparam T type of TLV element; T must be WireEncodable,
108 * and must have a Error nested type
109 * \throw Error error during encoding or saving
110 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700111template<typename T>
Yingdi Yuf50098d2014-02-26 14:26:29 -0800112void
Junxiao Shif2515a72016-08-19 02:21:59 +0000113save(const T& obj, std::ostream& os, IoEncoding encoding = BASE_64)
Yingdi Yuf50098d2014-02-26 14:26:29 -0800114{
Junxiao Shif2515a72016-08-19 02:21:59 +0000115 Block block;
Junxiao Shi2d4be252016-08-17 04:29:00 +0000116 try {
Junxiao Shif2515a72016-08-19 02:21:59 +0000117 block = obj.wireEncode();
Junxiao Shi2d4be252016-08-17 04:29:00 +0000118 }
Junxiao Shif2515a72016-08-19 02:21:59 +0000119 catch (const typename T::Error& e) {
Junxiao Shi2d4be252016-08-17 04:29:00 +0000120 BOOST_THROW_EXCEPTION(Error(e.what()));
121 }
122 catch (const tlv::Error& e) {
123 BOOST_THROW_EXCEPTION(Error(e.what()));
124 }
Junxiao Shif2515a72016-08-19 02:21:59 +0000125
126 try {
127 namespace t = ndn::security::transform;
128 switch (encoding) {
129 case NO_ENCODING:
130 t::bufferSource(block.wire(), block.size()) >> t::streamSink(os);
131 break;
132 case BASE_64:
133 t::bufferSource(block.wire(), block.size()) >> t::base64Encode() >> t::streamSink(os);
134 break;
135 case HEX:
136 t::bufferSource(block.wire(), block.size()) >> t::hexEncode(true) >> t::streamSink(os);
137 break;
138 default:
139 BOOST_THROW_EXCEPTION(Error("unrecognized IoEncoding"));
140 }
141 }
142 catch (const ndn::security::transform::Error& e) {
143 BOOST_THROW_EXCEPTION(Error(e.what()));
144 }
Yingdi Yuf50098d2014-02-26 14:26:29 -0800145}
146
Junxiao Shif2515a72016-08-19 02:21:59 +0000147/** \brief saves a TLV element to a file
148 */
Yingdi Yuf50098d2014-02-26 14:26:29 -0800149template<typename T>
150void
Junxiao Shif2515a72016-08-19 02:21:59 +0000151save(const T& obj, const std::string& filename, IoEncoding encoding = BASE_64)
Yingdi Yuf50098d2014-02-26 14:26:29 -0800152{
Junxiao Shif2515a72016-08-19 02:21:59 +0000153 std::ofstream os(filename);
154 save(obj, os, encoding);
Yingdi Yuf50098d2014-02-26 14:26:29 -0800155}
156
157} // namespace io
158} // namespace ndn
159
160#endif // NDN_UTIL_IO_HPP