buffer.h
Go to the documentation of this file.
#pragma once
namespace grk
{
template<typename T>
struct AllocatorVanilla
{
T* alloc(size_t length)
{
return new T[length];
}
void dealloc(T* buf)
{
delete[] buf;
}
};
template<typename T>
struct AllocatorAligned
{
T* alloc(size_t length)
{
return (T*)grk_aligned_malloc(length * sizeof(T));
}
void dealloc(T* buf)
{
grk_aligned_free(buf);
}
};
template<typename T, template<typename TT> typename A>
struct grk_buf : A<T>
{
grk_buf(T* buffer, size_t off, size_t length, bool ownsData)
: buf(buffer), offset(off), len(length), owns_data(ownsData)
{}
grk_buf(T* buffer, size_t length) : grk_buf(buffer, 0, length, false) {}
grk_buf() : grk_buf(0, 0, 0, false) {}
grk_buf(T* buffer, size_t length, bool ownsData) : grk_buf(buffer, 0, length, ownsData) {}
virtual ~grk_buf()
{
dealloc();
}
explicit grk_buf(const grk_buf& rhs)
{
this->operator=(rhs);
}
grk_buf& operator=(const grk_buf& rhs) // copy assignment
{
return operator=(&rhs);
}
grk_buf& operator=(const grk_buf* rhs) // copy assignment
{
if(this != rhs)
{ // self-assignment check expected
buf = rhs->buf;
offset = rhs->offset;
len = rhs->len;
owns_data = false;
}
return *this;
}
inline bool canRead(void)
{
return offset < len;
}
inline T read(void)
{
return buf[offset++];
}
inline bool write(T val)
{
if(offset == len)
return false;
buf[offset++] = val;
return true;
}
inline bool write(T* b, size_t size)
{
if(offset + size > len)
return false;
memcpy(buf + offset, b, size);
offset += size;
return true;
}
virtual bool alloc(size_t length)
{
if(buf && len > length)
return true;
dealloc();
buf = A<T>::alloc(length);
if(!buf)
return false;
len = length;
offset = 0;
owns_data = true;
return true;
}
virtual void dealloc()
{
if(owns_data)
A<T>::dealloc(buf);
buf = nullptr;
owns_data = false;
offset = 0;
len = 0;
}
// set buf to buf without owning it
void attach(T* buffer)
{
grk_buf<T, A>::dealloc();
buf = buffer;
}
// set buf to buf and own it
void acquire(T* buffer)
{
grk_buf<T, A>::dealloc();
buffer = buf;
owns_data = true;
}
// transfer buf to buffer, and cease owning it
void transfer(T** buffer)
{
if(buffer)
{
assert(!buf || owns_data);
*buffer = buf;
buf = nullptr;
owns_data = false;
}
}
size_t remainingLength(void)
{
return len - offset;
}
void incrementOffset(ptrdiff_t off)
{
/* we allow the offset to move to one location beyond end of buffer segment*/
if(off > 0)
{
if(offset > (size_t)(SIZE_MAX - (size_t)off))
{
GRK_WARN("grk_buf8: overflow");
offset = len;
}
else if(offset + (size_t)off > len)
{
#ifdef DEBUG_SEG_BUF
GRK_WARN("grk_buf8: attempt to increment buffer offset out of bounds");
#endif
offset = len;
}
else
{
offset = offset + (size_t)off;
}
}
else if(off < 0)
{
if(offset < (size_t)(-off))
{
GRK_WARN("grk_buf8: underflow");
offset = 0;
}
else
{
offset = (size_t)((ptrdiff_t)offset + off);
}
}
}
T* currPtr(void) const
{
if(!buf)
return nullptr;
return buf + offset;
}
T* buf; /* internal array*/
size_t offset; /* current offset into array */
size_t len; /* length of array */
bool owns_data; /* true if buffer manages the buf array */
};
using grk_buf8 = grk_buf<uint8_t, AllocatorVanilla>;
using grk_buf8_aligned = grk_buf<uint8_t, AllocatorAligned>;
template<typename T>
struct grk_buf2d_simple
{
grk_buf2d_simple() : grk_buf2d_simple(nullptr, 0, 0) {}
grk_buf2d_simple(T* buf, uint32_t stride, uint32_t height)
: buf_(buf), stride_(stride), height_(height)
{}
grk_buf2d_simple& incX_IN_PLACE(size_t deltaX)
{
buf_ += deltaX;
return *this;
}
grk_buf2d_simple& incY_IN_PLACE(size_t deltaY)
{
buf_ += deltaY * stride_;
return *this;
}
T* buf_;
uint32_t stride_;
uint32_t height_;
};
template<typename T, template<typename TT> typename A>
struct grk_buf2d : protected grk_buf<T, A>, public grk_rect32
{
grk_buf2d(T* buffer, bool ownsData, uint32_t w, uint32_t strd, uint32_t h)
: grk_buf<T, A>(buffer, ownsData), grk_rect32(0, 0, w, h), stride(strd)
{}
grk_buf2d(uint32_t w, uint32_t h) : grk_buf2d(nullptr, false, w, 0, h) {}
explicit grk_buf2d(const grk_rect32* b)
: grk_buf<T, A>(nullptr, false), grk_rect32(b->x0, b->y0, b->x1, b->y1), stride(0)
{}
explicit grk_buf2d(const grk_rect32& b)
: grk_buf<T, A>(nullptr, false), grk_rect32(b.x0, b.y0, b.x1, b.y1), stride(0)
{}
grk_buf2d(const grk_rect32& b, [[maybe_unused]] bool useOrigin)
: grk_buf<T, A>(nullptr, false), grk_rect32(b), stride(0)
{}
grk_buf2d(void) : grk_buf2d(nullptr, 0, 0, 0, false) {}
explicit grk_buf2d(const grk_buf2d& rhs)
: grk_buf<T, A>(rhs), grk_rect32(rhs), stride(rhs.stride)
{}
grk_buf2d_simple<T> simple(void) const
{
return grk_buf2d_simple<T>(this->buf, this->stride, this->height());
}
grk_buf2d_simple<float> simpleF(void) const
{
return grk_buf2d_simple<float>((float*)this->buf, this->stride, this->height());
}
grk_buf2d& operator=(const grk_buf2d& rhs) // copy assignment
{
return operator=(&rhs);
}
grk_buf2d& operator=(const grk_buf2d* rhs) // copy assignment
{
if(this != rhs)
{ // self-assignment check expected
grk_buf<T, A>::operator=(rhs);
grk_rect32::operator=(rhs);
stride = rhs->stride;
}
return *this;
}
virtual ~grk_buf2d() = default;
bool alloc2d(bool clear)
{
if(!this->buf && width() && height())
{
if(!stride)
stride = grk_make_aligned_width(width());
uint64_t data_size_needed = (uint64_t)stride * height() * sizeof(T);
if(!data_size_needed)
return true;
if(!grk_buf<T, A>::alloc(data_size_needed))
{
grk::GRK_ERROR("Failed to allocate aligned memory buffer of dimensions %u x %u",
stride, height());
return false;
}
if(clear)
memset(this->buf, 0, data_size_needed);
}
return true;
}
// set buf to buffer without owning it
void attach(T* buffer, uint32_t strd)
{
grk_buf<T, A>::attach(buffer);
stride = strd;
}
void attach(grk_buf2d& rhs, uint32_t x, uint32_t y)
{
attach(&rhs, x, y);
}
void attach(grk_buf2d& rhs)
{
attach(&rhs, 0, 0);
}
void attach(grk_buf2d* rhs, uint32_t x, uint32_t y)
{
if(!rhs)
return;
grk_buf<T, A>::dealloc();
this->buf = rhs->address(x, y);
this->len = rhs->len;
this->owns_data = false;
stride = rhs->stride;
}
void attach(grk_buf2d* rhs)
{
attach(rhs, 0, 0);
}
// set buf to buf and own it
void acquire(T* buffer, uint32_t strd)
{
grk_buf<T, A>::acquire(buffer);
stride = strd;
}
// transfer buf to buf, and cease owning it
void transfer(T** buffer, uint32_t* strd)
{
if(buffer)
{
grk_buf<T, A>::transfer(buffer);
*strd = stride;
}
}
bool isWindowValid(grk_rect32 win)
{
return !(win.x0 >= x1 || win.x1 <= x0 || win.x1 > x1 || win.y0 >= y1 || win.y1 <= win.y0 ||
win.y1 > y1);
}
// rhs coordinates are in "this" coordinate system
template<typename F>
void copyFrom(const grk_buf2d& src, F filter)
{
return copyFrom(&src, filter);
}
// rhs coordinates are in "this" coordinate system
template<typename F>
void copyFrom(const grk_buf2d* src, F filter)
{
auto inter = intersection(src);
if(inter.empty())
return;
if(!src->buf)
return;
T* ptr = this->buf + (inter.y0 * stride + inter.x0);
T* srcPtr = src->buf + ((inter.y0 - src->y0) * src->stride + inter.x0 - src->x0);
uint32_t len = inter.width();
for(uint32_t j = inter.y0; j < inter.y1; ++j)
{
filter.copy(ptr, srcPtr, len);
ptr += stride;
srcPtr += src->stride;
}
}
struct memcpy_from
{
void copy(T* dst, T* src, uint32_t len)
{
memcpy(dst, src, len);
}
};
void copyFrom(const grk_buf2d& src)
{
copy(src, memcpy_from());
}
T* getBuffer(void) const
{
return this->currPtr();
}
T* address(uint32_t x, uint32_t y)
{
return this->currPtr() + (uint64_t)x + (uint64_t)y * stride;
}
uint32_t stride;
};
} // namespace grk
SIZE_MAX
#define SIZE_MAX
Definition MemManager.cpp:29
grk
Copyright (C) 2016-2023 Grok Image Compression Inc.
Definition ICacheable.h:20
grk::grk_read
void grk_read(const uint8_t *buffer, TYPE *value, uint32_t numBytes)
Definition BufferedStream.h:239
grk::grk_make_aligned_width
uint32_t grk_make_aligned_width(uint32_t width)
Definition MemManager.cpp:35
grk::GRK_ERROR
void GRK_ERROR(const char *fmt,...)
Definition logger.cpp:58
grk::GRK_WARN
void GRK_WARN(const char *fmt,...)
Definition logger.cpp:49
grk::grk_aligned_malloc
void * grk_aligned_malloc(size_t size)
Allocate memory aligned to a 16 byte boundary.
Definition MemManager.cpp:76
grk::grk_aligned_free
void grk_aligned_free(void *ptr)
Definition MemManager.cpp:80
grk::AllocatorAligned
Definition buffer.h:36
grk::AllocatorAligned::dealloc
void dealloc(T *buf)
Definition buffer.h:41
grk::AllocatorAligned::alloc
T * alloc(size_t length)
Definition buffer.h:37
grk::AllocatorVanilla
Definition buffer.h:24
grk::AllocatorVanilla::dealloc
void dealloc(T *buf)
Definition buffer.h:29
grk::AllocatorVanilla::alloc
T * alloc(size_t length)
Definition buffer.h:25
grk::grk_buf2d::memcpy_from
Definition buffer.h:374
grk::grk_buf2d::memcpy_from::copy
void copy(T *dst, T *src, uint32_t len)
Definition buffer.h:375
grk::grk_buf2d_simple
Definition buffer.h:206
grk::grk_buf2d_simple::grk_buf2d_simple
grk_buf2d_simple(T *buf, uint32_t stride, uint32_t height)
Definition buffer.h:208
grk::grk_buf2d_simple::grk_buf2d_simple
grk_buf2d_simple()
Definition buffer.h:207
grk::grk_buf2d_simple::buf_
T * buf_
Definition buffer.h:223
grk::grk_buf2d_simple::height_
uint32_t height_
Definition buffer.h:225
grk::grk_buf2d_simple::incX_IN_PLACE
grk_buf2d_simple & incX_IN_PLACE(size_t deltaX)
Definition buffer.h:211
grk::grk_buf2d_simple::incY_IN_PLACE
grk_buf2d_simple & incY_IN_PLACE(size_t deltaY)
Definition buffer.h:217
grk::grk_buf2d_simple::stride_
uint32_t stride_
Definition buffer.h:224
grk::grk_buf2d
Definition buffer.h:230
grk::grk_buf2d::transfer
void transfer(T **buffer, uint32_t *strd)
Definition buffer.h:327
grk::grk_buf2d::copyFrom
void copyFrom(const grk_buf2d &src, F filter)
Definition buffer.h:348
grk::grk_buf2d::grk_buf2d
grk_buf2d(uint32_t w, uint32_t h)
Definition buffer.h:234
grk::grk_buf2d::getBuffer
T * getBuffer(void) const
Definition buffer.h:384
grk::grk_buf2d::attach
void attach(T *buffer, uint32_t strd)
Definition buffer.h:293
grk::grk_buf2d::attach
void attach(grk_buf2d *rhs, uint32_t x, uint32_t y)
Definition buffer.h:306
grk::grk_buf2d::grk_buf2d
grk_buf2d(const grk_rect32 &b, bool useOrigin)
Definition buffer.h:241
grk::grk_buf2d::attach
void attach(grk_buf2d *rhs)
Definition buffer.h:316
grk::grk_buf2d::attach
void attach(grk_buf2d &rhs, uint32_t x, uint32_t y)
Definition buffer.h:298
grk::grk_buf2d::copyFrom
void copyFrom(const grk_buf2d &src)
Definition buffer.h:380
grk::grk_buf2d::alloc2d
bool alloc2d(bool clear)
Definition buffer.h:271
grk::grk_buf2d::copyFrom
void copyFrom(const grk_buf2d *src, F filter)
Definition buffer.h:354
grk::grk_buf2d::grk_buf2d
grk_buf2d(void)
Definition buffer.h:244
grk::grk_buf2d::grk_buf2d
grk_buf2d(const grk_rect32 &b)
Definition buffer.h:238
grk::grk_buf2d::grk_buf2d
grk_buf2d(const grk_buf2d &rhs)
Definition buffer.h:245
grk::grk_buf2d::grk_buf2d
grk_buf2d(const grk_rect32 *b)
Definition buffer.h:235
grk::grk_buf2d::operator=
grk_buf2d & operator=(const grk_buf2d *rhs)
Definition buffer.h:260
grk::grk_buf2d::operator=
grk_buf2d & operator=(const grk_buf2d &rhs)
Definition buffer.h:256
grk::grk_buf2d::~grk_buf2d
virtual ~grk_buf2d()=default
grk::grk_buf2d::address
T * address(uint32_t x, uint32_t y)
Definition buffer.h:388
grk::grk_buf2d::grk_buf2d
grk_buf2d(T *buffer, bool ownsData, uint32_t w, uint32_t strd, uint32_t h)
Definition buffer.h:231
grk::grk_buf2d::acquire
void acquire(T *buffer, uint32_t strd)
Definition buffer.h:321
grk::grk_buf2d::simpleF
grk_buf2d_simple< float > simpleF(void) const
Definition buffer.h:252
grk::grk_buf2d::simple
grk_buf2d_simple< T > simple(void) const
Definition buffer.h:248
grk::grk_buf2d::stride
uint32_t stride
Definition buffer.h:392
grk::grk_buf2d::isWindowValid
bool isWindowValid(grk_rect32 win)
Returns whether window bounds are valid (non empty and within buffer bounds)
Definition buffer.h:341
grk::grk_buf2d::attach
void attach(grk_buf2d &rhs)
Definition buffer.h:302
grk::grk_buf
Definition buffer.h:48
grk::grk_buf::remainingLength
size_t remainingLength(void)
Definition buffer.h:150
grk::grk_buf::attach
void attach(T *buffer)
Definition buffer.h:127
grk::grk_buf::read
T read(void)
Definition buffer.h:82
grk::grk_buf::grk_buf
grk_buf(T *buffer, size_t length)
Definition buffer.h:52
grk::grk_buf::owns_data
bool owns_data
Definition buffer.h:198
grk::grk_buf::len
size_t len
Definition buffer.h:197
grk::grk_buf::incrementOffset
void incrementOffset(ptrdiff_t off)
Definition buffer.h:154
grk::grk_buf::acquire
void acquire(T *buffer)
Definition buffer.h:133
grk::grk_buf::write
bool write(T *b, size_t size)
Definition buffer.h:94
grk::grk_buf::transfer
void transfer(T **buffer)
Definition buffer.h:140
grk::grk_buf::grk_buf
grk_buf(T *buffer, size_t off, size_t length, bool ownsData)
Definition buffer.h:49
grk::grk_buf::grk_buf
grk_buf()
Definition buffer.h:53
grk::grk_buf::write
bool write(T val)
Definition buffer.h:86
grk::grk_buf::operator=
grk_buf & operator=(const grk_buf *rhs)
Definition buffer.h:67
grk::grk_buf::alloc
virtual bool alloc(size_t length)
Definition buffer.h:103
grk::grk_buf::grk_buf
grk_buf(const grk_buf &rhs)
Definition buffer.h:59
grk::grk_buf::canRead
bool canRead(void)
Definition buffer.h:78
grk::grk_buf::operator=
grk_buf & operator=(const grk_buf &rhs)
Definition buffer.h:63
grk::grk_buf::grk_buf
grk_buf(T *buffer, size_t length, bool ownsData)
Definition buffer.h:54
grk::grk_buf::currPtr
T * currPtr(void) const
Definition buffer.h:189
grk::grk_buf::~grk_buf
virtual ~grk_buf()
Definition buffer.h:55
grk::grk_buf::dealloc
virtual void dealloc()
Definition buffer.h:117
grk::grk_buf::buf
T * buf
Definition buffer.h:195
grk::grk_buf::offset
size_t offset
Definition buffer.h:196
grk::grk_rect< uint32_t >
grk::grk_rect< uint32_t >::width
uint32_t width() const
Definition geometry.h:335
grk::grk_rect< uint32_t >::y1
uint32_t y1
Definition geometry.h:124
grk::grk_rect< uint32_t >::x0
uint32_t x0
Definition geometry.h:124
grk::grk_rect< uint32_t >::intersection
grk_rect< uint32_t > intersection(const grk_rect< uint32_t > rhs) const
Definition geometry.h:281
grk::grk_rect< uint32_t >::x1
uint32_t x1
Definition geometry.h:124
grk::grk_rect< uint32_t >::height
uint32_t height() const
Definition geometry.h:339
grk::grk_rect< uint32_t >::operator=
grk_rect< uint32_t > & operator=(const grk_rect< uint32_t > &rhs)
Definition geometry.h:201
grk::grk_rect< uint32_t >::y0
uint32_t y0
Definition geometry.h:124