Skip to content

Commit d69363b

Browse files
committed
lazy: expose exact indexed source records
Retain record extents during indexing and provide stream-safe access to an instance's original Part 21 record without materializing it.
1 parent 6d7e383 commit d69363b

5 files changed

Lines changed: 61 additions & 0 deletions

File tree

include/cllazyfile/lazyInstMgr.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ class SC_LAZYFILE_EXPORT lazyInstMgr {
125125
}
126126
LazyInstanceIdView forwardReferences( instanceID id );
127127
LazyInstanceIdView reverseReferences( instanceID id );
128+
/** Copy the exact indexed source record for an instance. Returns an
129+
* empty string when the ID is missing or ambiguous. */
130+
std::string sourceRecord( instanceID id );
131+
128132
/// returns a vector containing the instances that match `type`
129133
instanceTypes_t::cvector * getInstances( std::string type, bool caseSensitive = false ) { /*const*/
130134
if( !caseSensitive ) {

include/cllazyfile/sectionReader.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,12 @@ class SC_LAZYFILE_EXPORT sectionReader {
7272
SDAI_Application_instance * getRealInstance( const Registry * reg, lazyFileOffset begin, instanceID instance,
7373
const std::string & typeName = "", const std::string & schName = "", bool header = false );
7474

75+
/** Return one indexed source record without materializing it. The
76+
* stream position is restored before returning. This is intended
77+
* for lightweight adapters which can detach scalar/reference data
78+
* directly from Part 21 source. */
79+
std::string sourceRecord( lazyFileOffset begin, uint64_t length );
80+
7581
sectionID ID() const {
7682
return _sectionID;
7783
}

src/cllazyfile/lazyInstMgr.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,20 @@ LazyInstanceIdView lazyInstMgr::reverseReferences( instanceID id ) {
129129
return LazyInstanceIdView( _revInstanceRefs.find( id ) );
130130
}
131131

132+
std::string lazyInstMgr::sourceRecord( instanceID id ) {
133+
instanceStreamPos_t::cvector * positions = _instanceStreamPos.find( id );
134+
std::map<instanceID, uint64_t>::const_iterator bytes = _instanceSourceBytes.find( id );
135+
if( !positions || positions->size() != 1 || bytes == _instanceSourceBytes.end() ||
136+
bytes->second == 0 ) {
137+
return std::string();
138+
}
139+
const instancePosition & position = positions->front();
140+
if( position.section >= _dataSections.size() || !_dataSections[position.section] ) {
141+
return std::string();
142+
}
143+
return _dataSections[position.section]->sourceRecord( position.begin, bytes->second );
144+
}
145+
132146
void lazyInstMgr::observeScan( fileID file, lazyFileOffset offset, lazyFileOffset fileSize ) {
133147
if( _cancelled ) return;
134148
if( _cancellationCallback && _cancellationCallback() ) {

src/cllazyfile/lazy_index_test.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,16 @@ int main( int argc, char ** argv ) {
4646
"forward reference index failed" );
4747
require( manager.reverseReferences( 1 ).size() == 1 && manager.reverseReferences( 1 )[0] == 3,
4848
"reverse reference index failed" );
49+
const std::string firstSource = manager.sourceRecord( 1 );
50+
const std::string secondSource = manager.sourceRecord( 2 );
51+
require( firstSource.find( "#1=A(" ) != std::string::npos &&
52+
!firstSource.empty() && firstSource[firstSource.size() - 1] == ';',
53+
"first exact source record failed" );
54+
require( secondSource.find( "#2=B();" ) != std::string::npos &&
55+
!secondSource.empty() && secondSource[secondSource.size() - 1] == ';',
56+
"second exact source record or stream restoration failed" );
57+
require( manager.sourceRecord( 99 ).empty(),
58+
"missing source record was not empty" );
4959

5060
lazyInstMgr cancelled;
5161
uint64_t cancellationCalls = 0;

src/cllazyfile/sectionReader.cc

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <string>
1111
#include <assert.h>
1212
#include <limits.h>
13+
#include <limits>
1314

1415
#ifdef _WIN32
1516
# define strtoull _strtoui64
@@ -108,6 +109,32 @@ std::streampos sectionReader::findNormalString( const std::string & str, bool se
108109
}
109110

110111

112+
std::string sectionReader::sourceRecord( lazyFileOffset begin, uint64_t length ) {
113+
if( begin == 0 || length == 0 ||
114+
length > static_cast<uint64_t>( std::numeric_limits<std::streamsize>::max() ) ||
115+
length > static_cast<uint64_t>( std::numeric_limits<size_t>::max() ) ) {
116+
return std::string();
117+
}
118+
119+
const std::streampos saved = _file.tellg();
120+
_file.clear();
121+
_file.seekg( static_cast<std::streamoff>( begin ) );
122+
if( !_file.good() ) {
123+
_file.clear();
124+
if( saved != std::streampos( -1 ) ) _file.seekg( saved );
125+
return std::string();
126+
}
127+
128+
std::string source( static_cast<size_t>( length ), '\0' );
129+
_file.read( &source[0], static_cast<std::streamsize>( length ) );
130+
const bool complete = static_cast<uint64_t>( _file.gcount() ) == length;
131+
132+
_file.clear();
133+
if( saved != std::streampos( -1 ) ) _file.seekg( saved );
134+
return complete ? source : std::string();
135+
}
136+
137+
111138
//NOTE different behavior than const char * GetKeyword( istream & in, const char * delims, ErrorDescriptor & err ) in read_func.cc
112139
// returns pointer to the contents of a static std::string
113140
const char * sectionReader::getDelimitedKeyword( const char * delimiters ) {

0 commit comments

Comments
 (0)