]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/gil/io/device.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / gil / io / 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
18 namespace 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
25 namespace detail {
26
27 template < typename T > struct buff_item
28 {
29 static const unsigned int size = sizeof( T );
30 };
31
32 template <> struct buff_item< void >
33 {
34 static const unsigned int size = 1;
35 };
36
37 /*!
38 * Implements the IODevice concept c.f. to \ref IODevice required by Image libraries like
39 * libjpeg and libpng.
40 *
41 * \todo switch to a sane interface as soon as there is
42 * something good in boost. I.E. the IOChains library
43 * would fit very well here.
44 *
45 * This implementation is based on FILE*.
46 */
47 template< typename FormatTag >
48 class file_stream_device
49 {
50 public:
51
52 using format_tag_t = FormatTag;
53
54 public:
55
56 /// Used to overload the constructor.
57 struct read_tag {};
58 struct write_tag {};
59
60 ///
61 /// Constructor
62 ///
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
69 ///
70 /// Constructor
71 ///
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
87 ///
88 /// Constructor
89 ///
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
96 ///
97 /// Constructor
98 ///
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
114 ///
115 /// Constructor
116 ///
117 file_stream_device( FILE* file )
118 : _file( file
119 , file_deleter
120 )
121 {}
122
123 FILE* get() { return _file.get(); }
124 const FILE* get() 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
142 ///@todo: change byte_t* to void*
143 std::size_t read( byte_t* data
144 , std::size_t count
145 )
146 {
147 std::size_t num_elements = fread( data
148 , 1
149 , static_cast<int>( count )
150 , get()
151 );
152
153 ///@todo: add compiler symbol to turn error checking on and off.
154 io_error_if( ferror( get() )
155 , "file_stream_device: file read error"
156 );
157
158 //libjpeg sometimes reads blocks in 4096 bytes even when the file is smaller than that.
159 //return value indicates how much was actually read
160 //returning less than "count" is not an error
161 return num_elements;
162 }
163
164 /// Reads array
165 template< typename T
166 , int N
167 >
168 void read( T (&buf)[N] )
169 {
170 io_error_if( read( buf, N ) < N
171 , "file_stream_device: file read error"
172 );
173 }
174
175 /// Reads byte
176 uint8_t read_uint8()
177 {
178 byte_t m[1];
179
180 read( m );
181 return m[0];
182 }
183
184 /// Reads 16 bit little endian integer
185 uint16_t read_uint16()
186 {
187 byte_t m[2];
188
189 read( m );
190 return (m[1] << 8) | m[0];
191 }
192
193 /// Reads 32 bit little endian integer
194 uint32_t read_uint32()
195 {
196 byte_t m[4];
197
198 read( m );
199 return (m[3] << 24) | (m[2] << 16) | (m[1] << 8) | m[0];
200 }
201
202 /// Writes number of elements from a buffer
203 template < typename T >
204 std::size_t write( const T* buf
205 , std::size_t count
206 )
207 {
208 std::size_t num_elements = fwrite( buf
209 , buff_item<T>::size
210 , count
211 , get()
212 );
213
214 //return value indicates how much was actually written
215 //returning less than "count" is not an error
216 return num_elements;
217 }
218
219 /// Writes array
220 template < typename T
221 , std::size_t N
222 >
223 void write( const T (&buf)[N] )
224 {
225 io_error_if( write( buf, N ) < N
226 , "file_stream_device: file write error"
227 );
228 return ;
229 }
230
231 /// Writes byte
232 void write_uint8( uint8_t x )
233 {
234 byte_t m[1] = { x };
235 write(m);
236 }
237
238 /// Writes 16 bit little endian integer
239 void write_uint16( uint16_t x )
240 {
241 byte_t m[2];
242
243 m[0] = byte_t( x >> 0 );
244 m[1] = byte_t( x >> 8 );
245
246 write( m );
247 }
248
249 /// Writes 32 bit little endian integer
250 void write_uint32( uint32_t x )
251 {
252 byte_t m[4];
253
254 m[0] = byte_t( x >> 0 );
255 m[1] = byte_t( x >> 8 );
256 m[2] = byte_t( x >> 16 );
257 m[3] = byte_t( x >> 24 );
258
259 write( m );
260 }
261
262 void seek( long count, int whence = SEEK_SET )
263 {
264 io_error_if( fseek( get()
265 , count
266 , whence
267 ) != 0
268 , "file_stream_device: file seek error"
269 );
270 }
271
272 long int tell()
273 {
274 long int pos = ftell( get() );
275
276 io_error_if( pos == -1L
277 , "file_stream_device: file position error"
278 );
279
280 return pos;
281 }
282
283 void flush()
284 {
285 fflush( get() );
286 }
287
288 /// Prints formatted ASCII text
289 void print_line( const std::string& line )
290 {
291 std::size_t num_elements = fwrite( line.c_str()
292 , sizeof( char )
293 , line.size()
294 , get()
295 );
296
297 io_error_if( num_elements < line.size()
298 , "file_stream_device: line print error"
299 );
300 }
301
302 int error()
303 {
304 return ferror( get() );
305 }
306
307 private:
308
309 static void file_deleter( FILE* file )
310 {
311 if( file )
312 {
313 fclose( file );
314 }
315 }
316
317 private:
318
319 using file_ptr_t = std::shared_ptr<FILE> ;
320 file_ptr_t _file;
321 };
322
323 /**
324 * Input stream device
325 */
326 template< typename FormatTag >
327 class istream_device
328 {
329 public:
330 istream_device( std::istream& in )
331 : _in( in )
332 {
333 // does the file exists?
334 io_error_if( !in
335 , "istream_device: Stream is not valid."
336 );
337 }
338
339 int getc_unchecked()
340 {
341 return _in.get();
342 }
343
344 char getc()
345 {
346 int ch;
347
348 io_error_if( ( ch = _in.get() ) == EOF
349 , "istream_device: unexpected EOF"
350 );
351
352 return ( char ) ch;
353 }
354
355 std::size_t read( byte_t* data
356 , std::size_t count )
357 {
358 std::streamsize cr = 0;
359
360 do
361 {
362 _in.peek();
363 std::streamsize c = _in.readsome( reinterpret_cast< char* >( data )
364 , static_cast< std::streamsize >( count ));
365
366 count -= static_cast< std::size_t >( c );
367 data += c;
368 cr += c;
369
370 } while( count && _in );
371
372 return static_cast< std::size_t >( cr );
373 }
374
375 /// Reads array
376 template<typename T, int N>
377 void read(T (&buf)[N])
378 {
379 read(buf, N);
380 }
381
382 /// Reads byte
383 uint8_t read_uint8()
384 {
385 byte_t m[1];
386
387 read( m );
388 return m[0];
389 }
390
391 /// Reads 16 bit little endian integer
392 uint16_t read_uint16()
393 {
394 byte_t m[2];
395
396 read( m );
397 return (m[1] << 8) | m[0];
398 }
399
400 /// Reads 32 bit little endian integer
401 uint32_t read_uint32()
402 {
403 byte_t m[4];
404
405 read( m );
406 return (m[3] << 24) | (m[2] << 16) | (m[1] << 8) | m[0];
407 }
408
409 void seek( long count, int whence = SEEK_SET )
410 {
411 _in.seekg( count
412 , whence == SEEK_SET ? std::ios::beg
413 :( whence == SEEK_CUR ? std::ios::cur
414 : std::ios::end )
415 );
416 }
417
418 void write(const byte_t*, std::size_t)
419 {
420 io_error( "istream_device: Bad io error." );
421 }
422
423 void flush() {}
424
425 private:
426
427 std::istream& _in;
428 };
429
430 /**
431 * Output stream device
432 */
433 template< typename FormatTag >
434 class ostream_device
435 {
436 public:
437 ostream_device( std::ostream & out )
438 : _out( out )
439 {
440 }
441
442 std::size_t read(byte_t *, std::size_t)
443 {
444 io_error( "ostream_device: Bad io error." );
445 return 0;
446 }
447
448 void seek( long count, int whence )
449 {
450 _out.seekp( count
451 , whence == SEEK_SET
452 ? std::ios::beg
453 : ( whence == SEEK_CUR
454 ?std::ios::cur
455 :std::ios::end )
456 );
457 }
458
459 void write( const byte_t* data
460 , std::size_t count )
461 {
462 _out.write( reinterpret_cast<char const*>( data )
463 , static_cast<std::streamsize>( count )
464 );
465 }
466
467 /// Writes array
468 template < typename T
469 , std::size_t N
470 >
471 void write( const T (&buf)[N] )
472 {
473 write( buf, N );
474 }
475
476 /// Writes byte
477 void write_uint8( uint8_t x )
478 {
479 byte_t m[1] = { x };
480 write(m);
481 }
482
483 /// Writes 16 bit little endian integer
484 void write_uint16( uint16_t x )
485 {
486 byte_t m[2];
487
488 m[0] = byte_t( x >> 0 );
489 m[1] = byte_t( x >> 8 );
490
491 write( m );
492 }
493
494 /// Writes 32 bit little endian integer
495 void write_uint32( uint32_t x )
496 {
497 byte_t m[4];
498
499 m[0] = byte_t( x >> 0 );
500 m[1] = byte_t( x >> 8 );
501 m[2] = byte_t( x >> 16 );
502 m[3] = byte_t( x >> 24 );
503
504 write( m );
505 }
506
507 void flush()
508 {
509 _out << std::flush;
510 }
511
512 /// Prints formatted ASCII text
513 void print_line( const std::string& line )
514 {
515 _out << line;
516 }
517
518
519
520 private:
521
522 std::ostream& _out;
523 };
524
525
526 /**
527 * Metafunction to detect input devices.
528 * Should be replaced by an external facility in the future.
529 */
530 template< typename IODevice > struct is_input_device : std::false_type{};
531 template< typename FormatTag > struct is_input_device< file_stream_device< FormatTag > > : std::true_type{};
532 template< typename FormatTag > struct is_input_device< istream_device< FormatTag > > : std::true_type{};
533
534 template< typename FormatTag
535 , typename T
536 , typename D = void
537 >
538 struct is_adaptable_input_device : std::false_type{};
539
540 template <typename FormatTag, typename T>
541 struct is_adaptable_input_device
542 <
543 FormatTag,
544 T,
545 typename std::enable_if
546 <
547 mp11::mp_or
548 <
549 std::is_base_of<std::istream, T>,
550 std::is_same<std::istream, T>
551 >::value
552 >::type
553 > : std::true_type
554 {
555 using device_type = istream_device<FormatTag>;
556 };
557
558 template< typename FormatTag >
559 struct is_adaptable_input_device< FormatTag
560 , FILE*
561 , void
562 >
563 : std::true_type
564 {
565 using device_type = file_stream_device<FormatTag>;
566 };
567
568 ///
569 /// Metafunction to decide if a given type is an acceptable read device type.
570 ///
571 template< typename FormatTag
572 , typename T
573 , typename D = void
574 >
575 struct is_read_device : std::false_type
576 {};
577
578 template <typename FormatTag, typename T>
579 struct is_read_device
580 <
581 FormatTag,
582 T,
583 typename std::enable_if
584 <
585 mp11::mp_or
586 <
587 is_input_device<FormatTag>,
588 is_adaptable_input_device<FormatTag, T>
589 >::value
590 >::type
591 > : std::true_type
592 {
593 };
594
595
596 /**
597 * Metafunction to detect output devices.
598 * Should be replaced by an external facility in the future.
599 */
600 template<typename IODevice> struct is_output_device : std::false_type{};
601
602 template< typename FormatTag > struct is_output_device< file_stream_device< FormatTag > > : std::true_type{};
603 template< typename FormatTag > struct is_output_device< ostream_device < FormatTag > > : std::true_type{};
604
605 template< typename FormatTag
606 , typename IODevice
607 , typename D = void
608 >
609 struct is_adaptable_output_device : std::false_type {};
610
611 template <typename FormatTag, typename T>
612 struct is_adaptable_output_device
613 <
614 FormatTag,
615 T,
616 typename std::enable_if
617 <
618 mp11::mp_or
619 <
620 std::is_base_of<std::ostream, T>,
621 std::is_same<std::ostream, T>
622 >::value
623 >::type
624 > : std::true_type
625 {
626 using device_type = ostream_device<FormatTag>;
627 };
628
629 template<typename FormatTag> struct is_adaptable_output_device<FormatTag,FILE*,void>
630 : std::true_type
631 {
632 using device_type = file_stream_device<FormatTag>;
633 };
634
635
636 ///
637 /// Metafunction to decide if a given type is an acceptable read device type.
638 ///
639 template< typename FormatTag
640 , typename T
641 , typename D = void
642 >
643 struct is_write_device : std::false_type
644 {};
645
646 template <typename FormatTag, typename T>
647 struct is_write_device
648 <
649 FormatTag,
650 T,
651 typename std::enable_if
652 <
653 mp11::mp_or
654 <
655 is_output_device<FormatTag>,
656 is_adaptable_output_device<FormatTag, T>
657 >::value
658 >::type
659 > : std::true_type
660 {
661 };
662
663 } // namespace detail
664
665 template< typename Device, typename FormatTag > class scanline_reader;
666 template< typename Device, typename FormatTag, typename ConversionPolicy > class reader;
667
668 template< typename Device, typename FormatTag, typename Log = no_log > class writer;
669
670 template< typename Device, typename FormatTag > class dynamic_image_reader;
671 template< typename Device, typename FormatTag, typename Log = no_log > class dynamic_image_writer;
672
673
674 namespace detail {
675
676 template< typename T >
677 struct is_reader : std::false_type
678 {};
679
680 template< typename Device
681 , typename FormatTag
682 , typename ConversionPolicy
683 >
684 struct is_reader< reader< Device
685 , FormatTag
686 , ConversionPolicy
687 >
688 > : std::true_type
689 {};
690
691 template< typename T >
692 struct is_dynamic_image_reader : std::false_type
693 {};
694
695 template< typename Device
696 , typename FormatTag
697 >
698 struct is_dynamic_image_reader< dynamic_image_reader< Device
699 , FormatTag
700 >
701 > : std::true_type
702 {};
703
704 template< typename T >
705 struct is_writer : std::false_type
706 {};
707
708 template< typename Device
709 , typename FormatTag
710 >
711 struct is_writer< writer< Device
712 , FormatTag
713 >
714 > : std::true_type
715 {};
716
717 template< typename T >
718 struct is_dynamic_image_writer : std::false_type
719 {};
720
721 template< typename Device
722 , typename FormatTag
723 >
724 struct is_dynamic_image_writer< dynamic_image_writer< Device
725 , FormatTag
726 >
727 > : std::true_type
728 {};
729
730 } // namespace detail
731
732 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
733 #pragma warning(pop)
734 #endif
735
736 } // namespace gil
737 } // namespace boost
738
739 #endif