Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Implementing InputStreams  (Read 2059 times)

0 Members and 1 Guest are viewing this topic.

dk123

  • Newbie
  • *
  • Posts: 49
    • View Profile
Implementing InputStreams
« on: February 04, 2015, 03:42:26 am »
Hi, I'm trying to implement a custom InputStream but I'm having trouble doing so.
I seem to be opening the zip file just fine, and the library I'm using (https://bitbucket.org/wbenny/ziplib/wiki/Home) automatically gives me an istream* to the
data.

Yet I keep failing when I try to load the texture with the stream through:
texture.loadFromStream

Any ideas as to what I'm doing incorrectly?

P.S. I'm currently trying to develop this to be able to open password protected zip files.
This is code for a game engine I'm currently building and my users seem to want the
added security - hence I can't just use physfs or some other pre-existing library.

Here's my implementation:

Header)
Code: [Select]
#include <ZipFile.h>

namespace lvn
{
class NStream : public sf::InputStream
{
private:
ZipArchiveEntry::Ptr m_entry;
std::shared_ptr<std::istream> m_File = nullptr;
std::string m_filename;
//bool m_file_is_open = false;

public:
static bool ReadTxtFile( std::string filepath, tstring& textbuffer );

NStream( std::string pathName="" );

virtual ~NStream();

bool isOpen() const;

bool open( std::string pathName );

void close();

virtual sf::Int64 read( void* data, sf::Int64 size );

virtual sf::Int64 seek( sf::Int64 position );

virtual sf::Int64 tell();

virtual sf::Int64 getSize();

};
}

CPP)
Code: [Select]
#include <ZipFile.h>
#include "NStream.h"

namespace lvn
{
NStream::NStream( std::string pathName )
//: m_File( 0x00 )
{
using namespace std;
open( pathName );
}

NStream::~NStream( )
{
close( );
}

bool NStream::isOpen( ) const
{
//return (m_File != 0x0);
return ( m_File != nullptr );
}

//Ex. Images//albert.png
bool NStream::open( std::string pathName )
{
using namespace std;
close( );
auto archive_name = pathName.substr( 0, pathName.find( "/" ) ) + (".vndat"); //need to add the archive extension to the name

ZipArchive::Ptr archive = ZipFile::Open( archive_name );
m_entry = archive->GetEntry( pathName );
if ( m_entry == nullptr )
return false;

m_File = make_shared<istream>( nullptr );
m_File->rdbuf( m_entry->GetDecompressionStream()->rdbuf() );
m_filename = pathName;

return isOpen( );
}

void NStream::close( )
{
m_File.reset( );
}

sf::Int64 NStream::read( void* data, sf::Int64 size )
{
if ( !isOpen( ) )
return -1;

auto posPrev = tell();
m_File->read( static_cast<char *>( data ), size );
auto cur = tell();

return tell() - posPrev;
}

sf::Int64 NStream::seek( sf::Int64 position )
{
if ( !isOpen( ) )
return -1;

m_File->seekg( position );
return tell( );
}

sf::Int64 NStream::tell( )
{
if ( !isOpen( ) )
return -1;

// istream returns the offset in bytes or -1 on error just like SFML wants.
return m_File->tellg( );
}

sf::Int64 NStream::getSize( )
{
if ( !isOpen( ) )
return -1;

//get length of file (by seeking to end), then restore original offset
const auto originalIdx = tell( );
m_File->seekg( 0, m_File->end );
const sf::Int64 length = tell( );
seek( originalIdx );

// tell returns length of file or -1 on error just like SFML wants.
return length;
}
}

ChronicRat

  • Sr. Member
  • ****
  • Posts: 327
  • C++ programmer
    • View Profile
    • My blog
Re: Implementing InputStreams
« Reply #1 on: February 04, 2015, 07:07:17 am »
I don't know what will do compiler's optimizer, but "isOpen" better as inline in header file.
I can share as I made it in my framework - https://bitbucket.org/SteelRat/gipe/src/711aa6630f0db3f277c4484ffc15f99051d368a3/src/filesystem/?at=default
« Last Edit: February 04, 2015, 07:09:41 am by ChronicRat »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Implementing InputStreams
« Reply #2 on: February 04, 2015, 07:42:29 am »
What error do you get? Have you tried to run step by step with your debugger?

Here is a std::istream based implementation that you can check for reference (ignore the Android stuff):
https://github.com/SFML/SFML/blob/feature/no_libsndfile_all_os/src/SFML/System/FileInputStream.cpp
Laurent Gomila - SFML developer

Ruckamongus

  • Jr. Member
  • **
  • Posts: 70
    • View Profile
Re: Implementing InputStreams
« Reply #3 on: February 04, 2015, 08:03:45 am »
I don't know what will do compiler's optimizer, but "isOpen" better as inline in header file.
I can share as I made it in my framework - https://bitbucket.org/SteelRat/gipe/src/711aa6630f0db3f277c4484ffc15f99051d368a3/src/filesystem/?at=default
I do agree, but using "inline" in a header file is unnecessary; implementations inside header files are implicitly inline anyway.

dk123

  • Newbie
  • *
  • Posts: 49
    • View Profile
Re: Implementing InputStreams
« Reply #4 on: February 04, 2015, 11:22:36 pm »
Thank you for all the replies, I managed to fix the problem by using a stringstream instead of istream.

 

anything