blob: cad5a26083284a22ee677df4c7f47079c62f43d5 [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/**
Alexander Afanasyeve6835fe2017-01-19 20:05:01 -08003 * Copyright (c) 2013-2017 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 Shi435bb552016-09-04 03:14:47 +000065namespace detail {
66
67template<typename T>
68static void
69checkInnerError(typename T::Error*)
70{
71 static_assert(std::is_base_of<tlv::Error, typename T::Error>::value,
72 "T::Error, if declared, must inherit from ndn::tlv::Error");
73}
74
75template<typename T>
76static void
77checkInnerError(...)
78{
79 // T::Error is not declared
80}
81
82} // namespace detail
83
Junxiao Shi160701a2016-08-30 11:35:25 +000084/** \brief loads a TLV block from a stream
85 * \return if success, the Block and true
86 * otherwise, a default-constructed Block and false
87 */
88optional<Block>
Junxiao Shi4ce0bcf2016-09-03 07:09:03 +000089loadBlock(std::istream& is, IoEncoding encoding = BASE64);
Junxiao Shi160701a2016-08-30 11:35:25 +000090
Junxiao Shif2515a72016-08-19 02:21:59 +000091/** \brief loads a TLV element from a stream
92 * \tparam T type of TLV element; T must be WireDecodable,
93 * and must have a Error nested type
94 * \return the TLV element, or nullptr if an error occurs
95 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070096template<typename T>
97shared_ptr<T>
Junxiao Shi4ce0bcf2016-09-03 07:09:03 +000098load(std::istream& is, IoEncoding encoding = BASE64)
Yingdi Yuf50098d2014-02-26 14:26:29 -080099{
Junxiao Shi435bb552016-09-04 03:14:47 +0000100 BOOST_CONCEPT_ASSERT((WireDecodable<T>));
101 detail::checkInnerError<T>(nullptr);
102
Junxiao Shi160701a2016-08-30 11:35:25 +0000103 optional<Block> block = loadBlock(is, encoding);
104 if (!block) {
Junxiao Shi2d4be252016-08-17 04:29:00 +0000105 return nullptr;
106 }
Junxiao Shif2515a72016-08-19 02:21:59 +0000107
108 try {
Junxiao Shi435bb552016-09-04 03:14:47 +0000109 return make_shared<T>(*block);
Junxiao Shif2515a72016-08-19 02:21:59 +0000110 }
Junxiao Shi435bb552016-09-04 03:14:47 +0000111 catch (const tlv::Error&) {
Junxiao Shi2d4be252016-08-17 04:29:00 +0000112 return nullptr;
113 }
Yingdi Yuf50098d2014-02-26 14:26:29 -0800114}
115
Junxiao Shif2515a72016-08-19 02:21:59 +0000116/** \brief loads a TLV element from a file
117 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700118template<typename T>
119shared_ptr<T>
Junxiao Shi4ce0bcf2016-09-03 07:09:03 +0000120load(const std::string& filename, IoEncoding encoding = BASE64)
Yingdi Yuf50098d2014-02-26 14:26:29 -0800121{
Junxiao Shif2515a72016-08-19 02:21:59 +0000122 std::ifstream is(filename);
Yingdi Yuf50098d2014-02-26 14:26:29 -0800123 return load<T>(is, encoding);
124}
125
Junxiao Shi160701a2016-08-30 11:35:25 +0000126/** \brief saves a TLV block to a stream
127 * \throw Error error during saving
128 */
129void
Junxiao Shi4ce0bcf2016-09-03 07:09:03 +0000130saveBlock(const Block& block, std::ostream& os, IoEncoding encoding = BASE64);
Junxiao Shi160701a2016-08-30 11:35:25 +0000131
Junxiao Shif2515a72016-08-19 02:21:59 +0000132/** \brief saves a TLV element to a stream
133 * \tparam T type of TLV element; T must be WireEncodable,
134 * and must have a Error nested type
135 * \throw Error error during encoding or saving
136 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700137template<typename T>
Yingdi Yuf50098d2014-02-26 14:26:29 -0800138void
Junxiao Shi4ce0bcf2016-09-03 07:09:03 +0000139save(const T& obj, std::ostream& os, IoEncoding encoding = BASE64)
Yingdi Yuf50098d2014-02-26 14:26:29 -0800140{
Junxiao Shi435bb552016-09-04 03:14:47 +0000141 BOOST_CONCEPT_ASSERT((WireEncodable<T>));
142 detail::checkInnerError<T>(nullptr);
143
Junxiao Shif2515a72016-08-19 02:21:59 +0000144 Block block;
Junxiao Shi2d4be252016-08-17 04:29:00 +0000145 try {
Junxiao Shif2515a72016-08-19 02:21:59 +0000146 block = obj.wireEncode();
Junxiao Shi2d4be252016-08-17 04:29:00 +0000147 }
Junxiao Shi2d4be252016-08-17 04:29:00 +0000148 catch (const tlv::Error& e) {
149 BOOST_THROW_EXCEPTION(Error(e.what()));
150 }
Junxiao Shif2515a72016-08-19 02:21:59 +0000151
Junxiao Shi160701a2016-08-30 11:35:25 +0000152 saveBlock(block, os, encoding);
Yingdi Yuf50098d2014-02-26 14:26:29 -0800153}
154
Junxiao Shif2515a72016-08-19 02:21:59 +0000155/** \brief saves a TLV element to a file
156 */
Yingdi Yuf50098d2014-02-26 14:26:29 -0800157template<typename T>
158void
Junxiao Shi4ce0bcf2016-09-03 07:09:03 +0000159save(const T& obj, const std::string& filename, IoEncoding encoding = BASE64)
Yingdi Yuf50098d2014-02-26 14:26:29 -0800160{
Junxiao Shif2515a72016-08-19 02:21:59 +0000161 std::ofstream os(filename);
162 save(obj, os, encoding);
Yingdi Yuf50098d2014-02-26 14:26:29 -0800163}
164
165} // namespace io
166} // namespace ndn
167
168#endif // NDN_UTIL_IO_HPP