aimsdata  5.0.5
Neuroimaging data handling
writer_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 /*
35  * writer class
36  */
37 #ifndef AIMS_IO_WRITER_D_H
38 #define AIMS_IO_WRITER_D_H
39 
40 
41 #include <aims/io/writer.h>
42 #include <aims/io/fileFormat.h>
43 #include <aims/def/settings.h>
47 #include <set>
48 #include <soma-io/io/writer.h>
50 
51 #define AIMS_INSTANTIATE_WRITER( T ) \
52  namespace aims { \
53  template class aims::Writer< T >; \
54  template bool \
55  GenericWriter::write< T >( const T &, bool, const std::string * ); \
56  }
57 
58  #define AIMS_INSTANTIATE_ONLY_WRITER( T ) \
59  namespace aims { \
60  template class aims::Writer< T >; \
61  }
62 
63 #include <iostream>
64 
65 
66 /* WARNING: be careful to include <aims/io/datatypecode.h> before
67  including this writer_d.h header
68 */
69 
70 namespace aims
71 {
72 
73  template <typename T>
74  bool GenericWriter::write( const T & obj, bool ascii,
75  const std::string* format )
76  {
77  Writer<T> *writer = dynamic_cast< Writer<T> * >( this );
78  if ( ! writer ) {
80  }
81  return writer->write( obj, ascii, format );
82  }
83 
84 
85 
86  template<class T>
87  std::string Writer<T>::writtenObjectType() const
88  {
89  return carto::DataTypeCode<T>().objectType();
90  }
91 
92 
93  template<class T>
95  {
96  return carto::DataTypeCode<T>().dataType();
97  }
98 
99 
100  template<class T>
102  {
104  }
105 
106 
107  template<class T>
108  bool Writer<T>::write( const T & obj, bool ascii, const std::string* format )
109  {
110  // force loading plugins if it has not been done already
112 
113  bool exactformat = false;
115 
116  // Copy aims settings to options
117  options->copyProperties(
119  Settings::settings().getValue() ) );
120 
121  if( !_options.isNull() )
122  {
123  try
124  {
125  carto::Object exact = _options->getProperty( "exact_format" );
126  exactformat = (bool) exact->getScalar();
127  }
128  catch( ... )
129  {
130  }
131  options->copyProperties( _options );
132  }
133 
134  if( !options->hasProperty( "ascii" ) )
135  options->setProperty( "ascii", ascii );
136 
137  std::string _format;
138  if( !format )
139  {
140  try
141  {
142  carto::Object oformat = options->getProperty( "format" );
143  _format = oformat->getString();
144  format = &_format;
145  }
146  catch( ... )
147  {
148  }
149  }
150  else
151  options->setProperty( "format", *format );
152 
153  // try first soma-io writer (since 2013)
154  // try first 3 passes
155  try
156  {
157  // building uri
158  std::string uri = _filename;
159  if( ascii || format )
160  uri += "?";
161  if( ascii )
162  uri += "ascii";
163  if( ascii && format )
164  uri += "&";
165  if ( format )
166  uri += ( "format=" + *format );
167 
168  soma::Writer<T> writer( uri );
169  // copy options so that they are not modified
171  // Copy aims settings to options
172  options->copyProperties(
174  Settings::settings().getValue() ) );
175 
176  if( !_options.isNull() )
177  options->copyProperties( _options );
178  return writer.write( obj, options, 1, 3 );
179  }
180  catch( ... )
181  {
182  }
183 
184  // if it failed, continue with aims writer.
185 
186  std::set<std::string> tried;
187  FileFormat<T> *writer;
188  std::set<std::string>::iterator notyet = tried.end();
189  int excp = 0;
190  int exct = -1;
191  std::string excm;
192 
193  if( format ) // priority to format hint
194  {
195 
196  writer = FileFormatDictionary<T>::fileFormat( *format );
197  if( writer )
198  {
199 #ifdef AIMS_DEBUG_IO
200  std::cout << "1. try writer " << *format << std::endl;
201 #endif
202  try
203  {
204  if( writer->write( _filename, obj, options ) )
205  return true;
206  else if( exactformat )
207  throw carto::wrong_format_error( std::string( "1. Cannot write "
208  "object in format " ) + *format, _filename );
209  }
210  catch( std::exception & e )
211  {
212  if( exactformat )
213  throw;
214  carto::io_error::keepExceptionPriority( e, excp, exct, excm,
215  5 );
216  }
217  tried.insert( *format );
218  }
219  }
220 
221  std::string bname = carto::FileUtil::basename( _filename );
222  std::string::size_type pos = bname.find( '.' );
223  std::string::size_type dlen = _filename.length() - bname.length();
224  std::string ext;
225 
226  if( pos != std::string::npos )
227  ext = _filename.substr( dlen+pos+1, _filename.length() - pos - 1 );
228 
229  const std::map<std::string, std::list<std::string> > & extensions
231 
232  std::map<std::string, std::list<std::string> >::const_iterator iext
233  = extensions.find( ext ),
234  eext = extensions.end();
235  std::list<std::string>::const_iterator ie, ee;
236 
237  if( ext.empty() )
238  {
239  // no extension: use settings for default_writer if one is specified
240  const Settings &sett = Settings::settings();
241  try
242  {
243  carto::Object defwriters = sett.getProperty( "default_writers" );
244  carto::Object defformato;
245  try
246  {
247  defformato
248  = defwriters->getProperty( carto::DataTypeCode<T>::name() );
249  }
250  catch( std::exception & )
251  {
252  // exact type not found, try just the object type
253  defformato
254  = defwriters->getProperty( carto::DataTypeCode<T>::objectType() );
255  }
256  if( defformato )
257  {
258  std::string defformat = defformato->getString();
259 
260  if( tried.find( defformat ) == notyet )
261  {
262  writer = FileFormatDictionary<T>::fileFormat( defformat );
263  if( writer )
264  {
265 #ifdef AIMS_DEBUG_IO
266  std::cout << "2. try writer " << defformat << std::endl;
267 #endif
268  try
269  {
270  if( writer->write( _filename, obj, options ) )
271  return true;
272  else if( exactformat )
273  throw carto::wrong_format_error( std::string( "2. Cannot write "
274  "object in format " ) + defformat, _filename );
275  }
276  catch( std::exception & e )
277  {
278  if( exactformat )
279  throw;
280  carto::io_error::keepExceptionPriority( e, excp, exct, excm,
281  5 );
282  }
283  tried.insert( defformat );
284  }
285  }
286  }
287  }
288  catch( std::exception & )
289  {
290  }
291  }
292 
293  while( iext == eext && (pos=bname.find( '.', pos+1 ))!=std::string::npos )
294  {
295  ext = _filename.substr( dlen+pos+1, _filename.length() - pos - 1 );
296  iext = extensions.find( ext );
297  }
298 
299  // try every matching format until one works
300  if( iext != eext )
301  for( ie=iext->second.begin(), ee=iext->second.end(); ie!=ee; ++ie )
302  {
303  if( tried.find( *ie ) == notyet )
304  {
305  writer = FileFormatDictionary<T>::fileFormat( *ie );
306  if( writer )
307  {
308 #ifdef AIMS_DEBUG_IO
309  std::cout << "3. try writer " << *ie << std::endl;
310 #endif
311  try
312  {
313  if( writer->write( _filename, obj, options ) )
314  return true;
315  else if( exactformat )
316  throw carto::wrong_format_error( std::string( "3. Cannot write "
317  "object in format " ) + *ie, _filename );
318  }
319  catch( std::exception & e )
320  {
321 #ifdef AIMS_DEBUG_IO
322  std::cout << "3. failed for " << *ie << ": " << e.what()
323  << std::endl;
324 #endif
325  if( exactformat )
326  throw;
328  excm );
329  }
330  tried.insert( *ie );
331  }
332  }
333  }
334 
335  if( !ext.empty() )
336  {
337  // not found or none works: try writers with no extension
338  iext = extensions.find( "" );
339 
340  if( iext != eext )
341  for( ie=iext->second.begin(), ee=iext->second.end(); ie!=ee; ++ie )
342  if( tried.find( *ie ) == notyet )
343  {
344  writer = FileFormatDictionary<T>::fileFormat( *ie );
345  if( writer )
346  {
347 #ifdef AIMS_DEBUG_IO
348  std::cout << "4. try writer " << *ie << std::endl;
349 #endif
350  try
351  {
352  if( writer->write( _filename, obj, options ) )
353  return true;
354  else if( exactformat )
355  throw carto::wrong_format_error( std::string( "4. Cannot write "
356  "object in format " ) + *ie, _filename );
357  }
358  catch( std::exception & e )
359  {
360  if( exactformat )
361  throw;
363  excm );
364  }
365  tried.insert( *ie );
366  }
367  }
368  }
369 
370  // still not found ? well, try EVERY format this time...
371  for( iext=extensions.begin(); iext!=eext; ++iext )
372  for( ie=iext->second.begin(), ee=iext->second.end(); ie!=ee; ++ie )
373  if( tried.find( *ie ) == notyet )
374  {
375  writer = FileFormatDictionary<T>::fileFormat( *ie );
376  if( writer )
377  {
378 #ifdef AIMS_DEBUG_IO
379  std::cout << "5. try writer " << *ie << std::endl;
380 #endif
381  try
382  {
383  if( writer->write( _filename, obj, options ) )
384  return true;
385  else if( exactformat )
386  throw carto::wrong_format_error( std::string( "5. Cannot write "
387  "object in format " ) + *ie, _filename );
388  }
389  catch( std::exception & e )
390  {
391  if( exactformat )
392  throw;
394  excm );
395  }
396  tried.insert( *ie );
397  }
398  }
399 
400  // try first soma-io writer (since 2013)
401  // try pass 4
402  try{
403  // building uri
404  std::string uri = _filename;
405  if( ascii || format )
406  uri += "?";
407  if( ascii )
408  uri += "ascii";
409  if( ascii && format )
410  uri += "&";
411  if ( format )
412  uri += ( "format=" + *format );
413 
414  soma::Writer<T> writer( uri );
415  return writer.write( obj, _options, 4, 4 );
416  } catch( ... ) {}
417  // if it failed, it's hopeless
418 
419  // still not succeeded, it's hopeless...
420  carto::io_error::launchExcept( exct, excm,
421  _filename + " : no matching format" );
422  return( false );
423  }
424 
425 }
426 
427 
428 #endif
429 
430 
bool write(const T &obj, bool ascii=false, const std::string *format=0)
Finds the correct format and writes the object.
Definition: writer_d.h:74
const std::string & fileName() const
get output file name
Definition: writer.h:71
static std::string basename(const std::string &)
static void keepExceptionPriority(std::exception &e, int &prio, int &type, std::string &message, int raiseprio=0)
virtual std::string writtenObjectType() const
Definition: writer_d.h:87
The class for EcatSino data write operation.
Definition: border.h:44
static Object reference(T &value)
std::string name()
const carto::Object options() const
Definition: writer.h:72
virtual bool write(const T &obj, carto::Object options=carto::none(), int passbegin=1, int passend=4)
virtual bool write(const T &obj, bool ascii=false, const std::string *format=0)
Finds the correct format and writes the object.
Definition: writer_d.h:108
static const std::map< std::string, std::list< std::string > > & extensions()
Definition: fileFormat_d.h:105
static FileFormat< T > * fileFormat(const std::string &format)
Definition: fileFormat_d.h:199
virtual bool write(const std::string &, const T &, carto::Object options=carto::none())
the base class has a default implementation which only returns false so if your new format only suppo...
Definition: fileFormat_d.h:73
virtual std::string writtenObjectDataType() const
Definition: writer_d.h:94
std::string _filename
Definition: writer.h:80
static Object value()
static Settings & settings()
Generic writer for every format of Aims object.
Definition: writer.h:92
std::map< std::string, Object > Dictionary
static void launchExcept(int code, const std::string &msg, const std::string &defmsg="")
static void load(int verboseLevel=-1, bool forcereload=false)
Low-level object IO format: each specific format has such a reader / writer.
Definition: fileFormat.h:61
virtual std::string writtenObjectFullType() const
Definition: writer_d.h:101
carto::Object _options
Definition: writer.h:81