soma-io 6.0.6
reader_d.h
Go to the documentation of this file.
1/* This software and supporting documentation are distributed by
2 * Institut Federatif de Recherche 49
3 * CEA/NeuroSpin, Batiment 145,
4 * 91191 Gif-sur-Yvette cedex
5 * France
6 *
7 * This software is governed by the CeCILL-B license under
8 * French law and abiding by the rules of distribution of free software.
9 * You can use, modify and/or redistribute the software under the
10 * terms of the CeCILL-B license as circulated by CEA, CNRS
11 * and INRIA at the following URL "http://www.cecill.info".
12 *
13 * As a counterpart to the access to the source code and rights to copy,
14 * modify and redistribute granted by the license, users are provided only
15 * with a limited warranty and the software's author, the holder of the
16 * economic rights, and the successive licensors have only limited
17 * liability.
18 *
19 * In this respect, the user's attention is drawn to the risks associated
20 * with loading, using, modifying and/or developing or reproducing the
21 * software by the user in light of its specific status of free software,
22 * that may mean that it is complicated to manipulate, and that also
23 * therefore means that it is reserved for developers and experienced
24 * professionals having in-depth computer knowledge. Users are therefore
25 * encouraged to load and test the software's suitability as regards their
26 * requirements in conditions enabling the security of their systems and/or
27 * data to be ensured and, more generally, to use and operate it in the
28 * same conditions as regards security.
29 *
30 * The fact that you are presently reading this means that you have had
31 * knowledge of the CeCILL-B license and that you accept its terms.
32 */
33
34#ifndef SOMAIO_IO_READER_D_H
35#define SOMAIO_IO_READER_D_H
36//--- soma-io ----------------------------------------------------------------
38#include <soma-io/datasourceinfo/datasourceinfo.h> // format info
39#include <soma-io/datasourceinfo/datasourceinfoloader.h> // format check
40#include <soma-io/datasource/datasourcelist.h> // member
41#include <soma-io/datasource/datasource.h> // useful for none() pointer
42#include <soma-io/datasource/filedatasource.h> // used by constructor
43#include <soma-io/datasource/streamdatasource.h> // used by constructor
44#include <soma-io/io/formatdictionary.h> // used by read() method
45#include <soma-io/io/reader.h> // class declaration
46#include <soma-io/reader/formatreader.h> // used by read() method
47#include <soma-io/allocator/allocator.h> // allocator management
48//--- cartobase --------------------------------------------------------------
49#include <cartobase/exception/ioexcept.h> // launch exception
50#include <cartobase/object/object.h> // header & options
51#include <cartobase/object/property.h> // header & options
52#include <cartobase/stream/fileutil.h> // finding file extension
53//--- system -----------------------------------------------------------------
54#include <set>
55#include <map>
56//--- debug ------------------------------------------------------------------
57#include <cartobase/config/verbose.h>
58#define localMsg( message ) cartoCondMsg( 4, message, "READER" )
59// localMsg must be undef at end of file
60// #undef localMsg
61// #define localMsg( message ) std::cerr << (message) << std::endl;
62
63//----------------------------------------------------------------------------
64
65namespace soma
66{
67 //==========================================================================
68 // C O N S T R U C T O R S
69 //==========================================================================
70 template<class T> Reader<T>::Reader()
72 {
73 }
74
76 : _datasourceinfo( new DataSourceInfo( ds ) )
77 {
78 }
79
81 : _datasourceinfo( new DataSourceInfo( *dsi ) )
82 {
83 }
84
85 template<class T> Reader<T>::Reader( const std::string& filename )
87 carto::rc_ptr<DataSource>( new FileDataSource( filename ) )
88 ) )
89 {
90 }
91
92 template<class T> Reader<T>::Reader( std::istream & stream )
94 carto::rc_ptr<DataSource>( new IStreamDataSource( stream ) )
95 ) )
96 {
97 }
98
99 template<class T> Reader<T>::~Reader()
100 {
101 }
102
103 //==========================================================================
104 // A L L O C A T O R
105 //==========================================================================
106 template <typename T>
108 {
109 _alloccontext = ac;
110 }
111
112 template <typename T>
114 {
115 return _alloccontext;
116 }
117
118 //==========================================================================
119 // O P T I O N S
120 //==========================================================================
121 template<class T>
126
127 template<class T>
129 {
130 return _options;
131 }
132
133 template<class T>
135 {
136 return _options;
137 }
138
139 //==========================================================================
140 // D A T A S O U R C E
141 //==========================================================================
142 template<class T>
144 {
145 if ( !_datasourceinfo->list().empty( "default" ) ) {
146 _datasourceinfo->list().dataSource() = ds;
147 } else {
148 _datasourceinfo->list().addDataSource( "default", ds );
149 }
150 }
151
152 template<class T>
153 void Reader<T>::attach( const std::string & filename, offset_t offset )
154 {
155 if ( !_datasourceinfo->list().empty( "default" ) ) {
156 _datasourceinfo->list().dataSource()
157 = carto::rc_ptr<DataSource>( new FileDataSource( filename, offset ) );
158 } else {
159 _datasourceinfo->list().addDataSource( "default",
160 carto::rc_ptr<DataSource>( new FileDataSource( filename, offset ) ) );
161 }
162 }
163
164 template<class T>
165 void Reader<T>::attach( std::istream & stream )
166 {
167 if ( !_datasourceinfo->list().empty( "default" ) ) {
168 _datasourceinfo->list().dataSource()
170 } else {
171 _datasourceinfo->list().addDataSource( "default",
173 }
174 }
175
176 template<class T>
178 {
179 if ( !_datasourceinfo->list().empty( "default" ) ) {
180 return _datasourceinfo->list().dataSource();
181 } else {
182 return DataSource::none();
183 }
184 }
185
186 template<class T>
188 {
189 if ( !_datasourceinfo->list().empty() ) {
190 return _datasourceinfo->list().dataSource();
191 } else {
192 return DataSource::none();
193 }
194 }
195
196 template <typename T>
198 {
199 if( _datasourceinfo->list().dataSource() )
200 _datasourceinfo->list().dataSource()->flush();
201 }
202
203
204 template <typename T>
206 {
207 if( _datasourceinfo->list().dataSource() )
208 _datasourceinfo->list().dataSource()->close();
209 }
210
211 //==========================================================================
212 // R E A D M E T H O D S
213 //==========================================================================
214
215 //--- useful typedef -------------------------------------------------------
216 typedef std::multimap<std::string,std::string> multi_S;
217 typedef std::set<std::string> set_S;
218 typedef std::pair<std::multimap<std::string, std::string>::const_iterator,
219 std::multimap<std::string, std::string>::const_iterator> pair_cit_S;
220 //--------------------------------------------------------------------------
221
222 template<class T>
223 bool Reader<T>::read( T & obj, carto::Object header,
224 int passbegin, int passend )
225 {
227 + _datasourceinfo->url() + " reading existing object" );
228
229 if( !header.isNone() )
230 _datasourceinfo->header() = header;
231
232 if( !dataSource() )
233 throw std::runtime_error( "Reader with no source of data" );
234 if( !_options.get() )
236
238 std::string uri = _datasourceinfo->list().dataSource()->url();
239 std::string filename = FileUtil::uriFilename( uri );
240 carto::Object urioptions = FileUtil::uriOptions( uri );
241 if( urioptions.get() ) {
242 _datasourceinfo->list().dataSource()
243 .reset( new FileDataSource( filename ) );
244 _options->copyProperties( urioptions );
245 }
246
248 DataSourceInfoLoader dsil; // manages the case of a not-none header
249 DataSourceInfo dsi = dsil.check(
251 ( passbegin < 2 ? 1 : passbegin - 1 ), passend - 1 );
252 if( dsi.list().empty() )
253 dsil.launchException();
254 if( !dsi.header().get() )
255 dsil.launchException();
256 *_datasourceinfo = dsi;
257 try {
258 if( _options->getProperty( "partial_reading" )->getScalar() )
259 /* disable mmap here because partial reading on an already allocated
260 volume is not compatible with mmap */
261 _datasourceinfo->capabilities().setMemoryMapping( false );
262 } catch( ... ) {
263 }
264 _alloccontext.setDataSourceInfo( _datasourceinfo );
265
266 std::string format;
267 if( !_options->getProperty( "format", format )
268 && !_datasourceinfo->header()->getProperty( "format", format ) )
269 _datasourceinfo->header()->getProperty( "file_type", format );
270
271 localMsg( "using format " + format + " for file: " + uri );
272
274 set_S tried;
275 std::set<FormatReader<T> *> triedf;
276 FormatReader<T> * reader;
277 std::unique_ptr<FormatReader<T> > readerc;
278 set_S::iterator notyet = tried.end();
279 typename std::set<FormatReader<T> *>::iterator notyetf = triedf.end();
280 int excp = 0;
281 int exct = -1;
282 std::string excm;
283
284 localMsg( "trying to find readers using pass range: [" + carto::toString(passbegin)
285 + "-" + carto::toString(passend) + "]" );
286
287#ifdef CARTO_DEBUG
288 std::set<std::string> read_formats = FormatDictionary<T>::readFormats();
289 std::set<std::string>::const_iterator fit, fie = read_formats.end();
290
291 localMsg( "registered formats for <" + carto::DataTypeCode<T>::name() + ">:");
292 for(fit = read_formats.begin(); fit!=fie; ++fit)
293 localMsg(" - " + *fit);
294#endif
295
297 if( passbegin <= 1 && passend >=1 && !format.empty() )
298 {
299 localMsg( "1. try to find reader of " + format + " for file: " + uri );
300 reader = FormatDictionary<T>::readFormat( format );
301 localMsg( "1. reader found " + carto::toString(reader) );
302 if( reader )
303 {
304 try {
305 localMsg( "1. try reader " + format );
306 readerc.reset( reader->clone() );
307 readerc->setupAndRead( obj, _datasourceinfo,
309 localMsg( "1. " + format + " OK" );
310 return true;
311 }
312 catch( std::exception & e ) {
313 localMsg( "1. " + format + " failed" );
314 carto::io_error::keepExceptionPriority( e, excp, exct, excm, 5 );
315 }
316 tried.insert( format );
317 triedf.insert( reader );
318 }
319 }
320
321 std::string ext = carto::FileUtil::extension( filename );
322 const multi_S & extensions = FormatDictionary<T>::readExtensions();
323 pair_cit_S iext;
324 multi_S::const_iterator ie, ee;
325
327 if( passbegin <= 2 && passend >=2 )
328 {
329 localMsg( "2. try to find reader using extension " + ext + " for file: " + uri );
330 iext = extensions.equal_range( ext );
331 for( ie=iext.first, ee = iext.second; ie!=ee; ++ie ) {
332 if( tried.find( ie->second ) == notyet )
333 {
334 localMsg( "2. try to find reader of " + ie->second + " for file: " + uri );
335 reader = FormatDictionary<T>::readFormat( ie->second );
336 localMsg( "2. reader found " + carto::toString(reader) );
337 if( reader && triedf.find( reader ) == notyetf ) {
338 try {
339 localMsg( "2. try reader " + ie->second );
340 readerc.reset( reader->clone() );
341 readerc->setupAndRead( obj, _datasourceinfo,
343 localMsg( "2. " + ie->second + " OK" );
344 return true;
345 }
346 catch( std::exception & e ) {
347 localMsg( "2. " + ie->second + " failed" );
348 carto::io_error::keepExceptionPriority( e, excp, exct, excm );
349 }
350 tried.insert( ie->second );
351 triedf.insert( reader );
352 }
353 }
354 }
355 }
356
358 if( passbegin <= 3 && passend >= 3 && !ext.empty())
359 {
360 localMsg( "3. try to find reader using no extension for file: " + uri );
361 iext = extensions.equal_range( "" );
362 for( ie=iext.first, ee=iext.second; ie!=ee; ++ie ) {
363 if( tried.find( ie->second ) == notyet ) {
364 localMsg( "3. try to find reader of " + ie->second + " for file: " + uri );
365 reader = FormatDictionary<T>::readFormat( ie->second );
366 localMsg( "3. reader found " + carto::toString(reader) );
367 if( reader && triedf.find( reader ) == notyetf )
368 {
369 try {
370 localMsg( "3. try reader " + ie->second );
371 readerc.reset( reader->clone() );
372 readerc->setupAndRead( obj, _datasourceinfo,
374 localMsg( "3. " + ie->second + " OK" );
375 return true;
376 }
377 catch( std::exception & e ) {
378 localMsg( "3. " + ie->second + " failed" );
379 carto::io_error::keepExceptionPriority( e, excp, exct, excm );
380 }
381 tried.insert( ie->second );
382 triedf.insert( reader );
383 }
384 }
385 }
386 }
387
389 if( passbegin <= 4 && passend >= 4 )
390 {
391 localMsg( "4. try every reader for file: " + uri );
392 iext.first = extensions.begin();
393 iext.second = extensions.end();
394 for( ie=iext.first, ee=iext.second; ie!=ee; ++ie ) {
395 if( tried.find( ie->second ) == notyet ) {
396 localMsg( "4. try to find reader of " + ie->second + " for file: " + uri );
397 reader = FormatDictionary<T>::readFormat( ie->second );
398 localMsg( "4. reader found " + carto::toString(reader) );
399 if( reader && triedf.find( reader ) == notyetf )
400 {
401 try {
402 localMsg( "4. try reader " + ie->second );
403 readerc.reset( reader->clone() );
404 readerc->setupAndRead( obj, _datasourceinfo,
406 localMsg( "4. " + ie->second + " OK" );
407 return true;
408 }
409 catch( std::exception & e ) {
410 localMsg( "4. " + ie->second + " failed" );
411 carto::io_error::keepExceptionPriority( e, excp, exct, excm );
412 }
413 tried.insert( ie->second );
414 triedf.insert( reader );
415 }
416 }
417 }
418 }
419
422 filename + " : no matching format" );
423 return false;
424 }
425
426 template<class T>
427 T* Reader<T>::read( carto::Object header, int passbegin, int passend )
428 {
430 + _datasourceinfo->url() );
431
432 if( !header.isNone() )
433 _datasourceinfo->header() = header;
434
435 if( !dataSource() )
436 throw std::runtime_error( "Reader with no source of data" );
437 if( !_options.get() )
439
441 std::string uri = _datasourceinfo->list().dataSource()->url();
442 std::string filename = FileUtil::uriFilename( uri );
443 carto::Object urioptions = FileUtil::uriOptions( uri );
444 if( urioptions.get() ) {
445 _datasourceinfo->list().dataSource()
446 .reset( new FileDataSource( filename ) );
447 _options->copyProperties( urioptions );
448 }
449
451 DataSourceInfoLoader dsil; // manages the case of a not-none header
453 if( dsi.list().empty() )
454 dsil.launchException();
455 if( dsi.header().get() )
456 dsil.launchException();
457 *_datasourceinfo = dsi;
458 _alloccontext.setDataSourceInfo( _datasourceinfo );
459
460 std::string format;
461 if( !_options->getProperty( "format", format )
462 && !_datasourceinfo->header()->getProperty( "format", format ) )
463 _datasourceinfo->header()->getProperty( "file_type", format );
464
465 localMsg( "using format " + format + " for file: " + uri );
466
468 set_S tried;
469 std::set<FormatReader<T> *> triedf;
470 FormatReader<T> * reader;
471 std::unique_ptr<FormatReader<T> > readerc;
472 set_S::iterator notyet = tried.end();
473 typename std::set<FormatReader<T> *>::iterator notyetf = triedf.end();
474 T * obj;
475 int excp = 0;
476 int exct = -1;
477 std::string excm;
478
479 localMsg( "trying to find readers using pass range: [" + carto::toString(passbegin)
480 + "-" + carto::toString(passend) + "]" );
481
482#ifdef CARTO_DEBUG
483 std::set<std::string> read_formats = FormatDictionary<T>::readFormats();
484 std::set<std::string>::const_iterator fit, fie = read_formats.end();
485
486 localMsg( "registered formats for <" + carto::DataTypeCode<T>::name() + ">:");
487 for(fit = read_formats.begin(); fit!=fie; ++fit)
488 localMsg(" - " + *fit);
489#endif
490
492 if( passbegin <= 1 && passend >= 1 && !format.empty() )
493 {
494 localMsg( "1. try to find reader of " + format + " for file: " + uri );
495 reader = FormatDictionary<T>::readFormat( format );
496 localMsg( "1. reader found " + carto::toString(reader) );
497 if( reader )
498 {
499 try
500 {
501 localMsg( "1. try reader " + format );
502 readerc.reset( reader->clone() );
503 obj = readerc->createAndRead( _datasourceinfo,
505 if( obj )
506 {
507 localMsg( "1. " + format + " OK" );
508 return obj;
509 }
510 }
511 catch( std::exception & e )
512 {
513 localMsg( "1. " + format + " failed" );
514 carto::io_error::keepExceptionPriority( e, excp, exct, excm, 5 );
515 }
516 tried.insert( format );
517 triedf.insert( reader );
518 }
519 }
520
521 std::string ext = carto::FileUtil::extension( filename );
522
523 const multi_S & extensions = FormatDictionary<T>::readExtensions();
524
525 pair_cit_S iext;
526 multi_S::const_iterator ie, ee;
527
529 if( passbegin <= 2 && passend >= 2 )
530 {
531 localMsg( "2. try to find reader using extension " + ext + " for file: " + uri );
532 iext = extensions.equal_range( ext );
533 for( ie=iext.first, ee=iext.second; ie!=ee; ++ie )
534 {
535 if( tried.find( ie->second ) == notyet )
536 {
537 localMsg( "2. try to find reader of " + ie->second + " for file: " + uri );
538 reader = FormatDictionary<T>::readFormat( ie->second );
539 localMsg( "2. reader found " + carto::toString(reader) );
540 if( reader && triedf.find( reader ) == notyetf )
541 {
542 try
543 {
544 localMsg( "2. try reader " + ie->second );
545 readerc.reset( reader->clone() );
546 obj = readerc->createAndRead( _datasourceinfo,
548 if( obj )
549 {
550 localMsg( "2. " + ie->second + " OK" );
551 return obj;
552 }
553 }
554 catch( std::exception & e )
555 {
556 localMsg( "2. " + ie->second + " failed" );
557 carto::io_error::keepExceptionPriority( e, excp, exct, excm );
558 }
559 tried.insert( ie->second );
560 triedf.insert( reader );
561 }
562 }
563 }
564 }
565
567 if( passbegin <= 3 && passend >= 3 && !ext.empty() )
568 {
569 localMsg( "3. try to find reader using no extension for file: " + uri );
570 iext = extensions.equal_range( "" );
571 for( ie=iext.first, ee=iext.second; ie!=ee; ++ie ) {
572 if( tried.find( ie->second ) == notyet ) {
573 localMsg( "3. try to find reader of " + ie->second + " for file: " + uri );
574 reader = FormatDictionary<T>::readFormat( ie->second );
575 localMsg( "3. reader found " + carto::toString(reader) );
576 if( reader && triedf.find( reader ) == notyetf )
577 {
578 try {
579 localMsg( "3. try reader " + ie->second );
580 readerc.reset( reader->clone() );
581 obj = readerc->createAndRead( _datasourceinfo,
583 if( obj ) {
584 localMsg( "3. " + ie->second + " OK" );
585 return obj;
586 }
587 } catch( std::exception & e ) {
588 localMsg( "3. " + ie->second + " failed" );
589 carto::io_error::keepExceptionPriority( e, excp, exct, excm );
590 }
591 tried.insert( ie->second );
592 triedf.insert( reader );
593 }
594 }
595 }
596 }
597
599 if( passbegin <= 4 && passend >= 4 )
600 {
601 localMsg( "4. try every reader for file: " + uri );
602 iext.first = extensions.begin();
603 iext.second = extensions.end();
604 for( ie=iext.first, ee=iext.second; ie!=ee; ++ie ) {
605 if( tried.find( ie->second ) == notyet ) {
606 localMsg( "4. try to find reader of " + ie->second + " for file: " + uri );
607 reader = FormatDictionary<T>::readFormat( ie->second );
608 localMsg( "4. reader found " + carto::toString(reader) );
609 if( reader && triedf.find( reader ) == notyetf )
610 {
611 try {
612 localMsg( "4. try reader " + ie->second );
613 readerc.reset( reader->clone() );
614 obj = readerc->createAndRead( _datasourceinfo,
616 if( obj ) {
617 localMsg( "4. " + ie->second + " OK" );
618 return obj;
619 }
620 } catch( std::exception & e ) {
621 localMsg( "4. " + ie->second + " failed" );
622 carto::io_error::keepExceptionPriority( e, excp, exct, excm );
623 }
624 tried.insert( ie->second );
625 triedf.insert( reader );
626 }
627 }
628 }
629 }
630
633 filename + " : no matching format" );
634 return 0;
635 }
636
637}
638
639#undef localMsg
640#endif
std::string name()
static std::string extension(const std::string &)
static Object value()
bool isNone() const
static void keepExceptionPriority(std::exception &e, int &prio, int &type, std::string &message, int raiseprio=0)
static void launchExcept(int code, const std::string &msg, const std::string &defmsg="")
T * get() const
Allocation context.
Definition allocator.h:261
Generic information retreiver / checker for all data sources and file formats.
DataSourceInfo check(DataSourceInfo dsi, carto::Object options=carto::none(), int passbegin=1, int passend=3)
Finds the right format checker.
Informative object used by IO system.
const DataSourceList & list() const
const carto::Object & header() const
bool empty() const
Returns true only if no keyword inserted.
Abstraction layer for various data sources (file, buffer, socket...).
Definition datasource.h:65
static const carto::rc_ptr< DataSource > none()
An empty ref-counter that is more convenient than calling a constructor of rc_ptr<DataSource> (useful...
static const std::multimap< std::string, std::string > & readExtensions()
static std::set< std::string > readFormats()
static FormatReader< T > * readFormat(const std::string &format)
Low-level object IO reader specialized for a specific format.
virtual FormatReader< T > * clone() const =0
Duplicate the FormatReader.
DataSource on a std::istream (read-only stream)
void close()
Definition reader_d.h:205
void setAllocatorContext(const AllocatorContext &ac)
Definition reader_d.h:107
AllocatorContext _alloccontext
Definition reader.h:169
const carto::rc_ptr< DataSource > dataSource() const
Definition reader_d.h:177
carto::Object options() const
Definition reader_d.h:128
carto::Object _options
Definition reader.h:170
virtual bool read(T &obj, carto::Object header=carto::none(), int passbegin=1, int passend=4)
Finds the correct format and reads the object.
Definition reader_d.h:223
void flush()
Definition reader_d.h:197
const AllocatorContext & allocatorContext() const
Definition reader_d.h:113
virtual ~Reader()
Definition reader_d.h:99
void setOptions(carto::Object options)
Definition reader_d.h:122
void attach(carto::rc_ptr< DataSource > ds)
Definition reader_d.h:143
carto::rc_ptr< DataSourceInfo > _datasourceinfo
Definition reader.h:168
#define localMsg(message)
std::string toString(const T &object)
std::pair< std::multimap< std::string, std::string >::const_iterator, std::multimap< std::string, std::string >::const_iterator > pair_cit_S
Definition reader_d.h:219
std::set< std::string > set_S
Definition reader_d.h:217
std::multimap< std::string, std::string > multi_S
Definition reader_d.h:216
unsigned long long offset_t
Offsets are 64 bits if supported.
Definition datasource.h:51