/src/libpagemaker/src/lib/libpagemaker_utils.cpp
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* |
3 | | * This file is part of the libpagemaker project. |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | | */ |
9 | | |
10 | | #include "libpagemaker_utils.h" |
11 | | |
12 | | #include <cassert> |
13 | | #include <cstdarg> |
14 | | |
15 | | namespace libpagemaker |
16 | | { |
17 | | |
18 | | namespace |
19 | | { |
20 | | |
21 | | void checkStream(const RVNGInputStreamPtr &input) |
22 | 1.72M | { |
23 | 1.72M | if (!input || input->isEnd()) |
24 | 0 | throw EndOfStreamException(); |
25 | 1.72M | } |
26 | | |
27 | | struct SeekFailedException : public PMDStreamException {}; |
28 | | |
29 | | } |
30 | | |
31 | | #ifdef DEBUG |
32 | | void debugPrint(const char *const format, ...) |
33 | | { |
34 | | va_list args; |
35 | | va_start(args, format); |
36 | | std::vfprintf(stderr, format, args); |
37 | | va_end(args); |
38 | | } |
39 | | #endif |
40 | | |
41 | | uint8_t readU8(const RVNGInputStreamPtr &input, bool /* bigEndian */) |
42 | 69 | { |
43 | 69 | checkStream(input); |
44 | | |
45 | 69 | unsigned long numBytesRead; |
46 | 69 | uint8_t const *p = input->read(sizeof(uint8_t), numBytesRead); |
47 | | |
48 | 69 | if (p && numBytesRead == sizeof(uint8_t)) |
49 | 69 | return *(uint8_t const *)(p); |
50 | 0 | throw EndOfStreamException(); |
51 | 69 | } |
52 | | |
53 | | int8_t readS8(const RVNGInputStreamPtr &input, bool /* bigEndian */) |
54 | 0 | { |
55 | 0 | return static_cast<int8_t>(readU8(input)); |
56 | 0 | } |
57 | | |
58 | | uint16_t readU16(const RVNGInputStreamPtr &input, bool bigEndian) |
59 | 1.03M | { |
60 | 1.03M | checkStream(input); |
61 | | |
62 | 1.03M | unsigned long numBytesRead; |
63 | 1.03M | uint8_t const *p = input->read(sizeof(uint16_t), numBytesRead); |
64 | | |
65 | 1.03M | if (p && numBytesRead == sizeof(uint16_t)) |
66 | 1.03M | { |
67 | 1.03M | if (bigEndian) |
68 | 1.03M | return static_cast<uint16_t>((uint16_t)p[1]|((uint16_t)p[0]<<8)); |
69 | 3 | return static_cast<uint16_t>((uint16_t)p[0]|((uint16_t)p[1]<<8)); |
70 | 1.03M | } |
71 | 0 | throw EndOfStreamException(); |
72 | 1.03M | } |
73 | | |
74 | | int16_t readS16(const RVNGInputStreamPtr &input, const bool bigEndian) |
75 | 1.03M | { |
76 | 1.03M | return static_cast<int16_t>(readU16(input, bigEndian)); |
77 | 1.03M | } |
78 | | |
79 | | uint32_t readU32(const RVNGInputStreamPtr &input, bool bigEndian) |
80 | 516k | { |
81 | 516k | checkStream(input); |
82 | | |
83 | 516k | unsigned long numBytesRead; |
84 | 516k | uint8_t const *p = input->read(sizeof(uint32_t), numBytesRead); |
85 | | |
86 | 516k | if (p && numBytesRead == sizeof(uint32_t)) |
87 | 516k | { |
88 | 516k | if (bigEndian) |
89 | 516k | return (uint32_t)p[3]|((uint32_t)p[2]<<8)|((uint32_t)p[1]<<16)|((uint32_t)p[0]<<24); |
90 | 0 | return (uint32_t)p[0]|((uint32_t)p[1]<<8)|((uint32_t)p[2]<<16)|((uint32_t)p[3]<<24); |
91 | 516k | } |
92 | 0 | throw EndOfStreamException(); |
93 | 516k | } |
94 | | |
95 | | int32_t readS32(const RVNGInputStreamPtr &input, const bool bigEndian) |
96 | 0 | { |
97 | 0 | return static_cast<int32_t>(readU32(input, bigEndian)); |
98 | 0 | } |
99 | | |
100 | | uint64_t readU64(const RVNGInputStreamPtr &input, bool bigEndian) |
101 | 0 | { |
102 | 0 | checkStream(input); |
103 | |
|
104 | 0 | unsigned long numBytesRead; |
105 | 0 | uint8_t const *p = input->read(sizeof(uint64_t), numBytesRead); |
106 | |
|
107 | 0 | if (p && numBytesRead == sizeof(uint64_t)) |
108 | 0 | { |
109 | 0 | if (bigEndian) |
110 | 0 | return (uint64_t)p[7]|((uint64_t)p[6]<<8)|((uint64_t)p[5]<<16)|((uint64_t)p[4]<<24)|((uint64_t)p[3]<<32)|((uint64_t)p[2]<<40)|((uint64_t)p[1]<<48)|((uint64_t)p[0]<<56); |
111 | 0 | return (uint64_t)p[0]|((uint64_t)p[1]<<8)|((uint64_t)p[2]<<16)|((uint64_t)p[3]<<24)|((uint64_t)p[4]<<32)|((uint64_t)p[5]<<40)|((uint64_t)p[6]<<48)|((uint64_t)p[7]<<56); |
112 | 0 | } |
113 | 0 | throw EndOfStreamException(); |
114 | 0 | } |
115 | | |
116 | | int64_t readS64(const RVNGInputStreamPtr &input, const bool bigEndian) |
117 | 0 | { |
118 | 0 | return static_cast<int64_t>(readU64(input, bigEndian)); |
119 | 0 | } |
120 | | |
121 | | const unsigned char *readNBytes(const RVNGInputStreamPtr &input, const unsigned long numBytes) |
122 | 0 | { |
123 | 0 | checkStream(input); |
124 | |
|
125 | 0 | unsigned long readBytes = 0; |
126 | 0 | const unsigned char *const s = input->read(numBytes, readBytes); |
127 | |
|
128 | 0 | if (numBytes != readBytes) |
129 | 0 | throw EndOfStreamException(); |
130 | | |
131 | 0 | return s; |
132 | 0 | } |
133 | | |
134 | | void skip(const RVNGInputStreamPtr &input, unsigned long numBytes) |
135 | 172k | { |
136 | 172k | checkStream(input); |
137 | | |
138 | 172k | seekRelative(input, static_cast<long>(numBytes)); |
139 | 172k | } |
140 | | |
141 | | void seek(const RVNGInputStreamPtr &input, const unsigned long pos) |
142 | 172k | { |
143 | 172k | if (!input) |
144 | 0 | throw EndOfStreamException(); |
145 | | |
146 | 172k | if (0 != input->seek(static_cast<long>(pos), librevenge::RVNG_SEEK_SET)) |
147 | 6 | throw SeekFailedException(); |
148 | 172k | } |
149 | | |
150 | | void seekRelative(const RVNGInputStreamPtr &input, const long pos) |
151 | 172k | { |
152 | 172k | if (!input) |
153 | 0 | throw EndOfStreamException(); |
154 | | |
155 | 172k | if (0 != input->seek(pos, librevenge::RVNG_SEEK_CUR)) |
156 | 0 | throw SeekFailedException(); |
157 | 172k | } |
158 | | |
159 | | unsigned long getLength(const RVNGInputStreamPtr &input) |
160 | 4 | { |
161 | 4 | if (!input) |
162 | 1 | throw EndOfStreamException(); |
163 | | |
164 | 3 | const long orig = input->tell(); |
165 | 3 | unsigned long end = 0; |
166 | | |
167 | 3 | if (0 == input->seek(0, librevenge::RVNG_SEEK_END)) |
168 | 3 | end = static_cast<unsigned long>(input->tell()); |
169 | 0 | else |
170 | 0 | { |
171 | | // RVNG_SEEK_END does not work. Use the harder way. |
172 | 0 | seek(input, 0); |
173 | 0 | while (!input->isEnd()) |
174 | 0 | { |
175 | 0 | readU8(input); |
176 | 0 | ++end; |
177 | 0 | } |
178 | 0 | } |
179 | | |
180 | 3 | seek(input, orig); |
181 | | |
182 | 3 | return end; |
183 | 4 | } |
184 | | |
185 | | EndOfStreamException::EndOfStreamException() |
186 | 1 | { |
187 | 1 | } |
188 | | |
189 | | } |
190 | | |
191 | | /* vim:set shiftwidth=2 softtabstop=2 expandtab: */ |