This commit is contained in:
castano 2011-04-06 01:56:51 +00:00
parent 42efc702ab
commit d277e48df5
2 changed files with 82 additions and 80 deletions

View File

@ -39,21 +39,28 @@ namespace nv
} }
template <typename T> template <typename T>
void construct(T * ptr, uint count) { void construct(T * restrict ptr, uint new_size, uint old_size) {
for (uint i = 0; i < count; i++) { for (uint i = old_size; i < new_size; i++) {
new(ptr+i) T; // placement new new(ptr+i) T; // placement new
} }
} }
template <typename T> template <typename T>
void destroy(T * ptr, uint count) { void construct(T * restrict ptr, uint new_size, uint old_size, const T & value) {
for (uint i = 0; i < count; i++) { for (uint i = old_size; i < new_size; i++) {
(ptr+i)->~T(); new(ptr+i) T(elem); // placement new
} }
} }
template <typename T> template <typename T>
void fill(T * restrict dst, const T & value, uint count) { void destroy(T * restrict ptr, uint new_size, uint old_size) {
for (uint i = new_size; i < old_size; i++) {
(ptr+i)->~T(); // Explicit call to the destructor
}
}
template <typename T>
void fill(T * restrict dst, uint count, const T & value) {
for (uint i = 0; i < count; i++) { for (uint i = 0; i < count; i++) {
dst[i] = value; dst[i] = value;
} }
@ -66,6 +73,18 @@ namespace nv
} }
} }
template <typename T>
bool find(const T & element, const T * restrict ptr, uint count, uint * index) {
for (uint i = 0; i < count; i++) {
if (ptr[i] == element) {
if (index != NULL) *index = i;
return true;
}
}
return false;
}
class Buffer class Buffer
{ {
@ -102,8 +121,36 @@ namespace nv
protected: protected:
// Release ownership of allocated memory and returns pointer to it.
NV_NOINLINE void * release() {
void * tmp = m_buffer;
m_buffer = NULL;
m_buffer_size = 0;
m_size = 0;
return tmp;
}
NV_NOINLINE void resize(uint new_size, uint element_size)
{
m_size = new_size;
if (new_size > m_buffer_size) {
uint new_buffer_size;
if (m_buffer_size == 0) {
// first allocation
new_buffer_size = new_size;
}
else {
// growing
new_buffer_size = new_size + (new_size >> 2);
}
allocate( new_buffer_size, element_size );
}
}
/// Change buffer size. /// Change buffer size.
NV_NOINLINE void allocate(uint count, uint size) NV_NOINLINE void allocate(uint count, uint element_size)
{ {
if (count == 0) { if (count == 0) {
// free the buffer. // free the buffer.
@ -114,7 +161,7 @@ namespace nv
} }
else { else {
// realloc the buffer // realloc the buffer
m_buffer = ::realloc(m_buffer, count * size); m_buffer = ::realloc(m_buffer, count * element_size);
} }
m_buffer_size = count; m_buffer_size = count;
@ -210,9 +257,11 @@ namespace nv
if (new_size > m_buffer_size) if (new_size > m_buffer_size)
{ {
const T copy(val); // create a copy in case value is inside of this array. const T copy(val); // create a copy in case value is inside of this array. // @@ Create a copy without side effects. Do not call constructor/destructor here.
resize(new_size);
buffer()[new_size-1] = copy; Buffer::resize(new_size, sizeof(T));
new (buffer()+new_size-1) T(copy);
} }
else else
{ {
@ -275,6 +324,12 @@ namespace nv
return buffer()[0]; return buffer()[0];
} }
/// Check if the given element is contained in the array.
NV_FORCEINLINE bool contains(const T & e) const
{
return find(e, NULL);
}
/// Return true if element found. /// Return true if element found.
NV_FORCEINLINE bool find(const T & element, uint * index) const NV_FORCEINLINE bool find(const T & element, uint * index) const
{ {
@ -282,21 +337,9 @@ namespace nv
} }
/// Return true if element found within the given range. /// Return true if element found within the given range.
bool find(const T & element, uint first, uint count, uint * index) const NV_FORCEINLINE bool find(const T & element, uint first, uint count, uint * index) const
{ {
for (uint i = first; i < first+count; i++) { return ::nv::find(element, buffer() + first, count, index);
if (buffer()[i] == element) {
if (index != NULL) *index = i;
return true;
}
}
return false;
}
/// Check if the given element is contained in the array.
NV_FORCEINLINE bool contains(const T & e) const
{
return find(e, NULL);
} }
/// Remove the element at the given index. This is an expensive operation! /// Remove the element at the given index. This is an expensive operation!
@ -372,71 +415,33 @@ namespace nv
/// Resize the vector preserving existing elements. /// Resize the vector preserving existing elements.
NV_NOINLINE void resize(uint new_size) void resize(uint new_size)
{ {
uint old_size = m_size; uint old_size = m_size;
m_size = new_size;
// @@ Use nv::destruct(...)
// Destruct old elements (if we're shrinking). // Destruct old elements (if we're shrinking).
for (uint i = new_size; i < old_size; i++) { destroy(buffer(), new_size, old_size);
(buffer()+i)->~T(); // Explicit call to the destructor
}
// @@ Move allocation logic to Buffer::allocate Buffer::resize(new_size, sizeof(T));
if (new_size > m_buffer_size) {
uint new_buffer_size;
if (m_buffer_size == 0) {
// first allocation
new_buffer_size = new_size;
}
else {
// growing
new_buffer_size = new_size + (new_size >> 2);
}
allocate( new_buffer_size );
}
// @@ Use nv::construct(...)
// Call default constructors // Call default constructors
for (uint i = old_size; i < new_size; i++) { construct(buffer(), new_size, old_size);
new(buffer()+i) T; // placement new
}
} }
/// Resize the vector preserving existing elements and initializing the /// Resize the vector preserving existing elements and initializing the
/// new ones with the given value. /// new ones with the given value.
NV_NOINLINE void resize( uint new_size, const T &elem ) void resize( uint new_size, const T &elem )
{ {
uint old_size = m_size; uint old_size = m_size;
m_size = new_size;
// @@ Use nv::destruct(...)
// Destruct old elements (if we're shrinking). // Destruct old elements (if we're shrinking).
for (uint i = new_size; i < old_size; i++ ) { destroy(buffer(), new_size, old_size);
(buffer()+i)->~T(); // Explicit call to the destructor
}
// @@ Move allocation logic to Buffer::allocate Buffer::resize(new_size, sizeof(T));
if (new_size > m_buffer_size) {
uint new_buffer_size;
if (m_buffer_size == 0) {
// first allocation
new_buffer_size = m_size;
}
else {
// growing
new_buffer_size = m_size + (m_size >> 2);
}
allocate( new_buffer_size );
}
// @@ Use nv::fill(...)
// Call copy constructors // Call copy constructors
for (uint i = old_size; i < new_size; i++ ) { construct(buffer(), new_size, old_size, elem);
new(buffer()+i) T( elem ); // placement new
}
} }
/// Clear the buffer. /// Clear the buffer.
@ -477,11 +482,7 @@ namespace nv
// Release ownership of allocated memory and returns pointer to it. // Release ownership of allocated memory and returns pointer to it.
T * release() { T * release() {
T * tmp = buffer(); return (T *)Buffer::release();
m_buffer = NULL;
m_buffer_size = 0;
m_size = 0;
return tmp;
} }
/// Array serialization. /// Array serialization.

View File

@ -244,13 +244,14 @@ FloatImage * nv::ImageIO::loadFloat(const char * fileName, Stream & s)
} }
} }
#else // defined(HAVE_FREEIMAGE) #else // defined(HAVE_FREEIMAGE)
#pragma NV_MESSAGE("TODO: Load TIFF and EXR files from stream.")
#if defined(HAVE_TIFF) #if defined(HAVE_TIFF)
#pragma NV_MESSAGE("TODO: Load TIFF from stream.")
if (strCaseCmp(extension, ".tif") == 0 || strCaseCmp(extension, ".tiff") == 0) { if (strCaseCmp(extension, ".tif") == 0 || strCaseCmp(extension, ".tiff") == 0) {
return loadFloatTIFF(fileName, s); return loadFloatTIFF(fileName, s);
} }
#endif #endif
#if defined(HAVE_OPENEXR) #if defined(HAVE_OPENEXR)
#pragma NV_MESSAGE("TODO: Load EXR from stream.")
if (strCaseCmp(extension, ".exr") == 0) { if (strCaseCmp(extension, ".exr") == 0) {
return loadFloatEXR(fileName, s); return loadFloatEXR(fileName, s);
} }
@ -647,15 +648,15 @@ bool nv::ImageIO::saveFloatFreeImage(FREE_IMAGE_FORMAT fif, Stream & s, const Fl
FREE_IMAGE_TYPE type; FREE_IMAGE_TYPE type;
if (componentCount == 1) if (componentCount == 1)
{ {
type = FIT_FLOAT; type = FIT_FLOAT;
} }
else if (componentCount == 3) else if (componentCount == 3)
{ {
type = FIT_RGBF; type = FIT_RGBF;
} }
else if (componentCount == 4) else if (componentCount == 4)
{ {
type = FIT_RGBAF; type = FIT_RGBAF;
} }
else { else {
return false; return false;