SymmetricCryptoBufSrc::pos_type SymmetricCryptoBufSrc::seekoff()

in src/aws-cpp-sdk-core/source/utils/crypto/CryptoBuf.cpp [23:117]


            SymmetricCryptoBufSrc::pos_type SymmetricCryptoBufSrc::seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which)
            {
                if(which == std::ios_base::in)
                {
                    auto curPos = m_stream.tellg();
                    //error on seek we may have read past the end already. Try resetting and seeking to the end first
                    if (curPos == pos_type(-1))
                    {
                        m_stream.clear();
                        m_stream.seekg(0, std::ios_base::end);
                        curPos = m_stream.tellg();
                    }

                    auto absPosition = ComputeAbsSeekPosition(off, dir, curPos);
                    size_t seekTo = static_cast<size_t>(absPosition);
                    size_t index = static_cast<size_t>(curPos);

                    if(index == seekTo)
                    {
                        return curPos;
                    }
                    else if (seekTo < index)
                    {
                        m_cipher.Reset();
                        m_stream.clear();
                        m_stream.seekg(0);
                        m_isFinalized = false;
                        index = 0;
                    }

                    CryptoBuffer cryptoBuffer;
                    while (m_cipher && index < seekTo && !m_isFinalized)
                    {
                        size_t max_read = std::min<size_t>(static_cast<size_t>(seekTo - index), m_bufferSize);

                        Aws::Utils::Array<char> buf(max_read);
                        size_t readSize(0);
                        if(m_stream)
                        {
                            m_stream.read(buf.GetUnderlyingData(), max_read);
                            readSize = static_cast<size_t>(m_stream.gcount());
                        }

                        if (readSize > 0)
                        {
                            if (m_cipherMode == CipherMode::Encrypt)
                            {
                                cryptoBuffer = m_cipher.EncryptBuffer(CryptoBuffer(reinterpret_cast<unsigned char*>(buf.GetUnderlyingData()), readSize));
                            }
                            else
                            {
                                cryptoBuffer = m_cipher.DecryptBuffer(CryptoBuffer(reinterpret_cast<unsigned char*>(buf.GetUnderlyingData()), readSize));
                            }
                        }
                        else
                        {
                            if (m_cipherMode == CipherMode::Encrypt)
                            {
                                cryptoBuffer = m_cipher.FinalizeEncryption();
                            }
                            else
                            {
                                cryptoBuffer = m_cipher.FinalizeDecryption();
                            }

                            m_isFinalized = true;
                        }

                        index += cryptoBuffer.GetLength();
                    }

                    if (cryptoBuffer.GetLength() && m_cipher)
                    {
                        CryptoBuffer putBackArea(m_putBack);

                        m_isBuf = CryptoBuffer({&putBackArea, &cryptoBuffer});
                        //in the very unlikely case that the cipher had less output than the source stream.
                        assert(seekTo <= index);
                        size_t newBufferPos = index > seekTo ? cryptoBuffer.GetLength() - (index - seekTo) : cryptoBuffer.GetLength();
                        char* baseBufPtr = reinterpret_cast<char*>(m_isBuf.GetUnderlyingData());
                        setg(baseBufPtr, baseBufPtr + m_putBack + newBufferPos, baseBufPtr + m_isBuf.GetLength());

                        return pos_type(seekTo);
                    }
                    else if (seekTo == 0)
                    {
                        m_isBuf = CryptoBuffer(m_putBack);
                        char* end = reinterpret_cast<char*>(m_isBuf.GetUnderlyingData() + m_isBuf.GetLength());
                        setg(end, end, end);
                        return pos_type(seekTo);
                    }
                }

                return pos_type(off_type(-1));
            }