Просмотр исходного кода

More documentation and slight refactor. (Unsure if engine starts atm due to unfinished Script changes)

Marko Pintera 11 лет назад
Родитель
Сommit
53901cc6d5

+ 0 - 1
CamelotCore/Include/CmMaterialRTTI.h

@@ -13,7 +13,6 @@
 #include "CmShader.h"
 #include "CmDebug.h"
 #include "CmException.h"
-#include "CmKeyValuePair.h"
 
 namespace CamelotFramework
 {

+ 3 - 2
CamelotFreeImgImporter/Source/CmFreeImgImporter.cpp

@@ -178,7 +178,8 @@ namespace CamelotFramework
 		FreeImage_SetOutputMessage(FreeImageLoadErrorHandler);
 
 		// Buffer stream into memory (TODO: override IO functions instead?)
-		MemoryDataStream memStream(fileData, true);
+		MemoryDataStream memStream(fileData);
+		fileData->close();
 
 		FIMEMORY* fiMem = FreeImage_OpenMemory(memStream.getPtr(), static_cast<DWORD>(memStream.size()));
 
@@ -207,7 +208,7 @@ namespace CamelotFramework
 		case FIT_INT32:
 		case FIT_DOUBLE:
 		default:
-			CM_EXCEPT(ItemIdentityException, "Unknown or unsupported image format");
+			CM_EXCEPT(InternalErrorException, "Unknown or unsupported image format");
 
 			break;
 		case FIT_BITMAP:

+ 0 - 1
CamelotUtility/CamelotUtility.vcxproj

@@ -282,7 +282,6 @@
     <ClInclude Include="Include\CmHString.h" />
     <ClInclude Include="Include\CmVector2I.h" />
     <ClInclude Include="Include\CmIReflectable.h" />
-    <ClInclude Include="Include\CmKeyValuePair.h" />
     <ClInclude Include="Include\CmLog.h" />
     <ClInclude Include="Include\CmManagedDataBlock.h" />
     <ClInclude Include="Include\CmMemoryAllocator.h" />

+ 0 - 3
CamelotUtility/CamelotUtility.vcxproj.filters

@@ -174,9 +174,6 @@
     <ClInclude Include="Include\CmWorkQueue.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="Include\CmKeyValuePair.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
     <ClInclude Include="Include\CmAsyncOp.h">
       <Filter>Header Files\Threading</Filter>
     </ClInclude>

+ 1 - 1
CamelotUtility/Include/CmColor.h

@@ -192,7 +192,7 @@ namespace CamelotFramework
             result.b = lhs * rhs.b;
             result.a = lhs * rhs.a;
 
-            return kProd;
+            return result;
         }
 
         inline Color& operator+= (const Color& rhs)

+ 175 - 338
CamelotUtility/Include/CmDataStream.h

@@ -19,260 +19,154 @@ namespace CamelotFramework
 		};
 
 	public:
-		/// Constructor for creating unnamed streams
-        DataStream(UINT16 accessMode = READ) : mSize(0), mAccess(accessMode) {}
-		/// Constructor for creating named streams
+        /**
+         * @brief	Creates an unnamed stream.
+         */
+        DataStream(UINT16 accessMode = READ) 
+			:mSize(0), mAccess(accessMode) 
+		{ }
+
+        /**
+         * @brief	Creates a named stream.
+         */
 		DataStream(const String& name, UINT16 accessMode = READ) 
-			: mName(name), mSize(0), mAccess(accessMode) {}
-		/// Returns the name of the stream, if it has one.
+			:mName(name), mSize(0), mAccess(accessMode) {}
+
+		virtual ~DataStream() {}
+
 		const String& getName(void) { return mName; }
-		/// Gets the access mode of the stream
 		UINT16 getAccessMode() const { return mAccess; }
-		/** Reports whether this stream is readable. */
+
 		virtual bool isReadable() const { return (mAccess & READ) != 0; }
-		/** Reports whether this stream is writeable. */
 		virtual bool isWriteable() const { return (mAccess & WRITE) != 0; }
-        virtual ~DataStream() {}
-		// Streaming operators
+       
+        /**
+         * @brief	Reads data from the buffer and copies it to the specified value.
+         */
         template<typename T> DataStream& operator>>(T& val);
-		/** Read the requisite number of bytes from the stream, 
-			stopping at the end of the file.
-		@param buf Reference to a buffer pointer
-		@param count Number of bytes to read
-		@returns The number of bytes read
-		*/
+
+		/**
+		 * @brief	Read the requisite number of bytes from the stream,
+		 *			stopping at the end of the file.
+		 *
+		 * @param	buf		Pre-allocated buffer to read the data into.
+		 * @param	count	Number of bytes to read.
+		 *
+		 * @return	Number of bytes actually read.
+		 * 			
+		 * @note	Stream must be created with READ access mode.
+		 */
 		virtual size_t read(void* buf, size_t count) = 0;
-		/** Write the requisite number of bytes from the stream (only applicable to 
-			streams that are not read-only)
-		@param buf Pointer to a buffer containing the bytes to write
-		@param count Number of bytes to write
-		@returns The number of bytes written
-		*/
-		virtual size_t write(const void* buf, size_t count)
-		{
-                        (void)buf;
-                        (void)count;
-			// default to not supported
-			return 0;
-		}
-
-		/** Get a single line from the stream.
-		@remarks
-			The delimiter character is not included in the data
-			returned, and it is skipped over so the next read will occur
-			after it. The buffer contents will include a
-			terminating character.
-        @note
-            If you used this function, you <b>must</b> open the stream in <b>binary mode</b>,
-            otherwise, it'll produce unexpected results.
-		@param buf Reference to a buffer pointer
-		@param maxCount The maximum length of data to be read, excluding the terminating character
-		@param delim The delimiter to stop at
-		@returns The number of bytes read, excluding the terminating character
-		*/
-		virtual size_t readLine(char* buf, size_t maxCount, const String& delim = "\n");
-		
-	    /** Returns a String containing the next line of data, optionally 
-		    trimmed for whitespace. 
-	    @remarks
-		    This is a convenience method for text streams only, allowing you to 
-		    retrieve a String object containing the next line of data. The data
-		    is read up to the next newline character and the result trimmed if
-		    required.
-        @note
-            If you used this function, you <b>must</b> open the stream in <b>binary mode</b>,
-            otherwise, it'll produce unexpected results.
-	    @param 
-		    trimAfter If true, the line is trimmed for whitespace (as in 
-		    String.trim(true,true))
-	    */
-	    virtual String getLine( bool trimAfter = true );
-
-	    /** Returns a String containing the entire stream. 
-	    @remarks
-		    This is a convenience method for text streams only, allowing you to 
-		    retrieve a String object containing all the data in the stream.
-	    */
-	    virtual String getAsString(void);
-
-		/** Skip a single line from the stream.
-        @note
-            If you used this function, you <b>must</b> open the stream in <b>binary mode</b>,
-            otherwise, it'll produce unexpected results.
-		@param delim The delimiter(s) to stop at
-		@returns The number of bytes skipped
-		*/
-		virtual size_t skipLine(const String& delim = "\n");
-
-		/** Skip a defined number of bytes. This can also be a negative value, in which case
-		the file pointer rewinds a defined number of bytes. */
-		virtual void skip(long count) = 0;
+
+		/**
+		 * @brief	Write the requisite number of bytes to the stream.
+		 *
+		 * @param	buf		Buffer containing bytes to write.
+		 * @param	count	Number of bytes to write.
+		 *
+		 * @return	Number of bytes actually written.
+		 * 			
+		 * @note	Stream must be created with WRITE access mode.
+		 */
+		virtual size_t write(const void* buf, size_t count) { return 0; }
+
+	    /**
+	     * @brief	Returns a string containing the entire stream.
+	     *
+		 * @note	 This is a convenience method for text streams only, allowing you to
+		 *			retrieve a String object containing all the data in the stream.
+	     */
+	    virtual String getAsString();
+
+	    /**
+	     * @brief	Returns a wide string containing the entire stream.
+	     *
+		 * @note	This is a convenience method for text streams only, allowing you to
+		 *			retrieve a WString object containing all the data in the stream.
+	     */
+	    virtual WString getAsWString();
+
+		/**
+		 * @brief	Skip a defined number of bytes. This can also be a negative value, in which case
+		 *			the file pointer rewinds a defined number of bytes.
+		 */
+		virtual void skip(size_t count) = 0;
 	
-		/** Repositions the read point to a specified byte.
-	    */
-	    virtual void seek( size_t pos ) = 0;
+	    /**
+	     * @brief	Repositions the read point to a specified byte.
+	     */
+	    virtual void seek(size_t pos) = 0;
 		
-		/** Returns the current byte offset from beginning */
-	    virtual size_t tell(void) const = 0;
-
-		/** Returns true if the stream has reached the end.
-	    */
-	    virtual bool eof(void) const = 0;
-
-		/** Returns the total size of the data to be read from the stream, 
-			or 0 if this is indeterminate for this stream. 
-		*/
-        size_t size(void) const { return mSize; }
+	    /**
+	     * @brief	Returns the current byte offset from beginning
+	     */
+	    virtual size_t tell() const = 0;
+
+	    /**
+	     * @brief	Returns true if the stream has reached the end.
+	     */
+	    virtual bool eof() const = 0;
+
+        /**
+		 * @brief	Returns the total size of the data to be read from the stream,
+		 *			or 0 if this is indeterminate for this stream.
+         */
+        size_t size() const { return mSize; }
 
-        /** Close the stream; this makes further operations invalid. */
-        virtual void close(void) = 0;
+        /**
+         * @brief	Close the stream. This makes further operations invalid.
+         */
+        virtual void close() = 0;
 		
 	protected:
-		/// The name (e.g. resource name) that can be used to identify the source fot his data (optional)
+		static const UINT32 StreamTempSize;
+
 		String mName;		
-        /// Size of the data in the stream (may be 0 if size cannot be determined)
         size_t mSize;
-		/// What type of access is allowed (AccessMode)
 		UINT16 mAccess;
-
-        #define OGRE_STREAM_TEMP_SIZE 128
 	};
 
-	/** Shared pointer to allow data streams to be passed around without
-		worrying about deallocation
-	*/
-	typedef std::shared_ptr<DataStream> DataStreamPtr;
-
-	/// List of DataStream items
-	typedef List<DataStreamPtr>::type DataStreamList;
-	/// Shared pointer to list of DataStream items
-	typedef std::shared_ptr<DataStreamList> DataStreamListPtr;
-
-	/** Common subclass of DataStream for handling data from chunks of memory.
-	*/
+	/**
+	 * @brief	Data stream for handling data from memory.
+	 */
 	class CM_UTILITY_EXPORT MemoryDataStream : public DataStream
