Boost GIL


device.hpp
1//
2// Copyright 2007-2012 Christian Henning, Andreas Pokorny
3//
4// Distributed under the Boost Software License, Version 1.0
5// See accompanying file LICENSE_1_0.txt or copy at
6// http://www.boost.org/LICENSE_1_0.txt
7//
8#ifndef BOOST_GIL_IO_DEVICE_HPP
9#define BOOST_GIL_IO_DEVICE_HPP
10
11#include <boost/gil/detail/mp11.hpp>
12#include <boost/gil/io/base.hpp>
13
14#include <cstdio>
15#include <memory>
16#include <type_traits>
17
18namespace boost { namespace gil {
19
20#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
21#pragma warning(push)
22#pragma warning(disable:4512) //assignment operator could not be generated
23#endif
24
25namespace detail {
26
27template < typename T > struct buff_item
28{
29 static const unsigned int size = sizeof( T );
30};
31
32template <> struct buff_item< void >
33{
34 static const unsigned int size = 1;
35};
36
47template< typename FormatTag >
49{
50public:
51
52 using format_tag_t = FormatTag;
53
54public:
55
57 struct read_tag {};
58 struct write_tag {};
59
63 file_stream_device( const std::string& file_name
64 , read_tag tag = read_tag()
65 )
66 : file_stream_device(file_name.c_str(), tag)
67 {}
68
72 file_stream_device( const char* file_name
73 , read_tag = read_tag()
74 )
75 {
76 FILE* file = nullptr;
77
78 io_error_if( ( file = fopen( file_name, "rb" )) == nullptr
79 , "file_stream_device: failed to open file for reading"
80 );
81
82 _file = file_ptr_t( file
83 , file_deleter
84 );
85 }
86
90 file_stream_device( const std::string& file_name
91 , write_tag tag
92 )
93 : file_stream_device(file_name.c_str(), tag)
94 {}
95
99 file_stream_device( const char* file_name
100 , write_tag
101 )
102 {
103 FILE* file = nullptr;
104
105 io_error_if( ( file = fopen( file_name, "wb" )) == nullptr
106 , "file_stream_device: failed to open file for writing"
107 );
108
109 _file = file_ptr_t( file
110 , file_deleter
111 );
112 }
113
117 file_stream_device( FILE* file )
118 : _file( file
119 , file_deleter
120 )
121 {}
122
123 auto get() -> FILE* { return _file.get(); }
124 auto get() const -> FILE const* { return _file.get(); }
125
126 int getc_unchecked()
127 {
128 return std::getc( get() );
129 }
130
131 char getc()
132 {
133 int ch;
134
135 io_error_if( ( ch = std::getc( get() )) == EOF
136 , "file_stream_device: unexpected EOF"
137 );
138
139 return ( char ) ch;
140 }
141
143 auto read(byte_t* data, std::size_t count) -> std::size_t
144 {
145 std::size_t num_elements = fread( data
146 , 1
147 , static_cast<int>( count )
148 , get()
149 );
150
152 io_error_if( ferror( get() )
153 , "file_stream_device: file read error"
154 );
155
156 //libjpeg sometimes reads blocks in 4096 bytes even when the file is smaller than that.
157 //return value indicates how much was actually read
158 //returning less than "count" is not an error
159 return num_elements;
160 }
161
163 template< typename T, int N>
164 void read( T (&buf)[N] )
165 {
166 io_error_if( read( buf, N ) < N
167 , "file_stream_device: file read error"
168 );
169 }
170
172 uint8_t read_uint8()
173 {
174 byte_t m[1];
175
176 read( m );
177 return m[0];
178 }
179
181 uint16_t read_uint16()
182 {
183 byte_t m[2];
184
185 read( m );
186 return (m[1] << 8) | m[0];
187 }
188
190 uint32_t read_uint32()
191 {
192 byte_t m[4];
193
194 read( m );
195 return (m[3] << 24) | (m[2] << 16) | (m[1] << 8) | m[0];
196 }
197
199 template < typename T >
200 auto write(T const* buf, std::size_t count) -> std::size_t
201 {
202 std::size_t num_elements = fwrite( buf
203 , buff_item<T>::size
204 , count
205 , get()
206 );
207
208 //return value indicates how much was actually written
209 //returning less than "count" is not an error
210 return num_elements;
211 }
212
214 template < typename T
215 , std::size_t N
216 >
217 void write( const T (&buf)[N] )
218 {
219 io_error_if( write( buf, N ) < N
220 , "file_stream_device: file write error"
221 );
222 return ;
223 }
224
226 void write_uint8( uint8_t x )
227 {
228 byte_t m[1] = { x };
229 write(m);
230 }
231
233 void write_uint16( uint16_t x )
234 {
235 byte_t m[2];
236
237 m[0] = byte_t( x >> 0 );
238 m[1] = byte_t( x >> 8 );
239
240 write( m );
241 }
242
244 void write_uint32( uint32_t x )
245 {
246 byte_t m[4];
247
248 m[0] = byte_t( x >> 0 );
249 m[1] = byte_t( x >> 8 );
250 m[2] = byte_t( x >> 16 );
251 m[3] = byte_t( x >> 24 );
252
253 write( m );
254 }
255
256 void seek( long count, int whence = SEEK_SET )
257 {
258 io_error_if( fseek( get()
259 , count
260 , whence
261 ) != 0
262 , "file_stream_device: file seek error"
263 );
264 }
265
266 long int tell()
267 {
268 long int pos = ftell( get() );
269
270 io_error_if( pos == -1L
271 , "file_stream_device: file position error"
272 );
273
274 return pos;
275 }
276
277 void flush()
278 {
279 fflush( get() );
280 }
281
283 void print_line( const std::string& line )
284 {
285 std::size_t num_elements = fwrite( line.c_str()
286 , sizeof( char )
287 , line.size()
288 , get()
289 );
290
291 io_error_if( num_elements < line.size()
292 , "file_stream_device: line print error"
293 );
294 }
295
296 int error()
297 {
298 return ferror( get() );
299 }
300
301private:
302
303 static void file_deleter( FILE* file )
304 {
305 if( file )
306 {
307 fclose( file );
308 }
309 }
310
311private:
312
313 using file_ptr_t = std::shared_ptr<FILE> ;
314 file_ptr_t _file;
315};
316
320template< typename FormatTag >
322{
323public:
324 istream_device( std::istream& in )
325 : _in( in )
326 {
327 // does the file exists?
328 io_error_if( !in
329 , "istream_device: Stream is not valid."
330 );
331 }
332
333 int getc_unchecked()
334 {
335 return _in.get();
336 }
337
338 char getc()
339 {
340 int ch;
341
342 io_error_if( ( ch = _in.get() ) == EOF
343 , "istream_device: unexpected EOF"
344 );
345
346 return ( char ) ch;
347 }
348
349 std::size_t read( byte_t* data
350 , std::size_t count )
351 {
352 std::streamsize cr = 0;
353
354 do
355 {
356 _in.peek();
357 std::streamsize c = _in.readsome( reinterpret_cast< char* >( data )
358 , static_cast< std::streamsize >( count ));
359
360 count -= static_cast< std::size_t >( c );
361 data += c;
362 cr += c;
363
364 } while( count && _in );
365
366 return static_cast< std::size_t >( cr );
367 }
368
370 template<typename T, int N>
371 void read(T (&buf)[N])
372 {
373 read(buf, N);
374 }
375
377 uint8_t read_uint8()
378 {
379 byte_t m[1];
380
381 read( m );
382 return m[0];
383 }
384
386 uint16_t read_uint16()
387 {
388 byte_t m[2];
389
390 read( m );
391 return (m[1] << 8) | m[0];
392 }
393
395 uint32_t read_uint32()
396 {
397 byte_t m[4];
398
399 read( m );
400 return (m[3] << 24) | (m[2] << 16) | (m[1] << 8) | m[0];
401 }
402
403 void seek( long count, int whence = SEEK_SET )
404 {
405 _in.seekg( count
406 , whence == SEEK_SET ? std::ios::beg
407 :( whence == SEEK_CUR ? std::ios::cur
408 : std::ios::end )
409 );
410 }
411
412 void write(const byte_t*, std::size_t)
413 {
414 io_error( "istream_device: Bad io error." );
415 }
416
417 void flush() {}
418
419private:
420
421 std::istream& _in;
422};
423
427template< typename FormatTag >
429{
430public:
431 ostream_device( std::ostream & out )
432 : _out( out )
433 {
434 }
435
436 std::size_t read(byte_t *, std::size_t)
437 {
438 io_error( "ostream_device: Bad io error." );
439 return 0;
440 }
441
442 void seek( long count, int whence )
443 {
444 _out.seekp( count
445 , whence == SEEK_SET
446 ? std::ios::beg
447 : ( whence == SEEK_CUR
448 ?std::ios::cur
449 :std::ios::end )
450 );
451 }
452
453 void write( const byte_t* data
454 , std::size_t count )
455 {
456 _out.write( reinterpret_cast<char const*>( data )
457 , static_cast<std::streamsize>( count )
458 );
459 }
460
462 template < typename T
463 , std::size_t N
464 >
465 void write( const T (&buf)[N] )
466 {
467 write( buf, N );
468 }
469
471 void write_uint8( uint8_t x )
472 {
473 byte_t m[1] = { x };
474 write(m);
475 }
476
478 void write_uint16( uint16_t x )
479 {
480 byte_t m[2];
481
482 m[0] = byte_t( x >> 0 );
483 m[1] = byte_t( x >> 8 );
484
485 write( m );
486 }
487
489 void write_uint32( uint32_t x )
490 {
491 byte_t m[4];
492
493 m[0] = byte_t( x >> 0 );
494 m[1] = byte_t( x >> 8 );
495 m[2] = byte_t( x >> 16 );
496 m[3] = byte_t( x >> 24 );
497
498 write( m );
499 }
500
501 void flush()
502 {
503 _out << std::flush;
504 }
505
507 void print_line( const std::string& line )
508 {
509 _out << line;
510 }
511
512
513
514private:
515
516 std::ostream& _out;
517};
518
519
524template< typename IODevice > struct is_input_device : std::false_type{};
525template< typename FormatTag > struct is_input_device< file_stream_device< FormatTag > > : std::true_type{};
526template< typename FormatTag > struct is_input_device< istream_device< FormatTag > > : std::true_type{};
527
528template< typename FormatTag
529 , typename T
530 , typename D = void
531 >
532struct is_adaptable_input_device : std::false_type{};
533
534template <typename FormatTag, typename T>
535struct is_adaptable_input_device
536<
537 FormatTag,
538 T,
539 typename std::enable_if
540 <
541 mp11::mp_or
542 <
543 std::is_base_of<std::istream, T>,
544 std::is_same<std::istream, T>
545 >::value
546 >::type
547> : std::true_type
548{
549 using device_type = istream_device<FormatTag>;
550};
551
552template< typename FormatTag >
553struct is_adaptable_input_device< FormatTag
554 , FILE*
555 , void
556 >
557 : std::true_type
558{
559 using device_type = file_stream_device<FormatTag>;
560};
561
565template< typename FormatTag
566 , typename T
567 , typename D = void
568 >
569struct is_read_device : std::false_type
570{};
571
572template <typename FormatTag, typename T>
573struct is_read_device
574<
575 FormatTag,
576 T,
577 typename std::enable_if
578 <
579 mp11::mp_or
580 <
581 is_input_device<FormatTag>,
582 is_adaptable_input_device<FormatTag, T>
583 >::value
584 >::type
585> : std::true_type
586{
587};
588
589
594template<typename IODevice> struct is_output_device : std::false_type{};
595
596template< typename FormatTag > struct is_output_device< file_stream_device< FormatTag > > : std::true_type{};
597template< typename FormatTag > struct is_output_device< ostream_device < FormatTag > > : std::true_type{};
598
599template< typename FormatTag
600 , typename IODevice
601 , typename D = void
602 >
603struct is_adaptable_output_device : std::false_type {};
604
605template <typename FormatTag, typename T>
606struct is_adaptable_output_device
607<
608 FormatTag,
609 T,
610 typename std::enable_if
611 <
612 mp11::mp_or
613 <
614 std::is_base_of<std::ostream, T>,
615 std::is_same<std::ostream, T>
616 >::value
617 >::type
618> : std::true_type
619{
620 using device_type = ostream_device<FormatTag>;
621};
622
623template<typename FormatTag> struct is_adaptable_output_device<FormatTag,FILE*,void>
624 : std::true_type
625{
626 using device_type = file_stream_device<FormatTag>;
627};
628
629
633template< typename FormatTag
634 , typename T
635 , typename D = void
636 >
637struct is_write_device : std::false_type
638{};
639
640template <typename FormatTag, typename T>
641struct is_write_device
642<
643 FormatTag,
644 T,
645 typename std::enable_if
646 <
647 mp11::mp_or
648 <
649 is_output_device<FormatTag>,
650 is_adaptable_output_device<FormatTag, T>
651 >::value
652 >::type
653> : std::true_type
654{
655};
656
657} // namespace detail
658
659template< typename Device, typename FormatTag > class scanline_reader;
660template< typename Device, typename FormatTag, typename ConversionPolicy > class reader;
661
662template< typename Device, typename FormatTag, typename Log = no_log > class writer;
663
664template< typename Device, typename FormatTag > class dynamic_image_reader;
665template< typename Device, typename FormatTag, typename Log = no_log > class dynamic_image_writer;
666
667
668namespace detail {
669
670template< typename T >
671struct is_reader : std::false_type
672{};
673
674template< typename Device
675 , typename FormatTag
676 , typename ConversionPolicy
677 >
678struct is_reader< reader< Device
679 , FormatTag
680 , ConversionPolicy
681 >
682 > : std::true_type
683{};
684
685template< typename T >
686struct is_dynamic_image_reader : std::false_type
687{};
688
689template< typename Device
690 , typename FormatTag
691 >
692struct is_dynamic_image_reader< dynamic_image_reader< Device
693 , FormatTag
694 >
695 > : std::true_type
696{};
697
698template< typename T >
699struct is_writer : std::false_type
700{};
701
702template< typename Device
703 , typename FormatTag
704 >
705struct is_writer< writer< Device
706 , FormatTag
707 >
708 > : std::true_type
709{};
710
711template< typename T >
712struct is_dynamic_image_writer : std::false_type
713{};
714
715template< typename Device
716 , typename FormatTag
717 >
718struct is_dynamic_image_writer< dynamic_image_writer< Device
719 , FormatTag
720 >
721 > : std::true_type
722{};
723
724} // namespace detail
725
726#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
727#pragma warning(pop)
728#endif
729
730} // namespace gil
731} // namespace boost
732
733#endif
file_stream_device(const std::string &file_name, read_tag tag=read_tag())
Definition: device.hpp:63
void write_uint32(uint32_t x)
Writes 32 bit little endian integer.
Definition: device.hpp:244
void print_line(const std::string &line)
Prints formatted ASCII text.
Definition: device.hpp:283
void write_uint8(uint8_t x)
Writes byte.
Definition: device.hpp:226
void read(T(&buf)[N])
Reads array.
Definition: device.hpp:164
file_stream_device(FILE *file)
Definition: device.hpp:117
uint16_t read_uint16()
Reads 16 bit little endian integer.
Definition: device.hpp:181
uint8_t read_uint8()
Reads byte.
Definition: device.hpp:172
file_stream_device(const char *file_name, write_tag)
Definition: device.hpp:99
auto read(byte_t *data, std::size_t count) -> std::size_t
Definition: device.hpp:143
file_stream_device(const std::string &file_name, write_tag tag)
Definition: device.hpp:90
void write(const T(&buf)[N])
Writes array.
Definition: device.hpp:217
file_stream_device(const char *file_name, read_tag=read_tag())
Definition: device.hpp:72
uint32_t read_uint32()
Reads 32 bit little endian integer.
Definition: device.hpp:190
void write_uint16(uint16_t x)
Writes 16 bit little endian integer.
Definition: device.hpp:233
auto write(T const *buf, std::size_t count) -> std::size_t
Writes number of elements from a buffer.
Definition: device.hpp:200
Definition: device.hpp:322
void read(T(&buf)[N])
Reads array.
Definition: device.hpp:371
uint16_t read_uint16()
Reads 16 bit little endian integer.
Definition: device.hpp:386
uint8_t read_uint8()
Reads byte.
Definition: device.hpp:377
uint32_t read_uint32()
Reads 32 bit little endian integer.
Definition: device.hpp:395
Definition: device.hpp:429
void write_uint32(uint32_t x)
Writes 32 bit little endian integer.
Definition: device.hpp:489
void print_line(const std::string &line)
Prints formatted ASCII text.
Definition: device.hpp:507
void write_uint8(uint8_t x)
Writes byte.
Definition: device.hpp:471
void write(const T(&buf)[N])
Writes array.
Definition: device.hpp:465
void write_uint16(uint16_t x)
Writes 16 bit little endian integer.
Definition: device.hpp:478
defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE)
Definition: algorithm.hpp:36
Used to overload the constructor.
Definition: device.hpp:57
Definition: device.hpp:524
Definition: device.hpp:594
Definition: device.hpp:570
Definition: device.hpp:638