/*
-Copyright (c) 2005-2006, John Hurst
+Copyright (c) 2005-2016, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
#include "KLV.h"
#include <list>
#include <vector>
+#include <set>
#include <map>
#include <wchar.h>
// used with TLVReader::Read*
//
// these are used below to manufacture arguments
-#define OBJ_READ_ARGS(s,l) Dict::Type(MDD_##s##_##l), &l
-#define OBJ_WRITE_ARGS(s,l) Dict::Type(MDD_##s##_##l), &l
-#define OBJ_TYPE_ARGS(t) Dict::Type(MDD_##t).ul
+#define OBJ_READ_ARGS(s,l) m_Dict->Type(MDD_##s##_##l), &l
+#define OBJ_WRITE_ARGS(s,l) m_Dict->Type(MDD_##s##_##l), &l
+#define OBJ_READ_ARGS_OPT(s,l) m_Dict->Type(MDD_##s##_##l), &l.get()
+#define OBJ_WRITE_ARGS_OPT(s,l) m_Dict->Type(MDD_##s##_##l), &l.get()
+#define OBJ_TYPE_ARGS(t) m_Dict->Type(MDD_##t).ul
namespace ASDCP
TLVReader();
ASDCP_NO_COPY_CONSTRUCT(TLVReader);
- bool FindTL(const MDDEntry&);
public:
TLVReader(const byte_t* p, ui32_t c, IPrimerLookup* = 0);
+ bool FindTL(const MDDEntry&);
Result_t ReadObject(const MDDEntry&, Kumu::IArchive*);
Result_t ReadUi8(const MDDEntry&, ui8_t*);
Result_t ReadUi16(const MDDEntry&, ui16_t*);
};
//
- template <class T>
- class Batch : public std::vector<T>, public Kumu::IArchive
+ template <class ContainerType>
+ class FixedSizeItemCollection : public ContainerType, public Kumu::IArchive
{
public:
- Batch() {}
- ~Batch() {}
+ FixedSizeItemCollection() {}
+ virtual ~FixedSizeItemCollection() {}
- //
- virtual bool Unarchive(Kumu::MemIOReader* Reader) {
- ui32_t ItemCount, ItemSize;
- if ( ! Reader->ReadUi32BE(&ItemCount) ) return false;
- if ( ! Reader->ReadUi32BE(&ItemSize) ) return false;
+ ui32_t ItemSize() const {
+ typename ContainerType::value_type tmp_item;
+ return tmp_item.ArchiveLength();
+ }
- if ( ( ItemCount > 65536 ) || ( ItemSize > 1024 ) )
- return false;
+ bool HasValue() const { return ! this->empty(); }
+ ui32_t ArchiveLength() const {
+ return ( sizeof(ui32_t) * 2 ) + ( (ui32_t)this->size() * this->ItemSize() );
+ }
+
+ bool Archive(Kumu::MemIOWriter* Writer) const {
+ if ( ! Writer->WriteUi32BE((ui32_t)this->size()) ) return false;
+ if ( ! Writer->WriteUi32BE((ui32_t)this->ItemSize()) ) return false;
+ if ( this->empty() ) return true;
+
+ typename ContainerType::const_iterator i;
bool result = true;
- for ( ui32_t i = 0; i < ItemCount && result; i++ )
+ for ( i = this->begin(); i != this->end() && result; ++i )
{
- T Tmp;
- result = Tmp.Unarchive(Reader);
-
- if ( result )
- push_back(Tmp);
+ result = i->Archive(Writer);
}
return result;
}
- inline virtual bool HasValue() const { return ! this->empty(); }
-
//
- virtual bool Archive(Kumu::MemIOWriter* Writer) const {
- if ( ! Writer->WriteUi32BE(this->size()) ) return false;
- byte_t* p = Writer->CurrentData();
-
- if ( ! Writer->WriteUi32BE(0) ) return false;
- if ( this->empty() ) return true;
-
- typename std::vector<T>::const_iterator l_i = this->begin();
- assert(l_i != this->end());
+ bool Unarchive(Kumu::MemIOReader* Reader) {
+ ui32_t item_count, item_size;
+ if ( ! Reader->ReadUi32BE(&item_count) ) return false;
+ if ( ! Reader->ReadUi32BE(&item_size) ) return false;
- ui32_t ItemSize = Writer->Remainder();
- if ( ! (*l_i).Archive(Writer) ) return false;
- ItemSize -= Writer->Remainder();
- Kumu::i2p<ui32_t>(KM_i32_BE(ItemSize), p);
- l_i++;
+ if ( item_count > 0 )
+ {
+ if ( this->ItemSize() != item_size ) return false;
+ }
bool result = true;
- for ( ; l_i != this->end() && result; l_i++ )
- result = (*l_i).Archive(Writer);
+ for ( ui32_t i = 0; i < item_count && result; ++i )
+ {
+ typename ContainerType::value_type tmp_item;
+ result = tmp_item.Unarchive(Reader);
+
+ if ( result )
+ {
+ this->push_back(tmp_item);
+ }
+ }
return result;
}
- //
- void Dump(FILE* stream = 0, ui32_t depth = 0)
- {
- char identbuf[IdentBufferLen];
+ void Dump(FILE* stream = 0, ui32_t depth = 0) {
+ char identbuf[IdentBufferLen];
- if ( stream == 0 )
+ if ( stream == 0 )
+ {
stream = stderr;
-
- typename std::vector<T>::iterator i = this->begin();
- for ( ; i != this->end(); i++ )
+ }
+
+ typename ContainerType::const_iterator i;
+ for ( i = this->begin(); i != this->end(); ++i )
+ {
fprintf(stream, " %s\n", (*i).EncodeString(identbuf, IdentBufferLen));
- }
+ }
+ }
};
+
+ template <class item_type>
+ class PushSet : public std::set<item_type>
+ {
+ public:
+ PushSet() {}
+ virtual ~PushSet() {}
+ void push_back(const item_type& item) { this->insert(item); }
+ };
+
+ template <class ItemType>
+ class Batch : public FixedSizeItemCollection<PushSet<ItemType> >
+ {
+ public:
+ Batch() {}
+ virtual ~Batch() {}
+ };
+
+ template <class ItemType>
+ class Array : public FixedSizeItemCollection<std::vector<ItemType> >
+ {
+ public:
+ Array() {}
+ virtual ~Array() {}
+ };
+
//
template <class T>
- class Array : public std::list<T>, public Kumu::IArchive
+ class SimpleArray : public std::list<T>, public Kumu::IArchive
{
public:
- Array() {}
- ~Array() {}
+ SimpleArray() {}
+ virtual ~SimpleArray() {}
//
- virtual bool Unarchive(Kumu::MemIOReader* Reader)
+ bool Unarchive(Kumu::MemIOReader* Reader)
{
bool result = true;
{
T Tmp;
result = Tmp.Unarchive(Reader);
- push_back(Tmp);
+
+ if ( result )
+ {
+ this->push_back(Tmp);
+ }
}
return result;
}
- inline virtual bool HasValue() const { return ! this->empty(); }
+ inline bool HasValue() const { return ! this->empty(); }
+
+ ui32_t ArchiveLength() const {
+ ui32_t arch_size = 0;
+
+ typename std::list<T>::const_iterator l_i = this->begin();
+
+ for ( ; l_i != this->end(); l_i++ )
+ arch_size += l_i->ArchiveLength();
+
+ return arch_size;
+ }
//
- virtual bool Archive(Kumu::MemIOWriter* Writer) const {
+ bool Archive(Kumu::MemIOWriter* Writer) const {
bool result = true;
typename std::list<T>::const_iterator l_i = this->begin();
};
//
- class Timestamp : public Kumu::IArchive
+ class ISO8String : public std::string, public Kumu::IArchive
{
public:
- ui16_t Year;
- ui8_t Month;
- ui8_t Day;
- ui8_t Hour;
- ui8_t Minute;
- ui8_t Second;
- ui8_t Tick;
-
- Timestamp();
- Timestamp(const Timestamp& rhs);
- Timestamp(const char* datestr);
- virtual ~Timestamp();
-
- const Timestamp& operator=(const Timestamp& rhs);
- bool operator<(const Timestamp& rhs) const;
- bool operator==(const Timestamp& rhs) const;
- bool operator!=(const Timestamp& rhs) const;
-
- // decode and set value from string formatted by EncodeAsString
- Result_t SetFromString(const char* datestr);
-
- // add the given number of days or hours to the timestamp value. Values less than zero
- // will cause the value to decrease
- void AddDays(i32_t);
- void AddHours(i32_t);
-
- // Write the timestamp value to the given buffer in the form 2004-05-01 13:20:00.000
- // returns 0 if the buffer is smaller than DateTimeLen
- const char* EncodeString(char* str_buf, ui32_t buf_len) const;
-
- //
- inline virtual bool Unarchive(Kumu::MemIOReader* Reader) {
- if ( ! Reader->ReadUi16BE(&Year) ) return false;
- if ( ! Reader->ReadRaw(&Month, 6) ) return false;
- return true;
- }
+ ISO8String() {}
+ ISO8String(const char*);
+ ISO8String(const std::string&);
+ ~ISO8String() {}
- inline virtual bool HasValue() const { return true; }
+ const ISO8String& operator=(const char*);
+ const ISO8String& operator=(const std::string&);
- //
- inline virtual bool Archive(Kumu::MemIOWriter* Writer) const {
- if ( ! Writer->WriteUi16BE(Year) ) return false;
- if ( ! Writer->WriteRaw(&Month, 6) ) return false;
- return true;
- }
+ const char* EncodeString(char* str_buf, ui32_t buf_len) const;
+ inline virtual bool HasValue() const { return ! empty(); }
+ inline virtual ui32_t ArchiveLength() const { return (ui32_t)(sizeof(ui32_t) + size()); }
+ virtual bool Unarchive(Kumu::MemIOReader* Reader);
+ virtual bool Archive(Kumu::MemIOWriter* Writer) const;
};
//
- class UTF16String : public Kumu::IArchive
+ class UTF16String : public std::string, public Kumu::IArchive
{
- ui16_t m_length;
- char m_buffer[IdentBufferLen];
- ASDCP_NO_COPY_CONSTRUCT(UTF16String);
-
public:
- UTF16String() : m_length(0) { *m_buffer = 0; }
+ UTF16String() {}
+ UTF16String(const char*);
+ UTF16String(const std::string&);
~UTF16String() {}
const UTF16String& operator=(const char*);
+ const UTF16String& operator=(const std::string&);
- //
- const char* EncodeString(char* str_buf, ui32_t buf_len) const {
- strncpy(str_buf, m_buffer, Kumu::xmin(buf_len, ((ui32_t)m_length+1)));
- str_buf[buf_len-1] = 0;
- return str_buf;
- }
-
+ const char* EncodeString(char* str_buf, ui32_t buf_len) const;
+ inline virtual bool HasValue() const { return ! empty(); }
+ inline virtual ui32_t ArchiveLength() const { return (ui32_t)(sizeof(ui32_t) + size()); }
virtual bool Unarchive(Kumu::MemIOReader* Reader);
- inline virtual bool HasValue() const { return m_length > 0; }
virtual bool Archive(Kumu::MemIOWriter* Writer) const;
};
Rational() {}
~Rational() {}
- Rational(const Rational& rhs) {
+ Rational(const Rational& rhs) : ASDCP::Rational(), IArchive() {
Numerator = rhs.Numerator;
Denominator = rhs.Denominator;
}
}
inline virtual bool HasValue() const { return true; }
+ inline virtual ui32_t ArchiveLength() const { return sizeof(ui32_t)*2; }
inline virtual bool Archive(Kumu::MemIOWriter* Writer) const {
if ( ! Writer->WriteUi32BE((ui32_t)Numerator) ) return false;
};
//
- class VersionType : public Kumu::IArchive
+ class LineMapPair : public Kumu::IArchive
+ {
+ public:
+ ui32_t First;
+ ui32_t Second;
+
+ LineMapPair() : First(0), Second() {}
+ ~LineMapPair() {}
+
+ LineMapPair(const ui32_t& first, const ui32_t& second) : IArchive() {
+ First = first;
+ Second = second;
+ }
+
+ LineMapPair(const LineMapPair& rhs) : IArchive() {
+ First = rhs.First;
+ Second = rhs.Second;
+ }
+
+ const LineMapPair& operator=(const LineMapPair& rhs) {
+ First = rhs.First;
+ Second = rhs.Second;
+ return *this;
+ }
+
+ //
+ inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
+ snprintf(str_buf, buf_len, "%d,%d", First, Second);
+ return str_buf;
+ }
+
+ inline virtual bool Unarchive(Kumu::MemIOReader* Reader) {
+ ui32_t n;
+ if ( ! Reader->ReadUi32BE(&n) ) return false;
+ if ( n != 2 ) return false;
+ if ( ! Reader->ReadUi32BE(&n) ) return false;
+ if ( n != 4 ) return false;
+ if ( ! Reader->ReadUi32BE((ui32_t*)&First) ) return false;
+ if ( ! Reader->ReadUi32BE((ui32_t*)&Second) ) return false;
+ return true;
+ }
+
+ inline virtual bool HasValue() const { return true; }
+ inline virtual ui32_t ArchiveLength() const { return sizeof(ui32_t)*4; }
+
+ inline virtual bool Archive(Kumu::MemIOWriter* Writer) const {
+ if ( ! Writer->WriteUi32BE(2UL) ) return false;
+ if ( ! Writer->WriteUi32BE(4UL) ) return false;
+ if ( ! Writer->WriteUi32BE((ui32_t)First) ) return false;
+ if ( ! Writer->WriteUi32BE((ui32_t)Second) ) return false;
+ return true;
+ }
+ };
+
+ //
+ class ColorPrimary : public Kumu::IArchive
{
- ASDCP_NO_COPY_CONSTRUCT(VersionType);
+ public:
+ ui16_t X;
+ ui16_t Y;
+
+ ColorPrimary() : X(0), Y(0) {}
+ ~ColorPrimary() {}
+
+ ColorPrimary(const ui16_t& x, const ui16_t& y) : X(x), Y(y) {}
+
+ ColorPrimary(const ColorPrimary& rhs) { Copy(rhs); }
+ const ColorPrimary& operator=(const ColorPrimary& rhs) { Copy(rhs); return *this; }
+
+ void Copy(const ColorPrimary& rhs) {
+ X = rhs.X;
+ Y = rhs.Y;
+ }
+
+ //
+ inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
+ snprintf(str_buf, buf_len, "%d,%d", X, Y);
+ return str_buf;
+ }
+ inline virtual bool Unarchive(Kumu::MemIOReader* Reader) {
+ if ( ! Reader->ReadUi16BE((ui16_t*)&X) ) return false;
+ if ( ! Reader->ReadUi16BE((ui16_t*)&Y) ) return false;
+ return true;
+ }
+
+ inline virtual bool HasValue() const { return X || Y; }
+ inline virtual ui32_t ArchiveLength() const { return sizeof(ui16_t)*2; }
+
+ inline virtual bool Archive(Kumu::MemIOWriter* Writer) const {
+ if ( ! Writer->WriteUi16BE((ui16_t)X) ) return false;
+ if ( ! Writer->WriteUi16BE((ui16_t)Y) ) return false;
+ return true;
+ }
+ };
+
+ //
+ class ThreeColorPrimaries : public Kumu::IArchive
+ {
public:
- enum Release_t { RL_UNKNOWN, RM_RELEASE, RL_DEVELOPMENT, RL_PATCHED, RL_BETA, RL_PRIVATE };
+ ColorPrimary First;
+ ColorPrimary Second;
+ ColorPrimary Third;
+
+ ThreeColorPrimaries() {}
+ ~ThreeColorPrimaries() {}
+
+ ThreeColorPrimaries(const ColorPrimary& first, const ColorPrimary& second, const ColorPrimary& third) :
+ First(first), Second(second), Third(third) {}
+
+ ThreeColorPrimaries(const ThreeColorPrimaries& rhs) { Copy(rhs); }
+ const ThreeColorPrimaries& operator=(const ThreeColorPrimaries& rhs) { Copy(rhs); return *this; }
+
+ void Copy(const ThreeColorPrimaries& rhs) {
+ First = rhs.First;
+ Second = rhs.Second;
+ Third = rhs.Third;
+ }
+
+ //
+ inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
+ snprintf(str_buf, buf_len, "%d,%d;%d,%d;%d,%d", First.X, First.Y, Second.X, Second.Y, Third.X, Third.Y);
+ return str_buf;
+ }
+
+ inline virtual bool Unarchive(Kumu::MemIOReader* Reader) {
+ First.Unarchive(Reader);
+ Second.Unarchive(Reader);
+ Third.Unarchive(Reader);
+ return true;
+ }
+
+ inline virtual bool HasValue() const {
+ return First.HasValue() || Second.HasValue() || Third.HasValue();
+ }
+
+ inline virtual ui32_t ArchiveLength() const {
+ return First.ArchiveLength()
+ + Second.ArchiveLength()
+ + Third.ArchiveLength();
+ }
+
+ inline virtual bool Archive(Kumu::MemIOWriter* Writer) const {
+ First.Archive(Writer);
+ Second.Archive(Writer);
+ Third.Archive(Writer);
+ return true;
+ }
+ };
+
+ //
+ class VersionType : public Kumu::IArchive
+ {
+ public:
+ enum Release_t { RL_UNKNOWN, RL_RELEASE, RL_DEVELOPMENT, RL_PATCHED, RL_BETA, RL_PRIVATE, RL_MAX };
ui16_t Major;
ui16_t Minor;
ui16_t Patch;
ui16_t Build;
- ui16_t Release;
+ Release_t Release;
VersionType() : Major(0), Minor(0), Patch(0), Build(0), Release(RL_UNKNOWN) {}
- ~VersionType() {}
+ VersionType(const VersionType& rhs) { Copy(rhs); }
+ virtual ~VersionType() {}
+
+ const VersionType& operator=(const VersionType& rhs) { Copy(rhs); return *this; }
+ void Copy(const VersionType& rhs) {
+ Major = rhs.Major;
+ Minor = rhs.Minor;
+ Patch = rhs.Patch;
+ Build = rhs.Build;
+ Release = rhs.Release;
+ }
+
void Dump(FILE* = 0);
const char* EncodeString(char* str_buf, ui32_t buf_len) const {
- snprintf(str_buf, buf_len, "%hu.%hu.%hu.%hur%hu", Major, Minor, Patch, Build, Release);
+ snprintf(str_buf, buf_len, "%hu.%hu.%hu.%hur%hu", Major, Minor, Patch, Build, ui16_t(Release));
return str_buf;
}
}
inline virtual bool HasValue() const { return true; }
+ inline virtual ui32_t ArchiveLength() const { return sizeof(ui16_t)*5; }
virtual bool Archive(Kumu::MemIOWriter* Writer) const {
if ( ! Writer->WriteUi16BE(Major) ) return false;
}
};
- //
- class Raw : public Kumu::ByteString, public Kumu::IArchive
+ /*
+ The RGBALayout type shall be a fixed-size 8 element sequence with a total length
+ of 16 bytes, where each element shall consist of the RGBAComponent type with the
+ following fields:
+
+ Code (UInt8): Enumerated value specifying component (i.e., component identifier).
+ "0" is the layout terminator.
+
+ Depth (UInt8): Integer specifying the number of bits occupied (see also G.2.26)
+ 1->32 indicates integer depth
+ 253 = HALF (floating point 16-bit value)
+ 254 = IEEE floating point 32-bit value
+ 255 = IEEE floating point 64-bit value
+ 0 = RGBALayout terminator
+
+ A Fill component indicates unused bits. After the components have been specified,
+ the remaining Code and Size fields shall be set to zero (0).
+
+ For each component in the Pixel, one of the following Codes or the terminator
+ shall be specified (explained below):
+
+ Code ASCII
+
+ */
+ struct RGBALayoutTableEntry
+ {
+ byte_t code;
+ char symbol;
+ const char* label;
+ };
+
+ struct RGBALayoutTableEntry const RGBALayoutTable[] = {
+ { 0x52, 'R', "Red component" },
+ { 0x47, 'G', "Green component" },
+ { 0x42, 'B', "Blue component" },
+ { 0x41, 'A', "Alpha component" },
+ { 0x72, 'r', "Red component (LSBs)" },
+ { 0x67, 'g', "Green component (LSBs)" },
+ { 0x62, 'b', "Blue component (LSBs)" },
+ { 0x61, 'a', "Alpha component (LSBs)" },
+ { 0x46, 'F', "Fill component" },
+ { 0x50, 'P', "Palette code" },
+ { 0x55, 'U', "Color Difference Sample (e.g. U, Cb, I etc.)" },
+ { 0x56, 'V', "Color Difference Sample (e.g. V, Cr, Q etc.)" },
+ { 0x57, 'W', "Composite Video" },
+ { 0x58, 'X', "Non co-sited luma component" },
+ { 0x59, 'Y', "Luma component" },
+ { 0x5a, 'Z', "Depth component (SMPTE ST 268 compatible)" },
+ { 0x75, 'u', "Color Difference Sample (e.g. U, Cb, I etc.) (LSBs)" },
+ { 0x76, 'v', "Color Difference Sample (e.g. V, Cr, Q etc.) (LSBs)" },
+ { 0x77, 'w', "Composite Video (LSBs)" },
+ { 0x78, 'x', "Non co-sited luma component (LSBs)" },
+ { 0x79, 'y', "Luma component (LSBs)" },
+ { 0x7a, 'z', "Depth component (LSBs) (SMPTE ST 268 compatible)" },
+ { 0xd8, 'X', "The DCDM X color component (see SMPTE ST 428-1 X')" },
+ { 0xd9, 'Y', "The DCDM Y color component (see SMPTE ST 428-1 Y')" },
+ { 0xda, 'Z', "The DCDM Z color component (see SMPTE ST 428-1 Z')" },
+ { 0x00, '_', "Terminator" }
+ };
+
+
+ size_t const RGBAValueLength = 16;
+
+ byte_t const RGBAValue_RGB_10[RGBAValueLength] = { 'R', 10, 'G', 10, 'B', 10, 0, 0 };
+ byte_t const RGBAValue_RGB_8[RGBAValueLength] = { 'R', 8, 'G', 8, 'B', 8, 0, 0 };
+ byte_t const RGBAValue_YUV_10[RGBAValueLength] = { 'Y', 10, 'U', 10, 'V', 10, 0, 0 };
+ byte_t const RGBAValue_YUV_8[RGBAValueLength] = { 'Y', 8, 'U', 8, 'V', 8, 0, 0 };
+ byte_t const RGBAValue_DCDM[RGBAValueLength] = { 0xd8, 10, 0xd9, 10, 0xda, 10, 0, 0 };
+
+
+ class RGBALayout : public Kumu::IArchive
{
- ASDCP_NO_COPY_CONSTRUCT(Raw);
+ byte_t m_value[RGBAValueLength];
+
+ public:
+ RGBALayout();
+ RGBALayout(const byte_t* value);
+ ~RGBALayout();
+
+ RGBALayout(const RGBALayout& rhs) { Set(rhs.m_value); }
+ const RGBALayout& operator=(const RGBALayout& rhs) { Set(rhs.m_value); return *this; }
+
+ void Set(const byte_t* value) {
+ memcpy(m_value, value, RGBAValueLength);
+ }
+
+ const char* EncodeString(char* buf, ui32_t buf_len) const;
+
+ bool HasValue() const { return true; }
+ ui32_t ArchiveLength() const { return RGBAValueLength; }
+
+ bool Archive(Kumu::MemIOWriter* Writer) const {
+ return Writer->WriteRaw(m_value, RGBAValueLength);
+ }
+
+ bool Unarchive(Kumu::MemIOReader* Reader) {
+ if ( Reader->Remainder() < RGBAValueLength )
+ {
+ return false;
+ }
+ memcpy(m_value, Reader->CurrentData(), RGBAValueLength);
+ Reader->SkipOffset(RGBAValueLength);
+ return true;
+ }
+ };
+
+
+ //
+ class Raw : public Kumu::ByteString
+ {
public:
Raw();
- ~Raw();
+ Raw(const Raw& rhs) { Copy(rhs); }
+ virtual ~Raw();
+
+ const Raw& operator=(const Raw& rhs) { Copy(rhs); return *this; }
+ void Copy(const Raw& rhs) {
+ if ( KM_SUCCESS(Capacity(rhs.Length())) )
+ {
+ Set(rhs);
+ }
+ }
//
virtual bool Unarchive(Kumu::MemIOReader* Reader);
- inline virtual bool HasValue() const { return Length() > 0; }
virtual bool Archive(Kumu::MemIOWriter* Writer) const;
const char* EncodeString(char* str_buf, ui32_t buf_len) const;
};