-	{
-	protected:
-        /// Pointer to the start of the data area
-	    UINT8* mData;
-        /// Pointer to the current position in the memory
-	    UINT8* mPos;
-        /// Pointer to the end of the memory
-	    UINT8* mEnd;
-        /// Do we delete the memory on close
-		bool mFreeOnClose;			
+	{		
 	public:
+		/**
+		 * @brief	Wrap an existing memory chunk in a stream.
+		 *
+		 * @param 	memory		Memory to wrap the data stream around.
+		 * @param	size		Size of the memory chunk in bytes.
+		 */
+		MemoryDataStream(void* memory, size_t size);
 		
-		/** Wrap an existing memory chunk in a stream.
-		@param pMem Pointer to the existing memory
-		@param size The size of the memory chunk in bytes
-		@param freeOnClose If true, the memory associated will be destroyed
-			when the stream is destroyed. Note: it's important that if you set
-			this option to true, that you allocated the memory using OGRE_ALLOC_T
-			with a category of MEMCATEGORY_GENERAL ensure the freeing of memory 
-			matches up.
-		@param readOnly Whether to make the stream on this memory read-only once created
-		*/
-		MemoryDataStream(void* pMem, size_t size, bool freeOnClose = false, bool readOnly = false);
+		/**
+		 * @brief	Create a stream which pre-buffers the contents of another stream. Data
+		 * 			from the other buffer will be entirely read and stored in an internal buffer.
+		 *
+		 * @param [in]	sourceStream		Stream to read data from.
+		 */
+		MemoryDataStream(DataStream& sourceStream);
 		
-		/** Wrap an existing memory chunk in a named stream.
-		@param name The name to give the stream
-		@param pMem Pointer to the existing memory
-		@param size The size of the memory chunk in bytes
-		@param freeOnClose If true, the memory associated will be destroyed
-			when the stream is destroyed. Note: it's important that if you set
-			this option to true, that you allocated the memory using OGRE_ALLOC_T
-			with a category of MEMCATEGORY_GENERAL ensure the freeing of memory 
-			matches up.
-		@param readOnly Whether to make the stream on this memory read-only once created
-		*/
-		MemoryDataStream(const String& name, void* pMem, size_t size, 
-				bool freeOnClose = false, bool readOnly = false);
-
-		/** Create a stream which pre-buffers the contents of another stream.
-		@remarks
-			This constructor can be used to intentionally read in the entire
-			contents of another stream, copying them to the internal buffer
-			and thus making them available in memory as a single unit.
-		@param sourceStream Another DataStream which will provide the source
-			of data
-		@param freeOnClose If true, the memory associated will be destroyed
-			when the stream is destroyed.
-		@param readOnly Whether to make the stream on this memory read-only once created
-		*/
-		MemoryDataStream(DataStream& sourceStream, 
-				bool freeOnClose = true, bool readOnly = false);
-		
-		/** Create a stream which pre-buffers the contents of another stream.
-		@remarks
-			This constructor can be used to intentionally read in the entire
-			contents of another stream, copying them to the internal buffer
-			and thus making them available in memory as a single unit.
-		@param sourceStream Weak reference to another DataStream which will provide the source
-			of data
-		@param freeOnClose If true, the memory associated will be destroyed
-			when the stream is destroyed.
-		@param readOnly Whether to make the stream on this memory read-only once created
-		*/
-		MemoryDataStream(DataStreamPtr& sourceStream, 
-				bool freeOnClose = true, bool readOnly = false);
-
-		/** Create a named stream which pre-buffers the contents of 
-			another stream.
-		@remarks
-			This constructor can be used to intentionally read in the entire
-			contents of another stream, copying them to the internal buffer
-			and thus making them available in memory as a single unit.
-		@param name The name to give the stream
-		@param sourceStream Another DataStream which will provide the source
-			of data
-		@param freeOnClose If true, the memory associated will be destroyed
-			when the stream is destroyed.
-		@param readOnly Whether to make the stream on this memory read-only once created
-		*/
-		MemoryDataStream(const String& name, DataStream& sourceStream, 
-				bool freeOnClose = true, bool readOnly = false);
-
-        /** Create a named stream which pre-buffers the contents of 
-        another stream.
-        @remarks
-        This constructor can be used to intentionally read in the entire
-        contents of another stream, copying them to the internal buffer
-        and thus making them available in memory as a single unit.
-        @param name The name to give the stream
-        @param sourceStream Another DataStream which will provide the source
-        of data
-        @param freeOnClose If true, the memory associated will be destroyed
-        when the stream is destroyed.
-		@param readOnly Whether to make the stream on this memory read-only once created
-        */
-        MemoryDataStream(const String& name, const DataStreamPtr& sourceStream, 
-            bool freeOnClose = true, bool readOnly = false);
-
-        /** Create a stream with a brand new empty memory chunk.
-		@param size The size of the memory chunk to create in bytes
-		@param freeOnClose If true, the memory associated will be destroyed
-			when the stream is destroyed.
-		@param readOnly Whether to make the stream on this memory read-only once created
-		*/
-		MemoryDataStream(size_t size, bool freeOnClose = true, bool readOnly = false);
-		/** Create a named stream with a brand new empty memory chunk.
-		@param name The name to give the stream
-		@param size The size of the memory chunk to create in bytes
-		@param freeOnClose If true, the memory associated will be destroyed
-			when the stream is destroyed.
-		@param readOnly Whether to make the stream on this memory read-only once created
-		*/
-		MemoryDataStream(const String& name, size_t size, 
-				bool freeOnClose = true, bool readOnly = false);
+		/**
+		 * @brief	Create a stream which pre-buffers the contents of another stream. Data
+		 * 			from the other buffer will be entirely read and stored in an internal buffer.
+		 *
+		 * @param [in]	sourceStream		Stream to read data from.
+		 */
+		MemoryDataStream(const DataStreamPtr& sourceStream);
 
 		~MemoryDataStream();
 
-		/** Get a pointer to the start of the memory block this stream holds. */
-		UINT8* getPtr(void) { return mData; }
+		/**
+		 * @brief	Get a pointer to the start of the memory block this stream holds.
+		 */
+		UINT8* getPtr() { return mData; }
 		
-		/** Get a pointer to the current position in the memory block this stream holds. */
-		UINT8* getCurrentPtr(void) { return mPos; }
+		/**
+		 * @brief	Get a pointer to the current position in the memory block this stream holds.
+		 */
+		UINT8* getCurrentPtr() { return mPos; }
 		
         /** 
 		 * @copydoc DataStream::read
@@ -284,20 +178,10 @@ namespace CamelotFramework
          */
 		size_t write(const void* buf, size_t count);
 
-        /** 
-		 * @copydoc DataStream::readLine
-         */
-		size_t readLine(char* buf, size_t maxCount, const String& delim = "\n");
-		
-        /** 
-		 * @copydoc DataStream::skipLine
-         */
-		size_t skipLine(const String& delim = "\n");
-
         /** 
 		 * @copydoc DataStream::skip
          */
-		void skip(long count);
+		void skip(size_t count);
 	
         /** 
 		 * @copydoc DataStream::seek
@@ -319,103 +203,53 @@ namespace CamelotFramework
          */
         void close(void);
 
-		/** Sets whether or not to free the encapsulated memory on close. */
-		void setFreeOnClose(bool free) { mFreeOnClose = free; }
-	};
+	protected:
+		UINT8* mData;
+		UINT8* mPos;
+		UINT8* mEnd;
 
-    /** Shared pointer to allow memory data streams to be passed around without
-    worrying about deallocation
-    */
-    typedef std::shared_ptr<MemoryDataStream> MemoryDataStreamPtr;
+		bool mFreeOnClose;
+	};
 
-    /** Common subclass of DataStream for handling data from 
-		std::basic_istream.
-	*/
+	/**
+	 * @brief	Data stream for handling data from standard streams.
+	 */
 	class CM_UTILITY_EXPORT FileDataStream : public DataStream
 	{
-	protected:
-		/// Reference to source stream (read)
-		std::shared_ptr<std::istream> mpInStream;
-		/// Reference to source file stream (read-only)
-		std::shared_ptr<std::ifstream> mpFStreamRO;
-		/// Reference to source file stream (read-write)
-		std::shared_ptr<std::fstream> mpFStream;
-        bool mFreeOnClose;	
-
-		void determineAccess();
 	public:
-		/** Construct a read-only stream from an STL stream
-        @param s Pointer to source stream
-        @param freeOnClose Whether to delete the underlying stream on 
-            destruction of this class
-        */
-		FileDataStream(std::shared_ptr<std::ifstream> s, 
-            bool freeOnClose = true);
-		/** Construct a read-write stream from an STL stream
-		@param s Pointer to source stream
-		@param freeOnClose Whether to delete the underlying stream on 
-		destruction of this class
-		*/
-		FileDataStream(std::shared_ptr<std::fstream> s, 
-			bool freeOnClose = true);
-
-		/** Construct named read-only stream from an STL stream
-        @param name The name to give this stream
-        @param s Pointer to source stream
-        @param freeOnClose Whether to delete the underlying stream on 
-            destruction of this class
-        */
-		FileDataStream(const String& name, 
-            std::shared_ptr<std::ifstream> s, 
-            bool freeOnClose = true);
-
-		/** Construct named read-write stream from an STL stream
-		@param name The name to give this stream
-		@param s Pointer to source stream
-		@param freeOnClose Whether to delete the underlying stream on 
-		destruction of this class
-		*/
-		FileDataStream(const String& name, 
-			std::shared_ptr<std::fstream> s, 
-			bool freeOnClose = true);
-
-		/** Construct named read-only stream from an STL stream, and tell it the size
-        @remarks
-            This variant tells the class the size of the stream too, which 
-            means this class does not need to seek to the end of the stream 
-            to determine the size up-front. This can be beneficial if you have
-            metadata about the contents of the stream already.
-        @param name The name to give this stream
-        @param s Pointer to source stream
-        @param size Size of the stream contents in bytes
-        @param freeOnClose Whether to delete the underlying stream on 
-            destruction of this class. If you specify 'true' for this you
-			must ensure that the stream was allocated using OGRE_NEW_T with 
-			MEMCATEGRORY_GENERAL.
-        */
-		FileDataStream(const String& name, 
-            std::shared_ptr<std::ifstream> s, 
-            size_t size, 
-            bool freeOnClose = true);
-
-		/** Construct named read-write stream from an STL stream, and tell it the size
-		@remarks
-		This variant tells the class the size of the stream too, which 
-		means this class does not need to seek to the end of the stream 
-		to determine the size up-front. This can be beneficial if you have
-		metadata about the contents of the stream already.
-		@param name The name to give this stream
-		@param s Pointer to source stream
-		@param size Size of the stream contents in bytes
-		@param freeOnClose Whether to delete the underlying stream on 
-		destruction of this class. If you specify 'true' for this you
-		must ensure that the stream was allocated using OGRE_NEW_T with 
-		MEMCATEGRORY_GENERAL.
-		*/
-		FileDataStream(const String& name, 
-			std::shared_ptr<std::fstream> s, 
-			size_t size, 
-			bool freeOnClose = true);
+		/**
+		 * @brief	Construct read-only stream from an standard stream.
+		 * 			
+		 *			If "freeOnClose" is true, the STL stream will be freed once the data stream is closed.
+		 */
+		FileDataStream(std::shared_ptr<std::ifstream> s, bool freeOnClose = true);
+
+		/**
+		 * @brief	Construct read-write stream from an standard stream.
+		 * 			
+		 *			If "freeOnClose" is true, the STL stream will be freed once the data stream is closed.
+		 */
+		FileDataStream(std::shared_ptr<std::fstream> s, bool freeOnClose = true);
+
+		/**
+		 * @brief	Construct read-only stream from an standard stream, and tell it the size.
+		 * 			
+		 *			Size parameter allows you to specify the size without requiring us to seek to the end of the stream
+		 *			to find the size.
+		 *			
+		 *			If "freeOnClose" is true, the STL stream will be freed once the data stream is closed.
+		 */
+		FileDataStream(std::shared_ptr<std::ifstream> s, size_t size, bool freeOnClose = true);
+
+		/**
+		 * @brief	Construct read-write stream from an standard stream, and tell it the size.
+		 * 			
+		 *			Size parameter allows you to specify the size without requiring us to seek to the end of the stream
+		 *			to find the size.
+		 *			
+		 *			If "freeOnClose" is true, the STL stream will be freed once the data stream is closed.
+		 */
+		FileDataStream(std::shared_ptr<std::fstream> s, size_t size, bool freeOnClose = true);
 
 		~FileDataStream();
 
@@ -429,15 +263,10 @@ namespace CamelotFramework
          */
 		size_t write(const void* buf, size_t count);
 
-        /** 
-		 * @copydoc DataStream::readLine
-         */
-        size_t readLine(char* buf, size_t maxCount, const String& delim = "\n");
-		
         /** 
 		 * @copydoc DataStream::skip
          */
-		void skip(long count);
+		void skip(size_t count);
 	
         /** 
 		 * @copydoc DataStream::seek
@@ -458,6 +287,14 @@ namespace CamelotFramework
 		 * @copydoc DataStream::close
          */
         void close();
+
+	protected:
+		std::shared_ptr<std::istream> mpInStream;
+		std::shared_ptr<std::ifstream> mpFStreamRO;
+		std::shared_ptr<std::fstream> mpFStream;
+		bool mFreeOnClose;	
+
+		void determineAccess();
 	};
 }
 

