yapf/blob.hpp
branchcustombridgeheads
changeset 5619 a2f1d08e2215
parent 5616 0570ae953222
child 5620 3b40a41f90d2
equal deleted inserted replaced
5618:a7db50b9f817 5619:a2f1d08e2215
    72 	{
    72 	{
    73 		InitEmpty();
    73 		InitEmpty();
    74 		AppendRaw(src);
    74 		AppendRaw(src);
    75 	}
    75 	}
    76 	/** move constructor - take ownership of blob data */
    76 	/** move constructor - take ownership of blob data */
    77 	FORCEINLINE CBlobBaseSimple(CHdr*& pHdr_1) {assert(pHdr_1 != NULL); ptr_u.m_pHdr_1 = pHdr_1; pHdr_1 = NULL;}
    77 	FORCEINLINE CBlobBaseSimple(CHdr * const & pHdr_1) {assert(pHdr_1 != NULL); ptr_u.m_pHdr_1 = pHdr_1; *(CHdr**)&pHdr_1 = NULL;}
    78 	/** destructor */
    78 	/** destructor */
    79 	FORCEINLINE ~CBlobBaseSimple() { Free(); }
    79 	FORCEINLINE ~CBlobBaseSimple() { Free(); }
    80 protected:
    80 protected:
    81 	/** initialize the empty blob by setting the ptr_u.m_pHdr_1 posize_ter to the static CHdr with
    81 	/** initialize the empty blob by setting the ptr_u.m_pHdr_1 posize_ter to the static CHdr with
    82 	*  both m_size and m_max_size containing zero */
    82 	*  both m_size and m_max_size containing zero */
   217 		}
   217 		}
   218 	}
   218 	}
   219 };
   219 };
   220 
   220 
   221 /** Blob - simple dynamic Titem_ array. Titem_ (template argument) is a placeholder for any type.
   221 /** Blob - simple dynamic Titem_ array. Titem_ (template argument) is a placeholder for any type.
   222 *  Titem_ can be any size_tegral type, posize_ter, or structure. Using Blob instead of just plain C array
   222 *  Titem_ can be any integral type, pointer, or structure. Using Blob instead of just plain C array
   223 *  simplifies the resource management in several ways:
   223 *  simplifies the resource management in several ways:
   224 *  1. When adding new item(s) it automatically grows capacity if needed.
   224 *  1. When adding new item(s) it automatically grows capacity if needed.
   225 *  2. When variable of type Blob comes out of scope it automatically frees the data buffer.
   225 *  2. When variable of type Blob comes out of scope it automatically frees the data buffer.
   226 *  3. Takes care about the actual data size (number of used items).
   226 *  3. Takes care about the actual data size (number of used items).
   227 *  4. Dynamically constructs only used items (as opposite of static array which constructs all items) */
   227 *  4. Dynamically constructs only used items (as opposite of static array which constructs all items) */
   229 class CBlobT : public Tbase_ {
   229 class CBlobT : public Tbase_ {
   230 	// make template arguments public:
   230 	// make template arguments public:
   231 public:
   231 public:
   232 	typedef Titem_ Titem;
   232 	typedef Titem_ Titem;
   233 	typedef Tbase_ Tbase;
   233 	typedef Tbase_ Tbase;
       
   234 	typedef typename Tbase::size_t size_t;
   234 
   235 
   235 	static const size_t Titem_size = sizeof(Titem);
   236 	static const size_t Titem_size = sizeof(Titem);
   236 
   237 
   237 	struct OnTransfer {
   238 	struct OnTransfer {
   238 		typename Tbase_::CHdr *m_pHdr_1;
   239 		typename Tbase_::CHdr *m_pHdr_1;
   239 		OnTransfer(OnTransfer& src) : m_pHdr_1(src.m_pHdr_1) {assert(src.m_pHdr_1 != NULL); src.m_pHdr_1 = NULL;}
   240 		OnTransfer(const OnTransfer& src) : m_pHdr_1(src.m_pHdr_1) {assert(src.m_pHdr_1 != NULL); *(typename Tbase_::CHdr**)&src.m_pHdr_1 = NULL;}
   240 		OnTransfer(CBlobT& src) : m_pHdr_1(src.ptr_u.m_pHdr_1) {src.InitEmpty();}
   241 		OnTransfer(CBlobT& src) : m_pHdr_1(src.ptr_u.m_pHdr_1) {src.InitEmpty();}
   241 		~OnTransfer() {assert(m_pHdr_1 == NULL);}
   242 		~OnTransfer() {assert(m_pHdr_1 == NULL);}
   242 	};
   243 	};
   243 
   244 
   244 	/** Default constructor - makes new Blob ready to accept any data */
   245 	/** Default constructor - makes new Blob ready to accept any data */
   245 	FORCEINLINE CBlobT() : Tbase() {}
   246 	FORCEINLINE CBlobT() : Tbase() {}
   246 	/** Constructor - makes new Blob with data */
   247 	/** Constructor - makes new Blob with data */
   247 	FORCEINLINE CBlobT(const Titem_ *p, size_t num_items) : Tbase((int8*)p, num_items * Titem_size) {}
   248 	FORCEINLINE CBlobT(const Titem_ *p, size_t num_items) : Tbase((int8*)p, num_items * Titem_size) {}
   248 	/** Copy constructor - make new blob to become copy of the original (source) blob */
   249 	/** Copy constructor - make new blob to become copy of the original (source) blob */
   249 	FORCEINLINE CBlobT(const Tbase& src) : Tbase(src) {assert((RawSize() % Titem_size) == 0);}
   250 	FORCEINLINE CBlobT(const Tbase& src) : Tbase(src) {assert((Tbase::RawSize() % Titem_size) == 0);}
   250 	/** Take ownership constructor */
   251 	/** Take ownership constructor */
   251 	FORCEINLINE CBlobT(OnTransfer& ot) : Tbase(ot.m_pHdr_1) {}
   252 	FORCEINLINE CBlobT(const OnTransfer& ot) : Tbase(ot.m_pHdr_1) {}
   252 	/** Destructor - ensures that allocated memory (if any) is freed */
   253 	/** Destructor - ensures that allocated memory (if any) is freed */
   253 	FORCEINLINE ~CBlobT() { Free(); }
   254 	FORCEINLINE ~CBlobT() { Free(); }
   254 	/** Check the validity of item index (only in debug mode) */
   255 	/** Check the validity of item index (only in debug mode) */
   255 	FORCEINLINE void CheckIdx(size_t idx) { assert(idx >= 0); assert(idx < Size()); }
   256 	FORCEINLINE void CheckIdx(size_t idx) { assert(idx >= 0); assert(idx < Size()); }
   256 	/** Return posize_ter to the first data item - non-const version */
   257 	/** Return posize_ter to the first data item - non-const version */
   257 	FORCEINLINE Titem* Data() { return (Titem*)RawData(); }
   258 	FORCEINLINE Titem* Data() { return (Titem*)Tbase::RawData(); }
   258 	/** Return posize_ter to the first data item - const version */
   259 	/** Return posize_ter to the first data item - const version */
   259 	FORCEINLINE const Titem* Data() const { return (const Titem*)RawData(); }
   260 	FORCEINLINE const Titem* Data() const { return (const Titem*)Tbase::RawData(); }
   260 	/** Return posize_ter to the idx-th data item - non-const version */
   261 	/** Return posize_ter to the idx-th data item - non-const version */
   261 	FORCEINLINE Titem* Data(size_t idx) { CheckIdx(idx); return (Data() + idx); }
   262 	FORCEINLINE Titem* Data(size_t idx) { CheckIdx(idx); return (Data() + idx); }
   262 	/** Return posize_ter to the idx-th data item - const version */
   263 	/** Return posize_ter to the idx-th data item - const version */
   263 	FORCEINLINE const Titem* Data(size_t idx) const { CheckIdx(idx); return (Data() + idx); }
   264 	FORCEINLINE const Titem* Data(size_t idx) const { CheckIdx(idx); return (Data() + idx); }
   264 	/** Return number of items in the Blob */
   265 	/** Return number of items in the Blob */
   265 	FORCEINLINE size_t Size() const { return (RawSize() / Titem_size); }
   266 	FORCEINLINE size_t Size() const { return (Tbase::RawSize() / Titem_size); }
   266 	/** Return total number of items that can fit in the Blob without buffer reallocation */
   267 	/** Return total number of items that can fit in the Blob without buffer reallocation */
   267 	FORCEINLINE size_t MaxSize() const { return (MaxRawSize() / Titem_size); }
   268 	FORCEINLINE size_t MaxSize() const { return (Tbase::MaxRawSize() / Titem_size); }
   268 	/** Return number of additional items that can fit in the Blob without buffer reallocation */
   269 	/** Return number of additional items that can fit in the Blob without buffer reallocation */
   269 	FORCEINLINE size_t GetReserve() const { return ((MaxRawSize() - RawSize()) / Titem_size); }
   270 	FORCEINLINE size_t GetReserve() const { return ((Tbase::MaxRawSize() - Tbase::RawSize()) / Titem_size); }
   270 	/** Free the memory occupied by Blob destroying all items */
   271 	/** Free the memory occupied by Blob destroying all items */
   271 	FORCEINLINE void Free()
   272 	FORCEINLINE void Free()
   272 	{
   273 	{
   273 		assert((RawSize() % Titem_size) == 0);
   274 		assert((Tbase::RawSize() % Titem_size) == 0);
   274 		size_t old_size = Size();
   275 		size_t old_size = Size();
   275 		if (old_size > 0) {
   276 		if (old_size > 0) {
   276 			// destroy removed items;
   277 			// destroy removed items;
   277 			Titem* pI_last_to_destroy = Data(0);
   278 			Titem* pI_last_to_destroy = Data(0);
   278 			for (Titem* pI = Data(old_size - 1); pI >= pI_last_to_destroy; pI--) pI->~Titem_();
   279 			for (Titem* pI = Data(old_size - 1); pI >= pI_last_to_destroy; pI--) pI->~Titem_();
   279 		}
   280 		}
   280 		Tbase::Free();
   281 		Tbase::Free();
   281 	}
   282 	}
   282 	/** Grow number of data items in Blob by given number - doesn't construct items */
   283 	/** Grow number of data items in Blob by given number - doesn't construct items */
   283 	FORCEINLINE Titem* GrowSizeNC(size_t num_items) { return (Titem*)GrowRawSize(num_items * Titem_size); }
   284 	FORCEINLINE Titem* GrowSizeNC(size_t num_items) { return (Titem*)Tbase::GrowRawSize(num_items * Titem_size); }
   284 	/** Grow number of data items in Blob by given number - constructs new items (using Titem_'s default constructor) */
   285 	/** Grow number of data items in Blob by given number - constructs new items (using Titem_'s default constructor) */
   285 	FORCEINLINE Titem* GrowSizeC(size_t num_items)
   286 	FORCEINLINE Titem* GrowSizeC(size_t num_items)
   286 	{
   287 	{
   287 		Titem* pI = GrowSizeNC(num_items);
   288 		Titem* pI = GrowSizeNC(num_items);
   288 		for (size_t i = num_items; i > 0; i--, pI++) new (pI) Titem();
   289 		for (size_t i = num_items; i > 0; i--, pI++) new (pI) Titem();
   289 	}
   290 	}
   290 	/** Destroy given number of items and reduce the Blob's data size */
   291 	/** Destroy given number of items and reduce the Blob's data size */
   291 	FORCEINLINE void ReduceSize(size_t num_items)
   292 	FORCEINLINE void ReduceSize(size_t num_items)
   292 	{
   293 	{
   293 		assert((RawSize() % Titem_size) == 0);
   294 		assert((Tbase::RawSize() % Titem_size) == 0);
   294 		size_t old_size = Size();
   295 		size_t old_size = Size();
   295 		assert(num_items <= old_size);
   296 		assert(num_items <= old_size);
   296 		size_t new_size = (num_items <= old_size) ? (old_size - num_items) : 0;
   297 		size_t new_size = (num_items <= old_size) ? (old_size - num_items) : 0;
   297 		// destroy removed items;
   298 		// destroy removed items;
   298 		Titem* pI_last_to_destroy = Data(new_size);
   299 		Titem* pI_last_to_destroy = Data(new_size);
   299 		for (Titem* pI = Data(old_size - 1); pI >= pI_last_to_destroy; pI--) pI->~Titem();
   300 		for (Titem* pI = Data(old_size - 1); pI >= pI_last_to_destroy; pI--) pI->~Titem();
   300 		// remove them
   301 		// remove them
   301 		ReduceRawSize(num_items * Titem_size);
   302 		Tbase::ReduceRawSize(num_items * Titem_size);
   302 	}
   303 	}
   303 	/** Append one data item at the end (calls Titem_'s default constructor) */
   304 	/** Append one data item at the end (calls Titem_'s default constructor) */
   304 	FORCEINLINE Titem* AppendNew()
   305 	FORCEINLINE Titem* AppendNew()
   305 	{
   306 	{
   306 		Titem& dst = *GrowSizeNC(1); // Grow size by one item
   307 		Titem& dst = *GrowSizeNC(1); // Grow size by one item
   342 			new (pItem) Titem_(*pLast);
   343 			new (pItem) Titem_(*pLast);
   343 		}
   344 		}
   344 		// destroy the last item
   345 		// destroy the last item
   345 		pLast->~Titem_();
   346 		pLast->~Titem_();
   346 		// and reduce the raw blob size
   347 		// and reduce the raw blob size
   347 		ReduceRawSize(Titem_size);
   348 		Tbase::ReduceRawSize(Titem_size);
   348 	}
   349 	}
   349 	/** Ensures that given number of items can be added to the end of Blob. Returns posize_ter to the
   350 	/** Ensures that given number of items can be added to the end of Blob. Returns posize_ter to the
   350 	*  first free (unused) item */
   351 	*  first free (unused) item */
   351 	FORCEINLINE Titem* MakeFreeSpace(size_t num_items) { return (Titem*)MakeRawFreeSpace(num_items * Titem_size); }
   352 	FORCEINLINE Titem* MakeFreeSpace(size_t num_items) { return (Titem*)Tbase::MakeRawFreeSpace(num_items * Titem_size); }
   352 
   353 
   353 	FORCEINLINE OnTransfer Transfer() {return OnTransfer(*this);};
   354 	FORCEINLINE OnTransfer Transfer() {return OnTransfer(*this);};
   354 };
   355 };
   355 
   356 
   356 
   357