Diffstat (limited to 'src/iii-extract-riff-chunk.cc') (more/less context) (ignore whitespace changes)
-rw-r--r-- | src/iii-extract-riff-chunk.cc | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/src/iii-extract-riff-chunk.cc b/src/iii-extract-riff-chunk.cc index 3a06db2..d53170d 100644 --- a/src/iii-extract-riff-chunk.cc +++ b/src/iii-extract-riff-chunk.cc | |||
@@ -1,114 +1,114 @@ | |||
1 | /* vim:set sw=8 nosi noai cin cino=:0,l1,g0: */ | 1 | /* vim:set sw=8 nosi noai cin cino=:0,l1,g0: */ |
2 | #include <stdint.h> | 2 | #include <stdint.h> |
3 | #include <stdlib.h> | 3 | #include <stdlib.h> |
4 | #include <getopt.h> | 4 | #include <getopt.h> |
5 | #include <cstring> | 5 | #include <cstring> |
6 | #include <iostream> | 6 | #include <iostream> |
7 | #include <fstream> | 7 | #include <fstream> |
8 | #include <stdexcept> | 8 | #include <stdexcept> |
9 | #include <cassert> | 9 | #include <cassert> |
10 | #include <list> | 10 | #include <list> |
11 | #include <string> | 11 | #include <string> |
12 | #include <iterator> | 12 | #include <iterator> |
13 | 13 | ||
14 | #include "config.h" | 14 | #include "config.h" |
15 | 15 | ||
16 | #define PHEADER \ | 16 | #define PHEADER \ |
17 | PACKAGE " Version " VERSION "\n" \ | 17 | PACKAGE " Version " VERSION "\n" \ |
18 | "Copyright (c) 2009-2010 Klever Group" | 18 | "Copyright (c) 2009-2011 Klever Group" |
19 | 19 | ||
20 | typedef uint32_t fourcc_type; | 20 | typedef uint32_t fourcc_type; |
21 | enum fourcc_value { | 21 | enum fourcc_value { |
22 | fourcc_RIFF = 0x46464952, fourcc_AVI = 0x20495641, fourcc_LIST = 0x5453494c, | 22 | fourcc_RIFF = 0x46464952, fourcc_AVI = 0x20495641, fourcc_LIST = 0x5453494c, |
23 | fourcc_hdrl = 0x6c726468, fourcc_strl = 0x6c727473, | 23 | fourcc_hdrl = 0x6c726468, fourcc_strl = 0x6c727473, |
24 | fourcc_ncdt = 0x7464636e, fourcc_ncvr = 0x7276636e, fourcc_nctg = 0x6774636e, fourcc_ncth = 0x6874636e | 24 | fourcc_ncdt = 0x7464636e, fourcc_ncvr = 0x7276636e, fourcc_nctg = 0x6774636e, fourcc_ncth = 0x6874636e |
25 | }; | 25 | }; |
26 | 26 | ||
27 | fourcc_type str2fourcc(const char *str) { | 27 | fourcc_type str2fourcc(const char *str) { |
28 | fourcc_type rv = 0; | 28 | fourcc_type rv = 0; |
29 | return *(fourcc_type*)strncpy((char*)&rv,str,sizeof(rv)); | 29 | return *(fourcc_type*)strncpy((char*)&rv,str,sizeof(rv)); |
30 | } | 30 | } |
31 | const std::string fourcc2str(fourcc_type fcc) { | 31 | const std::string fourcc2str(fourcc_type fcc) { |
32 | char rv[sizeof(fcc)+1]; | 32 | char rv[sizeof(fcc)+1]; |
33 | *(fourcc_type*)rv = fcc; | 33 | *(fourcc_type*)rv = fcc; |
34 | rv[sizeof(fcc)]=0; | 34 | rv[sizeof(fcc)]=0; |
35 | return rv; | 35 | return rv; |
36 | } | 36 | } |
37 | 37 | ||
38 | #pragma pack(1) | 38 | #pragma pack(1) |
39 | struct riff_sized_head { | 39 | struct riff_sized_head { |
40 | fourcc_type fourcc; | 40 | fourcc_type fourcc; |
41 | uint32_t size; | 41 | uint32_t size; |
42 | }; | 42 | }; |
43 | #pragma pack() | 43 | #pragma pack() |
44 | 44 | ||
45 | class exceptional_success : public std::exception { }; | 45 | class exceptional_success : public std::exception { }; |
46 | 46 | ||
47 | struct riff { | 47 | struct riff { |
48 | struct chunk_type { | 48 | struct chunk_type { |
49 | riff_sized_head head; | 49 | riff_sized_head head; |
50 | uint32_t left; | 50 | uint32_t left; |
51 | 51 | ||
52 | chunk_type(riff& r) { | 52 | chunk_type(riff& r) { |
53 | r.read(&head); | 53 | r.read(&head); |
54 | left = head.size; | 54 | left = head.size; |
55 | } | 55 | } |
56 | }; | 56 | }; |
57 | 57 | ||
58 | std::istream *in; | 58 | std::istream *in; |
59 | typedef std::list<chunk_type> chunks_type; | 59 | typedef std::list<chunk_type> chunks_type; |
60 | chunks_type chunks; | 60 | chunks_type chunks; |
61 | 61 | ||
62 | riff(std::istream& i) : in(&i) { } | 62 | riff(std::istream& i) : in(&i) { } |
63 | 63 | ||
64 | protected: | 64 | protected: |
65 | 65 | ||
66 | int begin_chunk() { | 66 | int begin_chunk() { |
67 | chunks.push_back( chunk_type(*this) ); | 67 | chunks.push_back( chunk_type(*this) ); |
68 | return chunks.size(); | 68 | return chunks.size(); |
69 | } | 69 | } |
70 | void end_chunk(int level) { | 70 | void end_chunk(int level) { |
71 | assert(in); assert(chunks.size()==level); | 71 | assert(in); assert(chunks.size()==level); |
72 | std::streamsize o = chunks.back().left; | 72 | std::streamsize o = chunks.back().left; |
73 | chunks.pop_back(); | 73 | chunks.pop_back(); |
74 | if(!o) return; | 74 | if(!o) return; |
75 | in->seekg(o,std::ios::cur); | 75 | in->seekg(o,std::ios::cur); |
76 | for(chunks_type::iterator i=chunks.begin(),ie=chunks.end() ;i!=ie; (i++)->left -= o) ; | 76 | for(chunks_type::iterator i=chunks.begin(),ie=chunks.end() ;i!=ie; (i++)->left -= o) ; |
77 | } | 77 | } |
78 | 78 | ||
79 | void read(void *p,size_t n) { | 79 | void read(void *p,size_t n) { |
80 | assert(in); | 80 | assert(in); |
81 | if( (!chunks.empty()) && chunks.back().left < n) | 81 | if( (!chunks.empty()) && chunks.back().left < n) |
82 | throw std::runtime_error("attempt to read beyond the end of chunk"); | 82 | throw std::runtime_error("attempt to read beyond the end of chunk"); |
83 | if(!in->read((char*)p,n)) | 83 | if(!in->read((char*)p,n)) |
84 | throw std::runtime_error("failed to read()"); | 84 | throw std::runtime_error("failed to read()"); |
85 | std::streamsize gc = in->gcount(); | 85 | std::streamsize gc = in->gcount(); |
86 | for(chunks_type::iterator i=chunks.begin(),ie=chunks.end();i!=ie;++i) { | 86 | for(chunks_type::iterator i=chunks.begin(),ie=chunks.end();i!=ie;++i) { |
87 | i->left -= gc; assert(i->left >= 0); | 87 | i->left -= gc; assert(i->left >= 0); |
88 | } | 88 | } |
89 | if(gc!=n) throw std::runtime_error("incomplete read()"); | 89 | if(gc!=n) throw std::runtime_error("incomplete read()"); |
90 | } | 90 | } |
91 | 91 | ||
92 | template<typename T> void read(T* v) { read(v,sizeof(*v)); } | 92 | template<typename T> void read(T* v) { read(v,sizeof(*v)); } |
93 | 93 | ||
94 | friend class scoped_chunk; | 94 | friend class scoped_chunk; |
95 | 95 | ||
96 | }; | 96 | }; |
97 | 97 | ||
98 | struct scoped_chunk { | 98 | struct scoped_chunk { |
99 | riff& rs; | 99 | riff& rs; |
100 | int level; | 100 | int level; |
101 | riff::chunks_type::reverse_iterator chunk_iterator; | 101 | riff::chunks_type::reverse_iterator chunk_iterator; |
102 | 102 | ||
103 | scoped_chunk(riff& rs_) : rs(rs_), level(rs.begin_chunk()), chunk_iterator(rs.chunks.rbegin()) { } | 103 | scoped_chunk(riff& rs_) : rs(rs_), level(rs.begin_chunk()), chunk_iterator(rs.chunks.rbegin()) { } |
104 | ~scoped_chunk() { rs.end_chunk(level); } | 104 | ~scoped_chunk() { rs.end_chunk(level); } |
105 | 105 | ||
106 | riff::chunk_type& chunk() { return *chunk_iterator; } | 106 | riff::chunk_type& chunk() { return *chunk_iterator; } |
107 | 107 | ||
108 | fourcc_type get_chunk_id() { return chunk().head.fourcc; } | 108 | fourcc_type get_chunk_id() { return chunk().head.fourcc; } |
109 | bool has(uint32_t bytes=1) { return chunk().left >= bytes; } | 109 | bool has(uint32_t bytes=1) { return chunk().left >= bytes; } |
110 | 110 | ||
111 | template<typename T> T read() { T rv; rs.read(&rv); return rv; } | 111 | template<typename T> T read() { T rv; rs.read(&rv); return rv; } |
112 | template<typename T> void read(T& t) { rs.read(&t); } | 112 | template<typename T> void read(T& t) { rs.read(&t); } |
113 | void read(void *p,size_t n) { rs.read(p,n); } | 113 | void read(void *p,size_t n) { rs.read(p,n); } |
114 | 114 | ||