+ 20 - 65
CamelotUtility/Include/CmDynLibManager.h

@@ -1,83 +1,38 @@
-/*
------------------------------------------------------------------------------
-This source file is part of OGRE
-    (Object-oriented Graphics Rendering Engine)
-For the latest info, see http://www.ogre3d.org/
-
-Copyright (c) 2000-2011 Torus Knot Software Ltd
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
------------------------------------------------------------------------------
-*/
 #pragma once
 
 #include "CmPrerequisitesUtil.h"
 #include "CmModule.h"
 
-namespace CamelotFramework {
-	/** \addtogroup Core
-	*  @{
-	*/
-	/** \addtogroup General
-	*  @{
-	*/
-	/** Manager for Dynamic-loading Libraries.
-        @remarks
-            This manager keeps a track of all the open dynamic-loading
-            libraries, opens them and returns references to already-open
-            libraries.
-    */
+namespace CamelotFramework 
+{
+    /**
+	 * @brief	This manager keeps a track of all the open dynamic-loading
+	 *			libraries, opens them and returns references to already-open
+	 *			libraries.
+	 *			
+	 * @note	Not thread safe.
+     */
     class CM_UTILITY_EXPORT DynLibManager: public Module<DynLibManager>
     {
-	protected:
-		typedef Map<String, DynLib*>::type DynLibList;
-		DynLibList mLibList;
     public:
-        /** Default constructor.
-            @note
-                <br>Should never be called as the singleton is automatically
-                created during the creation of the Root object.
-            @see
-                Root::Root
-        */
         DynLibManager();
-
-        /** Default destructor.
-            @see
-                Root::~Root
-        */
         virtual ~DynLibManager();
 
-        /** Loads the passed library.
-            @param
-                filename The name of the library. The extension can be omitted
-        */
+        /**
+         * @brief	Loads the given file as a dynamic library.
+         *
+         * @param	filename	The name of the library. The extension can be omitted
+         */
         DynLib* load(const String& filename);
 
-		/** Unloads the passed library.
-		@param
-		filename The name of the library. The extension can be omitted
-		*/
+		/**
+		 * @brief	Unloads the given library.
+		 */
 		void unload(DynLib* lib);
+
+	protected:
+		Map<String, DynLib*>::type mLoadedLibraries;
     };
 
 	CM_UTILITY_EXPORT DynLibManager& gDynLibManager();
-	/** @} */
-	/** @} */
 }

+ 67 - 51
CamelotUtility/Include/CmException.h

@@ -9,124 +9,140 @@
 
 namespace CamelotFramework
 {
+	/**
+	 * @brief	Base class for all Banshee exceptions.
+	 */
 	class CM_UTILITY_EXPORT Exception : public std::exception
     {
-    protected:
-        long mLine;
-		String mTypeName;
-        String mDescription;
-        String mSource;
-        String mFile;
-		mutable String mFullDesc;
     public:
-        /** Default constructor.
-        */
 		Exception(const char* type, const String& description, const String& source);
-
-        /** Advanced constructor.
-        */
 		Exception(const char* type, const String& description, const String& source, const char* file, long line);
 
-        /** Copy constructor.
-        */
         Exception(const Exception& rhs);
-
-		/// Needed for  compatibility with std::exception
 		~Exception() throw() {}
 
-        /** Assignment operator.
-        */
         void operator = (const Exception& rhs);
 
-        /** Returns a string with the full description of this error.
-            @remarks
-                The description contains the error number, the description
-                supplied by the thrower, what routine threw the exception,
-                and will also supply extra platform-specific information
-                where applicable. For example - in the case of a rendering
-                library error, the description of the error will include both
-                the place in which OGRE found the problem, and a text
-                description from the 3D rendering library, if available.
-        */
+		/**
+		 * @brief	Returns a string with the full description of the exception.
+		 *
+		 * @note	The description contains the error number, the description
+		 *			supplied by the thrower, what routine threw the exception,
+		 *			and will also supply extra platform-specific information
+		 *			where applicable.
+		 */
 		virtual const String& getFullDescription() const;
 
-        /** Gets the source function.
-        */
+		/**
+		 * @brief	Gets the source function that threw the exception.
+		 */
 		virtual const String& getSource() const { return mSource; }
 
-        /** Gets source file name.
-        */
+		/**
+		 * @brief	Gets the source file name in which the exception was thrown.
+		 */
 		virtual const String& getFile() const { return mFile; }
 
-        /** Gets line number.
-        */
+        /**
+         * @brief	Gets line number on which the exception was thrown.
+         */
         virtual long getLine() const { return mLine; }
 
-		/** Returns a string with only the 'description' field of this exception. Use 
-			getFullDescriptionto get a full description of the error including line number,
-			error number and what function threw the exception.
-        */
+		/**
+		 * @brief	Gets a short description about the exception.
+		 */
 		virtual const String& getDescription(void) const { return mDescription; }
 
-		/// Override std::exception::what
+		/**
+		 * @brief	Overriden std::exception::what. Returns the same value as "getFullDescription".
+		 */
 		const char* what() const throw() { return getFullDescription().c_str(); }
+
+	protected:
+		long mLine;
+		String mTypeName;
+		String mDescription;
+		String mSource;
+		String mFile;
+		mutable String mFullDesc;
     };
 
+	/**
+	 * @brief	Exception for signaling not implemented parts of the code.
+	 */
 	class CM_UTILITY_EXPORT NotImplementedException : public Exception 
 	{
 	public:
 		NotImplementedException(const String& inDescription, const String& inSource, const char* inFile, long inLine)
 			: Exception("NotImplementedException", inDescription, inSource, inFile, inLine) {}
 	};
+
+	/**
+	 * @brief	Exception for signaling file system errors when file could not be found.
+	 */
 	class CM_UTILITY_EXPORT FileNotFoundException : public Exception
 	{
 	public:
 		FileNotFoundException(const String& inDescription, const String& inSource, const char* inFile, long inLine)
 			: Exception("FileNotFoundException", inDescription, inSource, inFile, inLine) {}
 	};
+
+	/**
+	 * @brief	Exception for signaling general IO errors.
+	 * 			
+	 * @note	An example being failed to open a file or a network connection.
+	 */
 	class CM_UTILITY_EXPORT IOException : public Exception
 	{
 	public:
 		IOException(const String& inDescription, const String& inSource, const char* inFile, long inLine)
 			: Exception("IOException", inDescription, inSource, inFile, inLine) {}
 	};
+
+	/**
+	 * @brief	Exception for signaling not currently executing code in not in a valid state.
+	 */
 	class CM_UTILITY_EXPORT InvalidStateException : public Exception
 	{
 	public:
 		InvalidStateException(const String& inDescription, const String& inSource, const char* inFile, long inLine)
 			: Exception("InvalidStateException", inDescription, inSource, inFile, inLine) {}
 	};
+
+	/**
+	 * @brief	Exception for signaling not some parameters you have provided are not valid.
+	 */
 	class CM_UTILITY_EXPORT InvalidParametersException : public Exception
 	{
 	public:
 		InvalidParametersException(const String& inDescription, const String& inSource, const char* inFile, long inLine)
 			: Exception("InvalidParametersException", inDescription, inSource, inFile, inLine) {}
 	};
-	class CM_UTILITY_EXPORT ItemIdentityException : public Exception
-	{
-	public:
-		ItemIdentityException(const String& inDescription, const String& inSource, const char* inFile, long inLine)
-			: Exception("ItemIdentityException", inDescription, inSource, inFile, inLine) {}
-	};
+
+	/**
+	 * @brief	Exception for signaling an internal error, normally something that shouldn't have happened or
+	 * 			wasn't anticipated by the programmers of that system.
+	 */
 	class CM_UTILITY_EXPORT InternalErrorException : public Exception
 	{
 	public:
 		InternalErrorException(const String& inDescription, const String& inSource, const char* inFile, long inLine)
 			: Exception("InternalErrorException", inDescription, inSource, inFile, inLine) {}
 	};
+
+	/**
+	 * @brief	Exception for signaling an error in a rendering API.
+	 */
 	class CM_UTILITY_EXPORT RenderingAPIException : public Exception
 	{
 	public:
 		RenderingAPIException(const String& inDescription, const String& inSource, const char* inFile, long inLine)
 			: Exception("RenderingAPIException", inDescription, inSource, inFile, inLine) {}
 	};
-	class CM_UTILITY_EXPORT RuntimeAssertionException : public Exception
-	{
-	public:
-		RuntimeAssertionException(const String& inDescription, const String& inSource, const char* inFile, long inLine)
-			: Exception("RuntimeAssertionException", inDescription, inSource, inFile, inLine) {}
-	};
 
+	/**
+	 * @brief Macro for throwing exceptions that will automatically fill out function name, file name and line number of the exception.
+	 */
 #ifndef CM_EXCEPT
 #define CM_EXCEPT(type, desc)	\
 	{                           \

+ 84 - 1
CamelotUtility/Include/CmFileSystem.h

@@ -4,28 +4,111 @@
 
 namespace CamelotFramework
 {
+	/**
+	 * @brief	Utility class for dealing with files.
+	 */
 	class CM_UTILITY_EXPORT FileSystem
 	{
 	public:
+		/**
+		 * @brief	Opens a file and returns a data stream capable of reading or writing to that file.
+		 *
+		 * @param	fullPath	Full path to a file.
+		 * @param	readOnly	(optional) If true, returned stream will only be readable.
+		 */
 		static DataStreamPtr openFile(const WString& fullPath, bool readOnly = true);
+
+		/**
+		 * @brief	Opens a file and returns a data stream capable of reading and writing to that file.
+		 * 			If file doesn't exist new one will be created.
+		 *
+		 * @param	fullPath	Full path to a file.
+		 */
 		static DataStreamPtr createAndOpenFile(const WString& fullPath);
 
+		/**
+		 * @brief	Returns the size of a file in bytes.
+		 *
+		 * @param	fullPath	Full path to a file.
+		 */
 		static UINT64 getFileSize(const WString& fullPath);
 
+		/**
+		 * @brief	Deletes a file or a folder at the specified path.
+		 *
+		 * @param	fullPath   	Full path to a file or a folder..
+		 * @param	recursively	(optional) If true, non-empty folders will have their contents
+		 * 						deleted as well. Otherwise an exception will be
+		 * 						thrown for non-empty folders.
+		 */
 		static void remove(const WString& fullPath, bool recursively = true);
+
+		/**
+		 * @brief	Moves a file or a folder from one to another path. This
+		 * 			can also be used as a rename operation.
+		 *
+		 * @param	oldPath			 	Full path to the old file/folder.
+		 * @param	newPath			 	Full path to the new file/folder.
+		 * @param	overwriteExisting	(optional) If true, any existing file/folder at the new location will be overwritten,
+		 * 								otherwise an exception will be thrown if a file/folder already exists.
+		 */
 		static void move(const WString& oldPath, const WString& newPath, bool overwriteExisting = true);
 
+		/**
+		 * @brief	Creates a folder at the specified path.
+		 *
+		 * @param	fullPath	Full path to a full folder to create.
+		 */
 		static void createDir(const WString& fullPath);
 
+		/**
+		 * @brief	Returns true if a file or a folder exists at the specified path.
+		 *
+		 * @param	fullPath	Full path to a file or folder.
+		 */
 		static bool exists(const WString& fullPath);
+
+		/**
+		 * @brief	Returns true if a file exists at the specified path.
+		 *
+		 * @param	fullPath	Full path to a file or folder.
+		 */
 		static bool isFile(const WString& fullPath);
+
+		/**
+		 * @brief	Returns true if a folder exists at the specified path.
+		 *
+		 * @param	fullPath	Full path to a file or folder.
+		 */
 		static bool isDirectory(const WString& fullPath);
 
+		/**
+		 * @brief	Returns all files or folders located in the specified folder.
+		 *
+		 * @param	dirPath			   	Full path to the folder to retrieve children files/folders from.
+		 * @param [out]	files	   		Full paths to all files located directly in specified folder.
+		 * @param [out]	directories		Full paths to all folders located directly in specified folder.
+		 */
 		static void getChildren(const WString& dirPath, Vector<WString>::type& files, Vector<WString>::type& directories);
 
+		/**
+		 * @brief	Returns the last modified time of a file or a folder at the specified path.
+		 *
+		 * @param	fullPath	Full path to a file or a folder.
+		 */
 		static std::time_t getLastModifiedTime(const WString& fullPath);
 
+		/**
+		 * @brief	Returns the path to the currently working directory.
+		 */
 		static WString getWorkingDirectoryPath();
-		static WString getParentDirectory(const WString& path);
+
+		/**
+		 * @brief	Returns a parent path of the provided file path.
+		 * 			If path represents a directory, then that directory path is returned.
+		 * 			
+		 * @param	fullPath	Full path to a file.
+		 */
+		static WString getParentDirectory(const WString& fullPath);
 	};
 }

+ 5 - 3
CamelotUtility/Include/CmFrameAlloc.h

@@ -5,13 +5,11 @@
 namespace CamelotFramework
 {
 	/**
-	 * @brief	Frame allocator. Very fast allocations but can only free all of its memory at once.
+	 * @brief	Frame allocator. Performs very fast allocations but can only free all of its memory at once.
 	 * 			Perfect for allocations that last just a single frame.
 	 * 			
 	 * @note	Not thread safe with an exception. "alloc" and "clear" methods need to be called from the same thread.
 	 * 			"dealloc" is thread safe and can be called from any thread.
-	 * 			
-	 *			Each allocation comes with a pretty hefty 4 byte memory overhead, so don't use it for small allocations.
 	 */
 	class CM_UTILITY_EXPORT FrameAlloc
 	{
@@ -38,6 +36,8 @@ namespace CamelotFramework
 		 * @brief	Allocates a new block of memory of the specified size.
 		 *
 		 * @param	amount	Amount of memory to allocate, in bytes.
+		 * 					
+		 * @note	Not thread safe.
 		 */
 		UINT8* alloc(UINT32 amount);
 
@@ -53,6 +53,8 @@ namespace CamelotFramework
 
 		/**
 		 * @brief	Deallocates all allocated memory.
+		 * 			
+		 * @note	Not thread safe.
 		 */
 		void clear();
 

+ 5 - 0
CamelotUtility/Include/CmFwdDeclUtil.h

@@ -62,6 +62,11 @@ namespace CamelotFramework
 	typedef std::shared_ptr<MeshData> MeshDataPtr;
 	typedef std::shared_ptr<PixelData> PixelDataPtr;
 	typedef std::shared_ptr<GpuResourceData> GpuResourceDataPtr;
+	typedef std::shared_ptr<DataStream> DataStreamPtr;
+	typedef std::shared_ptr<MemoryDataStream> MemoryDataStreamPtr;
+
+	typedef List<DataStreamPtr>::type DataStreamList;
+	typedef std::shared_ptr<DataStreamList> DataStreamListPtr;
 
 	enum TypeID_Utility
 	{

+ 0 - 36
CamelotUtility/Include/CmKeyValuepair.h

@@ -1,36 +0,0 @@
-#pragma once
-
-#include "CmPrerequisitesUtil.h"
-#include "CmIReflectable.h"
-#include "CmRTTIType.h"
-
-namespace CamelotFramework
-{
-	template <typename Key, typename Value, typename RTTIClass>
-	class KeyValuePair : public IReflectable
-	{
-	public:
-		KeyValuePair() {}
-		KeyValuePair(const Key& key, const Value& value)
-			:mKey(key), mValue(value)
-		{ }
-
-		Key mKey;
-		Value mValue;
-
-		/************************************************************************/
-		/* 								RTTI		                     		*/
-		/************************************************************************/
-
-	public:
-		static RTTITypeBase* getRTTIStatic()
-		{
-			return RTTIClass::instance();
-		}
-
-		virtual RTTITypeBase* getRTTI() const
-		{
-			return KeyValuePair<Key, Value, RTTIClass>::getRTTIStatic();
-		}
-	};
-}

+ 8 - 24
CamelotUtility/Include/CmLog.h

@@ -6,8 +6,8 @@
 namespace CamelotFramework
 {
 	/**
-	 * @brief	A single log entry, usually used in QtLogModel as
-	 * 			a representation of a log entry in the Console window.
+	 * @brief	A single log entry, containing a message and a channel the message
+	 * 			was recorded on.
 	 */
 	class CM_UTILITY_EXPORT LogEntry
 	{
@@ -23,29 +23,17 @@ namespace CamelotFramework
 	};
 
 	/**
-	 * @brief	Used for logging messages to a file. Can also send out callbacks to
-	 * 			registered classes when a message is received, so they can do with it as they wish.
+	 * @brief	Used for logging messages. Can categorize messages according to channels, save the log to a file
+	 * 			and send out callbacks when a new message is added.
 	 */
 	class CM_UTILITY_EXPORT Log
 	{
 	public:
-		/**
-		 * @brief	Constructor.
-		 *
-		 * @param	logFilePath		  	Full pathname of the log file. Should have a .html extension.
-		 * @param	autoSave		  	(optional) Whether to save the log to disk whenever a new message
-		 * 								is added. (Useful when you want to make sure your log is up to
-		 * 								date after a crash). The log file will only be saved on exit, or
-		 * 								if you call save manually.
-		 * @param	suppressFileOutput	(optional) If true, log won't be saved to a file, even if you
-		 * 								call save manually.
-		 */
-		Log(const String& logFilePath = "", bool autoSave = true, bool suppressFileOutput = false);
+		Log();
 		~Log();
 
 		/**
-		 * @brief	Logs a new message. If autoSave is enabled it will automatically save the message to
-		 * 			disk.
+		 * @brief	Logs a new message. 
 		 *
 		 * @param	message	The message describing the log entry.
 		 * @param	channel Channel in which to store the log entry.
@@ -53,22 +41,18 @@ namespace CamelotFramework
 		void logMsg(const String& message, const String& channel);
 
 		/**
-		 * @brief	Removes all log entries. If autoSave is enabled the file on disk will be cleared too.
+		 * @brief	Removes all log entries. 
 		 */
 		void clear();
 
 		/**
 		 * @brief	Saves the log file to disk.
 		 */
-		void flush();
+		void saveToFile(const WString& path);
 
 	private:
 		Vector<LogEntry*>::type mEntries;
 
-		bool mAutoSave;
-		bool mSuppressFileOutput;
-		String mSaveFilePath;
-
 		/**
 		 * @brief	Called whenever a new entry is added.
 		 */

+ 8 - 2
CamelotUtility/Include/CmManagedDataBlock.h

@@ -6,6 +6,9 @@ namespace CamelotFramework
 {
 	/**
 	 * @brief	Data block holding an array of bytes, usually used in serialization.
+	 * 			
+	 *			Ownership of the data blocked is passed to the latest copy of the ManagedDataBlock.
+	 *			Data will be automatically freed once the last copy is destroyed.
 	 */
 	class CM_UTILITY_EXPORT ManagedDataBlock
 	{
@@ -13,11 +16,13 @@ namespace CamelotFramework
 		/**
 		 * @brief	Constructor
 		 *
-		 * @param [in]	data		Array of bytes to store. Direct pointer to the provided
+		 * @param 	data			Array of bytes to store. Direct pointer to the provided
 		 * 							array will be stored, no copying will be done. 
 		 * @param	size			Size of the array, in bytes.
+		 * @param	deallocator		Deallocator that will be used for freeing the data. If null, the default
+		 * 							deallocator will be used.	
 		 */
-		ManagedDataBlock(UINT8* data, UINT32 size);
+		ManagedDataBlock(UINT8* data, UINT32 size, std::function<void(UINT8*)> deallocator = nullptr); 
 
 		/**
 		 * @brief	Constructor that will automatically allocate an internal buffer of the specified size.
@@ -39,6 +44,7 @@ namespace CamelotFramework
 		UINT8* mData;
 		UINT32 mSize;
 		bool mManaged;
+		std::function<void(UINT8*)> mDeallocator;
 		mutable bool mIsDataOwner;
 	};
 }

+ 16 - 2
CamelotUtility/Include/CmMemAllocProfiler.h

@@ -4,6 +4,7 @@ namespace CamelotFramework
 {
 	/**
 	 * @brief	Specialized allocator for profiler so we can avoid tracking internal profiler memory allocations
+	 * 			which would skew profiler results.
 	 */
 	class ProfilerAlloc
 	{};
@@ -16,21 +17,34 @@ namespace CamelotFramework
 	class MemoryAllocator<ProfilerAlloc> : public MemoryAllocatorBase
 	{
 	public:
-		static inline void* allocate(UINT32 bytes)
+		/**
+		 * @brief	Allocates the given number of bytes.
+		 */
+		static inline void* allocate(size_t bytes)
 		{
 			return malloc(bytes);
 		}
 
-		static inline void* allocateArray(UINT32 bytes, UINT32 count)
+		/**
+		 * @brief	Allocates the given a number of objects, each of the given number of bytes.
+		 */
+		static inline void* allocateArray(size_t bytes, UINT32 count)
 		{
 			return malloc(bytes * count);
 		}
 
+		/**
+		 * @brief	Frees memory previously allocated with "allocate".
+		 */
 		static inline void free(void* ptr)
 		{
 			::free(ptr);
 		}
 
+		/**
+		 * @brief	Frees memory previously allocated with "freeArray". "count" must match the
+		 * 			original value when array was allocated.
+		 */
 		static inline void freeArray(void* ptr, UINT32 count)
 		{
 			::free(ptr);

+ 5 - 5
CamelotUtility/Include/CmMemoryAllocator.h

@@ -49,7 +49,7 @@ namespace CamelotFramework
 	class MemoryAllocator : public MemoryAllocatorBase
 	{
 	public:
-		static inline void* allocate(UINT32 bytes)
+		static inline void* allocate(size_t bytes)
 		{
 #if CM_PROFILING_ENABLED
 			incAllocCount();
@@ -58,7 +58,7 @@ namespace CamelotFramework
 			return malloc(bytes);
 		}
 
-		static inline void* allocateArray(UINT32 bytes, UINT32 count)
+		static inline void* allocateArray(size_t bytes, UINT32 count)
 		{
 #if CM_PROFILING_ENABLED
 			incAllocCount();
@@ -112,7 +112,7 @@ namespace CamelotFramework
 	 * @brief	Allocates the specified number of bytes.
 	 */
 	template<class Alloc> 
-	inline void* cm_alloc(UINT32 count)
+	inline void* cm_alloc(size_t count)
 	{
 		return MemoryAllocator<Alloc>::allocate(count);
 	}
@@ -204,7 +204,7 @@ namespace CamelotFramework
 	/**
 	 * @brief	Allocates the specified number of bytes.
 	 */
-	inline void* cm_alloc(UINT32 count)
+	inline void* cm_alloc(size_t count)
 	{
 		return MemoryAllocator<GenAlloc>::allocate(count);
 	}
@@ -360,7 +360,7 @@ namespace CamelotFramework
 		// allocate but don't initialize num elements of type T
 		pointer allocate (size_type num, const void* = 0) 
 		{
-			pointer ret = (pointer)(cm_alloc<Alloc>((UINT32)num*sizeof(T)));
+			pointer ret = (pointer)(cm_alloc<Alloc>((size_t)num*sizeof(T)));
 			return ret;
 		}
 

+ 90 - 461
CamelotUtility/Source/CmDataStream.cpp

@@ -4,304 +4,88 @@
 
 namespace CamelotFramework 
 {
-    template <typename T> DataStream& DataStream::operator >>(T& val)
-    {
-        read(static_cast<void*>(&val), sizeof(T));
-        return *this;
-    }
+	const UINT32 DataStream::StreamTempSize = 128;
 
-    String DataStream::getLine(bool trimAfter)
+    template <typename T> DataStream& DataStream::operator>> (T& val)
     {
-        char tmpBuf[OGRE_STREAM_TEMP_SIZE];
-        String retString;
-        size_t readCount;
-        // Keep looping while not hitting delimiter
-        while ((readCount = read(tmpBuf, OGRE_STREAM_TEMP_SIZE-1)) != 0)
-        {
-            // Terminate string
-            tmpBuf[readCount] = '\0';
-
-            char* p = strchr(tmpBuf, '\n');
-            if (p != 0)
-            {
-                // Reposition backwards
-                skip((long)(p + 1 - tmpBuf - readCount));
-                *p = '\0';
-            }
-
-            retString += tmpBuf;
-
-            if (p != 0)
-            {
-                // Trim off trailing CR if this was a CR/LF entry
-                if (retString.length() && retString[retString.length()-1] == '\r')
-                {
-                    retString.erase(retString.length()-1, 1);
-                }
-
-                // Found terminator, break out
-                break;
-            }
-        }
-
-        if (trimAfter)
-        {
-            StringUtil::trim(retString);
-        }
+        read(static_cast<void*>(&val), sizeof(T));
 
-        return retString;
+        return *this;
     }
 
-    size_t DataStream::readLine(char* buf, size_t maxCount, const String& delim)
-    {
-		// Deal with both Unix & Windows LFs
-		bool trimCR = false;
-		if (delim.find_first_of('\n') != String::npos)
+	String DataStream::getAsString()
+	{
+		// Read the entire buffer - ideally in one read, but if the size of
+		// the buffer is unknown, do multiple fixed size reads.
+		size_t bufSize = (mSize > 0 ? mSize : 4096);
+		StringStream::char_type* tempBuffer = (StringStream::char_type*)cm_alloc(bufSize);
+
+		// Ensure read from begin of stream
+		seek(0);
+		StringStream result;
+		while (!eof())
 		{
-			trimCR = true;
+			size_t numReadBytes = read(tempBuffer, bufSize);
+			result.write(tempBuffer, numReadBytes);
 		}
 
-        char tmpBuf[OGRE_STREAM_TEMP_SIZE];
-        size_t chunkSize = std::min(maxCount, (size_t)OGRE_STREAM_TEMP_SIZE-1);
-        size_t totalCount = 0;
-        size_t readCount; 
-        while (chunkSize && (readCount = read(tmpBuf, chunkSize)) != 0)
-        {
-            // Terminate
-            tmpBuf[readCount] = '\0';
-
-            // Find first delimiter
-            size_t pos = strcspn(tmpBuf, delim.c_str());
-
-            if (pos < readCount)
-            {
-                // Found terminator, reposition backwards
-                skip((long)(pos + 1 - readCount));
-            }
-
-            // Are we genuinely copying?
-            if (buf)
-            {
-                memcpy(buf+totalCount, tmpBuf, pos);
-            }
-            totalCount += pos;
-
-            if (pos < readCount)
-            {
-                // Trim off trailing CR if this was a CR/LF entry
-                if (trimCR && totalCount && buf[totalCount-1] == '\r')
-                {
-                    --totalCount;
-                }
-
-                // Found terminator, break out
-                break;
-            }
-
-            // Adjust chunkSize for next time
-            chunkSize = std::min(maxCount-totalCount, (size_t)OGRE_STREAM_TEMP_SIZE-1);
-        }
-
-        // Terminate
-        buf[totalCount] = '\0';
-
-        return totalCount;
-    }
-
-    size_t DataStream::skipLine(const String& delim)
-    {
-        char tmpBuf[OGRE_STREAM_TEMP_SIZE];
-        size_t total = 0;
-        size_t readCount;
-        // Keep looping while not hitting delimiter
-        while ((readCount = read(tmpBuf, OGRE_STREAM_TEMP_SIZE-1)) != 0)
-        {
-            // Terminate string
-            tmpBuf[readCount] = '\0';
-
-            // Find first delimiter
-            size_t pos = strcspn(tmpBuf, delim.c_str());
-
-            if (pos < readCount)
-            {
-                // Found terminator, reposition backwards
-                skip((long)(pos + 1 - readCount));
-
-                total += pos + 1;
-
-                // break out
-                break;
-            }
-
-            total += readCount;
-        }
+		free(tempBuffer);
+		return result.str();
+	}
 
-        return total;
-    }
+	WString DataStream::getAsWString()
+	{
+		// Read the entire buffer - ideally in one read, but if the size of
+		// the buffer is unknown, do multiple fixed size reads.
+		size_t bufSize = (mSize > 0 ? mSize : 4096);
+		WStringStream::char_type* tempBuffer = (WStringStream::char_type*)cm_alloc(bufSize);
+
+		// Ensure read from begin of stream
+		seek(0);
+		WStringStream result;
+		while (!eof())
+		{
+			size_t numReadBytes = read(tempBuffer, bufSize);
+			result.write(tempBuffer, numReadBytes);
+		}
 
-    String DataStream::getAsString()
-    {
-        // Read the entire buffer - ideally in one read, but if the size of
-        // the buffer is unknown, do multiple fixed size reads.
-        size_t bufSize = (mSize > 0 ? mSize : 4096);
-        char* pBuf = (char*)malloc(sizeof(char) * bufSize);
-        // Ensure read from begin of stream
-        seek(0);
-        String result;
-        while (!eof())
-        {
-            size_t nr = read(pBuf, bufSize);
-            result.append(pBuf, nr);
-        }
-        free(pBuf);
-        return result;
-    }
+		free(tempBuffer);
+		return result.str();
+	}
 
-    MemoryDataStream::MemoryDataStream(void* pMem, size_t inSize, bool freeOnClose, bool readOnly)
-		: DataStream(static_cast<UINT16>(readOnly ? READ : (READ | WRITE)))
+    MemoryDataStream::MemoryDataStream(void* memory, size_t inSize)
+		: DataStream(READ | WRITE), mData(nullptr)
     {
-        mData = mPos = static_cast<UINT8*>(pMem);
+        mData = mPos = static_cast<UINT8*>(memory);
         mSize = inSize;
         mEnd = mData + mSize;
-        mFreeOnClose = freeOnClose;
-        assert(mEnd >= mPos);
-    }
 
-    MemoryDataStream::MemoryDataStream(const String& name, void* pMem, size_t inSize, 
-        bool freeOnClose, bool readOnly)
-        : DataStream(name, static_cast<UINT16>(readOnly ? READ : (READ | WRITE)))
-    {
-        mData = mPos = static_cast<UINT8*>(pMem);
-        mSize = inSize;
-        mEnd = mData + mSize;
-        mFreeOnClose = freeOnClose;
         assert(mEnd >= mPos);
     }
 
-    MemoryDataStream::MemoryDataStream(DataStream& sourceStream, 
-        bool freeOnClose, bool readOnly)
-        : DataStream(static_cast<UINT16>(readOnly ? READ : (READ | WRITE)))
+    MemoryDataStream::MemoryDataStream(DataStream& sourceStream)
+        : DataStream(READ | WRITE), mData(nullptr)
     {
         // Copy data from incoming stream
         mSize = sourceStream.size();
-        if (mSize == 0 && !sourceStream.eof())
-        {
-            // size of source is unknown, read all of it into memory
-            String contents = sourceStream.getAsString();
-            mSize = contents.size();
-            mData = (UINT8*)malloc(sizeof(UINT8) * mSize);
-            mPos = mData;
-            memcpy(mData, contents.data(), mSize);
-            mEnd = mData + mSize;
-        }
-        else
-        {
-            mData = (UINT8*)malloc(sizeof(UINT8) * mSize);
-            mPos = mData;
-            mEnd = mData + sourceStream.read(mData, mSize);
-            mFreeOnClose = freeOnClose;
-        }
-        assert(mEnd >= mPos);
-    }
 
-    MemoryDataStream::MemoryDataStream(DataStreamPtr& sourceStream, 
-        bool freeOnClose, bool readOnly)
-        : DataStream(static_cast<UINT16>(readOnly ? READ : (READ | WRITE)))
-    {
-        // Copy data from incoming stream
-        mSize = sourceStream->size();
-        if (mSize == 0 && !sourceStream->eof())
-        {
-            // size of source is unknown, read all of it into memory
-            String contents = sourceStream->getAsString();
-            mSize = contents.size();
-            mData = (UINT8*)malloc(sizeof(UINT8) * mSize);
-            mPos = mData;
-            memcpy(mData, contents.data(), mSize);
-            mEnd = mData + mSize;
-        }
-        else
-        {
-            mData = (UINT8*)malloc(sizeof(UINT8) * mSize);
-            mPos = mData;
-            mEnd = mData + sourceStream->read(mData, mSize);
-            mFreeOnClose = freeOnClose;
-        }
-        assert(mEnd >= mPos);
-    }
+		mData = (UINT8*)cm_alloc(sizeof(UINT8) * mSize);
+		mPos = mData;
+		mEnd = mData + sourceStream.read(mData, mSize);
 
-    MemoryDataStream::MemoryDataStream(const String& name, DataStream& sourceStream, 
-        bool freeOnClose, bool readOnly)
-        : DataStream(name, static_cast<UINT16>(readOnly ? READ : (READ | WRITE)))
-    {
-        // Copy data from incoming stream
-        mSize = sourceStream.size();
-        if (mSize == 0 && !sourceStream.eof())
-        {
-            // size of source is unknown, read all of it into memory
-            String contents = sourceStream.getAsString();
-            mSize = contents.size();
-            mData = (UINT8*)malloc(sizeof(UINT8) * mSize);
-            mPos = mData;
-            memcpy(mData, contents.data(), mSize);
-            mEnd = mData + mSize;
-        }
-        else
-        {
-            mData = (UINT8*)malloc(sizeof(UINT8) * mSize);
-            mPos = mData;
-            mEnd = mData + sourceStream.read(mData, mSize);
-            mFreeOnClose = freeOnClose;
-        }
         assert(mEnd >= mPos);
     }
 
-    MemoryDataStream::MemoryDataStream(const String& name, const DataStreamPtr& sourceStream, 
-        bool freeOnClose, bool readOnly)
-        : DataStream(name, static_cast<UINT16>(readOnly ? READ : (READ | WRITE)))
+    MemoryDataStream::MemoryDataStream(const DataStreamPtr& sourceStream)
+        :DataStream(READ | WRITE), mData(nullptr)
     {
         // Copy data from incoming stream
         mSize = sourceStream->size();
-        if (mSize == 0 && !sourceStream->eof())
-        {
-            // size of source is unknown, read all of it into memory
-            String contents = sourceStream->getAsString();
-            mSize = contents.size();
-            mData = (UINT8*)malloc(sizeof(UINT8) * mSize);
-            mPos = mData;
-            memcpy(mData, contents.data(), mSize);
-            mEnd = mData + mSize;
-        }
-        else
-        {
-            mData = (UINT8*)malloc(sizeof(UINT8) * mSize);
-            mPos = mData;
-            mEnd = mData + sourceStream->read(mData, mSize);
-            mFreeOnClose = freeOnClose;
-        }
-        assert(mEnd >= mPos);
-    }
 
-    MemoryDataStream::MemoryDataStream(size_t inSize, bool freeOnClose, bool readOnly)
-        : DataStream(static_cast<UINT16>(readOnly ? READ : (READ | WRITE)))
-    {
-        mSize = inSize;
-        mFreeOnClose = freeOnClose;
-        mData = (UINT8*)malloc(sizeof(UINT8) * mSize);
-        mPos = mData;
-        mEnd = mData + mSize;
-        assert(mEnd >= mPos);
-    }
+		mData = (UINT8*)cm_alloc(sizeof(UINT8) * mSize);
+		mPos = mData;
+		mEnd = mData + sourceStream->read(mData, mSize);
 
-    MemoryDataStream::MemoryDataStream(const String& name, size_t inSize, 
-        bool freeOnClose, bool readOnly)
-        : DataStream(name, static_cast<UINT16>(readOnly ? READ : (READ | WRITE)))
-    {
-        mSize = inSize;
-        mFreeOnClose = freeOnClose;
-        mData = (UINT8*)malloc(sizeof(UINT8) * mSize);
-        mPos = mData;
-        mEnd = mData + mSize;
         assert(mEnd >= mPos);
     }
 
@@ -313,16 +97,17 @@ namespace CamelotFramework
     size_t MemoryDataStream::read(void* buf, size_t count)
     {
         size_t cnt = count;
-        // Read over end of memory?
+
         if (mPos + cnt > mEnd)
             cnt = mEnd - mPos;
         if (cnt == 0)
             return 0;
 
-        assert (cnt<=count);
+        assert (cnt <= count);
 
         memcpy(buf, mPos, cnt);
         mPos += cnt;
+
         return cnt;
     }
 
@@ -332,8 +117,7 @@ namespace CamelotFramework
 		if (isWriteable())
 		{
 			written = count;
-			// we only allow writing within the extents of allocated memory
-			// check for buffer overrun & disallow
+
 			if (mPos + written > mEnd)
 				written = mEnd - mPos;
 			if (written == 0)
@@ -342,168 +126,86 @@ namespace CamelotFramework
 			memcpy(mPos, buf, written);
 			mPos += written;
 		}
+
 		return written;
 	}
 
-    size_t MemoryDataStream::readLine(char* buf, size_t maxCount, const String& delim)
+    void MemoryDataStream::skip(size_t count)
     {
-        // Deal with both Unix & Windows LFs
-		bool trimCR = false;
-		if (delim.find_first_of('\n') != String::npos)
-		{
-			trimCR = true;
-		}
-
-        size_t pos = 0;
-
-        // Make sure pos can never go past the end of the data 
-        while (pos < maxCount && mPos < mEnd)
-        {
-            if (delim.find(*mPos) != String::npos)
-            {
-                // Trim off trailing CR if this was a CR/LF entry
-                if (trimCR && pos && buf[pos-1] == '\r')
-                {
-                    // terminate 1 character early
-                    --pos;
-                }
-
-                // Found terminator, skip and break out
-                ++mPos;
-                break;
-            }
-
-            buf[pos++] = *mPos++;
-        }
-
-        // terminate
-        buf[pos] = '\0';
-
-        return pos;
-    }
-
-    size_t MemoryDataStream::skipLine(const String& delim)
-    {
-        size_t pos = 0;
-
-        // Make sure pos can never go past the end of the data 
-        while (mPos < mEnd)
-        {
-            ++pos;
-            if (delim.find(*mPos++) != String::npos)
-            {
-                // Found terminator, break out
-                break;
-            }
-        }
-
-        return pos;
-
-    }
-
-    void MemoryDataStream::skip(long count)
-    {
-        size_t newpos = (size_t)( ( mPos - mData ) + count );
-        assert( mData + newpos <= mEnd );        
+        size_t newpos = (size_t)( (mPos - mData) + count );
+        assert(mData + newpos <= mEnd);        
 
         mPos = mData + newpos;
     }
 
-    void MemoryDataStream::seek( size_t pos )
+    void MemoryDataStream::seek(size_t pos)
     {
-        assert( mData + pos <= mEnd );
+        assert(mData + pos <= mEnd);
         mPos = mData + pos;
     }
 
-    size_t MemoryDataStream::tell(void) const
+    size_t MemoryDataStream::tell() const
 	{
-		//mData is start, mPos is current location
 		return mPos - mData;
 	}
 
-    bool MemoryDataStream::eof(void) const
+    bool MemoryDataStream::eof() const
     {
         return mPos >= mEnd;
     }
 
-    void MemoryDataStream::close(void)    
+    void MemoryDataStream::close()    
     {
-        if (mFreeOnClose && mData)
+        if (mData != nullptr)
         {
-            free(mData);
-            mData = 0;
+            cm_free(mData);
+            mData = nullptr;
         }
     }
 
     FileDataStream::FileDataStream(std::shared_ptr<std::ifstream> s, bool freeOnClose)
-        : DataStream(), mpInStream(s), mpFStreamRO(s), mpFStream(0), mFreeOnClose(freeOnClose)
+        : DataStream(READ), mpInStream(s), mpFStreamRO(s), mpFStream(0), mFreeOnClose(freeOnClose)
     {
-        // calculate the size
         mpInStream->seekg(0, std::ios_base::end);
         mSize = (size_t)mpInStream->tellg();
         mpInStream->seekg(0, std::ios_base::beg);
-		determineAccess();
-    }
 
-    FileDataStream::FileDataStream(const String& name, 
-        std::shared_ptr<std::ifstream> s, bool freeOnClose)
-        : DataStream(name), mpInStream(s), mpFStreamRO(s), mpFStream(0), mFreeOnClose(freeOnClose)
-    {
-        // calculate the size
-        mpInStream->seekg(0, std::ios_base::end);
-        mSize = (size_t)mpInStream->tellg();
-        mpInStream->seekg(0, std::ios_base::beg);
 		determineAccess();
     }
 
-    FileDataStream::FileDataStream(const String& name, 
-        std::shared_ptr<std::ifstream> s, size_t inSize, bool freeOnClose)
-        : DataStream(name), mpInStream(s), mpFStreamRO(s), mpFStream(0), mFreeOnClose(freeOnClose)
+    FileDataStream::FileDataStream(std::shared_ptr<std::ifstream> s, size_t inSize, bool freeOnClose)
+        : DataStream(READ), mpInStream(s), mpFStreamRO(s), mpFStream(0), mFreeOnClose(freeOnClose)
     {
-        // Size is passed in
         mSize = inSize;
+
 		determineAccess();
     }
 
 	FileDataStream::FileDataStream(std::shared_ptr<std::fstream> s, bool freeOnClose)
-		: DataStream(false), mpInStream(s), mpFStreamRO(0), mpFStream(s), mFreeOnClose(freeOnClose)
+		: DataStream(READ | WRITE), mpInStream(s), mpFStreamRO(0), mpFStream(s), mFreeOnClose(freeOnClose)
 	{
-		// writeable!
-		// calculate the size
 		mpInStream->seekg(0, std::ios_base::end);
 		mSize = (size_t)mpInStream->tellg();
 		mpInStream->seekg(0, std::ios_base::beg);
-		determineAccess();
-
-	}
 
-	FileDataStream::FileDataStream(const String& name, 
-		std::shared_ptr<std::fstream> s, bool freeOnClose)
-		: DataStream(name, false), mpInStream(s), mpFStreamRO(0), mpFStream(s), mFreeOnClose(freeOnClose)
-	{
-		// writeable!
-		// calculate the size
-		mpInStream->seekg(0, std::ios_base::end);
-		mSize = (size_t)mpInStream->tellg();
-		mpInStream->seekg(0, std::ios_base::beg);
 		determineAccess();
 	}
 
-	FileDataStream::FileDataStream(const String& name, 
-		std::shared_ptr<std::fstream> s, size_t inSize, bool freeOnClose)
-		: DataStream(name, false), mpInStream(s), mpFStreamRO(0), mpFStream(s), mFreeOnClose(freeOnClose)
+	FileDataStream::FileDataStream(std::shared_ptr<std::fstream> s, size_t inSize, bool freeOnClose)
+		: DataStream(READ | WRITE), mpInStream(s), mpFStreamRO(0), mpFStream(s), mFreeOnClose(freeOnClose)
 	{
-		// writeable!
-		// Size is passed in
 		mSize = inSize;
+
 		determineAccess();
 	}
 
 	void FileDataStream::determineAccess()
 	{
 		mAccess = 0;
+
 		if (mpInStream)
 			mAccess |= READ;
+
 		if (mpFStream)
 			mAccess |= WRITE;
 	}
@@ -516,6 +218,7 @@ namespace CamelotFramework
     size_t FileDataStream::read(void* buf, size_t count)
     {
 		mpInStream->read(static_cast<char*>(buf), static_cast<std::streamsize>(count));
+
         return (size_t)mpInStream->gcount();
     }
 
@@ -527,114 +230,40 @@ namespace CamelotFramework
 			mpFStream->write(static_cast<const char*>(buf), static_cast<std::streamsize>(count));
 			written = count;
 		}
-		return written;
-	}
 
-    size_t FileDataStream::readLine(char* buf, size_t maxCount,  const String& delim)
-    {
-		if (delim.empty())
-		{
-			CM_EXCEPT(InvalidParametersException, "No delimiter provided");
-		}
-		if (delim.size() > 1)
-		{
-			gDebug().log("WARNING: FileStreamDataStream::readLine - using only first delimeter", "DataStream");
-		}
-		// Deal with both Unix & Windows LFs
-		bool trimCR = false;
-		if (delim.at(0) == '\n') 
-		{
-			trimCR = true;
-		}
-		// maxCount + 1 since count excludes terminator in getline
-		mpInStream->getline(buf, static_cast<std::streamsize>(maxCount+1), delim.at(0));
-		size_t ret = (size_t)mpInStream->gcount();
-		// three options
-		// 1) we had an eof before we read a whole line
-		// 2) we ran out of buffer space
-		// 3) we read a whole line - in this case the delim character is taken from the stream but not written in the buffer so the read data is of length ret-1 and thus ends at index ret-2
-		// in all cases the buffer will be null terminated for us
-
-		if (mpInStream->eof()) 
-		{
-			// no problem
-		}
-		else if (mpInStream->fail())
-		{
-			// Did we fail because of maxCount hit? No - no terminating character
-			// in included in the count in this case
-			if (ret == maxCount)
-			{
-				// clear failbit for next time 
-				mpInStream->clear();
-			}
-			else
-			{
-				CM_EXCEPT(InternalErrorException, "Streaming error occurred");
-			}
-		}
-		else 
-		{
-			// we need to adjust ret because we want to use it as a
-			// pointer to the terminating null character and it is
-			// currently the length of the data read from the stream
-			// i.e. 1 more than the length of the data in the buffer and
-			// hence 1 more than the _index_ of the NULL character
-			--ret;
-		}
-
-		// trim off CR if we found CR/LF
-		if (trimCR && buf[ret-1] == '\r')
-		{
-			--ret;
-			buf[ret] = '\0';
-		}
-		return ret;
+		return written;
 	}
-
-    void FileDataStream::skip(long count)
-    {
-#if defined(STLPORT)
-		// Workaround for STLport issues: After reached eof of file stream,
-		// it's seems the stream was putted in intermediate state, and will be
-		// fail if try to repositioning relative to current position.
-		// Note: tellg() fail in this case too.
-		if (mpInStream->eof())
-		{
-			mpInStream->clear();
-			// Use seek relative to either begin or end to bring the stream
-			// back to normal state.
-			mpInStream->seekg(0, std::ios::end);
-		}
-#endif 		
-		mpInStream->clear(); //Clear fail status in case eof was set
+    void FileDataStream::skip(size_t count)
+    {	
+		mpInStream->clear(); // Clear fail status in case eof was set
 		mpInStream->seekg(static_cast<std::ifstream::pos_type>(count), std::ios::cur);
     }
 
-    void FileDataStream::seek( size_t pos )
+    void FileDataStream::seek(size_t pos)
     {
-		mpInStream->clear(); //Clear fail status in case eof was set
+		mpInStream->clear(); // Clear fail status in case eof was set
 		mpInStream->seekg(static_cast<std::streamoff>(pos), std::ios::beg);
 	}
 
-    size_t FileDataStream::tell(void) const
+    size_t FileDataStream::tell() const
 	{
-		mpInStream->clear(); //Clear fail status in case eof was set
+		mpInStream->clear(); // Clear fail status in case eof was set
+
 		return (size_t)mpInStream->tellg();
 	}
 
-    bool FileDataStream::eof(void) const
+    bool FileDataStream::eof() const
     {
         return mpInStream->eof();
     }
 
-    void FileDataStream::close(void)
+    void FileDataStream::close()
     {
         if (mpInStream)
         {
-			// Unfortunately, there is no file-specific shared class hierarchy between fstream and ifstream (!!)
 			if (mpFStreamRO)
 	            mpFStreamRO->close();
+
 			if (mpFStream)
 			{
 				mpFStream->flush();

+ 17 - 14
CamelotUtility/Source/CmDynLibManager.cpp

@@ -9,27 +9,30 @@ namespace CamelotFramework
 
     DynLib* DynLibManager::load( const String& filename)
     {
-		DynLibList::iterator i = mLibList.find(filename);
-		if (i != mLibList.end())
+		auto iterFind = mLoadedLibraries.find(filename);
+		if (iterFind != mLoadedLibraries.end())
 		{
-			return i->second;
+			return iterFind->second;
 		}
 		else
 		{
-	        DynLib* pLib = cm_new<DynLib>(filename);
-			pLib->load();        
-        	mLibList[filename] = pLib;
-	        return pLib;
+	        DynLib* newLib = new (cm_alloc<DynLib>()) DynLib(filename);
+
+			newLib->load();       
+        	mLoadedLibraries[filename] = newLib;
+
+	        return newLib;
 		}
     }
 
 	void DynLibManager::unload(DynLib* lib)
 	{
-		DynLibList::iterator i = mLibList.find(lib->getName());
-		if (i != mLibList.end())
+		auto iterFind = mLoadedLibraries.find(lib->getName());
+		if (iterFind != mLoadedLibraries.end())
 		{
-			mLibList.erase(i);
+			mLoadedLibraries.erase(iterFind);
 		}
+
 		lib->unload();
 		cm_delete(lib);
 	}
@@ -37,14 +40,14 @@ namespace CamelotFramework
 	DynLibManager::~DynLibManager()
     {
         // Unload & delete resources in turn
-        for( DynLibList::iterator it = mLibList.begin(); it != mLibList.end(); ++it )
+        for(auto& entry : mLoadedLibraries)
         {
-            it->second->unload();
-			cm_delete(it->second);
+            entry.second->unload();
+			cm_delete(entry.second);
         }
 
         // Empty the list
-        mLibList.clear();
+        mLoadedLibraries.clear();
     }
 
 	DynLibManager& gDynLibManager()

+ 6 - 6
CamelotUtility/Source/CmFileSystem.cpp

@@ -44,12 +44,12 @@ namespace CamelotFramework
 		if (rwStream)
 		{
 			// use the writeable stream 
-			stream = cm_new<FileDataStream, ScratchAlloc>(toString(fullPath), rwStream, (size_t)fileSize, true);
+			stream = cm_new<FileDataStream, ScratchAlloc>(rwStream, (size_t)fileSize, true);
 		}
 		else
 		{
 			// read-only stream
-			stream = cm_new<FileDataStream, ScratchAlloc>(toString(fullPath), roStream, (size_t)fileSize, true);
+			stream = cm_new<FileDataStream, ScratchAlloc>(roStream, (size_t)fileSize, true);
 		}
 		return cm_shared_ptr<FileDataStream, ScratchAlloc>(stream);
 	}
@@ -67,7 +67,7 @@ namespace CamelotFramework
 			CM_EXCEPT(FileNotFoundException, "Cannot open file: " + toString(fullPath));
 
 		/// Construct return stream, tell it to delete on destroy
-		return cm_shared_ptr<FileDataStream, ScratchAlloc>(toString(fullPath), rwStream, 0, true);
+		return cm_shared_ptr<FileDataStream, ScratchAlloc>(rwStream, 0, true);
 	}
 
 	UINT64 FileSystem::getFileSize(const WString& fullPath)
@@ -177,9 +177,9 @@ namespace CamelotFramework
 		return current_path().wstring().c_str();
 	}
 
-	WString FileSystem::getParentDirectory(const WString& path)
+	WString FileSystem::getParentDirectory(const WString& fullPath)
 	{
-		boost::filesystem3::path p(path.c_str());
+		boost::filesystem3::path p(fullPath.c_str());
 		
 		if(!is_directory(p))
 		{
@@ -187,6 +187,6 @@ namespace CamelotFramework
 			return dir.wstring().c_str();
 		}
 
-		return path;
+		return fullPath;
 	}
 }

+ 11 - 0
CamelotUtility/Source/CmFrameAlloc.cpp

@@ -37,19 +37,26 @@ namespace CamelotFramework
 
 	UINT8* FrameAlloc::alloc(UINT32 amount)
 	{
+#if CM_DEBUG_MODE
 		amount += sizeof(UINT32);
+#endif
 
 		UINT32 freeMem = mFreeBlock->mSize - mFreeBlock->mFreePtr;
 		if(amount > freeMem)
 			allocBlock(amount);
 
 		UINT8* data = mFreeBlock->alloc(amount);
+
+#if CM_DEBUG_MODE
 		mTotalAllocBytes += amount;
 
 		UINT32* storedSize = reinterpret_cast<UINT32*>(data);
 		*storedSize = amount;
 
 		return data + sizeof(UINT32);
+#else
+		return data;
+#endif
 	}
 
 	void FrameAlloc::dealloc(UINT8* data)
@@ -57,15 +64,19 @@ namespace CamelotFramework
 		// Dealloc is only used for debug and can be removed if needed. All the actual deallocation
 		// happens in "clear"
 			
+#if CM_DEBUG_MODE
 		data -= sizeof(UINT32);
 		UINT32* storedSize = reinterpret_cast<UINT32*>(data);
 		mTotalAllocBytes -= *storedSize;
+#endif
 	}
 
 	void FrameAlloc::clear()
 	{
+#if CM_DEBUG_MODE
 		if(mTotalAllocBytes.load() > 0)
 			CM_EXCEPT(InvalidStateException, "Not all frame allocated bytes were properly released.");
+#endif
 
 		// Merge all blocks into one
 		UINT32 totalBytes = 0;

+ 5 - 31
CamelotUtility/Source/CmLog.cpp

@@ -1,23 +1,19 @@
 #include "CmLog.h"
+#include "CmException.h"
 #include "boost/signal.hpp"
 
-void dbg_VSLog(const CamelotFramework::String& message);
-
 namespace CamelotFramework
 {
 	LogEntry::LogEntry(const String& msg, const String& level)
 		:mMsg(msg), mChannel(level)
 	{ }
 
-	Log::Log(const String& logFilePath, bool autoSave, bool suppressFileOutput)
-		:mAutoSave(autoSave), mSuppressFileOutput(suppressFileOutput), mSaveFilePath(logFilePath)
+	Log::Log()
 	{
 	}
 
 	Log::~Log()
 	{
-		flush();
-
 		for(auto iter = mEntries.begin(); iter != mEntries.end(); ++iter)
 			cm_delete<PoolAlloc>(*iter);
 	}
@@ -28,11 +24,6 @@ namespace CamelotFramework
 		mEntries.push_back(newEntry);
 
 		doOnEntryAdded(*newEntry);
-
-		dbg_VSLog(message);
-
-		if(mAutoSave)
-			flush();
 	}
 
 	void Log::clear()
@@ -41,33 +32,16 @@ namespace CamelotFramework
 			cm_delete<PoolAlloc>(*iter);
 
 		mEntries.clear();
-
-		if(mAutoSave)
-			flush();
 	}
 
-	void Log::flush()
+	void Log::saveToFile(const WString& path)
 	{
-		if(mSuppressFileOutput)
-			return;
-
-		// TODO - Write to disk and throw exception if it can't
+		// TODO - Save the log as HTML
+		CM_EXCEPT(NotImplementedException, "Log save to file not yet implemented.");
 	}
 
 	void Log::doOnEntryAdded(const LogEntry& entry)
 	{
 		onEntryAdded(entry);
 	}
-
-
-}
-
-// TODO: Debug only - Remove later
-
-#include <windows.h>
-
-void dbg_VSLog(const CamelotFramework::String& message)
-{
-	OutputDebugString(message.c_str());
-	OutputDebugString("\n");
 }

+ 10 - 4
CamelotUtility/Source/CmManagedDataBlock.cpp

@@ -3,12 +3,12 @@
 
 namespace CamelotFramework
 {
-	ManagedDataBlock::ManagedDataBlock(UINT8* data, UINT32 size)
-		:mData(data), mSize(size), mManaged(false), mIsDataOwner(true)
+	ManagedDataBlock::ManagedDataBlock(UINT8* data, UINT32 size, std::function<void(UINT8*)> deallocator)
+		:mData(data), mSize(size), mManaged(false), mIsDataOwner(true), mDeallocator(deallocator)
 	{ }
 
 	ManagedDataBlock::ManagedDataBlock(UINT32 size)
-		:mSize(size), mManaged(true), mIsDataOwner(true)
+		:mSize(size), mManaged(true), mIsDataOwner(true), mDeallocator(nullptr)
 	{
 		mData = (UINT8*)cm_alloc<ScratchAlloc>(size);
 	}
@@ -18,6 +18,7 @@ namespace CamelotFramework
 		mData = source.mData;
 		mSize = source.mSize;
 		mManaged = source.mManaged;
+		mDeallocator = source.mDeallocator;
 
 		mIsDataOwner = true;
 		source.mIsDataOwner = false;
@@ -26,6 +27,11 @@ namespace CamelotFramework
 	ManagedDataBlock::~ManagedDataBlock()
 	{
 		if(mManaged && mIsDataOwner)
-			cm_free<ScratchAlloc>(mData);
+		{
+			if(mDeallocator != nullptr)
+				mDeallocator(mData);
+			else
+				cm_free<ScratchAlloc>(mData);
+		}
 	}
 }

+ 49 - 101
Inspector.txt

@@ -4,45 +4,38 @@ Matrix3 field
 Matrix4 field
 GameObject field
 Resource field
-
 -------------
-Cursor
- - A way to save/load a set of cursors
 
- IMMEDIATE:
-  - Deleting first entry in input field moves the cursor incorrectly
-  - Test if parsing int/float value from int/float field actually works
-  - ProfilerOverlay elements are constantly dirty? even though I'm not calling update
+Update C++ side of the GUI so it properly uses GUIPanels
+ - (Remove current GUI and EditorGUI and replace them with GUIPanel)
+ - Ensure GUI panel clips any of its child GUIAreas to the panel area
 
-Other:
- - Refactor BuiltinMaterialFactory to BuiltinEngineResources
+Remove support for resizeable areas (Update ScriptGUIArea)
 
--------------
+Things to think about/do:
+ - Inspectable fields need TAB support
+  - Modify C++ GUIElement so I can do setNextTabElement(GUIElement*)
+ - Inspectable fields need Undo/Redo support. Consider how to best implement it
+  - C++ Undo/Redo system needs nested contexts
+  - C++ Ensure that Undo/Redo works on per-field basis (undoing items within a field)
+  - Add C# UndoRedo
+ - Modify C++ Editor fields so that calling setValue doesn't update the visual value until focus is lost
+  - When user is currently writing in an input box I don't want refresh to overwrite that value.
+ - Expand/Collapse needs to work for both Components and their sub-objects (Structs, Arrays, etc.)
+ - Support for initializing SerializableObject/SerializableArray (and their fields, together with getters/setters)
+ - How do I refresh currently visible inspector fields.
+   - Also how will this be done with custom inspectors, when I might not use InspectableObject
+ - Currently I do not have a way to creating an Inspector field for just a single field, only for an entire object
+ - Finally once all other things are done implement support for multi-rank arrays, lists and dictionaries
 
-Boost any replacement: http://www.codeproject.com/Articles/11250/High-Performance-Dynamic-Typing-in-C-using-a-Repla
 
--------------
+How will UndoRedo keep a reference to the object? 
+ - What if the object gets destroyed? 
+ - Keeping a reference will prevent the object from being destroyed.
+   - Although heavy stuff is destroyed manually via Destroy anyway
 
-Get rid of the CamelotFramework namespace
- - I shouldn't need to prefix each variable with CM::
 
-Undocking a window wont remove the tabbed title bar
-While dragging an undocked window, dropping it over the main window (not over dock overlays) will not restore it
-
- - GameObjectField
-   - When dragging over GameObjectField cursor needs to change depending whether drop will be accepted or not
-   - How will I limit it to just certain component types?
-
-Make a common class for ScriptGUIElement as they all share:
- - Destroy(), DestroyInstance(), SetParent(), SetVisible() methods, and potentially others
-
-Add InsertElement to GUILayout
-
--------------
-Get rid of EditorGUI and GUI classes and instead make them a single class GUIPanel
- - IMPORANT. Consider replacing InspectorArea with GUIPanels (they internally in C++ are just clipped GUIAreas). This way I have a generic system
-
-IMPLEMENT:
+STUBBED IN METHODS:
 EditorWindow
  WindowResized
  Internal_GetWidth
@@ -55,82 +48,37 @@ SceneObject
  GetComponents
 GUIArea
  SetArea
-Refactor existing ScriptGUI and ScriptEditorGUI and add support for GUIPanel instead
-Remove support for resizable areas
-
-Tab indexes
- - EditorFields should have SetNextField method that allow you to set tab order directly
- - InspectableField are automatically assigned ID
-   - ID is part depth (also governs identation) and part sequential index
-   - This allows me to add/remove elements from objects like lists and arrays and not mess up the tab order
-   - Also collapse/expand doesn't require us to modify tab indexes
-   - InspectableObjects should likely have a reference to the Inspector so that they can query next InspectableField based on tab ID
-   - These IDs are then used for calling SetNextField on normal EditorFields
-
-Custom inspector
- - Custom inspector should have complete knowledge of the GUI objects within it (so that parent Inspector can expand/collapse it without worrying about the user forgetting to hide an element and messing up the other inspectors)
- - Since custom inspector should have all of its elements in a specific GUILayout, we should be able to just manipulate that GUILayout
-
-Positioning/Indentation
- - Inspector needs to be provided with a layout
- - Whenever an InspectableObject is created it will create a new X layout with a space (for indenting) and a Y layout (for child elements)
-   - We will provide it with parent layout from which to create those on
-   - And depth for determining indent amount
-   - For top level objects there is no space or X layout (depth is 0)
-  - InspectableFields will use the Layouts they are given by their parent InspectableObjects
-
-C++ bit for creating InspectableField
- - Need a way to list all fields in an object (should already have most of that functionality)
- - And hook up those fields with get/set callbacks for editing/updating
-
-UndoRedo
- - A global UndoRedo class for generic use
- - Specific UndoRedo for automatic use in InspectableField
- - Will likely need Undo/Redo context
-    - e.g. when in a text field I want to undo/redo my changes in that text field one by one
-    - but when I click outside maybe I just want to undo to the previous state before I even focused on that text field
-      - plus it doesn't make sense for example to undo a text field if I'm currently focusing on something in scene
-
----------------------------
-
-SerializableObject(object obj)
- - GetFields()
-
+SerializableObject
+SerializableArray
 SerializableField
- - Type
- - GetInt/SetInt
- - GetString/SetString
- - GetObject/SetObject
- - GetArray/SetArray
- - etc.
 
-SerializableArray
- - GetInt(arrayIdx)/SetInt(arrayIdx)
- - GetKVP(arrayIdx)/SetKVP(arrayIdx)
- - etc.
+ ----------------------
+
+ Non-inspector:
 
-SerializableDictionary
- - GetInt(key)/SetInt(key)
- - GetKVP(key)/SetKVP(key)
- - etc.
+  - Deleting first entry in input field moves the cursor incorrectly
+  - Test if parsing int/float value from int/float field actually works
+  - ProfilerOverlay elements are constantly dirty? even though I'm not calling update
+
+Refactor BuiltinMaterialFactory to BuiltinEngineResources
+
+Cursor
+ - A way to save/load a set of cursors
 
-----------------
+Get rid of the CamelotFramework namespace
+ - I shouldn't need to prefix each variable with CM::
 
-InspectableObject(SerializableObject)
- - Internally creates a list of InspectorFields (does not initialize any GUI elements)
- - CreateGUI(GUILayout) <- populates the GUI layout with every InspectorField
-     - For nested objects it creates child layouts and indents them appropriately
+Undocking a window wont remove the tabbed title bar
+While dragging an undocked window, dropping it over the main window (not over dock overlays) will not restore it
 
-InspectorField(SerializableField)
- - CreateGUI(GUILayout) <- Inserts the corresponding GUI element into the layout
+ - GameObjectField
+   - When dragging over GameObjectField cursor needs to change depending whether drop will be accepted or not
+   - How will I limit it to just certain component types?
 
--------------------
+Make a common class for ScriptGUIElement as they all share:
+ - Destroy(), DestroyInstance(), SetParent(), SetVisible() methods, and potentially others
 
-When creating a custom inspector, where will I store InspectorFields? Require user to store them?
- - I guess. If user doesn't store them they get destructed and upon destruction they remove their GUI element from the layout.
- - But what happens when Destroy is called? GUI elements get destroyed as normal and InspectorField will need to check for that, in which case it will essentially do nothing.
+Add InsertElement to GUILayout
 
-How do I refresh Inspector fields if source object changes?
- - Keep all InspectorFields in InspectorManager class, which will call Update on it regularily
- - If InspectorField GUI elements were destroyed then Update will show a warning
- - Otherwise you are required to call destroy on an InspectorField to properly remove it
+ Boost any replacement: http://www.codeproject.com/Articles/11250/High-Performance-Dynamic-Typing-in-C-using-a-Repla
+  - Also POCO has any class