vrshoot

diff libs/assimp/StreamReader.h @ 0:b2f14e535253

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 01 Feb 2014 19:58:19 +0200
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/libs/assimp/StreamReader.h	Sat Feb 01 19:58:19 2014 +0200
     1.3 @@ -0,0 +1,358 @@
     1.4 +/*
     1.5 +---------------------------------------------------------------------------
     1.6 +Open Asset Import Library (assimp)
     1.7 +---------------------------------------------------------------------------
     1.8 +
     1.9 +Copyright (c) 2006-2012, assimp team
    1.10 +
    1.11 +All rights reserved.
    1.12 +
    1.13 +Redistribution and use of this software in source and binary forms, 
    1.14 +with or without modification, are permitted provided that the following 
    1.15 +conditions are met:
    1.16 +
    1.17 +* Redistributions of source code must retain the above
    1.18 +  copyright notice, this list of conditions and the
    1.19 +  following disclaimer.
    1.20 +
    1.21 +* Redistributions in binary form must reproduce the above
    1.22 +  copyright notice, this list of conditions and the
    1.23 +  following disclaimer in the documentation and/or other
    1.24 +  materials provided with the distribution.
    1.25 +
    1.26 +* Neither the name of the assimp team, nor the names of its
    1.27 +  contributors may be used to endorse or promote products
    1.28 +  derived from this software without specific prior
    1.29 +  written permission of the assimp team.
    1.30 +
    1.31 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
    1.32 +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
    1.33 +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    1.34 +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
    1.35 +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    1.36 +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
    1.37 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    1.38 +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
    1.39 +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
    1.40 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
    1.41 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    1.42 +---------------------------------------------------------------------------
    1.43 +*/
    1.44 +
    1.45 +/** @file Defines the StreamReader class which reads data from
    1.46 + *  a binary stream with a well-defined endianess. */
    1.47 +
    1.48 +#ifndef AI_STREAMREADER_H_INCLUDED
    1.49 +#define AI_STREAMREADER_H_INCLUDED
    1.50 +
    1.51 +#include "ByteSwap.h"
    1.52 +
    1.53 +namespace Assimp {
    1.54 +
    1.55 +// --------------------------------------------------------------------------------------------
    1.56 +/** Wrapper class around IOStream to allow for consistent reading of binary data in both 
    1.57 + *  little and big endian format. Don't attempt to instance the template directly. Use 
    1.58 + *  StreamReaderLE to read from a little-endian stream and StreamReaderBE to read from a 
    1.59 + *  BE stream. The class expects that the endianess of any input data is known at 
    1.60 + *  compile-time, which should usually be true (#BaseImporter::ConvertToUTF8 implements
    1.61 + *  runtime endianess conversions for text files). 
    1.62 + *
    1.63 + *  XXX switch from unsigned int for size types to size_t? or ptrdiff_t?*/
    1.64 +// --------------------------------------------------------------------------------------------
    1.65 +template <bool SwapEndianess = false, bool RuntimeSwitch = false>
    1.66 +class StreamReader
    1.67 +{
    1.68 +
    1.69 +public:
    1.70 +
    1.71 +	// FIXME: use these data types throughout the whole library,
    1.72 +	// then change them to 64 bit values :-)
    1.73 +	
    1.74 +	typedef int diff;
    1.75 +	typedef unsigned int pos;
    1.76 +
    1.77 +public:
    1.78 +
    1.79 +
    1.80 +	// ---------------------------------------------------------------------
    1.81 +	/** Construction from a given stream with a well-defined endianess.
    1.82 +	 * 
    1.83 +	 *  The StreamReader holds a permanent strong reference to the
    1.84 +	 *  stream, which is released upon destruction.
    1.85 +	 *  @param stream Input stream. The stream is not restarted if
    1.86 +	 *    its file pointer is not at 0. Instead, the stream reader
    1.87 +	 *    reads from the current position to the end of the stream.
    1.88 +	 *  @param le If @c RuntimeSwitch is true: specifies whether the
    1.89 +	 *    stream is in little endian byte order. Otherwise the
    1.90 +	 *    endianess information is contained in the @c SwapEndianess
    1.91 +	 *    template parameter and this parameter is meaningless.  */
    1.92 +	StreamReader(boost::shared_ptr<IOStream> stream, bool le = false)
    1.93 +		: stream(stream)
    1.94 +		, le(le)
    1.95 +	{
    1.96 +		ai_assert(stream); 
    1.97 +		InternBegin();
    1.98 +	}
    1.99 +
   1.100 +	// ---------------------------------------------------------------------
   1.101 +	StreamReader(IOStream* stream, bool le = false)
   1.102 +		: stream(boost::shared_ptr<IOStream>(stream))
   1.103 +		, le(le)
   1.104 +	{
   1.105 +		ai_assert(stream);
   1.106 +		InternBegin();
   1.107 +	}
   1.108 +
   1.109 +	// ---------------------------------------------------------------------
   1.110 +	~StreamReader() {
   1.111 +		delete[] buffer;
   1.112 +	}
   1.113 +
   1.114 +public:
   1.115 +
   1.116 +	// deprecated, use overloaded operator>> instead
   1.117 +
   1.118 +	// ---------------------------------------------------------------------
   1.119 +	/** Read a float from the stream  */
   1.120 +	float GetF4()
   1.121 +	{
   1.122 +		return Get<float>();
   1.123 +	}
   1.124 +
   1.125 +	// ---------------------------------------------------------------------
   1.126 +	/** Read a double from the stream  */
   1.127 +	double GetF8()	{
   1.128 +		return Get<double>();
   1.129 +	}
   1.130 +
   1.131 +	// ---------------------------------------------------------------------
   1.132 +	/** Read a signed 16 bit integer from the stream */
   1.133 +	int16_t GetI2()	{
   1.134 +		return Get<int16_t>();
   1.135 +	}
   1.136 +
   1.137 +	// ---------------------------------------------------------------------
   1.138 +	/** Read a signed 8 bit integer from the stream */
   1.139 +	int8_t GetI1()	{
   1.140 +		return Get<int8_t>();
   1.141 +	}
   1.142 +
   1.143 +	// ---------------------------------------------------------------------
   1.144 +	/** Read an signed 32 bit integer from the stream */
   1.145 +	int32_t GetI4()	{
   1.146 +		return Get<int32_t>();
   1.147 +	}
   1.148 +
   1.149 +	// ---------------------------------------------------------------------
   1.150 +	/** Read a signed 64 bit integer from the stream */
   1.151 +	int64_t GetI8()	{
   1.152 +		return Get<int64_t>();
   1.153 +	}
   1.154 +
   1.155 +	// ---------------------------------------------------------------------
   1.156 +	/** Read a unsigned 16 bit integer from the stream */
   1.157 +	uint16_t GetU2()	{
   1.158 +		return Get<uint16_t>();
   1.159 +	}
   1.160 +
   1.161 +	// ---------------------------------------------------------------------
   1.162 +	/** Read a unsigned 8 bit integer from the stream */
   1.163 +	uint8_t GetU1()	{
   1.164 +		return Get<uint8_t>();
   1.165 +	}
   1.166 +
   1.167 +	// ---------------------------------------------------------------------
   1.168 +	/** Read an unsigned 32 bit integer from the stream */
   1.169 +	uint32_t GetU4()	{
   1.170 +		return Get<uint32_t>();
   1.171 +	}
   1.172 +
   1.173 +	// ---------------------------------------------------------------------
   1.174 +	/** Read a unsigned 64 bit integer from the stream */
   1.175 +	uint64_t GetU8()	{
   1.176 +		return Get<uint64_t>();
   1.177 +	}
   1.178 +
   1.179 +public:
   1.180 +
   1.181 +	// ---------------------------------------------------------------------
   1.182 +	/** Get the remaining stream size (to the end of the srream) */
   1.183 +	unsigned int GetRemainingSize() const {
   1.184 +		return (unsigned int)(end - current);
   1.185 +	}
   1.186 +
   1.187 +
   1.188 +	// ---------------------------------------------------------------------
   1.189 +	/** Get the remaining stream size (to the current read limit). The
   1.190 +	 *  return value is the remaining size of the stream if no custom
   1.191 +	 *  read limit has been set. */
   1.192 +	unsigned int GetRemainingSizeToLimit() const {
   1.193 +		return (unsigned int)(limit - current);
   1.194 +	}
   1.195 +
   1.196 +
   1.197 +	// ---------------------------------------------------------------------
   1.198 +	/** Increase the file pointer (relative seeking)  */
   1.199 +	void IncPtr(int plus)	{
   1.200 +		current += plus;
   1.201 +		if (current > limit) {
   1.202 +			throw DeadlyImportError("End of file or read limit was reached");
   1.203 +		}
   1.204 +	}
   1.205 +
   1.206 +	// ---------------------------------------------------------------------
   1.207 +	/** Get the current file pointer */
   1.208 +	int8_t* GetPtr() const	{
   1.209 +		return current;
   1.210 +	}
   1.211 +
   1.212 +
   1.213 +	// ---------------------------------------------------------------------
   1.214 +	/** Set current file pointer (Get it from #GetPtr). This is if you
   1.215 +	 *  prefer to do pointer arithmetics on your own or want to copy 
   1.216 +	 *  large chunks of data at once. 
   1.217 +	 *  @param p The new pointer, which is validated against the size
   1.218 +	 *    limit and buffer boundaries. */
   1.219 +	void SetPtr(int8_t* p)	{
   1.220 +
   1.221 +		current = p;
   1.222 +		if (current > limit || current < buffer) {
   1.223 +			throw DeadlyImportError("End of file or read limit was reached");
   1.224 +		}
   1.225 +	}
   1.226 +
   1.227 +	// ---------------------------------------------------------------------
   1.228 +	/** Copy n bytes to an external buffer
   1.229 +	 *  @param out Destination for copying
   1.230 +	 *  @param bytes Number of bytes to copy */
   1.231 +	void CopyAndAdvance(void* out, size_t bytes)	{
   1.232 +
   1.233 +		int8_t* ur = GetPtr();
   1.234 +		SetPtr(ur+bytes); // fire exception if eof
   1.235 +
   1.236 +		memcpy(out,ur,bytes);
   1.237 +	}
   1.238 +
   1.239 +
   1.240 +	// ---------------------------------------------------------------------
   1.241 +	/** Get the current offset from the beginning of the file */
   1.242 +	int GetCurrentPos() const	{
   1.243 +		return (unsigned int)(current - buffer);
   1.244 +	}
   1.245 +
   1.246 +	void SetCurrentPos(size_t pos) {
   1.247 +		SetPtr(buffer + pos);
   1.248 +	}
   1.249 +
   1.250 +	// ---------------------------------------------------------------------
   1.251 +	/** Setup a temporary read limit
   1.252 +	 * 
   1.253 +	 *  @param limit Maximum number of bytes to be read from
   1.254 +	 *    the beginning of the file. Specifying UINT_MAX
   1.255 +	 *    resets the limit to the original end of the stream. */
   1.256 +	void SetReadLimit(unsigned int _limit)	{
   1.257 +
   1.258 +		if (UINT_MAX == _limit) {
   1.259 +			limit = end;
   1.260 +			return;
   1.261 +		}
   1.262 +
   1.263 +		limit = buffer + _limit;
   1.264 +		if (limit > end) {
   1.265 +			throw DeadlyImportError("StreamReader: Invalid read limit");
   1.266 +		}
   1.267 +	}
   1.268 +
   1.269 +	// ---------------------------------------------------------------------
   1.270 +	/** Get the current read limit in bytes. Reading over this limit
   1.271 +	 *  accidentially raises an exception.  */
   1.272 +	int GetReadLimit() const	{
   1.273 +		return (unsigned int)(limit - buffer);
   1.274 +	}
   1.275 +
   1.276 +	// ---------------------------------------------------------------------
   1.277 +	/** Skip to the read limit in bytes. Reading over this limit
   1.278 +	 *  accidentially raises an exception. */
   1.279 +	void SkipToReadLimit()	{
   1.280 +		current = limit;
   1.281 +	}
   1.282 +
   1.283 +	// ---------------------------------------------------------------------
   1.284 +	/** overload operator>> and allow chaining of >> ops. */
   1.285 +	template <typename T>
   1.286 +	StreamReader& operator >> (T& f) {
   1.287 +		f = Get<T>(); 
   1.288 +		return *this;
   1.289 +	}
   1.290 +
   1.291 +private:
   1.292 +
   1.293 +	// ---------------------------------------------------------------------
   1.294 +	/** Generic read method. ByteSwap::Swap(T*) *must* be defined */
   1.295 +	template <typename T>
   1.296 +	T Get()	{
   1.297 +		if (current + sizeof(T) > limit) {
   1.298 +			throw DeadlyImportError("End of file or stream limit was reached");
   1.299 +		}
   1.300 +
   1.301 +#ifdef __arm__
   1.302 +		T f;
   1.303 +		memcpy (&f, current, sizeof(T));
   1.304 +#else
   1.305 +		T f = *((const T*)current);
   1.306 +#endif	
   1.307 +		Intern :: Getter<SwapEndianess,T,RuntimeSwitch>() (&f,le);
   1.308 +
   1.309 +		current += sizeof(T);
   1.310 +		return f;
   1.311 +	}
   1.312 +
   1.313 +	// ---------------------------------------------------------------------
   1.314 +	void InternBegin() {
   1.315 +		if (!stream) {
   1.316 +			// incase someone wonders: StreamReader is frequently invoked with
   1.317 +			// no prior validation whether the input stream is valid. Since
   1.318 +			// no one bothers changing the error message, this message here
   1.319 +			// is passed down to the caller and 'unable to open file'
   1.320 +			// simply describes best what happened.
   1.321 +			throw DeadlyImportError("StreamReader: Unable to open file");
   1.322 +		}
   1.323 +
   1.324 +		const size_t s = stream->FileSize() - stream->Tell();
   1.325 +		if (!s) {
   1.326 +			throw DeadlyImportError("StreamReader: File is empty or EOF is already reached");
   1.327 +		}
   1.328 +
   1.329 +		current = buffer = new int8_t[s];
   1.330 +		const size_t read = stream->Read(current,1,s);
   1.331 +		// (read < s) can only happen if the stream was opened in text mode, in which case FileSize() is not reliable
   1.332 +		ai_assert(read <= s);
   1.333 +		end = limit = &buffer[read];
   1.334 +	}
   1.335 +
   1.336 +private:
   1.337 +
   1.338 +
   1.339 +	boost::shared_ptr<IOStream> stream;
   1.340 +	int8_t *buffer, *current, *end, *limit;
   1.341 +	bool le;
   1.342 +};
   1.343 +
   1.344 +
   1.345 +// --------------------------------------------------------------------------------------------
   1.346 +// `static` StreamReaders. Their byte order is fixed and they might be a little bit faster.
   1.347 +#ifdef AI_BUILD_BIG_ENDIAN
   1.348 +	typedef StreamReader<true>  StreamReaderLE;
   1.349 +	typedef StreamReader<false> StreamReaderBE;
   1.350 +#else
   1.351 +	typedef StreamReader<true>  StreamReaderBE;
   1.352 +	typedef StreamReader<false> StreamReaderLE;
   1.353 +#endif
   1.354 +
   1.355 +// `dynamic` StreamReader. The byte order of the input data is specified in the
   1.356 +// c'tor. This involves runtime branching and might be a little bit slower.
   1.357 +typedef StreamReader<true,true> StreamReaderAny;
   1.358 +
   1.359 +} // end namespace Assimp
   1.360 +
   1.361 +#endif // !! AI_STREAMREADER_H_INCLUDED