Changeset - r14866:33478c3e40d3
[Not reviewed]
master
0 1 0
yexo - 14 years ago 2010-03-19 20:13:15
yexo@openttd.org
(svn r19472) -Codechange: reorder the static members of ByteBlob and add Zero() (skidd13)
1 file changed with 43 insertions and 36 deletions:
0 comments (0 inline, 0 general)
src/misc/blob.hpp
Show inline comments
 
@@ -68,53 +68,94 @@ private:
 
	static BlobHeader hdrEmpty[];
 

	
 
public:
 
	static const uint tail_reserve = 4; ///< four extra bytes will be always allocated and zeroed at the end
 
	static const uint header_size = sizeof(BlobHeader);
 

	
 
	/** default constructor - initializes empty blob */
 
	FORCEINLINE ByteBlob() { InitEmpty(); }
 

	
 
	/** move constructor - take ownership of blob data */
 
	FORCEINLINE ByteBlob(BlobHeader * const & src)
 
	{
 
		assert(src != NULL);
 
		header = src;
 
		*const_cast<BlobHeader**>(&src) = NULL;
 
	}
 

	
 
	/** destructor */
 
	FORCEINLINE ~ByteBlob()
 
	{
 
		Free();
 
	}
 

	
 
protected:
 
	/** initialize the empty blob by setting the header pointer to the static BlobHeader with
 
	/** all allocation should happen here */
 
	static FORCEINLINE BlobHeader *RawAlloc(uint num_bytes)
 
	{
 
		return (BlobHeader*)MallocT<byte>(num_bytes);
 
	}
 

	
 
	/** Return header pointer to the static BlobHeader with
 
	 *  both items and capacity containing zero */
 
	static FORCEINLINE BlobHeader *Zero()
 
	{
 
		return const_cast<BlobHeader *>(&ByteBlob::hdrEmpty[1]);
 
	}
 

	
 
	/** simple allocation policy - can be optimized later */
 
	static FORCEINLINE uint AllocPolicy(uint min_alloc)
 
	{
 
		if (min_alloc < (1 << 9)) {
 
			if (min_alloc < (1 << 5)) return (1 << 5);
 
			return (min_alloc < (1 << 7)) ? (1 << 7) : (1 << 9);
 
		}
 
		if (min_alloc < (1 << 15)) {
 
			if (min_alloc < (1 << 11)) return (1 << 11);
 
			return (min_alloc < (1 << 13)) ? (1 << 13) : (1 << 15);
 
		}
 
		if (min_alloc < (1 << 20)) {
 
			if (min_alloc < (1 << 17)) return (1 << 17);
 
			return (min_alloc < (1 << 19)) ? (1 << 19) : (1 << 20);
 
		}
 
		min_alloc = (min_alloc | ((1 << 20) - 1)) + 1;
 
		return min_alloc;
 
	}
 

	
 
	/** all deallocations should happen here */
 
	static FORCEINLINE void RawFree(BlobHeader *p)
 
	{
 
		/* Just to silence an unsilencable GCC 4.4+ warning. */
 
		assert(p != ByteBlob::hdrEmpty);
 

	
 
		/* In case GCC warns about the following, see GCC's PR38509 why it is bogus. */
 
		free(p);
 
	}
 

	
 
	/** initialize the empty blob */
 
	FORCEINLINE void InitEmpty()
 
	{
 
		header = const_cast<BlobHeader *>(&ByteBlob::hdrEmpty[1]);
 
		header = Zero();
 
	}
 

	
 
	/** initialize blob by attaching it to the given header followed by data */
 
	FORCEINLINE void Init(BlobHeader *src)
 
	{
 
		header = &src[1];
 
	}
 

	
 
	/** blob header accessor - use it rather than using the pointer arithmetics directly - non-const version */
 
	FORCEINLINE BlobHeader& Hdr()
 
	{
 
		return *(header - 1);
 
	}
 

	
 
	/** blob header accessor - use it rather than using the pointer arithmetics directly - const version */
 
	FORCEINLINE const BlobHeader& Hdr() const
 
	{
 
		return *(header - 1);
 
	}
 

	
 
	/** return reference to the actual blob size - used when the size needs to be modified */
 
	FORCEINLINE uint& LengthRef()
 
	{
 
		return Hdr().items;
 
@@ -196,82 +237,48 @@ public:
 
	/** reallocate blob data if needed */
 
	void SmartAlloc(uint new_size)
 
	{
 
		uint old_max_size = Capacity();
 
		if (old_max_size >= new_size) return;
 
		/* calculate minimum block size we need to allocate */
 
		uint min_alloc_size = header_size + new_size + tail_reserve;
 
		/* ask allocation policy for some reasonable block size */
 
		uint alloc_size = AllocPolicy(min_alloc_size);
 
		/* allocate new block */
 
		BlobHeader *tmp = RawAlloc(alloc_size);
 
		/* setup header */
 
		tmp->items = Length();
 
		tmp->capacity = alloc_size - (header_size + tail_reserve);
 
		/* copy existing data */
 
		if (Length() > 0)
 
			memcpy(tmp + 1, data, tmp->items);
 
		/* replace our block with new one */
 
		BlobHeader *pOldHdr = &Hdr();
 
		Init(tmp);
 
		if (old_max_size > 0)
 
			RawFree(pOldHdr);
 
	}
 

	
 
	/** simple allocation policy - can be optimized later */
 
	FORCEINLINE static uint AllocPolicy(uint min_alloc)
 
	{
 
		if (min_alloc < (1 << 9)) {
 
			if (min_alloc < (1 << 5)) return (1 << 5);
 
			return (min_alloc < (1 << 7)) ? (1 << 7) : (1 << 9);
 
		}
 
		if (min_alloc < (1 << 15)) {
 
			if (min_alloc < (1 << 11)) return (1 << 11);
 
			return (min_alloc < (1 << 13)) ? (1 << 13) : (1 << 15);
 
		}
 
		if (min_alloc < (1 << 20)) {
 
			if (min_alloc < (1 << 17)) return (1 << 17);
 
			return (min_alloc < (1 << 19)) ? (1 << 19) : (1 << 20);
 
		}
 
		min_alloc = (min_alloc | ((1 << 20) - 1)) + 1;
 
		return min_alloc;
 
	}
 

	
 
	/** all allocation should happen here */
 
	static FORCEINLINE BlobHeader *RawAlloc(uint num_bytes)
 
	{
 
		return (BlobHeader*)MallocT<byte>(num_bytes);
 
	}
 

	
 
	/** all deallocations should happen here */
 
	static FORCEINLINE void RawFree(BlobHeader *p)
 
	{
 
		/* Just to silence an unsilencable GCC 4.4+ warning. */
 
		assert(p != ByteBlob::hdrEmpty);
 

	
 
		/* In case GCC warns about the following, see GCC's PR38509 why it is bogus. */
 
		free(p);
 
	}
 
	/** fixing the four bytes at the end of blob data - useful when blob is used to hold string */
 
	FORCEINLINE void FixTail() const
 
	{
 
		if (Capacity() > 0) {
 
			byte *p = &data[Length()];
 
			for (uint i = 0; i < tail_reserve; i++) {
 
				p[i] = 0;
 
			}
 
		}
 
	}
 
};
 

	
 
/** Blob - simple dynamic T array. T (template argument) is a placeholder for any type.
 
 *  T can be any integral type, pointer, or structure. Using Blob instead of just plain C array
 
 *  simplifies the resource management in several ways:
 
 *  1. When adding new item(s) it automatically grows capacity if needed.
 
 *  2. When variable of type Blob comes out of scope it automatically frees the data buffer.
 
 *  3. Takes care about the actual data size (number of used items).
 
 *  4. Dynamically constructs only used items (as opposite of static array which constructs all items) */
 
template <typename T>
 
class CBlobT : public ByteBlob {
 
	/* make template arguments public: */
 
public:
 
	typedef ByteBlob base;
0 comments (0 inline, 0 general)