389 lines
13 KiB
C++
389 lines
13 KiB
C++
//| Copyright: (C) 2020-2024 Kevin Larke <contact AT larke DOT org>
|
|
//| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file.
|
|
#include "cwCommon.h"
|
|
#include "cwLog.h"
|
|
#include "cwCommonImpl.h"
|
|
#include "cwFile.h"
|
|
#include "cwVariant.h"
|
|
|
|
namespace cw
|
|
{
|
|
namespace variant
|
|
{
|
|
typedef struct _variantDesc_str
|
|
{
|
|
unsigned flags;
|
|
const char* label;
|
|
const char* fmt;
|
|
unsigned byteN;
|
|
} variantDesc_t;
|
|
|
|
variantDesc_t _variantDescArray[] = {
|
|
|
|
{ kCharVFl, "char", "c", sizeof(char) },
|
|
{ kUCharVFl, "uchar", "c", sizeof(unsigned char) },
|
|
{ kInt8VFl, "uint8", "i", sizeof(std::uint8_t) },
|
|
{ kUInt8VFl, "int8", "i", sizeof(std::int8_t) },
|
|
{ kInt16VFl, "uint16", "i", sizeof(std::uint16_t) },
|
|
{ kUInt16VFl,"int16", "i", sizeof(std::int16_t) },
|
|
{ kInt32VFl, "uint32", "i", sizeof(std::uint32_t) },
|
|
{ kUInt32VFl,"int32", "i", sizeof(std::int32_t) },
|
|
{ kInt64VFl, "uint64", "li", sizeof(std::uint64_t) },
|
|
{ kUInt64VFl,"int64", "li", sizeof(std::int64_t) },
|
|
{ kBoolVFl, "bool", "i", sizeof(bool) },
|
|
{ kFloatVFl, "float", "f", sizeof(float) },
|
|
{ kDoubleVFl,"double", "f", sizeof(double) },
|
|
|
|
{ kPtrVFl | kCharVFl, "char_ptr", "p", sizeof(char) },
|
|
{ kPtrVFl | kUCharVFl, "uchar_ptr", "p", sizeof(unsigned char) },
|
|
{ kPtrVFl | kInt8VFl, "uint8_ptr", "p", sizeof(std::uint8_t) },
|
|
{ kPtrVFl | kUInt8VFl, "int8_ptr", "p", sizeof(std::int8_t) },
|
|
{ kPtrVFl | kInt16VFl, "uint16_ptr", "p", sizeof(std::uint16_t) },
|
|
{ kPtrVFl | kUInt16VFl, "int16_ptr", "p", sizeof(std::int16_t) },
|
|
{ kPtrVFl | kInt32VFl, "uint32_ptr", "p", sizeof(std::uint32_t) },
|
|
{ kPtrVFl | kUInt32VFl, "int32_ptr", "p", sizeof(std::int32_t) },
|
|
{ kPtrVFl | kInt64VFl, "uint64_ptr", "p", sizeof(std::uint64_t) },
|
|
{ kPtrVFl | kUInt64VFl, "int64_ptr", "p", sizeof(std::int64_t) },
|
|
{ kPtrVFl | kBoolVFl, "bool_ptr", "p", sizeof(bool) },
|
|
{ kPtrVFl | kFloatVFl, "float_ptr", "p", sizeof(float) },
|
|
{ kPtrVFl | kDoubleVFl, "double_ptr", "p", sizeof(double) },
|
|
|
|
{ 0, nullptr, nullptr, 0 }
|
|
|
|
};
|
|
|
|
const variantDesc_t* _flagsToDesc( unsigned flags, bool reportErrorFl=true )
|
|
{
|
|
variantDesc_t* v = _variantDescArray;
|
|
|
|
for(; v->flags!=0; ++v)
|
|
if( v->flags == flags )
|
|
return v;
|
|
|
|
if( reportErrorFl )
|
|
cwLogError(kInvalidArgRC,"The variant flags 0x%x is invalid.");
|
|
return nullptr;
|
|
}
|
|
|
|
const char* safeFlagsToLabel( unsigned flags )
|
|
{
|
|
const variantDesc_t* d = _flagsToDesc(flags,false);
|
|
return d == nullptr ? "<invalid>" : d->label;
|
|
}
|
|
|
|
rc_t _get_uint8( const value_t& v, std::uint8_t& r )
|
|
{
|
|
switch( v.flags )
|
|
{
|
|
case kCharVFl: r = v.u.c; break;
|
|
case kUCharVFl: r = v.u.uc; break;
|
|
case kInt8VFl: r = v.u.i8; break;
|
|
case kUInt8VFl: r = v.u.u8; break;
|
|
case kBoolVFl: r = v.u.b; break;
|
|
default:
|
|
return cwLogError(kInvalidArgRC,"Invalid type conversion. Cannot convert '%s' to 'double'.", safeFlagsToLabel(v.flags) );
|
|
}
|
|
return kOkRC;
|
|
}
|
|
|
|
rc_t _get_int8( const value_t& v, std::int8_t& r )
|
|
{
|
|
switch( v.flags )
|
|
{
|
|
case kCharVFl: r = v.u.c; break;
|
|
case kUCharVFl: r = v.u.uc; break;
|
|
case kInt8VFl: r = v.u.i8; break;
|
|
case kUInt8VFl: r = v.u.u8; break;
|
|
case kBoolVFl: r = v.u.b; break;
|
|
default:
|
|
return cwLogError(kInvalidArgRC,"Invalid type conversion. Cannot convert '%s' to 'double'.", safeFlagsToLabel(v.flags) );
|
|
}
|
|
return kOkRC;
|
|
}
|
|
|
|
|
|
rc_t _get_uint16( const value_t& v, std::uint16_t& r )
|
|
{
|
|
switch( v.flags )
|
|
{
|
|
case kCharVFl: r = v.u.c; break;
|
|
case kUCharVFl: r = v.u.uc; break;
|
|
case kInt8VFl: r = v.u.i8; break;
|
|
case kUInt8VFl: r = v.u.u8; break;
|
|
case kInt16VFl: r = v.u.i16; break;
|
|
case kUInt16VFl: r = v.u.u16; break;
|
|
case kBoolVFl: r = v.u.b; break;
|
|
default:
|
|
return cwLogError(kInvalidArgRC,"Invalid type conversion. Cannot convert '%s' to 'double'.", safeFlagsToLabel(v.flags) );
|
|
}
|
|
return kOkRC;
|
|
}
|
|
|
|
rc_t _get_int16( const value_t& v, std::int16_t& r )
|
|
{
|
|
switch( v.flags )
|
|
{
|
|
case kCharVFl: r = v.u.c; break;
|
|
case kUCharVFl: r = v.u.uc; break;
|
|
case kInt8VFl: r = v.u.i8; break;
|
|
case kUInt8VFl: r = v.u.u8; break;
|
|
case kInt16VFl: r = v.u.i16; break;
|
|
case kUInt16VFl: r = v.u.u16; break;
|
|
case kBoolVFl: r = v.u.b; break;
|
|
default:
|
|
return cwLogError(kInvalidArgRC,"Invalid type conversion. Cannot convert '%s' to 'double'.", safeFlagsToLabel(v.flags) );
|
|
}
|
|
return kOkRC;
|
|
}
|
|
|
|
rc_t _get_uint32( const value_t& v, std::uint32_t& r )
|
|
{
|
|
switch( v.flags )
|
|
{
|
|
case kCharVFl: r = v.u.c; break;
|
|
case kUCharVFl: r = v.u.uc; break;
|
|
case kInt8VFl: r = v.u.i8; break;
|
|
case kUInt8VFl: r = v.u.u8; break;
|
|
case kInt16VFl: r = v.u.i16; break;
|
|
case kUInt16VFl: r = v.u.u16; break;
|
|
case kInt32VFl: r = v.u.i32; break;
|
|
case kUInt32VFl: r = v.u.u32; break;
|
|
case kBoolVFl: r = v.u.b; break;
|
|
default:
|
|
return cwLogError(kInvalidArgRC,"Invalid type conversion. Cannot convert '%s' to 'double'.", safeFlagsToLabel(v.flags) );
|
|
}
|
|
return kOkRC;
|
|
}
|
|
|
|
|
|
rc_t _get_int32( const value_t& v, std::int32_t& r )
|
|
{
|
|
switch( v.flags )
|
|
{
|
|
case kCharVFl: r = v.u.c; break;
|
|
case kUCharVFl: r = v.u.uc; break;
|
|
case kInt8VFl: r = v.u.i8; break;
|
|
case kUInt8VFl: r = v.u.u8; break;
|
|
case kInt16VFl: r = v.u.i16; break;
|
|
case kUInt16VFl: r = v.u.u16; break;
|
|
case kInt32VFl: r = v.u.i32; break;
|
|
case kUInt32VFl: r = v.u.u32; break;
|
|
case kBoolVFl: r = v.u.b; break;
|
|
default:
|
|
return cwLogError(kInvalidArgRC,"Invalid type conversion. Cannot convert '%s' to 'double'.", safeFlagsToLabel(v.flags) );
|
|
}
|
|
return kOkRC;
|
|
}
|
|
|
|
rc_t _get_uint64( const value_t& v, std::uint64_t& r )
|
|
{
|
|
switch( v.flags )
|
|
{
|
|
case kCharVFl: r = v.u.c; break;
|
|
case kUCharVFl: r = v.u.uc; break;
|
|
case kInt8VFl: r = v.u.i8; break;
|
|
case kUInt8VFl: r = v.u.u8; break;
|
|
case kInt16VFl: r = v.u.i16; break;
|
|
case kUInt16VFl: r = v.u.u16; break;
|
|
case kInt32VFl: r = v.u.i32; break;
|
|
case kUInt32VFl: r = v.u.u32; break;
|
|
case kInt64VFl: r = v.u.i64; break;
|
|
case kUInt64VFl: r = v.u.u64; break;
|
|
case kBoolVFl: r = v.u.b; break;
|
|
case kFloatVFl: r = v.u.f; break;
|
|
case kDoubleVFl: r = v.u.d; break;
|
|
default:
|
|
return cwLogError(kInvalidArgRC,"Invalid type conversion. Cannot convert '%s' to 'double'.", safeFlagsToLabel(v.flags) );
|
|
}
|
|
return kOkRC;
|
|
}
|
|
|
|
rc_t _get_int64( const value_t& v, std::int64_t& r )
|
|
{
|
|
switch( v.flags )
|
|
{
|
|
case kCharVFl: r = v.u.c; break;
|
|
case kUCharVFl: r = v.u.uc; break;
|
|
case kInt8VFl: r = v.u.i8; break;
|
|
case kUInt8VFl: r = v.u.u8; break;
|
|
case kInt16VFl: r = v.u.i16; break;
|
|
case kUInt16VFl: r = v.u.u16; break;
|
|
case kInt32VFl: r = v.u.i32; break;
|
|
case kUInt32VFl: r = v.u.u32; break;
|
|
case kInt64VFl: r = v.u.i64; break;
|
|
case kUInt64VFl: r = v.u.u64; break;
|
|
case kBoolVFl: r = v.u.b; break;
|
|
case kFloatVFl: r = v.u.f; break;
|
|
case kDoubleVFl: r = v.u.d; break;
|
|
default:
|
|
return cwLogError(kInvalidArgRC,"Invalid type conversion. Cannot convert '%s' to 'double'.", safeFlagsToLabel(v.flags) );
|
|
}
|
|
return kOkRC;
|
|
}
|
|
|
|
rc_t _get_bool( const value_t& v, bool& r )
|
|
{
|
|
switch( v.flags )
|
|
{
|
|
case kCharVFl: r = v.u.c!=0; break;
|
|
case kUCharVFl: r = v.u.uc!=0; break;
|
|
case kInt8VFl: r = v.u.i8!=0; break;
|
|
case kUInt8VFl: r = v.u.u8!=0; break;
|
|
case kInt16VFl: r = v.u.i16!=0; break;
|
|
case kUInt16VFl: r = v.u.u16!=0; break;
|
|
case kInt32VFl: r = v.u.i32!=0; break;
|
|
case kUInt32VFl: r = v.u.u32!=0; break;
|
|
case kInt64VFl: r = v.u.i64!=0; break;
|
|
case kUInt64VFl: r = v.u.u64!=0; break;
|
|
case kBoolVFl: r = v.u.b; break;
|
|
case kFloatVFl: r = v.u.f!=0.0; break;
|
|
case kDoubleVFl: r = v.u.d!=0.0; break;
|
|
default:
|
|
return cwLogError(kInvalidArgRC,"Invalid type conversion. Cannot convert '%s' to 'double'.", safeFlagsToLabel(v.flags) );
|
|
}
|
|
return kOkRC;
|
|
}
|
|
|
|
rc_t _get_float( const value_t& v, float& r )
|
|
{
|
|
switch( v.flags )
|
|
{
|
|
case kCharVFl: r = v.u.c; break;
|
|
case kUCharVFl: r = v.u.uc; break;
|
|
case kInt8VFl: r = v.u.i8; break;
|
|
case kUInt8VFl: r = v.u.u8; break;
|
|
case kInt16VFl: r = v.u.i16; break;
|
|
case kUInt16VFl: r = v.u.u16; break;
|
|
case kInt32VFl: r = v.u.i32; break;
|
|
case kUInt32VFl: r = v.u.u32; break;
|
|
case kInt64VFl: r = v.u.i64; break;
|
|
case kUInt64VFl: r = v.u.u64; break;
|
|
case kBoolVFl: r = v.u.b; break;
|
|
case kFloatVFl: r = v.u.f; break;
|
|
default:
|
|
return cwLogError(kInvalidArgRC,"Invalid type conversion. Cannot convert '%s' to 'double'.", safeFlagsToLabel(v.flags) );
|
|
}
|
|
return kOkRC;
|
|
}
|
|
|
|
rc_t _get_double( const value_t& v, double& r )
|
|
{
|
|
switch( v.flags )
|
|
{
|
|
case kCharVFl: r = v.u.c; break;
|
|
case kUCharVFl: r = v.u.uc; break;
|
|
case kInt8VFl: r = v.u.i8; break;
|
|
case kUInt8VFl: r = v.u.u8; break;
|
|
case kInt16VFl: r = v.u.i16; break;
|
|
case kUInt16VFl: r = v.u.u16; break;
|
|
case kInt32VFl: r = v.u.i32; break;
|
|
case kUInt32VFl: r = v.u.u32; break;
|
|
case kInt64VFl: r = v.u.i64; break;
|
|
case kUInt64VFl: r = v.u.u64; break;
|
|
case kBoolVFl: r = v.u.b; break;
|
|
case kFloatVFl: r = v.u.f; break;
|
|
case kDoubleVFl: r = v.u.d; break;
|
|
default:
|
|
return cwLogError(kInvalidArgRC,"Invalid type conversion. Cannot convert '%s' to 'double'.", safeFlagsToLabel(v.flags) );
|
|
}
|
|
return kOkRC;
|
|
}
|
|
|
|
|
|
rc_t get( const value_t& v, std::int8_t& r ) { return _get_int8(v,r); }
|
|
rc_t get( const value_t& v, std::uint8_t& r ) { return _get_uint8(v,r); }
|
|
rc_t get( const value_t& v, std::int16_t& r ) { return _get_int16(v,r); }
|
|
rc_t get( const value_t& v, std::uint16_t& r ) { return _get_uint16(v,r); }
|
|
rc_t get( const value_t& v, std::int32_t& r ) { return _get_int32(v,r); }
|
|
rc_t get( const value_t& v, std::uint32_t& r ) { return _get_uint32(v,r); }
|
|
rc_t get( const value_t& v, std::int64_t& r ) { return _get_int64(v,r); }
|
|
rc_t get( const value_t& v, std::uint64_t& r ) { return _get_uint64(v,r); }
|
|
rc_t get( const value_t& v, bool& r ) { return _get_bool(v,r); }
|
|
rc_t get( const value_t& v, float& r ) { return _get_float(v,r); }
|
|
rc_t get( const value_t& v, double& r ) { return _get_double(v,r); }
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
const char* cw::variant::flagsToLabel( unsigned flags )
|
|
{
|
|
const variantDesc_t* v;
|
|
if((v = _flagsToDesc(flags)) != nullptr )
|
|
return v->label;
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
unsigned cw::variant::flagsToBytes( unsigned flags )
|
|
{
|
|
const variantDesc_t* v;
|
|
if((v = _flagsToDesc(flags)) != nullptr )
|
|
return v->byteN;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
cw::rc_t cw::variant::print( const value_t& v, const char* fmt)
|
|
{
|
|
rc_t rc = kOkRC;
|
|
const variantDesc_t* d;
|
|
|
|
if((d = _flagsToDesc(v.flags)) != nullptr )
|
|
{
|
|
char f[32+1];
|
|
snprintf(f,32,"%s%s%s", "%", fmt==nullptr ? "":fmt, d->fmt);
|
|
|
|
if( v.flags & kPtrVFl )
|
|
printf(fmt,v.u.vp);
|
|
else
|
|
{
|
|
switch( v.flags )
|
|
{
|
|
case kCharVFl: printf(f,v.u.c); break;
|
|
case kUCharVFl: printf(f,v.u.uc); break;
|
|
case kInt8VFl: printf(f,v.u.i8); break;
|
|
case kUInt8VFl: printf(f,v.u.u8); break;
|
|
case kInt16VFl: printf(f,v.u.i16); break;
|
|
case kUInt16VFl: printf(f,v.u.u16); break;
|
|
case kInt32VFl:
|
|
printf(f,v.u.i32);
|
|
break;
|
|
|
|
case kUInt32VFl: printf(f,v.u.u32); break;
|
|
case kInt64VFl: printf(f,v.u.i64); break;
|
|
case kUInt64VFl: printf(f,v.u.u64); break;
|
|
case kBoolVFl: printf(f,v.u.b); break;
|
|
case kFloatVFl: printf(f,v.u.f); break;
|
|
case kDoubleVFl: printf(f,v.u.d); break;
|
|
default:
|
|
assert(0);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
cw::rc_t cw::variant::write( file::handle_t fH, const value_t& v )
|
|
{
|
|
rc_t rc;
|
|
if((rc = file::writeUInt( fH, &v.flags)) == kOkRC )
|
|
rc = file::write( fH, &v.u, sizeof(v.u));
|
|
return rc;
|
|
}
|
|
|
|
cw::rc_t cw::variant::read( file::handle_t fH, value_t& v )
|
|
{
|
|
rc_t rc;
|
|
if((rc = file::readUInt( fH, &v.flags)) == kOkRC )
|
|
rc = file::read( fH, &v.u, sizeof(v.u));
|
|
return rc;
|
|
}
|
|
|
|
|