virtual std::streampos seekoff (std::streamoff off, std::ios_base::seekdir way, std::ios_base::openmode which = std::ios_base::in) { std::streamoff newpos; if ( way == std::ios_base::beg ) { newpos = off; } else if ( way == std::ios_base::cur ) { newpos = _curPos + off; } else if ( way == std::ios_base::end ) { newpos = _numChars + off; } else { return -1; } if ( newpos<0 || newpos>_numChars ) return -1; if ( ARCHIVE_POS(_streambuf->pubseekpos( STREAM_POS(_startPos+newpos), which)) < 0 ) return -1; _curPos = newpos; return _curPos; }
/** read whole contents of streambuf 'buf' \return size of data malloced and copied into \param[out] buffer unless size is 0 (in which case buffer is set to NULL for convenience, so you can blindly free) requires put pointer is at end for determining size (e.g. just-written iostream) */ inline std::size_t read_streambuf_malloc(std::streambuf& buf, void*& buffer) { typedef std::streambuf::pos_type Pos; typedef std::streambuf::off_type Off; Pos sz = buf.pubseekoff(0, std::ios::end, std::ios_base::out); if (sz > 0 && seek_ok(sz) && seek_ok(buf.pubseekpos(0, std::ios_base::in))) return buf.sgetn((char*)(buffer = std::malloc(sz)), sz); else { buffer = 0; return 0; } }
// -------------------------------------------------------------------------- // -------------------------------------------------------------------------- bool t_single_scenario_campaign_file_header::read( std::streambuf & stream, t_progress_handler * progress_handler_ptr ) { m_map_data_start = stream.pubseekoff( 0, std::ios::cur ); m_map_data_end = stream.pubseekoff( 0, std::ios::end ); stream.pubseekpos( m_map_data_start ); try { t_inflate_filter inflater( stream ); if ( !::read( inflater, *m_map_header_ptr, progress_handler_ptr ) ) return false; } catch ( t_inflate_filter::t_data_error const & ) { return false; } return true; }
// -------------------------------------------------------------------------- // -------------------------------------------------------------------------- bool t_multi_scenario_campaign_file_header::read( std::streambuf & stream, t_progress_handler * progress_handler_ptr ) { int const k_current_format_version = 1; int format_version = get< t_uint16 >( stream ); if ( format_version < 0 || format_version > k_current_format_version ) return false; std::string new_name; std::string new_description; if ( !read_string16( stream, new_name ) || ( format_version >= 1 && !read_string16( stream, new_description ) ) ) return false; int map_count = get< t_uint16 >( stream ); if ( map_count <= 0 ) return false; std::vector< std::streambuf::off_type > map_data_sizes( map_count ); std::vector< t_map_info > new_map_info_vector( map_count ); int map_num; for ( map_num = 0; map_num < map_count; ++map_num ) map_data_sizes[ map_num ] = get< t_uint32 >( stream ); std::streambuf::pos_type start_pos = stream.pubseekoff( 0, std::ios::cur ); map_num = 0; while( true ) { std::streambuf::pos_type end_pos = start_pos + map_data_sizes[ map_num ]; t_map_info & map_info = new_map_info_vector[ map_num ]; map_info.data_start = start_pos; map_info.data_end = end_pos; map_info.header_ptr = new t_map_header; stream.pubseekpos( start_pos ); try { t_inflate_filter inflater( stream ); if ( !::read( inflater, *map_info.header_ptr, progress_handler_ptr ) ) return false; } catch ( t_inflate_filter::t_data_error const & ) { return false; } if ( ++map_num >= map_count ) break; start_pos = end_pos; } m_name.swap( new_name ); m_description.swap( new_description ); m_map_info_vector.swap( new_map_info_vector ); return true; }
virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode) override { ASSERT(_streambuf); return _streambuf->pubseekpos(pos, mode); }