blob: 5d457fc5fea87950b8f9ef011427e5da6578b138 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesaventoa84f4642017-08-23 16:14:51 -04002/*
Junxiao Shi68b53852018-07-25 13:56:38 -06003 * Copyright (c) 2013-2018 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
Junxiao Shi435bb552016-09-04 03:14:47 +000025#include "concepts.hpp"
Yingdi Yuf50098d2014-02-26 14:26:29 -080026#include "../encoding/block.hpp"
27
Yingdi Yuf50098d2014-02-26 14:26:29 -080028#include <fstream>
Yingdi Yuf50098d2014-02-26 14:26:29 -080029
Yingdi Yuf50098d2014-02-26 14:26:29 -080030namespace ndn {
31namespace io {
32
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070033class Error : public std::runtime_error
34{
35public:
Junxiao Shi68b53852018-07-25 13:56:38 -060036 using std::runtime_error::runtime_error;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070037};
Yingdi Yuf50098d2014-02-26 14:26:29 -080038
Junxiao Shif2515a72016-08-19 02:21:59 +000039/** \brief indicates how a file or stream is encoded
40 */
Yingdi Yuf50098d2014-02-26 14:26:29 -080041enum IoEncoding {
Junxiao Shi4ce0bcf2016-09-03 07:09:03 +000042 /** \brief binary without encoding
43 */
44 NO_ENCODING,
45
46 /** \brief base64 encoding
47 *
48 * \p save() inserts a newline after every 64 characters,
49 * \p load() can accept base64 text with or without newlines
50 */
51 BASE64,
52
53 /** \brief hexadecimal encoding
54 *
55 * \p save() uses uppercase letters A-F, \p load() can accept mixed-case
56 */
57 HEX
Yingdi Yuf50098d2014-02-26 14:26:29 -080058};
59
Junxiao Shi435bb552016-09-04 03:14:47 +000060namespace detail {
61
62template<typename T>
63static void
64checkInnerError(typename T::Error*)
65{
66 static_assert(std::is_base_of<tlv::Error, typename T::Error>::value,
67 "T::Error, if declared, must inherit from ndn::tlv::Error");
68}
69
70template<typename T>
71static void
72checkInnerError(...)
73{
74 // T::Error is not declared
75}
76
77} // namespace detail
78
Junxiao Shi160701a2016-08-30 11:35:25 +000079/** \brief loads a TLV block from a stream
80 * \return if success, the Block and true
81 * otherwise, a default-constructed Block and false
82 */
83optional<Block>
Junxiao Shi4ce0bcf2016-09-03 07:09:03 +000084loadBlock(std::istream& is, IoEncoding encoding = BASE64);
Junxiao Shi160701a2016-08-30 11:35:25 +000085
Junxiao Shif2515a72016-08-19 02:21:59 +000086/** \brief loads a TLV element from a stream
87 * \tparam T type of TLV element; T must be WireDecodable,
88 * and must have a Error nested type
89 * \return the TLV element, or nullptr if an error occurs
90 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070091template<typename T>
92shared_ptr<T>
Junxiao Shi4ce0bcf2016-09-03 07:09:03 +000093load(std::istream& is, IoEncoding encoding = BASE64)
Yingdi Yuf50098d2014-02-26 14:26:29 -080094{
Junxiao Shi435bb552016-09-04 03:14:47 +000095 BOOST_CONCEPT_ASSERT((WireDecodable<T>));
96 detail::checkInnerError<T>(nullptr);
97
Junxiao Shi160701a2016-08-30 11:35:25 +000098 optional<Block> block = loadBlock(is, encoding);
99 if (!block) {
Junxiao Shi2d4be252016-08-17 04:29:00 +0000100 return nullptr;
101 }
Junxiao Shif2515a72016-08-19 02:21:59 +0000102
103 try {
Junxiao Shi435bb552016-09-04 03:14:47 +0000104 return make_shared<T>(*block);
Junxiao Shif2515a72016-08-19 02:21:59 +0000105 }
Junxiao Shi435bb552016-09-04 03:14:47 +0000106 catch (const tlv::Error&) {
Junxiao Shi2d4be252016-08-17 04:29:00 +0000107 return nullptr;
108 }
Yingdi Yuf50098d2014-02-26 14:26:29 -0800109}
110
Junxiao Shif2515a72016-08-19 02:21:59 +0000111/** \brief loads a TLV element from a file
112 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700113template<typename T>
114shared_ptr<T>
Junxiao Shi4ce0bcf2016-09-03 07:09:03 +0000115load(const std::string& filename, IoEncoding encoding = BASE64)
Yingdi Yuf50098d2014-02-26 14:26:29 -0800116{
Junxiao Shif2515a72016-08-19 02:21:59 +0000117 std::ifstream is(filename);
Yingdi Yuf50098d2014-02-26 14:26:29 -0800118 return load<T>(is, encoding);
119}
120
Junxiao Shi160701a2016-08-30 11:35:25 +0000121/** \brief saves a TLV block to a stream
122 * \throw Error error during saving
123 */
124void
Junxiao Shi4ce0bcf2016-09-03 07:09:03 +0000125saveBlock(const Block& block, std::ostream& os, IoEncoding encoding = BASE64);
Junxiao Shi160701a2016-08-30 11:35:25 +0000126
Junxiao Shif2515a72016-08-19 02:21:59 +0000127/** \brief saves a TLV element to a stream
128 * \tparam T type of TLV element; T must be WireEncodable,
129 * and must have a Error nested type
130 * \throw Error error during encoding or saving
131 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700132template<typename T>
Yingdi Yuf50098d2014-02-26 14:26:29 -0800133void
Junxiao Shi4ce0bcf2016-09-03 07:09:03 +0000134save(const T& obj, std::ostream& os, IoEncoding encoding = BASE64)
Yingdi Yuf50098d2014-02-26 14:26:29 -0800135{
Junxiao Shi435bb552016-09-04 03:14:47 +0000136 BOOST_CONCEPT_ASSERT((WireEncodable<T>));
137 detail::checkInnerError<T>(nullptr);
138
Junxiao Shif2515a72016-08-19 02:21:59 +0000139 Block block;
Junxiao Shi2d4be252016-08-17 04:29:00 +0000140 try {
Junxiao Shif2515a72016-08-19 02:21:59 +0000141 block = obj.wireEncode();
Junxiao Shi2d4be252016-08-17 04:29:00 +0000142 }
Junxiao Shi2d4be252016-08-17 04:29:00 +0000143 catch (const tlv::Error& e) {
144 BOOST_THROW_EXCEPTION(Error(e.what()));
145 }
Junxiao Shif2515a72016-08-19 02:21:59 +0000146
Junxiao Shi160701a2016-08-30 11:35:25 +0000147 saveBlock(block, os, encoding);
Yingdi Yuf50098d2014-02-26 14:26:29 -0800148}
149
Junxiao Shif2515a72016-08-19 02:21:59 +0000150/** \brief saves a TLV element to a file
151 */
Yingdi Yuf50098d2014-02-26 14:26:29 -0800152template<typename T>
153void
Junxiao Shi4ce0bcf2016-09-03 07:09:03 +0000154save(const T& obj, const std::string& filename, IoEncoding encoding = BASE64)
Yingdi Yuf50098d2014-02-26 14:26:29 -0800155{
Junxiao Shif2515a72016-08-19 02:21:59 +0000156 std::ofstream os(filename);
157 save(obj, os, encoding);
Yingdi Yuf50098d2014-02-26 14:26:29 -0800158}
159
160} // namespace io
161} // namespace ndn
162
163#endif // NDN_UTIL_IO_HPP