blob: 7da812e35e5f095ad80d167f13c14df97bffc616 [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
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 <iostream>
29#include <fstream>
Yingdi Yuf50098d2014-02-26 14:26:29 -080030
Yingdi Yuf50098d2014-02-26 14:26:29 -080031namespace ndn {
32namespace io {
33
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070034class Error : public std::runtime_error
35{
36public:
37 explicit
38 Error(const std::string& what)
39 : std::runtime_error(what)
40 {
41 }
42};
Yingdi Yuf50098d2014-02-26 14:26:29 -080043
Junxiao Shif2515a72016-08-19 02:21:59 +000044/** \brief indicates how a file or stream is encoded
45 */
Yingdi Yuf50098d2014-02-26 14:26:29 -080046enum IoEncoding {
Junxiao Shi4ce0bcf2016-09-03 07:09:03 +000047 /** \brief binary without encoding
48 */
49 NO_ENCODING,
50
51 /** \brief base64 encoding
52 *
53 * \p save() inserts a newline after every 64 characters,
54 * \p load() can accept base64 text with or without newlines
55 */
56 BASE64,
57
58 /** \brief hexadecimal encoding
59 *
60 * \p save() uses uppercase letters A-F, \p load() can accept mixed-case
61 */
62 HEX
Yingdi Yuf50098d2014-02-26 14:26:29 -080063};
64
Junxiao Shi4ce0bcf2016-09-03 07:09:03 +000065constexpr IoEncoding DEPRECATED(BASE_64) = BASE64;
66
Junxiao Shi435bb552016-09-04 03:14:47 +000067namespace detail {
68
69template<typename T>
70static void
71checkInnerError(typename T::Error*)
72{
73 static_assert(std::is_base_of<tlv::Error, typename T::Error>::value,
74 "T::Error, if declared, must inherit from ndn::tlv::Error");
75}
76
77template<typename T>
78static void
79checkInnerError(...)
80{
81 // T::Error is not declared
82}
83
84} // namespace detail
85
Junxiao Shi160701a2016-08-30 11:35:25 +000086/** \brief loads a TLV block from a stream
87 * \return if success, the Block and true
88 * otherwise, a default-constructed Block and false
89 */
90optional<Block>
Junxiao Shi4ce0bcf2016-09-03 07:09:03 +000091loadBlock(std::istream& is, IoEncoding encoding = BASE64);
Junxiao Shi160701a2016-08-30 11:35:25 +000092
Junxiao Shif2515a72016-08-19 02:21:59 +000093/** \brief loads a TLV element from a stream
94 * \tparam T type of TLV element; T must be WireDecodable,
95 * and must have a Error nested type
96 * \return the TLV element, or nullptr if an error occurs
97 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070098template<typename T>
99shared_ptr<T>
Junxiao Shi4ce0bcf2016-09-03 07:09:03 +0000100load(std::istream& is, IoEncoding encoding = BASE64)
Yingdi Yuf50098d2014-02-26 14:26:29 -0800101{
Junxiao Shi435bb552016-09-04 03:14:47 +0000102 BOOST_CONCEPT_ASSERT((WireDecodable<T>));
103 detail::checkInnerError<T>(nullptr);
104
Junxiao Shi160701a2016-08-30 11:35:25 +0000105 optional<Block> block = loadBlock(is, encoding);
106 if (!block) {
Junxiao Shi2d4be252016-08-17 04:29:00 +0000107 return nullptr;
108 }
Junxiao Shif2515a72016-08-19 02:21:59 +0000109
110 try {
Junxiao Shi435bb552016-09-04 03:14:47 +0000111 return make_shared<T>(*block);
Junxiao Shif2515a72016-08-19 02:21:59 +0000112 }
Junxiao Shi435bb552016-09-04 03:14:47 +0000113 catch (const tlv::Error&) {
Junxiao Shi2d4be252016-08-17 04:29:00 +0000114 return nullptr;
115 }
Yingdi Yuf50098d2014-02-26 14:26:29 -0800116}
117
Junxiao Shif2515a72016-08-19 02:21:59 +0000118/** \brief loads a TLV element from a file
119 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700120template<typename T>
121shared_ptr<T>
Junxiao Shi4ce0bcf2016-09-03 07:09:03 +0000122load(const std::string& filename, IoEncoding encoding = BASE64)
Yingdi Yuf50098d2014-02-26 14:26:29 -0800123{
Junxiao Shif2515a72016-08-19 02:21:59 +0000124 std::ifstream is(filename);
Yingdi Yuf50098d2014-02-26 14:26:29 -0800125 return load<T>(is, encoding);
126}
127
Junxiao Shi160701a2016-08-30 11:35:25 +0000128/** \brief saves a TLV block to a stream
129 * \throw Error error during saving
130 */
131void
Junxiao Shi4ce0bcf2016-09-03 07:09:03 +0000132saveBlock(const Block& block, std::ostream& os, IoEncoding encoding = BASE64);
Junxiao Shi160701a2016-08-30 11:35:25 +0000133
Junxiao Shif2515a72016-08-19 02:21:59 +0000134/** \brief saves a TLV element to a stream
135 * \tparam T type of TLV element; T must be WireEncodable,
136 * and must have a Error nested type
137 * \throw Error error during encoding or saving
138 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700139template<typename T>
Yingdi Yuf50098d2014-02-26 14:26:29 -0800140void
Junxiao Shi4ce0bcf2016-09-03 07:09:03 +0000141save(const T& obj, std::ostream& os, IoEncoding encoding = BASE64)
Yingdi Yuf50098d2014-02-26 14:26:29 -0800142{
Junxiao Shi435bb552016-09-04 03:14:47 +0000143 BOOST_CONCEPT_ASSERT((WireEncodable<T>));
144 detail::checkInnerError<T>(nullptr);
145
Junxiao Shif2515a72016-08-19 02:21:59 +0000146 Block block;
Junxiao Shi2d4be252016-08-17 04:29:00 +0000147 try {
Junxiao Shif2515a72016-08-19 02:21:59 +0000148 block = obj.wireEncode();
Junxiao Shi2d4be252016-08-17 04:29:00 +0000149 }
Junxiao Shi2d4be252016-08-17 04:29:00 +0000150 catch (const tlv::Error& e) {
151 BOOST_THROW_EXCEPTION(Error(e.what()));
152 }
Junxiao Shif2515a72016-08-19 02:21:59 +0000153
Junxiao Shi160701a2016-08-30 11:35:25 +0000154 saveBlock(block, os, encoding);
Yingdi Yuf50098d2014-02-26 14:26:29 -0800155}
156
Junxiao Shif2515a72016-08-19 02:21:59 +0000157/** \brief saves a TLV element to a file
158 */
Yingdi Yuf50098d2014-02-26 14:26:29 -0800159template<typename T>
160void
Junxiao Shi4ce0bcf2016-09-03 07:09:03 +0000161save(const T& obj, const std::string& filename, IoEncoding encoding = BASE64)
Yingdi Yuf50098d2014-02-26 14:26:29 -0800162{
Junxiao Shif2515a72016-08-19 02:21:59 +0000163 std::ofstream os(filename);
164 save(obj, os, encoding);
Yingdi Yuf50098d2014-02-26 14:26:29 -0800165}
166
167} // namespace io
168} // namespace ndn
169
170#endif // NDN_UTIL_IO_HPP