files.cpp

00001 // files.cpp - written and placed in the public domain by Wei Dai
00002 
00003 #include "pch.h"
00004 
00005 #ifndef CRYPTOPP_IMPORTS
00006 
00007 #include "files.h"
00008 
00009 #include <limits>
00010 
00011 NAMESPACE_BEGIN(CryptoPP)
00012 
00013 using namespace std;
00014 
00015 void Files_TestInstantiations()
00016 {
00017         FileStore f0;
00018         FileSource f1;
00019         FileSink f2;
00020 }
00021 
00022 void FileStore::StoreInitialize(const NameValuePairs &parameters)
00023 {
00024         m_file.reset(new std::ifstream);
00025         const char *fileName;
00026         if (parameters.GetValue(Name::InputFileName(), fileName))
00027         {
00028                 ios::openmode binary = parameters.GetValueWithDefault(Name::InputBinaryMode(), true) ? ios::binary : ios::openmode(0);
00029                 m_file->open(fileName, ios::in | binary);
00030                 if (!*m_file)
00031                         throw OpenErr(fileName);
00032                 m_stream = m_file.get();
00033         }
00034         else
00035         {
00036                 m_stream = NULL;
00037                 parameters.GetValue(Name::InputStreamPointer(), m_stream);
00038         }
00039         m_waiting = false;
00040 }
00041 
00042 lword FileStore::MaxRetrievable() const
00043 {
00044         if (!m_stream)
00045                 return 0;
00046 
00047         streampos current = m_stream->tellg();
00048         streampos end = m_stream->seekg(0, ios::end).tellg();
00049         m_stream->seekg(current);
00050         return end-current;
00051 }
00052 
00053 size_t FileStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
00054 {
00055         if (!m_stream)
00056         {
00057                 transferBytes = 0;
00058                 return 0;
00059         }
00060 
00061         lword size=transferBytes;
00062         transferBytes = 0;
00063 
00064         if (m_waiting)
00065                 goto output;
00066 
00067         while (size && m_stream->good())
00068         {
00069                 {
00070                 size_t spaceSize = 1024;
00071                 m_space = HelpCreatePutSpace(target, channel, 1, UnsignedMin(size_t(0)-1, size), spaceSize);
00072 
00073                 m_stream->read((char *)m_space, (unsigned int)STDMIN(size, (lword)spaceSize));
00074                 }
00075                 m_len = m_stream->gcount();
00076                 size_t blockedBytes;
00077 output:
00078                 blockedBytes = target.ChannelPutModifiable2(channel, m_space, m_len, 0, blocking);
00079                 m_waiting = blockedBytes > 0;
00080                 if (m_waiting)
00081                         return blockedBytes;
00082                 size -= m_len;
00083                 transferBytes += m_len;
00084         }
00085 
00086         if (!m_stream->good() && !m_stream->eof())
00087                 throw ReadErr();
00088 
00089         return 0;
00090 }
00091 
00092 size_t FileStore::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
00093 {
00094         if (!m_stream)
00095                 return 0;
00096 
00097         if (begin == 0 && end == 1)
00098         {
00099                 int result = m_stream->peek();
00100                 if (result == char_traits<char>::eof())
00101                         return 0;
00102                 else
00103                 {
00104                         size_t blockedBytes = target.ChannelPut(channel, byte(result), blocking);
00105                         begin += 1-blockedBytes;
00106                         return blockedBytes;
00107                 }
00108         }
00109 
00110         // TODO: figure out what happens on cin
00111         streampos current = m_stream->tellg();
00112         streampos endPosition = m_stream->seekg(0, ios::end).tellg();
00113         streampos newPosition = current + (streamoff)begin;
00114 
00115         if (newPosition >= endPosition)
00116         {
00117                 m_stream->seekg(current);
00118                 return 0;       // don't try to seek beyond the end of file
00119         }
00120         m_stream->seekg(newPosition);
00121         try
00122         {
00123                 assert(!m_waiting);
00124                 lword copyMax = end-begin;
00125                 size_t blockedBytes = const_cast<FileStore *>(this)->TransferTo2(target, copyMax, channel, blocking);
00126                 begin += copyMax;
00127                 if (blockedBytes)
00128                 {
00129                         const_cast<FileStore *>(this)->m_waiting = false;
00130                         return blockedBytes;
00131                 }
00132         }
00133         catch(...)
00134         {
00135                 m_stream->clear();
00136                 m_stream->seekg(current);
00137                 throw;
00138         }
00139         m_stream->clear();
00140         m_stream->seekg(current);
00141 
00142         return 0;
00143 }
00144 
00145 lword FileStore::Skip(lword skipMax)
00146 {
00147         lword oldPos = m_stream->tellg();
00148         std::istream::off_type offset;
00149         if (!SafeConvert(skipMax, offset))
00150                 throw InvalidArgument("FileStore: maximum seek offset exceeded");
00151         m_stream->seekg(offset, ios::cur);
00152         return (lword)m_stream->tellg() - oldPos;
00153 }
00154 
00155 void FileSink::IsolatedInitialize(const NameValuePairs &parameters)
00156 {
00157         m_file.reset(new std::ofstream);
00158         const char *fileName;
00159         if (parameters.GetValue(Name::OutputFileName(), fileName))
00160         {
00161                 ios::openmode binary = parameters.GetValueWithDefault(Name::OutputBinaryMode(), true) ? ios::binary : ios::openmode(0);
00162                 m_file->open(fileName, ios::out | ios::trunc | binary);
00163                 if (!*m_file)
00164                         throw OpenErr(fileName);
00165                 m_stream = m_file.get();
00166         }
00167         else
00168         {
00169                 m_stream = NULL;
00170                 parameters.GetValue(Name::OutputStreamPointer(), m_stream);
00171         }
00172 }
00173 
00174 bool FileSink::IsolatedFlush(bool hardFlush, bool blocking)
00175 {
00176         if (!m_stream)
00177                 throw Err("FileSink: output stream not opened");
00178 
00179         m_stream->flush();
00180         if (!m_stream->good())
00181                 throw WriteErr();
00182 
00183         return false;
00184 }
00185 
00186 size_t FileSink::Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
00187 {
00188         if (!m_stream)
00189                 throw Err("FileSink: output stream not opened");
00190 
00191         while (length > 0)
00192         {
00193                 std::streamsize size;
00194                 if (!SafeConvert(length, size))
00195                         size = numeric_limits<std::streamsize>::max();
00196                 m_stream->write((const char *)inString, size);
00197                 inString += size;
00198                 length -= size;
00199         }
00200 
00201         if (messageEnd)
00202                 m_stream->flush();
00203 
00204         if (!m_stream->good())
00205                 throw WriteErr();
00206 
00207         return 0;
00208 }
00209 
00210 NAMESPACE_END
00211 
00212 #endif

Generated on Sat Dec 23 02:07:07 2006 for Crypto++ by  doxygen 1.5.1-p1