- Main Page
- Namespaces
- Classes
- Files

# 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