Skip to content

Commit 8839fb3

Browse files
Fix Archive::describe to include sub-archives (#188) (#189)
C++: Making Archive::describe describe resources recursively. Fixes #189 188
1 parent 030481e commit 8839fb3

File tree

17 files changed

+453
-135
lines changed

17 files changed

+453
-135
lines changed

flatdata-cpp/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ C++ 11 implementation of `flatdata`
44

55
## Building
66

7-
First, build `flatdata-cpp` and install the requirements of the generator.
7+
First, install the requirements of the generator and build `flatdata-cpp`.
88

99
```shell
10-
pip3 install -r requirements.txt
11-
mkdir build
12-
cd build
10+
pip3 install -r flatdata-generator/requirements.txt
11+
cd flatdata-cpp
12+
mkdir build && cd build
1313
cmake ..
1414
make
1515
make test # optional

flatdata-cpp/include/flatdata/Archive.h

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class Archive
4646
/**
4747
* @brief Returns text description of the archive and its resources' state.
4848
*/
49-
std::string describe( ) const;
49+
std::string describe( size_t nest_level = 0u ) const;
5050

5151
/**
5252
* @brief Returns archive name. Is implemented by the concrete archive instances.
@@ -60,13 +60,15 @@ class Archive
6060

6161
protected:
6262
template < typename ResourceType >
63-
static void describe_resource( std::ostream& stream,
63+
static void describe_resource( size_t nest_level,
64+
std::ostream& stream,
6465
const char* name,
6566
const ResourceType& resource,
6667
bool too_large = false );
6768

6869
template < typename ResourceType >
69-
static void describe_resource( std::ostream& stream,
70+
static void describe_resource( size_t nest_level,
71+
std::ostream& stream,
7072
const char* name,
7173
const boost::optional< ResourceType >& resource,
7274
bool too_large = false );
@@ -107,7 +109,9 @@ class Archive
107109
bool optional,
108110
bool loaded,
109111
const char* details,
110-
bool too_large );
112+
bool are_details_nested,
113+
bool too_large,
114+
size_t nest_level );
111115

112116
private:
113117
/**
@@ -120,7 +124,7 @@ class Archive
120124
* @brief Describes all resources provided by the archive.
121125
* Is implemented by the concrete archive instances.
122126
*/
123-
virtual void describe_resources( std::ostream& stream ) const = 0;
127+
virtual void describe_resources( std::ostream& stream, size_t nest_level ) const = 0;
124128

125129
private:
126130
std::shared_ptr< flatdata::ResourceStorage > m_storage;
@@ -130,28 +134,52 @@ class Archive
130134

131135
// -------------------------------------------------------------------------------------------------
132136

137+
template < typename ResourceType >
138+
std::string
139+
get_description( const ResourceType& resource, bool is_archive, size_t nest_level )
140+
{
141+
std::string description;
142+
if ( is_archive )
143+
{
144+
++nest_level;
145+
}
146+
description = resource.describe( nest_level );
147+
return description;
148+
}
149+
133150
template < typename ResourceType >
134151
void
135-
Archive::describe_resource( std::ostream& stream,
152+
Archive::describe_resource( size_t nest_level,
153+
std::ostream& stream,
136154
const char* name,
137155
const ResourceType& resource,
138156
bool too_large )
139157
{
140-
auto initialized = static_cast< bool >( resource );
141-
describe_impl( stream, name, false, static_cast< bool >( resource ),
142-
initialized ? resource.describe( ).c_str( ) : "N/A", too_large );
158+
const auto initialized = static_cast< bool >( resource );
159+
const bool is_archive = std::is_base_of< Archive, ResourceType >::value;
160+
161+
describe_impl( stream, name, false, initialized,
162+
get_description( resource, is_archive, nest_level ).c_str( ), is_archive,
163+
too_large, nest_level );
143164
}
144165

145166
template < typename ResourceType >
146167
void
147-
Archive::describe_resource( std::ostream& stream,
168+
Archive::describe_resource( size_t nest_level,
169+
std::ostream& stream,
148170
const char* name,
149171
const boost::optional< ResourceType >& resource,
150172
bool too_large )
151173
{
152-
auto initialized = static_cast< bool >( resource );
174+
const auto initialized = static_cast< bool >( resource );
175+
const bool is_archive = std::is_base_of< Archive, ResourceType >::value;
176+
177+
const ResourceType ref = initialized ? *resource // valid ref
178+
: ResourceType( ); // ref to dummy, not used
179+
153180
describe_impl( stream, name, true, initialized ? static_cast< bool >( *resource ) : false,
154-
initialized ? resource->describe( ).c_str( ) : "N/A", too_large );
181+
get_description( ref, is_archive, nest_level ).c_str( ), is_archive, too_large,
182+
nest_level );
155183
}
156184

157185
template < typename ResourceType >

flatdata-cpp/include/flatdata/ArrayView.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class ArrayView
4444

4545
size_t size_in_bytes( ) const;
4646
size_t size( ) const;
47-
std::string describe( ) const;
47+
std::string describe( size_t nest_level = 0u ) const;
4848

4949
bool empty( ) const;
5050

flatdata-cpp/include/flatdata/MemoryDescriptor.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,17 @@ struct MemoryDescriptor
3131
}
3232

3333
std::string
34-
describe( ) const
34+
describe( size_t nest_level = 0 ) const
3535
{
3636
std::ostringstream ss;
37-
ss << "Raw data of size " << m_size;
37+
if ( this->operator bool( ) )
38+
{
39+
ss << "Raw data of size " << m_size;
40+
}
41+
else
42+
{
43+
ss << "Uninitialized Raw data";
44+
}
3845
return ss.str( );
3946
}
4047

flatdata-cpp/include/flatdata/MultiArrayView.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ class MultiArrayView
130130
}
131131

132132
size_t size( ) const;
133-
std::string describe( ) const;
133+
std::string describe( size_t unused = 0 ) const;
134134
explicit operator bool( ) const;
135135

136136
template < typename ElementType >
@@ -195,11 +195,17 @@ MultiArrayView< IndexType, Args... >::size( ) const
195195
}
196196

197197
template < typename IndexType, typename... Args >
198-
std::string
199-
MultiArrayView< IndexType, Args... >::describe( ) const
198+
std::string MultiArrayView< IndexType, Args... >::describe( size_t /*unused*/ ) const
200199
{
201200
std::ostringstream ss;
202-
ss << "MultiArray of size " << size( ) << ", with index: " << m_index.describe( );
201+
if ( this->operator bool( ) )
202+
{
203+
ss << "MultiArray of size " << size( ) << ", with index: " << m_index.describe( );
204+
}
205+
else
206+
{
207+
ss << "Uninitialized MultiArray";
208+
}
203209
return ss.str( );
204210
}
205211

flatdata-cpp/include/flatdata/internal/ArrayView.inl

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,17 @@ ArrayView< T >::end( ) const
136136
}
137137

138138
template < typename T >
139-
std::string
140-
ArrayView< T >::describe( ) const
139+
std::string ArrayView< T >::describe( size_t /*unused*/ ) const
141140
{
142141
std::ostringstream ss;
143-
ss << "Array of size: " << size( ) << " in " << size_in_bytes( ) << " bytes";
142+
if ( !empty( ) )
143+
{
144+
ss << "Array of size: " << size( ) << " in " << size_in_bytes( ) << " bytes";
145+
}
146+
else
147+
{
148+
ss << "Uninitialized Array";
149+
}
144150
return ss.str( );
145151
}
146152

flatdata-cpp/src/Archive.cpp

Lines changed: 56 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
namespace flatdata
1212
{
13+
constexpr size_t TAB_WIDTH = 4;
14+
1315
Archive::Archive( std::shared_ptr< flatdata::ResourceStorage > storage )
1416
: m_storage( std::move( storage ) )
1517
{
@@ -226,43 +228,69 @@ compute_diff( const char* expected, const char* found )
226228
}
227229

228230
std::string
229-
Archive::describe( ) const
231+
Archive::describe( size_t nest_level ) const
230232
{
233+
const auto newl = std::string( "\n" );
234+
const auto hline = std::string( 80, '=' ) + newl;
235+
const auto empty = std::string( "" );
236+
const bool is_root_node = ( nest_level == 0 );
237+
231238
std::ostringstream result;
232-
static const char* hline
233-
= "================================================================================";
234-
result << hline << std::endl
235-
<< "Flatdata Archive: " << name( ) << std::endl
236-
<< hline << std::endl;
239+
237240
if ( !m_storage )
238241
{
239-
result << " FATAL: Resource storage not initialized. Please check archive path."
240-
<< std::endl
241-
<< hline << std::endl;
242-
return result.str( );
242+
if ( is_root_node )
243+
{
244+
result << hline << "FATAL: Resource storage not initialized. Please check archive path."
245+
<< newl;
246+
}
247+
else
248+
{
249+
result << "Uninitialized Archive " << name( );
250+
}
243251
}
244252

245-
if ( !m_signature )
253+
if ( m_storage && !m_signature )
246254
{
247-
result << " FATAL: Archive signature does not match software expectations." << std::endl
248-
<< hline << std::endl;
255+
result << ( is_root_node ? hline : empty )
256+
<< "FATAL: Archive signature does not match software expectations."
257+
<< ( is_root_node ? newl : empty ) << hline;
249258
result << compute_diff(
250259
schema( ),
251260
m_storage->read_schema( internal::signature_name( name( ) ).c_str( ) ).char_ptr( ) );
252261
}
253262

254-
if ( !m_is_open )
263+
if ( m_storage && !m_is_open )
255264
{
256-
result << " FATAL: Archive initialization failed. Failed loading mandatory resources."
265+
// Error propagated to root and storage is not initialized in respective child. No root
266+
// check needed.
267+
result << hline
268+
<< "FATAL: Archive initialization failed. Failed loading mandatory resources."
257269
<< std::endl;
258270
}
259271

260-
result << std::endl
261-
<< "Resource Optional Too Large Loaded Details"
262-
<< std::endl
263-
<< hline << std::endl;
264-
describe_resources( result );
265-
result << hline << std::endl;
272+
if ( is_root_node )
273+
{
274+
result << hline << "Flatdata Archive: " << name( ) << std::endl
275+
<< hline
276+
<< "Resource Optional Too Large Loaded Details"
277+
<< std::endl
278+
<< hline;
279+
}
280+
else
281+
{
282+
const std::string indent( ( nest_level - 1 ) * TAB_WIDTH, ' ' );
283+
result << newl + indent + std::string( "|" ) + newl + indent + std::string( "|->" )
284+
<< " Flatdata Archive: " << name( ) << std::endl;
285+
}
286+
287+
describe_resources( result, nest_level );
288+
289+
if ( is_root_node )
290+
{
291+
result << hline;
292+
}
293+
266294
return result.str( );
267295
}
268296

@@ -272,17 +300,18 @@ Archive::describe_impl( std::ostream& stream,
272300
bool optional,
273301
bool loaded,
274302
const char* details,
275-
bool too_large )
303+
bool has_nested_details,
304+
bool too_large,
305+
size_t nest_level )
276306
{
277-
auto oldw = stream.width( );
278-
auto oldfill = stream.fill( );
279-
stream << std::left << std::setw( 37 ) << std::setfill( ' ' )
307+
const std::string indent( nest_level * TAB_WIDTH, ' ' );
308+
size_t offset = indent.size( );
309+
stream << indent << std::left << std::setw( 37 - offset ) << std::setfill( ' ' )
280310
<< std::string( name ).substr( 0, 30 ) << std::left << std::setw( 10 )
281311
<< std::setfill( ' ' ) << ( optional ? "YES" : "NO" ) << std::left << std::setw( 11 )
282312
<< std::setfill( ' ' ) << ( too_large ? "YES" : "NO" ) << std::left << std::setw( 10 )
283313
<< std::setfill( ' ' ) << ( static_cast< bool >( loaded ) ? "YES" : "NO" ) << details
284-
<< std::endl;
285-
stream << std::setw( oldw ) << std::setfill( oldfill );
314+
<< ( has_nested_details ? "" : "\n" );
286315
}
287316

288317
} // namespace flatdata

0 commit comments

Comments
 (0)