sharedArray formatting with size limit.
This commit is contained in:
+1
-1
@@ -184,7 +184,7 @@ struct FmtTree {
|
||||
if(!fmt._showValue) {
|
||||
strm<<"\n";
|
||||
} else if(varr.original_type()!=ArrayType::Value) {
|
||||
strm<<" = "<<varr<<"\n";
|
||||
strm<<" = "<<varr.format().limit(fmt._limit)<<"\n";
|
||||
} else {
|
||||
auto arr = varr.castTo<const Value>();
|
||||
strm<<" [\n";
|
||||
|
||||
+56
-46
@@ -82,7 +82,7 @@ protected:
|
||||
template<typename E1> friend struct sa_base;
|
||||
|
||||
std::shared_ptr<E> _data;
|
||||
size_t _size;
|
||||
size_t _count;
|
||||
public:
|
||||
|
||||
// shared_array()
|
||||
@@ -95,60 +95,61 @@ public:
|
||||
// shared_array(shared_ptr<T>, T*, size_t)
|
||||
|
||||
//! empty
|
||||
constexpr sa_base() :_size(0u) {}
|
||||
constexpr sa_base() :_count(0u) {}
|
||||
|
||||
// copyable
|
||||
sa_base(const sa_base&) = default;
|
||||
// movable
|
||||
inline sa_base(sa_base&& o) noexcept
|
||||
:_data(std::move(o._data)), _size(o._size)
|
||||
:_data(std::move(o._data)), _count(o._count)
|
||||
{
|
||||
o._size = 0;
|
||||
o._count = 0;
|
||||
}
|
||||
sa_base& operator=(const sa_base&) =default;
|
||||
inline sa_base& operator=(sa_base&& o) noexcept
|
||||
{
|
||||
_data = std::move(o._data);
|
||||
_size = o._size;
|
||||
o._size = 0;
|
||||
_count = o._count;
|
||||
o._count = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// use existing alloc with delete[]
|
||||
template<typename A>
|
||||
sa_base(A* a, size_t len)
|
||||
:_data(a, sa_default_delete<E>()),_size(len)
|
||||
:_data(a, sa_default_delete<E>()),_count(len)
|
||||
{}
|
||||
|
||||
// use existing alloc w/ custom deletor
|
||||
template<typename B>
|
||||
sa_base(E* a, B b, size_t len)
|
||||
:_data(a, b),_size(len)
|
||||
:_data(a, b),_count(len)
|
||||
{}
|
||||
|
||||
// build around existing shared_ptr
|
||||
sa_base(const std::shared_ptr<E>& a, size_t len)
|
||||
:_data(a),_size(len)
|
||||
:_data(a),_count(len)
|
||||
{}
|
||||
|
||||
// alias existing shared_ptr
|
||||
template<typename A>
|
||||
sa_base(const std::shared_ptr<A>& a, E* b, size_t len)
|
||||
:_data(a, b),_size(len)
|
||||
:_data(a, b),_count(len)
|
||||
{}
|
||||
|
||||
void clear() noexcept {
|
||||
_data.reset();
|
||||
_size = 0;
|
||||
_count = 0;
|
||||
}
|
||||
|
||||
void swap(sa_base& o) noexcept {
|
||||
std::swap(_data, o._data);
|
||||
std::swap(_size, o._data);
|
||||
std::swap(_count, o._data);
|
||||
}
|
||||
|
||||
inline size_t size() const { return _size; }
|
||||
inline bool empty() const noexcept { return _size==0; }
|
||||
//! Number of elements
|
||||
inline size_t size() const { return _count; }
|
||||
inline bool empty() const noexcept { return _count==0; }
|
||||
|
||||
inline bool unique() const noexcept { return !_data || _data.use_count()<=1; }
|
||||
|
||||
@@ -157,6 +158,23 @@ public:
|
||||
const std::shared_ptr<E>& dataPtr() const { return _data; }
|
||||
};
|
||||
|
||||
class Limiter {
|
||||
const void* _base;
|
||||
size_t _count;
|
||||
size_t _limit=0u;
|
||||
ArrayType _type;
|
||||
friend
|
||||
std::ostream& operator<<(std::ostream& strm, const Limiter& lim);
|
||||
public:
|
||||
Limiter(const void* base, size_t count, ArrayType type)
|
||||
:_base(base), _count(count), _type(type)
|
||||
{}
|
||||
Limiter& limit(size_t l) { _limit = l; return *this; }
|
||||
};
|
||||
|
||||
PVXS_API
|
||||
std::ostream& operator<<(std::ostream& strm, const Limiter&);
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/** std::vector-like contigious array of items passed by reference.
|
||||
@@ -229,7 +247,7 @@ public:
|
||||
shared_array(size_t c, V e)
|
||||
:base_t(new _E_non_const[c], c)
|
||||
{
|
||||
std::fill_n((_E_non_const*)this->_data.get(), this->_size, e);
|
||||
std::fill_n((_E_non_const*)this->_data.get(), this->_count, e);
|
||||
}
|
||||
|
||||
//! use existing alloc with delete[]
|
||||
@@ -260,7 +278,7 @@ public:
|
||||
|
||||
//! Extend size. Implies make_unique()
|
||||
void resize(size_t i) {
|
||||
if(!this->unique() || i!=this->_size) {
|
||||
if(!this->unique() || i!=this->_count) {
|
||||
shared_array o(i);
|
||||
std::copy_n(this->begin(), std::min(this->size(), i), o.begin());
|
||||
this->swap(o);
|
||||
@@ -281,7 +299,7 @@ private:
|
||||
*/
|
||||
inline E* base_ptr() const {
|
||||
#if defined(_MSC_VER) && _MSC_VER<=1600
|
||||
return this->_size ? this->_data.get() : (E*)(this-1);
|
||||
return this->_count ? this->_data.get() : (E*)(this-1);
|
||||
#else
|
||||
return this->_data.get();
|
||||
#endif
|
||||
@@ -294,7 +312,7 @@ public:
|
||||
inline const_iterator cbegin() const noexcept{return begin();}
|
||||
|
||||
//! end iteration
|
||||
inline iterator end() const noexcept{return this->base_ptr()+this->_size;}
|
||||
inline iterator end() const noexcept{return this->base_ptr()+this->_count;}
|
||||
inline const_iterator cend() const noexcept{return end();}
|
||||
|
||||
inline reverse_iterator rbegin() const noexcept{return reverse_iterator(end());}
|
||||
@@ -315,7 +333,7 @@ public:
|
||||
//! @throws std::out_of_range if empty() || i>=size().
|
||||
reference at(size_t i) const
|
||||
{
|
||||
if(i>this->_size)
|
||||
if(i > this->_count)
|
||||
throw std::out_of_range("Index out of bounds");
|
||||
return (*this)[i];
|
||||
}
|
||||
@@ -330,7 +348,7 @@ public:
|
||||
throw std::logic_error("Can't freeze non-unique shared_array");
|
||||
|
||||
// alias w/ implied cast to const.
|
||||
shared_array<typename std::add_const<E>::type> ret(this->_data, this->_data.get(), this->_size);
|
||||
shared_array<typename std::add_const<E>::type> ret(this->_data, this->_data.get(), this->_count);
|
||||
|
||||
// c++20 provides a move()-able alternative to the aliasing constructor.
|
||||
// until this stops being the future, we consume the src ref. and
|
||||
@@ -343,16 +361,20 @@ public:
|
||||
template<typename TO, typename std::enable_if<!std::is_void<TO>{} && (std::is_const<E>{} == std::is_const<TO>{}), int>::type =0>
|
||||
shared_array<TO>
|
||||
castTo() const {
|
||||
auto alen = this->_size*sizeof(E)/sizeof(TO);
|
||||
return shared_array<TO>(this->_data, static_cast<TO*>(this->_data.get()), alen);
|
||||
return shared_array<TO>(this->_data, static_cast<TO*>(this->_data.get()), this->_count);
|
||||
}
|
||||
|
||||
//! static_cast<TO>() to void, preserving const-ness
|
||||
template<typename TO, typename std::enable_if<std::is_void<TO>{} && (std::is_const<E>{} == std::is_const<TO>{}), int>::type =0>
|
||||
shared_array<TO>
|
||||
castTo() const {
|
||||
auto alen = this->_size*sizeof(E);
|
||||
return shared_array<TO>(this->_data, this->_data.get(), alen); // implied cast to void*
|
||||
return shared_array<TO>(this->_data, this->_data.get(), this->_count); // implied cast to void*
|
||||
}
|
||||
|
||||
detail::Limiter format() const {
|
||||
return Limiter(this->_data.get(),
|
||||
this->_count,
|
||||
detail::CaptureCode<typename std::remove_cv<E>::type>::code);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -455,7 +477,7 @@ public:
|
||||
throw std::logic_error("Can't freeze non-unique shared_array");
|
||||
|
||||
// alias w/ implied cast to const.
|
||||
shared_array<typename std::add_const<E>::type> ret(this->_data, this->_data.get(), this->_size, this->_type);
|
||||
shared_array<typename std::add_const<E>::type> ret(this->_data, this->_data.get(), this->_count, this->_type);
|
||||
|
||||
// c++20 provides a move()-able alternative to the aliasing constructor.
|
||||
// until this stops being the future, we consume the src ref. and
|
||||
@@ -468,8 +490,7 @@ public:
|
||||
template<typename TO, typename std::enable_if<!std::is_void<TO>{} && (std::is_const<E>{} == std::is_const<TO>{}), int>::type =0>
|
||||
shared_array<TO>
|
||||
castTo() const {
|
||||
auto alen = this->_size/sizeof(TO);
|
||||
return shared_array<TO>(this->_data, static_cast<TO*>(this->_data.get()), alen);
|
||||
return shared_array<TO>(this->_data, static_cast<TO*>(this->_data.get()), this->_count);
|
||||
}
|
||||
|
||||
// static_cast<TO>() to void, preserving const-ness
|
||||
@@ -480,6 +501,12 @@ public:
|
||||
// aka. simple copy
|
||||
return *this;
|
||||
}
|
||||
|
||||
detail::Limiter format() const {
|
||||
return detail::Limiter(this->_data.get(),
|
||||
this->_count,
|
||||
this->_type);
|
||||
}
|
||||
};
|
||||
|
||||
// non-const -> const
|
||||
@@ -500,29 +527,12 @@ shared_array_static_cast(const shared_array<FROM>& src)
|
||||
return src.template castTo<TO>();
|
||||
}
|
||||
|
||||
template<typename E, typename std::enable_if<!std::is_void<E>{}, int>::type =0>
|
||||
template<typename E>
|
||||
std::ostream& operator<<(std::ostream& strm, const shared_array<E>& arr)
|
||||
{
|
||||
strm<<'{'<<arr.size()<<"}[";
|
||||
for(size_t i=0; i<arr.size(); i++) {
|
||||
if(i>10) {
|
||||
strm<<"...";
|
||||
break;
|
||||
}
|
||||
strm<<arr[i];
|
||||
if(i+1<arr.size())
|
||||
strm<<", ";
|
||||
}
|
||||
strm<<']';
|
||||
return strm;
|
||||
return strm<<arr.format();
|
||||
}
|
||||
|
||||
PVXS_API
|
||||
std::ostream& operator<<(std::ostream& strm, const shared_array<const void>& arr);
|
||||
|
||||
PVXS_API
|
||||
std::ostream& operator<<(std::ostream& strm, const shared_array<void>& arr);
|
||||
|
||||
} // namespace pvxs
|
||||
|
||||
#endif // PVXS_SHAREDVECTOR_H
|
||||
|
||||
+49
-46
@@ -73,54 +73,57 @@ std::ostream& operator<<(std::ostream& strm, ArrayType code)
|
||||
return strm;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& strm, const shared_array<const void>& arr)
|
||||
{
|
||||
switch(arr.original_type()) {
|
||||
case ArrayType::Null: strm<<"[null]"; break;
|
||||
#define CASE(CODE, Type) case ArrayType::CODE: strm<<arr.castTo<const Type>(); break
|
||||
CASE(Bool, bool);
|
||||
CASE(UInt8, uint8_t);
|
||||
CASE(UInt16, uint16_t);
|
||||
CASE(UInt32, uint32_t);
|
||||
CASE(UInt64, uint64_t);
|
||||
CASE(Int8, int8_t);
|
||||
CASE(Int16, int16_t);
|
||||
CASE(Int32, int32_t);
|
||||
CASE(Int64, int64_t);
|
||||
CASE(Float32, float);
|
||||
CASE(Float64, double);
|
||||
CASE(String, std::string);
|
||||
CASE(Value, Value);
|
||||
#undef CASE
|
||||
}
|
||||
return strm;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& strm, const shared_array<void>& arr)
|
||||
{
|
||||
switch(arr.original_type()) {
|
||||
case ArrayType::Null: strm<<"[null]"; break;
|
||||
#define CASE(CODE, Type) case ArrayType::CODE: strm<<arr.castTo<Type>(); break
|
||||
CASE(Bool, bool);
|
||||
CASE(UInt8, uint8_t);
|
||||
CASE(UInt16, uint16_t);
|
||||
CASE(UInt32, uint32_t);
|
||||
CASE(UInt64, uint64_t);
|
||||
CASE(Int8, int8_t);
|
||||
CASE(Int16, int16_t);
|
||||
CASE(Int32, int32_t);
|
||||
CASE(Int64, int64_t);
|
||||
CASE(Float32, float);
|
||||
CASE(Float64, double);
|
||||
CASE(String, std::string);
|
||||
CASE(Value, Value);
|
||||
#undef CASE
|
||||
}
|
||||
return strm;
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
namespace {
|
||||
template<typename E>
|
||||
void showArr(std::ostream& strm, const void* raw, size_t count, size_t limit)
|
||||
{
|
||||
auto base = reinterpret_cast<const E*>(raw);
|
||||
|
||||
if(limit==0)
|
||||
limit=size_t(-1);
|
||||
|
||||
strm<<"{"<<count<<"}[";
|
||||
for(auto i : range(count)) {
|
||||
if(i!=0)
|
||||
strm<<", ";
|
||||
if(i>limit) {
|
||||
strm<<"...";
|
||||
break;
|
||||
}
|
||||
strm<<base[i];
|
||||
}
|
||||
strm<<']';
|
||||
}
|
||||
} // namespace
|
||||
|
||||
std::ostream& operator<<(std::ostream& strm, const Limiter& lim)
|
||||
{
|
||||
switch(lim._type) {
|
||||
#define CASE(CODE, Type) case ArrayType::CODE: showArr<Type>(strm, lim._base, lim._count, lim._limit); break
|
||||
CASE(Bool, bool);
|
||||
CASE(UInt8, uint8_t);
|
||||
CASE(UInt16, uint16_t);
|
||||
CASE(UInt32, uint32_t);
|
||||
CASE(UInt64, uint64_t);
|
||||
CASE(Int8, int8_t);
|
||||
CASE(Int16, int16_t);
|
||||
CASE(Int32, int32_t);
|
||||
CASE(Int64, int64_t);
|
||||
CASE(Float32, float);
|
||||
CASE(Float64, double);
|
||||
CASE(String, std::string);
|
||||
#undef CASE
|
||||
case ArrayType::Null:
|
||||
strm<<"{\?}[]";
|
||||
break;
|
||||
default:
|
||||
strm<<"[\?\?\?]";
|
||||
}
|
||||
return strm;
|
||||
}
|
||||
|
||||
Escaper::Escaper(const char* v)
|
||||
:val(v)
|
||||
,count(v ? strlen(v) : 0)
|
||||
|
||||
+2
-2
@@ -85,7 +85,7 @@ void testVoid()
|
||||
testOk1(!X.unique());
|
||||
testOk1(!Y.unique());
|
||||
testEq(X.size(), 2u);
|
||||
testEq(Y.size(), 8u);
|
||||
testEq(Y.size(), 2u);
|
||||
testEq(Y.original_type(), ArrayType::UInt32); // never const uint32_t
|
||||
|
||||
testThrows<std::logic_error>([&Y]() {
|
||||
@@ -99,7 +99,7 @@ void testVoid()
|
||||
testOk1(Y.unique());
|
||||
testOk1(Z.unique());
|
||||
testEq(Y.size(), 0u);
|
||||
testEq(Z.size(), 8u);
|
||||
testEq(Z.size(), 2u);
|
||||
}
|
||||
|
||||
void testFreeze()
|
||||
|
||||
+2
-2
@@ -386,7 +386,7 @@ void testFormat()
|
||||
" int32_t ahalf = 2468\n"
|
||||
" }\n"
|
||||
" ]\n"
|
||||
" struct[] more = [null]\n"
|
||||
" struct[] more = {\?}[]\n"
|
||||
" } array\n"
|
||||
"}\n"
|
||||
);
|
||||
@@ -417,7 +417,7 @@ void testFormat()
|
||||
"array.choice[1] null\n"
|
||||
"array.choice[2] union\n"
|
||||
"array.choice[2]->two.ahalf int32_t = 2468\n"
|
||||
"array.more struct[] = [null]\n"
|
||||
"array.more struct[] = {\?}[]\n"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -331,7 +331,7 @@ void testDeserialize2()
|
||||
});
|
||||
testOk1(!val["value"].isMarked());
|
||||
testOk1(!!val["arbitrary.sarr"].isMarked());
|
||||
testEq(val["arbitrary.sarr"].as<shared_array<const void>>().size(), 3u*sizeof(Value));
|
||||
testEq(val["arbitrary.sarr"].as<shared_array<const void>>().size(), 3u);
|
||||
testEq(val["arbitrary.sarr[0].value"].as<uint32_t>(), 0xdeadbeef);
|
||||
testEq(val["arbitrary.sarr[1]"]["value"].as<uint32_t>(), 0x1badfaceu);
|
||||
testEq(val["arbitrary.sarr[2].value"].type(), TypeCode::Null);
|
||||
@@ -358,7 +358,7 @@ void testDeserialize2()
|
||||
});
|
||||
testOk1(!val["value"].isMarked());
|
||||
testOk1(!!val["achoice"].isMarked());
|
||||
testEq(val["achoice"].as<shared_array<const void>>().size(), 3u*sizeof(Value));
|
||||
testEq(val["achoice"].as<shared_array<const void>>().size(), 3u);
|
||||
testEq(val["achoice[0]"].as<std::string>(), "theX");
|
||||
testEq(val["achoice[1]"].as<std::string>(), "theY");
|
||||
testEq(val["achoice[2]"].type(), TypeCode::Null);
|
||||
@@ -397,7 +397,7 @@ void testDeserialize2()
|
||||
});
|
||||
testOk1(!val["value"].isMarked());
|
||||
testOk1(!!val["anya"].isMarked());
|
||||
testEq(val["anya"].as<shared_array<const void>>().size(), 3u*sizeof(Value));
|
||||
testEq(val["anya"].as<shared_array<const void>>().size(), 3u);
|
||||
testEq(val["anya[0]"].as<uint32_t>(), 0x7bu);
|
||||
testEq(val["anya[1].q"].as<std::string>(), "theq");
|
||||
testEq(val["anya[2]"].type(), TypeCode::Null);
|
||||
|
||||
Reference in New Issue
Block a user