Botan
1.11.15
|
00001 /* 00002 * DataSource 00003 * (C) 1999-2007 Jack Lloyd 00004 * 2005 Matthew Gregan 00005 * 00006 * Botan is released under the Simplified BSD License (see license.txt) 00007 */ 00008 00009 #include <botan/data_src.h> 00010 #include <botan/exceptn.h> 00011 #include <fstream> 00012 #include <algorithm> 00013 00014 namespace Botan { 00015 00016 /* 00017 * Read a single byte from the DataSource 00018 */ 00019 size_t DataSource::read_byte(byte& out) 00020 { 00021 return read(&out, 1); 00022 } 00023 00024 /* 00025 * Peek a single byte from the DataSource 00026 */ 00027 size_t DataSource::peek_byte(byte& out) const 00028 { 00029 return peek(&out, 1, 0); 00030 } 00031 00032 /* 00033 * Discard the next N bytes of the data 00034 */ 00035 size_t DataSource::discard_next(size_t n) 00036 { 00037 size_t discarded = 0; 00038 byte dummy; 00039 for(size_t j = 0; j != n; ++j) 00040 discarded += read_byte(dummy); 00041 return discarded; 00042 } 00043 00044 /* 00045 * Read from a memory buffer 00046 */ 00047 size_t DataSource_Memory::read(byte out[], size_t length) 00048 { 00049 size_t got = std::min<size_t>(source.size() - offset, length); 00050 copy_mem(out, &source[offset], got); 00051 offset += got; 00052 return got; 00053 } 00054 00055 /* 00056 * Peek into a memory buffer 00057 */ 00058 size_t DataSource_Memory::peek(byte out[], size_t length, 00059 size_t peek_offset) const 00060 { 00061 const size_t bytes_left = source.size() - offset; 00062 if(peek_offset >= bytes_left) return 0; 00063 00064 size_t got = std::min(bytes_left - peek_offset, length); 00065 copy_mem(out, &source[offset + peek_offset], got); 00066 return got; 00067 } 00068 00069 /* 00070 * Check if the memory buffer is empty 00071 */ 00072 bool DataSource_Memory::end_of_data() const 00073 { 00074 return (offset == source.size()); 00075 } 00076 00077 /* 00078 * DataSource_Memory Constructor 00079 */ 00080 DataSource_Memory::DataSource_Memory(const std::string& in) : 00081 source(reinterpret_cast<const byte*>(in.data()), 00082 reinterpret_cast<const byte*>(in.data()) + in.length()), 00083 offset(0) 00084 { 00085 offset = 0; 00086 } 00087 00088 /* 00089 * Read from a stream 00090 */ 00091 size_t DataSource_Stream::read(byte out[], size_t length) 00092 { 00093 source.read(reinterpret_cast<char*>(out), length); 00094 if(source.bad()) 00095 throw Stream_IO_Error("DataSource_Stream::read: Source failure"); 00096 00097 size_t got = source.gcount(); 00098 total_read += got; 00099 return got; 00100 } 00101 00102 /* 00103 * Peek into a stream 00104 */ 00105 size_t DataSource_Stream::peek(byte out[], size_t length, size_t offset) const 00106 { 00107 if(end_of_data()) 00108 throw Invalid_State("DataSource_Stream: Cannot peek when out of data"); 00109 00110 size_t got = 0; 00111 00112 if(offset) 00113 { 00114 secure_vector<byte> buf(offset); 00115 source.read(reinterpret_cast<char*>(&buf[0]), buf.size()); 00116 if(source.bad()) 00117 throw Stream_IO_Error("DataSource_Stream::peek: Source failure"); 00118 got = source.gcount(); 00119 } 00120 00121 if(got == offset) 00122 { 00123 source.read(reinterpret_cast<char*>(out), length); 00124 if(source.bad()) 00125 throw Stream_IO_Error("DataSource_Stream::peek: Source failure"); 00126 got = source.gcount(); 00127 } 00128 00129 if(source.eof()) 00130 source.clear(); 00131 source.seekg(total_read, std::ios::beg); 00132 00133 return got; 00134 } 00135 00136 /* 00137 * Check if the stream is empty or in error 00138 */ 00139 bool DataSource_Stream::end_of_data() const 00140 { 00141 return (!source.good()); 00142 } 00143 00144 /* 00145 * Return a human-readable ID for this stream 00146 */ 00147 std::string DataSource_Stream::id() const 00148 { 00149 return identifier; 00150 } 00151 00152 /* 00153 * DataSource_Stream Constructor 00154 */ 00155 DataSource_Stream::DataSource_Stream(const std::string& path, 00156 bool use_binary) : 00157 identifier(path), 00158 source_p(new std::ifstream( 00159 path.c_str(), 00160 use_binary ? std::ios::binary : std::ios::in)), 00161 source(*source_p), 00162 total_read(0) 00163 { 00164 if(!source.good()) 00165 { 00166 delete source_p; 00167 throw Stream_IO_Error("DataSource: Failure opening file " + path); 00168 } 00169 } 00170 00171 /* 00172 * DataSource_Stream Constructor 00173 */ 00174 DataSource_Stream::DataSource_Stream(std::istream& in, 00175 const std::string& name) : 00176 identifier(name), 00177 source_p(nullptr), 00178 source(in), 00179 total_read(0) 00180 { 00181 } 00182 00183 /* 00184 * DataSource_Stream Destructor 00185 */ 00186 DataSource_Stream::~DataSource_Stream() 00187 { 00188 delete source_p; 00189 } 00190 00191 }