Warning, file /include/boost/gil/io/device.hpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef BOOST_GIL_IO_DEVICE_HPP
0010 #define BOOST_GIL_IO_DEVICE_HPP
0011
0012 #include <boost/gil/detail/mp11.hpp>
0013 #include <boost/gil/io/base.hpp>
0014
0015 #include <cstdio>
0016 #include <memory>
0017 #include <type_traits>
0018
0019 namespace boost { namespace gil {
0020
0021 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0022 #pragma warning(push)
0023 #pragma warning(disable:4512)
0024 #endif
0025
0026 namespace detail {
0027
0028 template < typename T > struct buff_item
0029 {
0030 static const unsigned int size = sizeof( T );
0031 };
0032
0033 template <> struct buff_item< void >
0034 {
0035 static const unsigned int size = 1;
0036 };
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048 template< typename FormatTag >
0049 class file_stream_device
0050 {
0051 public:
0052
0053 using format_tag_t = FormatTag;
0054
0055 public:
0056
0057
0058 struct read_tag {};
0059 struct write_tag {};
0060
0061
0062
0063
0064 file_stream_device( const std::string& file_name
0065 , read_tag tag = read_tag()
0066 )
0067 : file_stream_device(file_name.c_str(), tag)
0068 {}
0069
0070
0071
0072
0073 file_stream_device( const char* file_name
0074 , read_tag = read_tag()
0075 )
0076 {
0077 FILE* file = nullptr;
0078
0079 io_error_if( ( file = fopen( file_name, "rb" )) == nullptr
0080 , "file_stream_device: failed to open file for reading"
0081 );
0082
0083 _file = file_ptr_t( file
0084 , file_deleter
0085 );
0086 }
0087
0088
0089
0090
0091 file_stream_device( const std::string& file_name
0092 , write_tag tag
0093 )
0094 : file_stream_device(file_name.c_str(), tag)
0095 {}
0096
0097
0098
0099
0100 file_stream_device( const char* file_name
0101 , write_tag
0102 )
0103 {
0104 FILE* file = nullptr;
0105
0106 io_error_if( ( file = fopen( file_name, "wb" )) == nullptr
0107 , "file_stream_device: failed to open file for writing"
0108 );
0109
0110 _file = file_ptr_t( file
0111 , file_deleter
0112 );
0113 }
0114
0115
0116
0117
0118 file_stream_device( FILE* file )
0119 : _file( file
0120 , file_deleter
0121 )
0122 {}
0123
0124 auto get() -> FILE* { return _file.get(); }
0125 auto get() const -> FILE const* { return _file.get(); }
0126
0127 int getc_unchecked()
0128 {
0129 return std::getc( get() );
0130 }
0131
0132 char getc()
0133 {
0134 int ch;
0135
0136 io_error_if( ( ch = std::getc( get() )) == EOF
0137 , "file_stream_device: unexpected EOF"
0138 );
0139
0140 return ( char ) ch;
0141 }
0142
0143
0144 auto read(byte_t* data, std::size_t count) -> std::size_t
0145 {
0146 std::size_t num_elements = fread( data
0147 , 1
0148 , static_cast<int>( count )
0149 , get()
0150 );
0151
0152
0153 io_error_if( ferror( get() )
0154 , "file_stream_device: file read error"
0155 );
0156
0157
0158
0159
0160 return num_elements;
0161 }
0162
0163
0164 template< typename T, int N>
0165 void read( T (&buf)[N] )
0166 {
0167 io_error_if( read( buf, N ) < N
0168 , "file_stream_device: file read error"
0169 );
0170 }
0171
0172
0173 uint8_t read_uint8()
0174 {
0175 byte_t m[1];
0176
0177 read( m );
0178 return m[0];
0179 }
0180
0181
0182 uint16_t read_uint16()
0183 {
0184 byte_t m[2];
0185
0186 read( m );
0187 return (m[1] << 8) | m[0];
0188 }
0189
0190
0191 uint32_t read_uint32()
0192 {
0193 byte_t m[4];
0194
0195 read( m );
0196 return (m[3] << 24) | (m[2] << 16) | (m[1] << 8) | m[0];
0197 }
0198
0199
0200 template < typename T >
0201 auto write(T const* buf, std::size_t count) -> std::size_t
0202 {
0203 std::size_t num_elements = fwrite( buf
0204 , buff_item<T>::size
0205 , count
0206 , get()
0207 );
0208
0209
0210
0211 return num_elements;
0212 }
0213
0214
0215 template < typename T
0216 , std::size_t N
0217 >
0218 void write( const T (&buf)[N] )
0219 {
0220 io_error_if( write( buf, N ) < N
0221 , "file_stream_device: file write error"
0222 );
0223 return ;
0224 }
0225
0226
0227 void write_uint8( uint8_t x )
0228 {
0229 byte_t m[1] = { x };
0230 write(m);
0231 }
0232
0233
0234 void write_uint16( uint16_t x )
0235 {
0236 byte_t m[2];
0237
0238 m[0] = byte_t( x >> 0 );
0239 m[1] = byte_t( x >> 8 );
0240
0241 write( m );
0242 }
0243
0244
0245 void write_uint32( uint32_t x )
0246 {
0247 byte_t m[4];
0248
0249 m[0] = byte_t( x >> 0 );
0250 m[1] = byte_t( x >> 8 );
0251 m[2] = byte_t( x >> 16 );
0252 m[3] = byte_t( x >> 24 );
0253
0254 write( m );
0255 }
0256
0257 void seek( long count, int whence = SEEK_SET )
0258 {
0259 io_error_if( fseek( get()
0260 , count
0261 , whence
0262 ) != 0
0263 , "file_stream_device: file seek error"
0264 );
0265 }
0266
0267 long int tell()
0268 {
0269 long int pos = ftell( get() );
0270
0271 io_error_if( pos == -1L
0272 , "file_stream_device: file position error"
0273 );
0274
0275 return pos;
0276 }
0277
0278 void flush()
0279 {
0280 fflush( get() );
0281 }
0282
0283
0284 void print_line( const std::string& line )
0285 {
0286 std::size_t num_elements = fwrite( line.c_str()
0287 , sizeof( char )
0288 , line.size()
0289 , get()
0290 );
0291
0292 io_error_if( num_elements < line.size()
0293 , "file_stream_device: line print error"
0294 );
0295 }
0296
0297 int error()
0298 {
0299 return ferror( get() );
0300 }
0301
0302 private:
0303
0304 static void file_deleter( FILE* file )
0305 {
0306 if( file )
0307 {
0308 fclose( file );
0309 }
0310 }
0311
0312 private:
0313
0314 using file_ptr_t = std::shared_ptr<FILE> ;
0315 file_ptr_t _file;
0316 };
0317
0318
0319
0320
0321 template< typename FormatTag >
0322 class istream_device
0323 {
0324 public:
0325 istream_device( std::istream& in )
0326 : _in( in )
0327 {
0328
0329 io_error_if( !in
0330 , "istream_device: Stream is not valid."
0331 );
0332 }
0333
0334 int getc_unchecked()
0335 {
0336 return _in.get();
0337 }
0338
0339 char getc()
0340 {
0341 int ch;
0342
0343 io_error_if( ( ch = _in.get() ) == EOF
0344 , "istream_device: unexpected EOF"
0345 );
0346
0347 return ( char ) ch;
0348 }
0349
0350 std::size_t read( byte_t* data
0351 , std::size_t count )
0352 {
0353 std::streamsize cr = 0;
0354
0355 do
0356 {
0357 _in.peek();
0358 std::streamsize c = _in.readsome( reinterpret_cast< char* >( data )
0359 , static_cast< std::streamsize >( count ));
0360
0361 count -= static_cast< std::size_t >( c );
0362 data += c;
0363 cr += c;
0364
0365 } while( count && _in );
0366
0367 return static_cast< std::size_t >( cr );
0368 }
0369
0370
0371 template<typename T, int N>
0372 void read(T (&buf)[N])
0373 {
0374 read(buf, N);
0375 }
0376
0377
0378 uint8_t read_uint8()
0379 {
0380 byte_t m[1];
0381
0382 read( m );
0383 return m[0];
0384 }
0385
0386
0387 uint16_t read_uint16()
0388 {
0389 byte_t m[2];
0390
0391 read( m );
0392 return (m[1] << 8) | m[0];
0393 }
0394
0395
0396 uint32_t read_uint32()
0397 {
0398 byte_t m[4];
0399
0400 read( m );
0401 return (m[3] << 24) | (m[2] << 16) | (m[1] << 8) | m[0];
0402 }
0403
0404 void seek( long count, int whence = SEEK_SET )
0405 {
0406 _in.seekg( count
0407 , whence == SEEK_SET ? std::ios::beg
0408 :( whence == SEEK_CUR ? std::ios::cur
0409 : std::ios::end )
0410 );
0411 }
0412
0413 long int tell()
0414 {
0415 auto pos = _in.tellg();
0416
0417 io_error_if( pos == std::istream::pos_type(-1)
0418 , "istream_device: file position error"
0419 );
0420
0421 return static_cast<long int>(pos);
0422 }
0423
0424 void write(const byte_t*, std::size_t)
0425 {
0426 io_error( "istream_device: Bad io error." );
0427 }
0428
0429 void flush() {}
0430
0431 int error()
0432 {
0433 return _in.fail();
0434 }
0435
0436 private:
0437
0438 std::istream& _in;
0439 };
0440
0441
0442
0443
0444 template< typename FormatTag >
0445 class ostream_device
0446 {
0447 public:
0448 ostream_device( std::ostream & out )
0449 : _out( out )
0450 {
0451 }
0452
0453 std::size_t read(byte_t *, std::size_t)
0454 {
0455 io_error( "ostream_device: Bad io error." );
0456 return 0;
0457 }
0458
0459 void seek( long count, int whence )
0460 {
0461 _out.seekp( count
0462 , whence == SEEK_SET
0463 ? std::ios::beg
0464 : ( whence == SEEK_CUR
0465 ?std::ios::cur
0466 :std::ios::end )
0467 );
0468 }
0469
0470 long int tell()
0471 {
0472 auto pos = _out.tellp();
0473
0474 io_error_if( pos == std::ostream::pos_type(-1)
0475 , "ostream_device: file position error"
0476 );
0477
0478 return static_cast<long int>(pos);
0479 }
0480
0481 void write( const byte_t* data
0482 , std::size_t count )
0483 {
0484 _out.write( reinterpret_cast<char const*>( data )
0485 , static_cast<std::streamsize>( count )
0486 );
0487 }
0488
0489
0490 template < typename T
0491 , std::size_t N
0492 >
0493 void write( const T (&buf)[N] )
0494 {
0495 write( buf, N );
0496 }
0497
0498
0499 void write_uint8( uint8_t x )
0500 {
0501 byte_t m[1] = { x };
0502 write(m);
0503 }
0504
0505
0506 void write_uint16( uint16_t x )
0507 {
0508 byte_t m[2];
0509
0510 m[0] = byte_t( x >> 0 );
0511 m[1] = byte_t( x >> 8 );
0512
0513 write( m );
0514 }
0515
0516
0517 void write_uint32( uint32_t x )
0518 {
0519 byte_t m[4];
0520
0521 m[0] = byte_t( x >> 0 );
0522 m[1] = byte_t( x >> 8 );
0523 m[2] = byte_t( x >> 16 );
0524 m[3] = byte_t( x >> 24 );
0525
0526 write( m );
0527 }
0528
0529 void flush()
0530 {
0531 _out << std::flush;
0532 }
0533
0534
0535 void print_line( const std::string& line )
0536 {
0537 _out << line;
0538 }
0539
0540 int error()
0541 {
0542 return _out.fail();
0543 }
0544
0545 private:
0546
0547 std::ostream& _out;
0548 };
0549
0550
0551
0552
0553
0554
0555 template< typename IODevice > struct is_input_device : std::false_type{};
0556 template< typename FormatTag > struct is_input_device< file_stream_device< FormatTag > > : std::true_type{};
0557 template< typename FormatTag > struct is_input_device< istream_device< FormatTag > > : std::true_type{};
0558
0559 template< typename FormatTag
0560 , typename T
0561 , typename D = void
0562 >
0563 struct is_adaptable_input_device : std::false_type{};
0564
0565 template <typename FormatTag, typename T>
0566 struct is_adaptable_input_device
0567 <
0568 FormatTag,
0569 T,
0570 typename std::enable_if
0571 <
0572 mp11::mp_or
0573 <
0574 std::is_base_of<std::istream, T>,
0575 std::is_same<std::istream, T>
0576 >::value
0577 >::type
0578 > : std::true_type
0579 {
0580 using device_type = istream_device<FormatTag>;
0581 };
0582
0583 template< typename FormatTag >
0584 struct is_adaptable_input_device< FormatTag
0585 , FILE*
0586 , void
0587 >
0588 : std::true_type
0589 {
0590 using device_type = file_stream_device<FormatTag>;
0591 };
0592
0593
0594
0595
0596 template< typename FormatTag
0597 , typename T
0598 , typename D = void
0599 >
0600 struct is_read_device : std::false_type
0601 {};
0602
0603 template <typename FormatTag, typename T>
0604 struct is_read_device
0605 <
0606 FormatTag,
0607 T,
0608 typename std::enable_if
0609 <
0610 mp11::mp_or
0611 <
0612 is_input_device<FormatTag>,
0613 is_adaptable_input_device<FormatTag, T>
0614 >::value
0615 >::type
0616 > : std::true_type
0617 {
0618 };
0619
0620
0621
0622
0623
0624
0625 template<typename IODevice> struct is_output_device : std::false_type{};
0626
0627 template< typename FormatTag > struct is_output_device< file_stream_device< FormatTag > > : std::true_type{};
0628 template< typename FormatTag > struct is_output_device< ostream_device < FormatTag > > : std::true_type{};
0629
0630 template< typename FormatTag
0631 , typename IODevice
0632 , typename D = void
0633 >
0634 struct is_adaptable_output_device : std::false_type {};
0635
0636 template <typename FormatTag, typename T>
0637 struct is_adaptable_output_device
0638 <
0639 FormatTag,
0640 T,
0641 typename std::enable_if
0642 <
0643 mp11::mp_or
0644 <
0645 std::is_base_of<std::ostream, T>,
0646 std::is_same<std::ostream, T>
0647 >::value
0648 >::type
0649 > : std::true_type
0650 {
0651 using device_type = ostream_device<FormatTag>;
0652 };
0653
0654 template<typename FormatTag> struct is_adaptable_output_device<FormatTag,FILE*,void>
0655 : std::true_type
0656 {
0657 using device_type = file_stream_device<FormatTag>;
0658 };
0659
0660
0661
0662
0663
0664 template< typename FormatTag
0665 , typename T
0666 , typename D = void
0667 >
0668 struct is_write_device : std::false_type
0669 {};
0670
0671 template <typename FormatTag, typename T>
0672 struct is_write_device
0673 <
0674 FormatTag,
0675 T,
0676 typename std::enable_if
0677 <
0678 mp11::mp_or
0679 <
0680 is_output_device<FormatTag>,
0681 is_adaptable_output_device<FormatTag, T>
0682 >::value
0683 >::type
0684 > : std::true_type
0685 {
0686 };
0687
0688 }
0689
0690 template< typename Device, typename FormatTag > class scanline_reader;
0691 template< typename Device, typename FormatTag, typename ConversionPolicy > class reader;
0692
0693 template< typename Device, typename FormatTag, typename Log = no_log > class writer;
0694
0695 template< typename Device, typename FormatTag > class dynamic_image_reader;
0696 template< typename Device, typename FormatTag, typename Log = no_log > class dynamic_image_writer;
0697
0698
0699 namespace detail {
0700
0701 template< typename T >
0702 struct is_reader : std::false_type
0703 {};
0704
0705 template< typename Device
0706 , typename FormatTag
0707 , typename ConversionPolicy
0708 >
0709 struct is_reader< reader< Device
0710 , FormatTag
0711 , ConversionPolicy
0712 >
0713 > : std::true_type
0714 {};
0715
0716 template< typename T >
0717 struct is_dynamic_image_reader : std::false_type
0718 {};
0719
0720 template< typename Device
0721 , typename FormatTag
0722 >
0723 struct is_dynamic_image_reader< dynamic_image_reader< Device
0724 , FormatTag
0725 >
0726 > : std::true_type
0727 {};
0728
0729 template< typename T >
0730 struct is_writer : std::false_type
0731 {};
0732
0733 template< typename Device
0734 , typename FormatTag
0735 >
0736 struct is_writer< writer< Device
0737 , FormatTag
0738 >
0739 > : std::true_type
0740 {};
0741
0742 template< typename T >
0743 struct is_dynamic_image_writer : std::false_type
0744 {};
0745
0746 template< typename Device
0747 , typename FormatTag
0748 >
0749 struct is_dynamic_image_writer< dynamic_image_writer< Device
0750 , FormatTag
0751 >
0752 > : std::true_type
0753 {};
0754
0755 }
0756
0757 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0758 #pragma warning(pop)
0759 #endif
0760
0761 }
0762 }
0763
0764 #endif