Merge lp:~zorba-coders/zorba/feature-base64_streambuf into lp:zorba
- feature-base64_streambuf
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Matthias Brantner |
Approved revision: | 10894 |
Merged at revision: | 10894 |
Proposed branch: | lp:~zorba-coders/zorba/feature-base64_streambuf |
Merge into: | lp:zorba |
Diff against target: |
3118 lines (+2077/-451) 30 files modified
ChangeLog (+2/-1) doc/cxx/examples/binary.cpp (+17/-27) include/zorba/base64.h (+7/-10) include/zorba/base64_stream.h (+325/-0) include/zorba/internal/diagnostic.h (+20/-31) include/zorba/internal/streambuf.h (+40/-0) include/zorba/transcode_stream.h (+11/-15) src/api/CMakeLists.txt (+2/-0) src/api/base64_streambuf.cpp (+249/-0) src/api/base64impl.cpp (+37/-12) src/api/serialization/serializer.cpp (+6/-4) src/api/streambuf.cpp (+48/-0) src/api/transcode_streambuf.cpp (+4/-18) src/diagnostics/diagnostic_en.xml (+0/-8) src/diagnostics/pregenerated/dict_en.cpp (+0/-2) src/runtime/base64/base64_impl.cpp (+4/-7) src/unit_tests/CMakeLists.txt (+2/-0) src/unit_tests/test_base64.cpp (+286/-0) src/unit_tests/test_base64_streambuf.cpp (+141/-0) src/unit_tests/unit_test_list.h (+7/-12) src/unit_tests/unit_tests.cpp (+8/-9) src/util/CMakeLists.txt (+1/-0) src/util/ascii_util.cpp (+34/-0) src/util/ascii_util.h (+23/-0) src/util/base64_util.cpp (+359/-0) src/util/base64_util.h (+361/-0) src/util/icu_streambuf.cpp (+1/-1) src/util/string/rstring.h (+1/-1) src/zorbatypes/binary.cpp (+78/-287) src/zorbatypes/binary.h (+3/-6) |
To merge this branch: | bzr merge lp:~zorba-coders/zorba/feature-base64_streambuf |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Matthias Brantner | Approve | ||
Paul J. Lucas | Approve | ||
Review via email: mp+111984@code.launchpad.net |
Commit message
Added base64::streambuf class and replaced horribly inefficient base64 code.
Description of the change
Added base64::streambuf class and replaced horribly inefficient base64 code.
Paul J. Lucas (paul-lucas) : | # |
Matthias Brantner (matthias-brantner) wrote : | # |
Paul J. Lucas (paul-lucas) wrote : | # |
> Did the streambuf api (already released in 2.5) change?
No.
Zorba Build Bot (zorba-buildbot) wrote : | # |
Validation queue starting for merge proposal.
Log at: http://
Zorba Build Bot (zorba-buildbot) wrote : | # |
Validation queue job feature-
All tests succeeded!
Zorba Build Bot (zorba-buildbot) wrote : | # |
Voting does not meet specified criteria. Required: Approve > 1, Disapprove < 1, Needs Fixing < 1, Pending < 1. Got: 1 Approve, 1 Needs Information.
Matthias Brantner (matthias-brantner) : | # |
Zorba Build Bot (zorba-buildbot) wrote : | # |
Validation queue starting for merge proposal.
Log at: http://
Zorba Build Bot (zorba-buildbot) wrote : | # |
Validation queue job feature-
All tests succeeded!
Preview Diff
1 | === modified file 'ChangeLog' | |||
2 | --- ChangeLog 2012-06-25 17:16:19 +0000 | |||
3 | +++ ChangeLog 2012-06-26 01:34:26 +0000 | |||
4 | @@ -18,7 +18,8 @@ | |||
5 | 18 | * Fixed bug #867357 (Improved parser error messages) | 18 | * Fixed bug #867357 (Improved parser error messages) |
6 | 19 | * Fixed bug #932314 (non-comparable values must be treated as distinct by | 19 | * Fixed bug #932314 (non-comparable values must be treated as distinct by |
7 | 20 | fn:distinct-values) | 20 | fn:distinct-values) |
9 | 21 | * Fixed bug #991088$ (raise XUST0001 in trycatch with mixed updating and simple clauses) | 21 | * Fixed bug #1015580 (Add base64_streambuf / replace inefficient base64 code) |
10 | 22 | * Fixed bug #9910884 (raise XUST0001 in trycatch with mixed updating and simple clauses) | ||
11 | 22 | * Fixed bug #854506 (ugly type error messages) and partial fix for bug #867008 | 23 | * Fixed bug #854506 (ugly type error messages) and partial fix for bug #867008 |
12 | 23 | * Fixed bug #1008082 (bug in transform expr when a copy var is not used anywhere) | 24 | * Fixed bug #1008082 (bug in transform expr when a copy var is not used anywhere) |
13 | 24 | * Fixed bug #1003023$ (optimizer problems due to common subexpression after | 25 | * Fixed bug #1003023$ (optimizer problems due to common subexpression after |
14 | 25 | 26 | ||
15 | === modified file 'doc/cxx/examples/binary.cpp' | |||
16 | --- doc/cxx/examples/binary.cpp 2012-06-18 10:06:47 +0000 | |||
17 | +++ doc/cxx/examples/binary.cpp 2012-06-26 01:34:26 +0000 | |||
18 | @@ -25,35 +25,25 @@ | |||
19 | 25 | { | 25 | { |
20 | 26 | String lString("Hello Zorba"); | 26 | String lString("Hello Zorba"); |
21 | 27 | String lEncoded = zorba::encoding::Base64::encode(lString); | 27 | String lEncoded = zorba::encoding::Base64::encode(lString); |
24 | 28 | String lExpectedResult("SGVsbG8gWm9yYmE="); | 28 | return lEncoded == "SGVsbG8gWm9yYmE="; |
23 | 29 | return lEncoded == lExpectedResult; | ||
25 | 30 | } | 29 | } |
26 | 31 | 30 | ||
27 | 32 | bool | 31 | bool |
28 | 33 | decode_example() | 32 | decode_example() |
29 | 34 | { | 33 | { |
55 | 35 | String lEncoded("SGVsbG8gWm9yYmE="); | 34 | String lEncoded("SGVsbG8gWm9yYmE="); |
56 | 36 | String lDecoded = zorba::encoding::Base64::decode(lEncoded); | 35 | String lDecoded = zorba::encoding::Base64::decode(lEncoded); |
57 | 37 | return lDecoded == "Hello Zorba"; | 36 | return lDecoded == "Hello Zorba"; |
58 | 38 | 37 | } | |
59 | 39 | } | 38 | |
60 | 40 | 39 | int binary(int argc, char* argv[]) { | |
61 | 41 | int | 40 | |
62 | 42 | binary(int argc, char* argv[]) | 41 | std::cout << "executing example 1 (Base64 encoding of String)" << std::endl; |
63 | 43 | { | 42 | if (!encode_example()) return 1; |
64 | 44 | 43 | ||
65 | 45 | bool res = false; | 44 | std::cout << "executing example 2 (decoding of Base64 encoded String)" << std::endl; |
66 | 46 | 45 | if (!decode_example()) return 1; | |
67 | 47 | std::cout << "executing example 1 (Base64 encoding of String)" << std::endl; | 46 | |
68 | 48 | res = encode_example(); | 47 | return 0; |
69 | 49 | if (!res) return 1; | 48 | } |
70 | 50 | std::cout << std::endl; | 49 | /* vim:set et sw=2 ts=2: */ |
46 | 51 | |||
47 | 52 | std::cout << "executing example 2 (decoding of Base64 encoded String)" << std::endl; | ||
48 | 53 | res = decode_example(); | ||
49 | 54 | if (!res) return 1; | ||
50 | 55 | std::cout << std::endl; | ||
51 | 56 | |||
52 | 57 | return 0; | ||
53 | 58 | |||
54 | 59 | } | ||
71 | 60 | 50 | ||
72 | === modified file 'include/zorba/base64.h' | |||
73 | --- include/zorba/base64.h 2012-06-18 10:06:47 +0000 | |||
74 | +++ include/zorba/base64.h 2012-06-26 01:34:26 +0000 | |||
75 | @@ -21,12 +21,11 @@ | |||
76 | 21 | #include <zorba/config.h> | 21 | #include <zorba/config.h> |
77 | 22 | #include <zorba/zorba_string.h> | 22 | #include <zorba/zorba_string.h> |
78 | 23 | 23 | ||
80 | 24 | namespace zorba { namespace encoding { | 24 | namespace zorba { |
81 | 25 | namespace encoding { | ||
82 | 25 | 26 | ||
84 | 26 | class ZORBA_DLL_PUBLIC Base64 | 27 | struct ZORBA_DLL_PUBLIC Base64 |
85 | 27 | { | 28 | { |
86 | 28 | public: | ||
87 | 29 | |||
88 | 30 | static String | 29 | static String |
89 | 31 | encode(const String& aString); | 30 | encode(const String& aString); |
90 | 32 | 31 | ||
91 | @@ -38,12 +37,10 @@ | |||
92 | 38 | 37 | ||
93 | 39 | static String | 38 | static String |
94 | 40 | decode(std::istream& aStream); | 39 | decode(std::istream& aStream); |
95 | 41 | |||
96 | 42 | }; | 40 | }; |
97 | 43 | 41 | ||
103 | 44 | } /* end namespace encoding */ | 42 | } // namespace encoding |
104 | 45 | 43 | } // namespace zorba | |
105 | 46 | } /* end namespace zorba */ | 44 | |
106 | 47 | 45 | #endif /* ZORBA_BASE64_API_H */ | |
102 | 48 | #endif | ||
107 | 49 | /* vim:set et sw=2 ts=2: */ | 46 | /* vim:set et sw=2 ts=2: */ |
108 | 50 | 47 | ||
109 | === added file 'include/zorba/base64_stream.h' | |||
110 | --- include/zorba/base64_stream.h 1970-01-01 00:00:00 +0000 | |||
111 | +++ include/zorba/base64_stream.h 2012-06-26 01:34:26 +0000 | |||
112 | @@ -0,0 +1,325 @@ | |||
113 | 1 | /* | ||
114 | 2 | * Copyright 2006-2008 The FLWOR Foundation. | ||
115 | 3 | * | ||
116 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
117 | 5 | * you may not use this file except in compliance with the License. | ||
118 | 6 | * You may obtain a copy of the License at | ||
119 | 7 | * | ||
120 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
121 | 9 | * | ||
122 | 10 | * Unless required by applicable law or agreed to in writing, software | ||
123 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
124 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
125 | 13 | * See the License for the specific language governing permissions and | ||
126 | 14 | * limitations under the License. | ||
127 | 15 | */ | ||
128 | 16 | |||
129 | 17 | #ifndef ZORBA_BASE64_STREAM_API_H | ||
130 | 18 | #define ZORBA_BASE64_STREAM_API_H | ||
131 | 19 | |||
132 | 20 | #include <streambuf> | ||
133 | 21 | |||
134 | 22 | #include <zorba/config.h> | ||
135 | 23 | #include <zorba/internal/streambuf.h> | ||
136 | 24 | |||
137 | 25 | namespace zorba { | ||
138 | 26 | namespace base64 { | ||
139 | 27 | |||
140 | 28 | /////////////////////////////////////////////////////////////////////////////// | ||
141 | 29 | |||
142 | 30 | /** | ||
143 | 31 | * A %base64::streambuf is-a std::streambuf for encoding to and decoding from | ||
144 | 32 | * Base64 on-the-fly. | ||
145 | 33 | * | ||
146 | 34 | * To use it, replace a stream's streambuf: | ||
147 | 35 | * \code | ||
148 | 36 | * istream is; | ||
149 | 37 | * // ... | ||
150 | 38 | * base64::streambuf b64buf( is.rdbuf() ); | ||
151 | 39 | * is.ios::rdbuf( &b64buf ); | ||
152 | 40 | * \endcode | ||
153 | 41 | * Note that the %base64::streambuf must exist for as long as it's being used | ||
154 | 42 | * by the stream. If you are replacing the streabuf for a stream you did not | ||
155 | 43 | * create, you should set it back to the original streambuf: | ||
156 | 44 | * \code | ||
157 | 45 | * void f( ostream &os ) { | ||
158 | 46 | * base64::streambuf b64buf( os.rdbuf() ); | ||
159 | 47 | * try { | ||
160 | 48 | * os.ios::rdbuf( &b64buf ); | ||
161 | 49 | * // ... | ||
162 | 50 | * } | ||
163 | 51 | * catch ( ... ) { | ||
164 | 52 | * os.ios::rdbuf( b64buf.orig_streambuf() ); | ||
165 | 53 | * throw; | ||
166 | 54 | * } | ||
167 | 55 | * os.ios::rdbuf( b64buf.orig_streambuf() ); | ||
168 | 56 | * } | ||
169 | 57 | * \endcode | ||
170 | 58 | * Alternatively, you may wish to use either \c attach(), \c auto_attach, or | ||
171 | 59 | * \c base64::stream instead. | ||
172 | 60 | * | ||
173 | 61 | * \b Note: due to the nature of Base64-encoding, when writing, you \e must | ||
174 | 62 | * ensure that the streambuf is flushed (by calling either \c pubsync() on the | ||
175 | 63 | * streambuf or \c flush() on the owning stream) when done. | ||
176 | 64 | * | ||
177 | 65 | * While %base64::streambuf does support seeking, the positions are relative | ||
178 | 66 | * to the original byte stream. | ||
179 | 67 | */ | ||
180 | 68 | class ZORBA_DLL_PUBLIC streambuf : public std::streambuf { | ||
181 | 69 | public: | ||
182 | 70 | /** | ||
183 | 71 | * Constructs a %base64::streambuf. | ||
184 | 72 | * | ||
185 | 73 | * @param orig The original streambuf to read/write from/to. | ||
186 | 74 | * @throws std::invalid_argument if is not supported or \a orig is null. | ||
187 | 75 | */ | ||
188 | 76 | streambuf( std::streambuf *orig ); | ||
189 | 77 | |||
190 | 78 | /** | ||
191 | 79 | * Destructs a %base64::streambuf. | ||
192 | 80 | */ | ||
193 | 81 | ~streambuf(); | ||
194 | 82 | |||
195 | 83 | /** | ||
196 | 84 | * Gets the original streambuf. | ||
197 | 85 | * | ||
198 | 86 | * @return said streambuf. | ||
199 | 87 | */ | ||
200 | 88 | std::streambuf* orig_streambuf() const { | ||
201 | 89 | return orig_buf_; | ||
202 | 90 | } | ||
203 | 91 | |||
204 | 92 | protected: | ||
205 | 93 | void imbue( std::locale const& ); | ||
206 | 94 | pos_type seekoff( off_type, std::ios_base::seekdir, std::ios_base::openmode ); | ||
207 | 95 | pos_type seekpos( pos_type, std::ios_base::openmode ); | ||
208 | 96 | std::streambuf* setbuf( char_type*, std::streamsize ); | ||
209 | 97 | std::streamsize showmanyc(); | ||
210 | 98 | int sync(); | ||
211 | 99 | int_type overflow( int_type ); | ||
212 | 100 | int_type pbackfail( int_type ); | ||
213 | 101 | int_type underflow(); | ||
214 | 102 | std::streamsize xsgetn( char_type*, std::streamsize ); | ||
215 | 103 | std::streamsize xsputn( char_type const*, std::streamsize ); | ||
216 | 104 | |||
217 | 105 | private: | ||
218 | 106 | std::streambuf *orig_buf_; | ||
219 | 107 | |||
220 | 108 | char gbuf_[3]; | ||
221 | 109 | char pbuf_[3]; | ||
222 | 110 | int plen_; | ||
223 | 111 | |||
224 | 112 | void clear(); | ||
225 | 113 | void resetg(); | ||
226 | 114 | void resetp(); | ||
227 | 115 | void writep(); | ||
228 | 116 | |||
229 | 117 | // forbid | ||
230 | 118 | streambuf( streambuf const& ); | ||
231 | 119 | streambuf& operator=( streambuf const& ); | ||
232 | 120 | }; | ||
233 | 121 | |||
234 | 122 | /////////////////////////////////////////////////////////////////////////////// | ||
235 | 123 | |||
236 | 124 | } // namespace base64 | ||
237 | 125 | |||
238 | 126 | namespace internal { | ||
239 | 127 | namespace base64 { | ||
240 | 128 | |||
241 | 129 | ZORBA_DLL_PUBLIC | ||
242 | 130 | std::streambuf* alloc_streambuf( std::streambuf *orig ); | ||
243 | 131 | |||
244 | 132 | ZORBA_DLL_PUBLIC | ||
245 | 133 | int get_streambuf_index(); | ||
246 | 134 | |||
247 | 135 | } // namespace base64 | ||
248 | 136 | } // namespace internal | ||
249 | 137 | |||
250 | 138 | namespace base64 { | ||
251 | 139 | |||
252 | 140 | /////////////////////////////////////////////////////////////////////////////// | ||
253 | 141 | |||
254 | 142 | /** | ||
255 | 143 | * Attaches a base64::streambuf to a stream. Unlike using a | ||
256 | 144 | * base64::streambuf directly, this function will create the streambuf, | ||
257 | 145 | * attach it to the stream, and manage it for the lifetime of the stream | ||
258 | 146 | * automatically. | ||
259 | 147 | * | ||
260 | 148 | * @param ios The stream to attach the base64::streambuf to. If the stream | ||
261 | 149 | * already has a base64::streambuf attached to it, this function does | ||
262 | 150 | * nothing. | ||
263 | 151 | */ | ||
264 | 152 | template<typename charT,typename Traits> inline | ||
265 | 153 | void attach( std::basic_ios<charT,Traits> &ios ) { | ||
266 | 154 | int const index = internal::base64::get_streambuf_index(); | ||
267 | 155 | void *&pword = ios.pword( index ); | ||
268 | 156 | if ( !pword ) { | ||
269 | 157 | std::streambuf *const buf = | ||
270 | 158 | internal::base64::alloc_streambuf( ios.rdbuf() ); | ||
271 | 159 | ios.rdbuf( buf ); | ||
272 | 160 | pword = buf; | ||
273 | 161 | ios.register_callback( internal::stream_callback, index ); | ||
274 | 162 | } | ||
275 | 163 | } | ||
276 | 164 | |||
277 | 165 | /** | ||
278 | 166 | * Detaches a previously attached base64::streambuf from a stream. The | ||
279 | 167 | * streambuf is destroyed and the stream's original streambuf is restored. | ||
280 | 168 | * | ||
281 | 169 | * @param ios The stream to detach the base64::streambuf from. If the | ||
282 | 170 | * stream doesn't have a base64::streambuf attached to it, this function | ||
283 | 171 | * does nothing. | ||
284 | 172 | */ | ||
285 | 173 | template<typename charT,typename Traits> inline | ||
286 | 174 | void detach( std::basic_ios<charT,Traits> &ios ) { | ||
287 | 175 | int const index = internal::base64::get_streambuf_index(); | ||
288 | 176 | if ( streambuf *const buf = static_cast<streambuf*>( ios.pword( index ) ) ) { | ||
289 | 177 | ios.pword( index ) = 0; | ||
290 | 178 | ios.rdbuf( buf->orig_streambuf() ); | ||
291 | 179 | internal::dealloc_streambuf( buf ); | ||
292 | 180 | } | ||
293 | 181 | } | ||
294 | 182 | |||
295 | 183 | /** | ||
296 | 184 | * Checks whether the given stream has a base64::streambuf attached. | ||
297 | 185 | * | ||
298 | 186 | * @param ios The stream to check. | ||
299 | 187 | * @return \c true only if a base64::streambuf is attached. | ||
300 | 188 | */ | ||
301 | 189 | template<typename charT,typename Traits> inline | ||
302 | 190 | bool is_attached( std::basic_ios<charT,Traits> &ios ) { | ||
303 | 191 | return !!ios.pword( internal::base64::get_streambuf_index() ); | ||
304 | 192 | } | ||
305 | 193 | |||
306 | 194 | /** | ||
307 | 195 | * A %base64::auto_attach is a class that attaches a base64::streambuf to | ||
308 | 196 | * a stream and automatically detaches it when the %auto_attach object is | ||
309 | 197 | * destroyed. | ||
310 | 198 | * \code | ||
311 | 199 | * void f( ostream &os ) { | ||
312 | 200 | * base64::auto_attach<ostream> const raii( os, "ISO-8859-1" ); | ||
313 | 201 | * // ... | ||
314 | 202 | * } | ||
315 | 203 | * \endcode | ||
316 | 204 | * A %base64::auto_attach is useful for streams not created by you. | ||
317 | 205 | * | ||
318 | 206 | * @see http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization | ||
319 | 207 | */ | ||
320 | 208 | template<class StreamType> | ||
321 | 209 | class auto_attach { | ||
322 | 210 | public: | ||
323 | 211 | /** | ||
324 | 212 | * Constructs an %auto_attach object calling attach() on the given stream. | ||
325 | 213 | * | ||
326 | 214 | * @param stream The stream to attach the base64::streambuf to. If the | ||
327 | 215 | * stream already has a base64::streambuf attached to it, this contructor | ||
328 | 216 | * does nothing. | ||
329 | 217 | */ | ||
330 | 218 | auto_attach( StreamType &stream ) : stream_( stream ) { | ||
331 | 219 | attach( stream ); | ||
332 | 220 | } | ||
333 | 221 | |||
334 | 222 | /** | ||
335 | 223 | * Destroys this %auto_attach object calling detach() on the previously | ||
336 | 224 | * attached stream. | ||
337 | 225 | */ | ||
338 | 226 | ~auto_attach() { | ||
339 | 227 | detach( stream_ ); | ||
340 | 228 | } | ||
341 | 229 | |||
342 | 230 | private: | ||
343 | 231 | StreamType &stream_; | ||
344 | 232 | }; | ||
345 | 233 | |||
346 | 234 | /////////////////////////////////////////////////////////////////////////////// | ||
347 | 235 | |||
348 | 236 | /** | ||
349 | 237 | * A %base64::stream is used to wrap a C++ standard I/O stream with a | ||
350 | 238 | * base64::streambuf so that encoding/decoding and the management of the | ||
351 | 239 | * streambuf happens automatically. | ||
352 | 240 | * | ||
353 | 241 | * A %base64::stream is useful for streams created by you. | ||
354 | 242 | * | ||
355 | 243 | * @tparam StreamType The I/O stream class type to wrap. It must be a concrete | ||
356 | 244 | * stream class. | ||
357 | 245 | */ | ||
358 | 246 | template<class StreamType> | ||
359 | 247 | class stream : public StreamType { | ||
360 | 248 | public: | ||
361 | 249 | /** | ||
362 | 250 | * Constructs a %base64::stream. | ||
363 | 251 | */ | ||
364 | 252 | stream() : | ||
365 | 253 | #ifdef WIN32 | ||
366 | 254 | # pragma warning( push ) | ||
367 | 255 | # pragma warning( disable : 4355 ) | ||
368 | 256 | #endif /* WIN32 */ | ||
369 | 257 | b64buf_( this->rdbuf() ) | ||
370 | 258 | #ifdef WIN32 | ||
371 | 259 | # pragma warning( pop ) | ||
372 | 260 | #endif /* WIN32 */ | ||
373 | 261 | { | ||
374 | 262 | init(); | ||
375 | 263 | } | ||
376 | 264 | |||
377 | 265 | /** | ||
378 | 266 | * Constructs a %stream. | ||
379 | 267 | * | ||
380 | 268 | * @tparam StreamArgType The type of the first argument of \a StreamType's | ||
381 | 269 | * constructor. | ||
382 | 270 | * @param stream_arg The argument to pass as the first argument to | ||
383 | 271 | * \a StreamType's constructor. | ||
384 | 272 | */ | ||
385 | 273 | template<typename StreamArgType> | ||
386 | 274 | stream( StreamArgType stream_arg ) : | ||
387 | 275 | StreamType( stream_arg ), | ||
388 | 276 | #ifdef WIN32 | ||
389 | 277 | # pragma warning( push ) | ||
390 | 278 | # pragma warning( disable : 4355 ) | ||
391 | 279 | #endif /* WIN32 */ | ||
392 | 280 | b64buf_( this->rdbuf() ) | ||
393 | 281 | #ifdef WIN32 | ||
394 | 282 | # pragma warning( pop ) | ||
395 | 283 | #endif /* WIN32 */ | ||
396 | 284 | { | ||
397 | 285 | init(); | ||
398 | 286 | } | ||
399 | 287 | |||
400 | 288 | /** | ||
401 | 289 | * Constructs a %base64::stream. | ||
402 | 290 | * | ||
403 | 291 | * @tparam StreamArgType The type of the first argument of \a StreamType's | ||
404 | 292 | * constructor. | ||
405 | 293 | * @param stream_arg The argument to pass as the first argument to | ||
406 | 294 | * \a StreamType's constructor. | ||
407 | 295 | * @param mode The open-mode to pass to \a StreamType's constructor. | ||
408 | 296 | */ | ||
409 | 297 | template<typename StreamArgType> | ||
410 | 298 | stream( StreamArgType stream_arg, std::ios_base::openmode mode ) : | ||
411 | 299 | StreamType( stream_arg, mode ), | ||
412 | 300 | #ifdef WIN32 | ||
413 | 301 | # pragma warning( push ) | ||
414 | 302 | # pragma warning( disable : 4355 ) | ||
415 | 303 | #endif /* WIN32 */ | ||
416 | 304 | b64buf_( this->rdbuf() ) | ||
417 | 305 | #ifdef WIN32 | ||
418 | 306 | # pragma warning( pop ) | ||
419 | 307 | #endif /* WIN32 */ | ||
420 | 308 | { | ||
421 | 309 | init(); | ||
422 | 310 | } | ||
423 | 311 | |||
424 | 312 | private: | ||
425 | 313 | streambuf b64buf_; | ||
426 | 314 | |||
427 | 315 | void init() { | ||
428 | 316 | this->std::ios::rdbuf( &b64buf_ ); | ||
429 | 317 | } | ||
430 | 318 | }; | ||
431 | 319 | |||
432 | 320 | /////////////////////////////////////////////////////////////////////////////// | ||
433 | 321 | |||
434 | 322 | } // namespace base64 | ||
435 | 323 | } // namespace zorba | ||
436 | 324 | #endif /* ZORBA_BASE64_STREAM_API_H */ | ||
437 | 325 | /* vim:set et sw=2 ts=2: */ | ||
438 | 0 | 326 | ||
439 | === modified file 'include/zorba/internal/diagnostic.h' | |||
440 | --- include/zorba/internal/diagnostic.h 2012-06-18 10:06:47 +0000 | |||
441 | +++ include/zorba/internal/diagnostic.h 2012-06-26 01:34:26 +0000 | |||
442 | @@ -42,7 +42,7 @@ | |||
443 | 42 | /////////////////////////////////////////////////////////////////////////////// | 42 | /////////////////////////////////////////////////////////////////////////////// |
444 | 43 | 43 | ||
445 | 44 | /** | 44 | /** |
447 | 45 | * A %location hold the file location of an error. | 45 | * A %location holds the file location of an error. |
448 | 46 | */ | 46 | */ |
449 | 47 | class ZORBA_DLL_PUBLIC location { | 47 | class ZORBA_DLL_PUBLIC location { |
450 | 48 | public: | 48 | public: |
451 | @@ -71,21 +71,17 @@ | |||
452 | 71 | * Constructs a %location. | 71 | * Constructs a %location. |
453 | 72 | * | 72 | * |
454 | 73 | * @param file The name of the file where the error occurred. | 73 | * @param file The name of the file where the error occurred. |
457 | 74 | * @param line The line number of the file where the expression that | 74 | * @param line The line number of the file where the expression that raises |
458 | 75 | * raises the error begins. | 75 | * the error begins. |
459 | 76 | * @param column The column number, if any, of the file where the expression | 76 | * @param column The column number, if any, of the file where the expression |
465 | 77 | * that raises the error begins. | 77 | * that raises the error begins. |
466 | 78 | * @param line_end The end line number, if any, of the file where the expression | 78 | * @param line_end The end line number, if any, of the file where the |
467 | 79 | * causing the error ends. | 79 | * expression causing the error ends. |
468 | 80 | * @param column_end The end column number, if any, of the file where | 80 | * @param column_end The end column number, if any, of the file where the |
469 | 81 | * the xpression causing the error ends. | 81 | * xpression causing the error ends. |
470 | 82 | */ | 82 | */ |
477 | 83 | location( | 83 | location( char const *file, line_type line, column_type column = 0, |
478 | 84 | char const *file, | 84 | line_type line_end = 0, column_type column_end = 0 ) : |
473 | 85 | line_type line, | ||
474 | 86 | column_type column = 0, | ||
475 | 87 | line_type line_end = 0, | ||
476 | 88 | column_type column_end = 0) : | ||
479 | 89 | file_( file ), line_( line ), column_( column ), | 85 | file_( file ), line_( line ), column_( column ), |
480 | 90 | line_end_( line_end ), column_end_( column_end ) | 86 | line_end_( line_end ), column_end_( column_end ) |
481 | 91 | { | 87 | { |
482 | @@ -97,19 +93,16 @@ | |||
483 | 97 | * @tparam StringType The string type for \a file. | 93 | * @tparam StringType The string type for \a file. |
484 | 98 | * @param file The name of the file where the error occurred. | 94 | * @param file The name of the file where the error occurred. |
485 | 99 | * @param line The line number of the file where the error occurred. | 95 | * @param line The line number of the file where the error occurred. |
491 | 100 | * @param column The column number, if any, of the file where the error occurred. | 96 | * @param column The column number, if any, of the file where the error |
492 | 101 | * @param line_end The end line number, if any, of the file where the expression | 97 | * occurred. |
493 | 102 | * causing the error ends. | 98 | * @param line_end The end line number, if any, of the file where the |
494 | 103 | * @param column_end The end column number, if any, of the file where | 99 | * expression causing the error ends. |
495 | 104 | * the xpression causing the error ends. | 100 | * @param column_end The end column number, if any, of the file where the |
496 | 101 | * xpression causing the error ends. | ||
497 | 105 | */ | 102 | */ |
498 | 106 | template<class StringType> | 103 | template<class StringType> |
505 | 107 | location( | 104 | location( StringType const &file, line_type line, column_type column = 0, |
506 | 108 | StringType const &file, | 105 | line_type line_end = 0, column_type column_end = 0 ) : |
501 | 109 | line_type line, | ||
502 | 110 | column_type column = 0, | ||
503 | 111 | line_type line_end = 0, | ||
504 | 112 | column_type column_end = 0) : | ||
507 | 113 | file_( file.c_str() ), line_( line ), column_( column ), | 106 | file_( file.c_str() ), line_( line ), column_( column ), |
508 | 114 | line_end_( line_end ), column_end_( column_end ) | 107 | line_end_( line_end ), column_end_( column_end ) |
509 | 115 | { | 108 | { |
510 | @@ -189,12 +182,8 @@ | |||
511 | 189 | * @param column_end The column number, if any, where the error ends. | 182 | * @param column_end The column number, if any, where the error ends. |
512 | 190 | * occurred. | 183 | * occurred. |
513 | 191 | */ | 184 | */ |
520 | 192 | void set( | 185 | void set( char const *file, line_type line, column_type column = 0, |
521 | 193 | char const *file, | 186 | line_type line_end = 0, column_type column_end = 0 ) { |
516 | 194 | line_type line, | ||
517 | 195 | column_type column = 0, | ||
518 | 196 | line_type line_end = 0, | ||
519 | 197 | column_type column_end = 0) { | ||
522 | 198 | file_ = file; | 187 | file_ = file; |
523 | 199 | line_ = line; | 188 | line_ = line; |
524 | 200 | column_ = column; | 189 | column_ = column; |
525 | 201 | 190 | ||
526 | === added file 'include/zorba/internal/streambuf.h' | |||
527 | --- include/zorba/internal/streambuf.h 1970-01-01 00:00:00 +0000 | |||
528 | +++ include/zorba/internal/streambuf.h 2012-06-26 01:34:26 +0000 | |||
529 | @@ -0,0 +1,40 @@ | |||
530 | 1 | /* | ||
531 | 2 | * Copyright 2006-2008 The FLWOR Foundation. | ||
532 | 3 | * | ||
533 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
534 | 5 | * you may not use this file except in compliance with the License. | ||
535 | 6 | * You may obtain a copy of the License at | ||
536 | 7 | * | ||
537 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
538 | 9 | * | ||
539 | 10 | * Unless required by applicable law or agreed to in writing, software | ||
540 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
541 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
542 | 13 | * See the License for the specific language governing permissions and | ||
543 | 14 | * limitations under the License. | ||
544 | 15 | */ | ||
545 | 16 | |||
546 | 17 | #ifndef ZORBA_INTERNAL_STREAMBUF_H | ||
547 | 18 | #define ZORBA_INTERNAL_STREAMBUF_H | ||
548 | 19 | |||
549 | 20 | #include <streambuf> | ||
550 | 21 | |||
551 | 22 | #include <zorba/config.h> | ||
552 | 23 | |||
553 | 24 | namespace zorba { | ||
554 | 25 | namespace internal { | ||
555 | 26 | |||
556 | 27 | /////////////////////////////////////////////////////////////////////////////// | ||
557 | 28 | |||
558 | 29 | ZORBA_DLL_PUBLIC | ||
559 | 30 | void dealloc_streambuf( std::streambuf* ); | ||
560 | 31 | |||
561 | 32 | ZORBA_DLL_PUBLIC | ||
562 | 33 | void stream_callback( std::ios_base::event, std::ios_base&, int index ); | ||
563 | 34 | |||
564 | 35 | /////////////////////////////////////////////////////////////////////////////// | ||
565 | 36 | |||
566 | 37 | } // namespace internal | ||
567 | 38 | } // namespace zorba | ||
568 | 39 | #endif /* ZORBA_INTERNAL_STREAMBUF_H */ | ||
569 | 40 | /* vim:set et sw=2 ts=2: */ | ||
570 | 0 | 41 | ||
571 | === modified file 'include/zorba/transcode_stream.h' | |||
572 | --- include/zorba/transcode_stream.h 2012-06-18 10:06:47 +0000 | |||
573 | +++ include/zorba/transcode_stream.h 2012-06-26 01:34:26 +0000 | |||
574 | @@ -19,10 +19,10 @@ | |||
575 | 19 | 19 | ||
576 | 20 | #include <stdexcept> | 20 | #include <stdexcept> |
577 | 21 | #include <streambuf> | 21 | #include <streambuf> |
578 | 22 | #include <string> | ||
579 | 23 | 22 | ||
580 | 24 | #include <zorba/config.h> | 23 | #include <zorba/config.h> |
581 | 25 | #include <zorba/internal/proxy.h> | 24 | #include <zorba/internal/proxy.h> |
582 | 25 | #include <zorba/internal/streambuf.h> | ||
583 | 26 | #include <zorba/internal/unique_ptr.h> | 26 | #include <zorba/internal/unique_ptr.h> |
584 | 27 | 27 | ||
585 | 28 | namespace zorba { | 28 | namespace zorba { |
586 | @@ -120,20 +120,15 @@ | |||
587 | 120 | } // namespace transcode | 120 | } // namespace transcode |
588 | 121 | 121 | ||
589 | 122 | namespace internal { | 122 | namespace internal { |
597 | 123 | 123 | namespace transcode { | |
598 | 124 | ZORBA_DLL_PUBLIC | 124 | |
599 | 125 | zorba::transcode::streambuf* | 125 | ZORBA_DLL_PUBLIC |
600 | 126 | alloc_streambuf( char const *charset, std::streambuf *orig ); | 126 | std::streambuf* alloc_streambuf( char const *charset, std::streambuf *orig ); |
594 | 127 | |||
595 | 128 | ZORBA_DLL_PUBLIC | ||
596 | 129 | void dealloc_streambuf( zorba::transcode::streambuf* ); | ||
601 | 130 | 127 | ||
602 | 131 | ZORBA_DLL_PUBLIC | 128 | ZORBA_DLL_PUBLIC |
603 | 132 | int get_streambuf_index(); | 129 | int get_streambuf_index(); |
604 | 133 | 130 | ||
608 | 134 | ZORBA_DLL_PUBLIC | 131 | } // transcode |
606 | 135 | void stream_callback( std::ios_base::event, std::ios_base&, int index ); | ||
607 | 136 | |||
609 | 137 | } // namespace internal | 132 | } // namespace internal |
610 | 138 | 133 | ||
611 | 139 | namespace transcode { | 134 | namespace transcode { |
612 | @@ -153,10 +148,11 @@ | |||
613 | 153 | */ | 148 | */ |
614 | 154 | template<typename charT,typename Traits> inline | 149 | template<typename charT,typename Traits> inline |
615 | 155 | void attach( std::basic_ios<charT,Traits> &ios, char const *charset ) { | 150 | void attach( std::basic_ios<charT,Traits> &ios, char const *charset ) { |
617 | 156 | int const index = internal::get_streambuf_index(); | 151 | int const index = internal::transcode::get_streambuf_index(); |
618 | 157 | void *&pword = ios.pword( index ); | 152 | void *&pword = ios.pword( index ); |
619 | 158 | if ( !pword ) { | 153 | if ( !pword ) { |
621 | 159 | streambuf *const buf = internal::alloc_streambuf( charset, ios.rdbuf() ); | 154 | std::streambuf *const buf = |
622 | 155 | internal::transcode::alloc_streambuf( charset, ios.rdbuf() ); | ||
623 | 160 | ios.rdbuf( buf ); | 156 | ios.rdbuf( buf ); |
624 | 161 | pword = buf; | 157 | pword = buf; |
625 | 162 | ios.register_callback( internal::stream_callback, index ); | 158 | ios.register_callback( internal::stream_callback, index ); |
626 | @@ -173,7 +169,7 @@ | |||
627 | 173 | */ | 169 | */ |
628 | 174 | template<typename charT,typename Traits> inline | 170 | template<typename charT,typename Traits> inline |
629 | 175 | void detach( std::basic_ios<charT,Traits> &ios ) { | 171 | void detach( std::basic_ios<charT,Traits> &ios ) { |
631 | 176 | int const index = internal::get_streambuf_index(); | 172 | int const index = internal::transcode::get_streambuf_index(); |
632 | 177 | if ( streambuf *const buf = static_cast<streambuf*>( ios.pword( index ) ) ) { | 173 | if ( streambuf *const buf = static_cast<streambuf*>( ios.pword( index ) ) ) { |
633 | 178 | ios.pword( index ) = 0; | 174 | ios.pword( index ) = 0; |
634 | 179 | ios.rdbuf( buf->orig_streambuf() ); | 175 | ios.rdbuf( buf->orig_streambuf() ); |
635 | @@ -189,7 +185,7 @@ | |||
636 | 189 | */ | 185 | */ |
637 | 190 | template<typename charT,typename Traits> inline | 186 | template<typename charT,typename Traits> inline |
638 | 191 | bool is_attached( std::basic_ios<charT,Traits> &ios ) { | 187 | bool is_attached( std::basic_ios<charT,Traits> &ios ) { |
640 | 192 | return !!ios.pword( internal::get_streambuf_index() ); | 188 | return !!ios.pword( internal::transcode::get_streambuf_index() ); |
641 | 193 | } | 189 | } |
642 | 194 | 190 | ||
643 | 195 | /** | 191 | /** |
644 | 196 | 192 | ||
645 | === modified file 'src/api/CMakeLists.txt' | |||
646 | --- src/api/CMakeLists.txt 2012-06-18 10:06:47 +0000 | |||
647 | +++ src/api/CMakeLists.txt 2012-06-26 01:34:26 +0000 | |||
648 | @@ -49,6 +49,7 @@ | |||
649 | 49 | fileimpl.cpp | 49 | fileimpl.cpp |
650 | 50 | serializerimpl.cpp | 50 | serializerimpl.cpp |
651 | 51 | base64impl.cpp | 51 | base64impl.cpp |
652 | 52 | base64_streambuf.cpp | ||
653 | 52 | uriimpl.cpp | 53 | uriimpl.cpp |
654 | 53 | uriresolverimpl.cpp | 54 | uriresolverimpl.cpp |
655 | 54 | uri_resolver_wrappers.cpp | 55 | uri_resolver_wrappers.cpp |
656 | @@ -56,6 +57,7 @@ | |||
657 | 56 | zorba_functions.cpp | 57 | zorba_functions.cpp |
658 | 57 | annotationimpl.cpp | 58 | annotationimpl.cpp |
659 | 58 | auditimpl.cpp | 59 | auditimpl.cpp |
660 | 60 | streambuf.cpp | ||
661 | 59 | transcode_streambuf.cpp | 61 | transcode_streambuf.cpp |
662 | 60 | ) | 62 | ) |
663 | 61 | 63 | ||
664 | 62 | 64 | ||
665 | === added file 'src/api/base64_streambuf.cpp' | |||
666 | --- src/api/base64_streambuf.cpp 1970-01-01 00:00:00 +0000 | |||
667 | +++ src/api/base64_streambuf.cpp 2012-06-26 01:34:26 +0000 | |||
668 | @@ -0,0 +1,249 @@ | |||
669 | 1 | /* | ||
670 | 2 | * Copyright 2006-2008 The FLWOR Foundation. | ||
671 | 3 | * | ||
672 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
673 | 5 | * you may not use this file except in compliance with the License. | ||
674 | 6 | * You may obtain a copy of the License at | ||
675 | 7 | * | ||
676 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
677 | 9 | * | ||
678 | 10 | * Unless required by applicable law or agreed to in writing, software | ||
679 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
680 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
681 | 13 | * See the License for the specific language governing permissions and | ||
682 | 14 | * limitations under the License. | ||
683 | 15 | */ | ||
684 | 16 | |||
685 | 17 | #include "stdafx.h" | ||
686 | 18 | |||
687 | 19 | #include <stdexcept> | ||
688 | 20 | |||
689 | 21 | //#define ZORBA_DEBUG_BASE64_STREAMBUF | ||
690 | 22 | #ifdef ZORBA_DEBUG_BASE64_STREAMBUF | ||
691 | 23 | # include <stdio.h> | ||
692 | 24 | #endif | ||
693 | 25 | |||
694 | 26 | #include <zorba/base64_stream.h> | ||
695 | 27 | |||
696 | 28 | #include "util/base64_util.h" | ||
697 | 29 | |||
698 | 30 | using namespace std; | ||
699 | 31 | |||
700 | 32 | namespace zorba { | ||
701 | 33 | namespace base64 { | ||
702 | 34 | |||
703 | 35 | int const Large_External_Buf_Size = 4096; // must be a multiple of 4 | ||
704 | 36 | |||
705 | 37 | /////////////////////////////////////////////////////////////////////////////// | ||
706 | 38 | |||
707 | 39 | inline void streambuf::resetg() { | ||
708 | 40 | setg( gbuf_, gbuf_ + sizeof gbuf_, gbuf_ + sizeof gbuf_ ); | ||
709 | 41 | } | ||
710 | 42 | |||
711 | 43 | inline void streambuf::resetp() { | ||
712 | 44 | plen_ = 0; | ||
713 | 45 | } | ||
714 | 46 | |||
715 | 47 | inline void streambuf::writep() { | ||
716 | 48 | char chunk[4]; | ||
717 | 49 | orig_buf_->sputn( chunk, base64::encode( pbuf_, plen_, chunk ) ); | ||
718 | 50 | } | ||
719 | 51 | |||
720 | 52 | streambuf::streambuf( std::streambuf *orig ) : orig_buf_( orig ) { | ||
721 | 53 | if ( !orig ) | ||
722 | 54 | throw invalid_argument( "null streambuf" ); | ||
723 | 55 | clear(); | ||
724 | 56 | } | ||
725 | 57 | |||
726 | 58 | streambuf::~streambuf() { | ||
727 | 59 | if ( plen_ ) | ||
728 | 60 | writep(); | ||
729 | 61 | } | ||
730 | 62 | |||
731 | 63 | void streambuf::clear() { | ||
732 | 64 | resetg(); | ||
733 | 65 | resetp(); | ||
734 | 66 | } | ||
735 | 67 | |||
736 | 68 | void streambuf::imbue( std::locale const &loc ) { | ||
737 | 69 | orig_buf_->pubimbue( loc ); | ||
738 | 70 | } | ||
739 | 71 | |||
740 | 72 | streambuf::pos_type streambuf::seekoff( off_type o, ios_base::seekdir d, | ||
741 | 73 | ios_base::openmode m ) { | ||
742 | 74 | clear(); | ||
743 | 75 | return orig_buf_->pubseekoff( o, d, m ); | ||
744 | 76 | } | ||
745 | 77 | |||
746 | 78 | streambuf::pos_type streambuf::seekpos( pos_type p, ios_base::openmode m ) { | ||
747 | 79 | clear(); | ||
748 | 80 | return orig_buf_->pubseekpos( p, m ); | ||
749 | 81 | } | ||
750 | 82 | |||
751 | 83 | std::streambuf* streambuf::setbuf( char_type *p, streamsize s ) { | ||
752 | 84 | orig_buf_->pubsetbuf( p, s ); | ||
753 | 85 | return this; | ||
754 | 86 | } | ||
755 | 87 | |||
756 | 88 | streamsize streambuf::showmanyc() { | ||
757 | 89 | return orig_buf_->in_avail(); | ||
758 | 90 | } | ||
759 | 91 | |||
760 | 92 | int streambuf::sync() { | ||
761 | 93 | if ( plen_ ) | ||
762 | 94 | writep(); | ||
763 | 95 | return orig_buf_->pubsync(); | ||
764 | 96 | } | ||
765 | 97 | |||
766 | 98 | streambuf::int_type streambuf::overflow( int_type c ) { | ||
767 | 99 | #ifdef ZORBA_DEBUG_BASE64_STREAMBUF | ||
768 | 100 | printf( "overflow()\n" ); | ||
769 | 101 | #endif | ||
770 | 102 | bool const is_eof = traits_type::eq_int_type( c, traits_type::eof() ); | ||
771 | 103 | if ( !is_eof ) | ||
772 | 104 | pbuf_[ plen_++ ] = traits_type::to_char_type( c ); | ||
773 | 105 | if ( plen_ == sizeof pbuf_ || (is_eof && plen_) ) { | ||
774 | 106 | writep(); | ||
775 | 107 | resetp(); | ||
776 | 108 | } | ||
777 | 109 | return c; | ||
778 | 110 | } | ||
779 | 111 | |||
780 | 112 | streambuf::int_type streambuf::pbackfail( int_type c ) { | ||
781 | 113 | if ( gptr() > eback() ) | ||
782 | 114 | gbump( -1 ); | ||
783 | 115 | return orig_buf_->sputbackc( traits_type::to_char_type( c ) ); | ||
784 | 116 | } | ||
785 | 117 | |||
786 | 118 | streambuf::int_type streambuf::underflow() { | ||
787 | 119 | #ifdef ZORBA_DEBUG_BASE64_STREAMBUF | ||
788 | 120 | printf( "underflow()\n" ); | ||
789 | 121 | #endif | ||
790 | 122 | char chunk[4]; | ||
791 | 123 | int chunk_len = 0; | ||
792 | 124 | |||
793 | 125 | while ( gptr() >= egptr() ) { | ||
794 | 126 | int_type const c = orig_buf_->sbumpc(); | ||
795 | 127 | bool is_eof = false; | ||
796 | 128 | if ( traits_type::eq_int_type( c, traits_type::eof() ) ) { | ||
797 | 129 | if ( !chunk_len ) | ||
798 | 130 | return traits_type::eof(); | ||
799 | 131 | is_eof = true; | ||
800 | 132 | } else { | ||
801 | 133 | chunk[ chunk_len++ ] = traits_type::to_char_type( c ); | ||
802 | 134 | } | ||
803 | 135 | if ( chunk_len == sizeof chunk || (is_eof && chunk_len) ) { | ||
804 | 136 | streamsize const n = base64::decode( chunk, chunk_len, eback() ); | ||
805 | 137 | setg( gbuf_, gbuf_, gbuf_ + n ); | ||
806 | 138 | } | ||
807 | 139 | } | ||
808 | 140 | return traits_type::to_int_type( *gptr() ); | ||
809 | 141 | } | ||
810 | 142 | |||
811 | 143 | streamsize streambuf::xsgetn( char_type *to, streamsize size ) { | ||
812 | 144 | #ifdef ZORBA_DEBUG_BASE64_STREAMBUF | ||
813 | 145 | printf( "xsgetn()\n" ); | ||
814 | 146 | #endif | ||
815 | 147 | streamsize return_size = 0; | ||
816 | 148 | |||
817 | 149 | if ( streamsize const gsize = egptr() - gptr() ) { | ||
818 | 150 | // | ||
819 | 151 | // Get any chunk fragment pending the the get buffer first. | ||
820 | 152 | // | ||
821 | 153 | streamsize const n = min( gsize, size ); | ||
822 | 154 | traits_type::copy( to, gptr(), n ); | ||
823 | 155 | gbump( n ); | ||
824 | 156 | to += n; | ||
825 | 157 | size -= n, return_size += n; | ||
826 | 158 | } | ||
827 | 159 | |||
828 | 160 | // | ||
829 | 161 | // Must get bytes in terms of encoded size. | ||
830 | 162 | // | ||
831 | 163 | size = base64::encoded_size( size ); | ||
832 | 164 | |||
833 | 165 | while ( size ) { | ||
834 | 166 | char ebuf[ Large_External_Buf_Size ]; | ||
835 | 167 | streamsize const get = min( (streamsize)(sizeof ebuf), size ); | ||
836 | 168 | if ( streamsize got = orig_buf_->sgetn( ebuf, get ) ) { | ||
837 | 169 | streamsize const decoded = base64::decode( ebuf, got, to ); | ||
838 | 170 | to += decoded; | ||
839 | 171 | size -= got, return_size += decoded; | ||
840 | 172 | } else | ||
841 | 173 | break; | ||
842 | 174 | } | ||
843 | 175 | |||
844 | 176 | return return_size; | ||
845 | 177 | } | ||
846 | 178 | |||
847 | 179 | streamsize streambuf::xsputn( char_type const *from, streamsize size ) { | ||
848 | 180 | #ifdef ZORBA_DEBUG_BASE64_STREAMBUF | ||
849 | 181 | printf( "xsputn()\n" ); | ||
850 | 182 | #endif | ||
851 | 183 | streamsize return_size = 0; | ||
852 | 184 | |||
853 | 185 | // | ||
854 | 186 | // Put any chunk fragment pending in the put buffer by completing it first. | ||
855 | 187 | // | ||
856 | 188 | while ( plen_ && size ) { | ||
857 | 189 | overflow( *from ); | ||
858 | 190 | ++from, --size, ++return_size; | ||
859 | 191 | } | ||
860 | 192 | |||
861 | 193 | while ( size >= 3 ) { | ||
862 | 194 | char ebuf[ Large_External_Buf_Size ]; | ||
863 | 195 | streamsize const put = min( (streamsize)(sizeof ebuf), size ); | ||
864 | 196 | streamsize const encoded = base64::encode( from, put, ebuf ); | ||
865 | 197 | orig_buf_->sputn( ebuf, encoded ); | ||
866 | 198 | from += put, size -= put, return_size += put; | ||
867 | 199 | } | ||
868 | 200 | |||
869 | 201 | // | ||
870 | 202 | // Put any remaining chunk fragment into the put buffer. | ||
871 | 203 | // | ||
872 | 204 | if ( size ) { | ||
873 | 205 | traits_type::copy( pbuf_, from, size ); | ||
874 | 206 | plen_ = size; | ||
875 | 207 | } | ||
876 | 208 | |||
877 | 209 | return return_size; | ||
878 | 210 | } | ||
879 | 211 | |||
880 | 212 | /////////////////////////////////////////////////////////////////////////////// | ||
881 | 213 | |||
882 | 214 | } // namespace base64 | ||
883 | 215 | |||
884 | 216 | namespace internal { | ||
885 | 217 | namespace base64 { | ||
886 | 218 | |||
887 | 219 | // Both new & delete are done inside Zorba rather than in the header to | ||
888 | 220 | // guarantee that they're cross-DLL-boundary safe on Windows. | ||
889 | 221 | |||
890 | 222 | std::streambuf* alloc_streambuf( std::streambuf *orig ) { | ||
891 | 223 | return new zorba::base64::streambuf( orig ); | ||
892 | 224 | } | ||
893 | 225 | |||
894 | 226 | int get_streambuf_index() { | ||
895 | 227 | // | ||
896 | 228 | // This function is out-of-line because it has a static constant within it. | ||
897 | 229 | // It has a static constant within it to guarantee (1) initialization before | ||
898 | 230 | // use and (2) initialization happens exactly once. | ||
899 | 231 | // | ||
900 | 232 | // See: "Standard C++ IOStreams and Locales: Advanced Programmer's Guide and | ||
901 | 233 | // Reference," Angelika Langer and Klaus Kreft, Addison-Wesley, 2000, section | ||
902 | 234 | // 3.3.1.1: "Initializing and Maintaining the iword/pword Index." | ||
903 | 235 | // | ||
904 | 236 | // See: "The C++ Programming Language," Bjarne Stroustrup, Addison-Wesley, | ||
905 | 237 | // 2000, section 10.4.8: "Local Static Store." | ||
906 | 238 | // | ||
907 | 239 | static int const index = ios_base::xalloc(); | ||
908 | 240 | return index; | ||
909 | 241 | } | ||
910 | 242 | |||
911 | 243 | } // namespace base64 | ||
912 | 244 | } // namespace internal | ||
913 | 245 | |||
914 | 246 | /////////////////////////////////////////////////////////////////////////////// | ||
915 | 247 | |||
916 | 248 | } // namespace zorba | ||
917 | 249 | /* vim:set et sw=2 ts=2: */ | ||
918 | 0 | 250 | ||
919 | === modified file 'src/api/base64impl.cpp' | |||
920 | --- src/api/base64impl.cpp 2012-06-18 10:06:47 +0000 | |||
921 | +++ src/api/base64impl.cpp 2012-06-26 01:34:26 +0000 | |||
922 | @@ -17,45 +17,70 @@ | |||
923 | 17 | 17 | ||
924 | 18 | #include <sstream> | 18 | #include <sstream> |
925 | 19 | #include <zorba/base64.h> | 19 | #include <zorba/base64.h> |
926 | 20 | #include <zorba/diagnostic_list.h> | ||
927 | 20 | 21 | ||
928 | 21 | #include <zorba/config.h> | 22 | #include <zorba/config.h> |
929 | 22 | #include <zorba/zorba_string.h> | 23 | #include <zorba/zorba_string.h> |
930 | 23 | 24 | ||
932 | 24 | #include "zorbatypes/binary.h" | 25 | #include "diagnostics/dict.h" |
933 | 26 | #include "diagnostics/xquery_exception.h" | ||
934 | 27 | #include "util/base64_util.h" | ||
935 | 25 | 28 | ||
936 | 29 | #define CATCH_BASE64_EXCEPTION() \ | ||
937 | 30 | catch ( base64::exception const &e ) { \ | ||
938 | 31 | throw XQUERY_EXCEPTION( \ | ||
939 | 32 | err::FORG0001, ERROR_PARAMS( e.invalid_char(), ZED( Base64BadChar ) ) \ | ||
940 | 33 | ); \ | ||
941 | 34 | } \ | ||
942 | 35 | catch ( std::invalid_argument const& ) { \ | ||
943 | 36 | throw XQUERY_EXCEPTION( \ | ||
944 | 37 | err::FORG0001, ERROR_PARAMS( "", ZED( Base64Multiple4 ) ) \ | ||
945 | 38 | ); \ | ||
946 | 39 | } | ||
947 | 26 | 40 | ||
948 | 27 | namespace zorba { | 41 | namespace zorba { |
949 | 28 | namespace encoding { | 42 | namespace encoding { |
950 | 29 | 43 | ||
951 | 30 | String Base64::encode(const String& aString) | 44 | String Base64::encode(const String& aString) |
952 | 31 | { | 45 | { |
957 | 32 | std::stringstream lStream; | 46 | String result; |
958 | 33 | lStream << aString; | 47 | base64::encode( aString.data(), aString.size(), &result ); |
959 | 34 | 48 | return result; | |
956 | 35 | return encode(lStream); | ||
960 | 36 | } | 49 | } |
961 | 37 | 50 | ||
962 | 38 | 51 | ||
963 | 39 | String Base64::encode(std::istream& aStream) | 52 | String Base64::encode(std::istream& aStream) |
964 | 40 | { | 53 | { |
966 | 41 | return zorba::Base64::encode(aStream).str(); | 54 | String result; |
967 | 55 | base64::encode( aStream, &result ); | ||
968 | 56 | return result; | ||
969 | 42 | } | 57 | } |
970 | 43 | 58 | ||
971 | 44 | 59 | ||
972 | 45 | String Base64::decode(const String& aString) | 60 | String Base64::decode(const String& aString) |
973 | 46 | { | 61 | { |
977 | 47 | std::stringstream lStream; | 62 | try { |
978 | 48 | lStream << aString; | 63 | String result; |
979 | 49 | return decode(lStream); | 64 | base64::decode( |
980 | 65 | aString.data(), aString.size(), &result, base64::dopt_ignore_ws | ||
981 | 66 | ); | ||
982 | 67 | return result; | ||
983 | 68 | } | ||
984 | 69 | CATCH_BASE64_EXCEPTION() | ||
985 | 50 | } | 70 | } |
986 | 51 | 71 | ||
987 | 52 | 72 | ||
988 | 53 | String Base64::decode(std::istream& aStream) | 73 | String Base64::decode(std::istream& aStream) |
989 | 54 | { | 74 | { |
991 | 55 | return zorba::Base64::decode(aStream).str(); | 75 | try { |
992 | 76 | String result; | ||
993 | 77 | base64::decode( aStream, &result, base64::dopt_ignore_ws ); | ||
994 | 78 | return result; | ||
995 | 79 | } | ||
996 | 80 | CATCH_BASE64_EXCEPTION() | ||
997 | 56 | } | 81 | } |
998 | 57 | 82 | ||
999 | 58 | 83 | ||
1002 | 59 | } /* end namespace encoding */ | 84 | } // namespace encoding |
1003 | 60 | } /* end namespace zorba */ | 85 | } // namespace zorba |
1004 | 61 | /* vim:set et sw=2 ts=2: */ | 86 | /* vim:set et sw=2 ts=2: */ |
1005 | 62 | 87 | ||
1006 | === modified file 'src/api/serialization/serializer.cpp' | |||
1007 | --- src/api/serialization/serializer.cpp 2012-06-18 10:06:47 +0000 | |||
1008 | +++ src/api/serialization/serializer.cpp 2012-06-26 01:34:26 +0000 | |||
1009 | @@ -2300,7 +2300,9 @@ | |||
1010 | 2300 | std::istream& stream = item->getStream(); | 2300 | std::istream& stream = item->getStream(); |
1011 | 2301 | if (item->isEncoded()) | 2301 | if (item->isEncoded()) |
1012 | 2302 | { | 2302 | { |
1014 | 2303 | tr << Base64::decode(stream); | 2303 | zstring decoded; |
1015 | 2304 | Base64::decode(stream, &decoded); | ||
1016 | 2305 | tr << decoded; | ||
1017 | 2304 | } | 2306 | } |
1018 | 2305 | else | 2307 | else |
1019 | 2306 | { | 2308 | { |
1020 | @@ -2322,9 +2324,9 @@ | |||
1021 | 2322 | 2324 | ||
1022 | 2323 | if (item->isEncoded()) | 2325 | if (item->isEncoded()) |
1023 | 2324 | { | 2326 | { |
1027 | 2325 | std::stringstream tmp; | 2327 | zstring decoded; |
1028 | 2326 | tmp.write(value, len); | 2328 | Base64::decode(value, len, &decoded); |
1029 | 2327 | tr << Base64::decode(tmp); | 2329 | tr << decoded; |
1030 | 2328 | } | 2330 | } |
1031 | 2329 | else | 2331 | else |
1032 | 2330 | { | 2332 | { |
1033 | 2331 | 2333 | ||
1034 | === added file 'src/api/streambuf.cpp' | |||
1035 | --- src/api/streambuf.cpp 1970-01-01 00:00:00 +0000 | |||
1036 | +++ src/api/streambuf.cpp 2012-06-26 01:34:26 +0000 | |||
1037 | @@ -0,0 +1,48 @@ | |||
1038 | 1 | /* | ||
1039 | 2 | * Copyright 2006-2008 The FLWOR Foundation. | ||
1040 | 3 | * | ||
1041 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
1042 | 5 | * you may not use this file except in compliance with the License. | ||
1043 | 6 | * You may obtain a copy of the License at | ||
1044 | 7 | * | ||
1045 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
1046 | 9 | * | ||
1047 | 10 | * Unless required by applicable law or agreed to in writing, software | ||
1048 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
1049 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
1050 | 13 | * See the License for the specific language governing permissions and | ||
1051 | 14 | * limitations under the License. | ||
1052 | 15 | */ | ||
1053 | 16 | |||
1054 | 17 | #include "stdafx.h" | ||
1055 | 18 | #include <zorba/internal/streambuf.h> | ||
1056 | 19 | |||
1057 | 20 | using namespace std; | ||
1058 | 21 | |||
1059 | 22 | namespace zorba { | ||
1060 | 23 | namespace internal { | ||
1061 | 24 | |||
1062 | 25 | /////////////////////////////////////////////////////////////////////////////// | ||
1063 | 26 | |||
1064 | 27 | // "delete" is done here inside Zorba rather than in the header to guarantee | ||
1065 | 28 | // that it's cross-DLL-boundary safe on Windows. | ||
1066 | 29 | |||
1067 | 30 | void dealloc_streambuf( streambuf *buf ) { | ||
1068 | 31 | delete buf; | ||
1069 | 32 | } | ||
1070 | 33 | |||
1071 | 34 | void stream_callback( ios_base::event e, ios_base &ios, int index ) { | ||
1072 | 35 | // | ||
1073 | 36 | // See: "Standard C++ IOStreams and Locales: Advanced Programmer's Guide and | ||
1074 | 37 | // Reference," Angelika Langer and Klaus Kreft, Addison-Wesley, 2000, section | ||
1075 | 38 | // 3.3.1.4: "Using Stream Callbacks for Memory Management." | ||
1076 | 39 | // | ||
1077 | 40 | if ( e == ios_base::erase_event ) | ||
1078 | 41 | delete static_cast<streambuf*>( ios.pword( index ) ); | ||
1079 | 42 | } | ||
1080 | 43 | |||
1081 | 44 | /////////////////////////////////////////////////////////////////////////////// | ||
1082 | 45 | |||
1083 | 46 | } // namespace internal | ||
1084 | 47 | } // namespace zorba | ||
1085 | 48 | /* vim:set et sw=2 ts=2: */ | ||
1086 | 0 | 49 | ||
1087 | === modified file 'src/api/transcode_streambuf.cpp' | |||
1088 | --- src/api/transcode_streambuf.cpp 2012-06-18 10:06:47 +0000 | |||
1089 | +++ src/api/transcode_streambuf.cpp 2012-06-26 01:34:26 +0000 | |||
1090 | @@ -81,8 +81,7 @@ | |||
1091 | 81 | return proxy_buf_->sgetn( to, size ); | 81 | return proxy_buf_->sgetn( to, size ); |
1092 | 82 | } | 82 | } |
1093 | 83 | 83 | ||
1096 | 84 | streamsize streambuf::xsputn( char_type const *from, | 84 | streamsize streambuf::xsputn( char_type const *from, streamsize size ) { |
1095 | 85 | streamsize size ) { | ||
1097 | 86 | return proxy_buf_->sputn( from, size ); | 85 | return proxy_buf_->sputn( from, size ); |
1098 | 87 | } | 86 | } |
1099 | 88 | 87 | ||
1100 | @@ -103,19 +102,15 @@ | |||
1101 | 103 | /////////////////////////////////////////////////////////////////////////////// | 102 | /////////////////////////////////////////////////////////////////////////////// |
1102 | 104 | 103 | ||
1103 | 105 | namespace internal { | 104 | namespace internal { |
1104 | 105 | namespace transcode { | ||
1105 | 106 | 106 | ||
1106 | 107 | // Both new & delete are done here inside Zorba rather than in the header to | 107 | // Both new & delete are done here inside Zorba rather than in the header to |
1107 | 108 | // guarantee that they're cross-DLL-boundary safe on Windows. | 108 | // guarantee that they're cross-DLL-boundary safe on Windows. |
1108 | 109 | 109 | ||
1111 | 110 | zorba::transcode::streambuf* | 110 | std::streambuf* alloc_streambuf( char const *charset, std::streambuf *orig ) { |
1110 | 111 | alloc_streambuf( char const *charset, std::streambuf *orig ) { | ||
1112 | 112 | return new zorba::transcode::streambuf( charset, orig ); | 111 | return new zorba::transcode::streambuf( charset, orig ); |
1113 | 113 | } | 112 | } |
1114 | 114 | 113 | ||
1115 | 115 | void dealloc_streambuf( zorba::transcode::streambuf *buf ) { | ||
1116 | 116 | delete buf; | ||
1117 | 117 | } | ||
1118 | 118 | |||
1119 | 119 | int get_streambuf_index() { | 114 | int get_streambuf_index() { |
1120 | 120 | // | 115 | // |
1121 | 121 | // This function is out-of-line because it has a static constant within it. | 116 | // This function is out-of-line because it has a static constant within it. |
1122 | @@ -133,16 +128,7 @@ | |||
1123 | 133 | return index; | 128 | return index; |
1124 | 134 | } | 129 | } |
1125 | 135 | 130 | ||
1136 | 136 | void stream_callback( ios_base::event e, ios_base &ios, int index ) { | 131 | } // namespace transcode |
1127 | 137 | // | ||
1128 | 138 | // See: "Standard C++ IOStreams and Locales: Advanced Programmer's Guide and | ||
1129 | 139 | // Reference," Angelika Langer and Klaus Kreft, Addison-Wesley, 2000, section | ||
1130 | 140 | // 3.3.1.4: "Using Stream Callbacks for Memory Management." | ||
1131 | 141 | // | ||
1132 | 142 | if ( e == ios_base::erase_event ) | ||
1133 | 143 | delete static_cast<streambuf*>( ios.pword( index ) ); | ||
1134 | 144 | } | ||
1135 | 145 | |||
1137 | 146 | } // namespace internal | 132 | } // namespace internal |
1138 | 147 | 133 | ||
1139 | 148 | /////////////////////////////////////////////////////////////////////////////// | 134 | /////////////////////////////////////////////////////////////////////////////// |
1140 | 149 | 135 | ||
1141 | === modified file 'src/diagnostics/diagnostic_en.xml' | |||
1142 | --- src/diagnostics/diagnostic_en.xml 2012-06-18 10:06:47 +0000 | |||
1143 | +++ src/diagnostics/diagnostic_en.xml 2012-06-26 01:34:26 +0000 | |||
1144 | @@ -2888,14 +2888,6 @@ | |||
1145 | 2888 | <value>invalid Base64 character</value> | 2888 | <value>invalid Base64 character</value> |
1146 | 2889 | </entry> | 2889 | </entry> |
1147 | 2890 | 2890 | ||
1148 | 2891 | <entry key="Base64Equals"> | ||
1149 | 2892 | <value>in Base64, '=' must be at the end and followed by one of [AEIMQUYcgkosw048]</value> | ||
1150 | 2893 | </entry> | ||
1151 | 2894 | |||
1152 | 2895 | <entry key="Base64EqualsEquals"> | ||
1153 | 2896 | <value>in Base64, "==" must be at the end and followed by one of [AQgw]</value> | ||
1154 | 2897 | </entry> | ||
1155 | 2898 | |||
1156 | 2899 | <entry key="Base64Multiple4"> | 2891 | <entry key="Base64Multiple4"> |
1157 | 2900 | <value>Base64 data must be a multiple of 4 characters</value> | 2892 | <value>Base64 data must be a multiple of 4 characters</value> |
1158 | 2901 | </entry> | 2893 | </entry> |
1159 | 2902 | 2894 | ||
1160 | === modified file 'src/diagnostics/pregenerated/dict_en.cpp' | |||
1161 | --- src/diagnostics/pregenerated/dict_en.cpp 2012-06-18 10:06:47 +0000 | |||
1162 | +++ src/diagnostics/pregenerated/dict_en.cpp 2012-06-26 01:34:26 +0000 | |||
1163 | @@ -546,8 +546,6 @@ | |||
1164 | 546 | { "~BadXMLNoOpeningTag", "closing tag without matching opening tag" }, | 546 | { "~BadXMLNoOpeningTag", "closing tag without matching opening tag" }, |
1165 | 547 | { "~BadXQueryVersion", "unsupported XQuery version" }, | 547 | { "~BadXQueryVersion", "unsupported XQuery version" }, |
1166 | 548 | { "~Base64BadChar", "invalid Base64 character" }, | 548 | { "~Base64BadChar", "invalid Base64 character" }, |
1167 | 549 | { "~Base64Equals", "in Base64, '=' must be at the end and followed by one of [AEIMQUYcgkosw048]" }, | ||
1168 | 550 | { "~Base64EqualsEquals", "in Base64, \"==\" must be at the end and followed by one of [AQgw]" }, | ||
1169 | 551 | { "~Base64Multiple4", "Base64 data must be a multiple of 4 characters" }, | 549 | { "~Base64Multiple4", "Base64 data must be a multiple of 4 characters" }, |
1170 | 552 | { "~BaseURI", "base URI" }, | 550 | { "~BaseURI", "base URI" }, |
1171 | 553 | { "~BoxCondTooManyColumns", "box condition has more columns than index" }, | 551 | { "~BoxCondTooManyColumns", "box condition has more columns than index" }, |
1172 | 554 | 552 | ||
1173 | === modified file 'src/runtime/base64/base64_impl.cpp' | |||
1174 | --- src/runtime/base64/base64_impl.cpp 2012-06-18 10:06:47 +0000 | |||
1175 | +++ src/runtime/base64/base64_impl.cpp 2012-06-26 01:34:26 +0000 | |||
1176 | @@ -66,7 +66,7 @@ | |||
1177 | 66 | { | 66 | { |
1178 | 67 | if (lItem->isEncoded()) | 67 | if (lItem->isEncoded()) |
1179 | 68 | { | 68 | { |
1181 | 69 | lResultString = Base64::decode(lItem->getStream()); | 69 | Base64::decode(lItem->getStream(), &lResultString); |
1182 | 70 | } | 70 | } |
1183 | 71 | else | 71 | else |
1184 | 72 | { | 72 | { |
1185 | @@ -93,10 +93,7 @@ | |||
1186 | 93 | 93 | ||
1187 | 94 | if (lItem->isEncoded()) | 94 | if (lItem->isEncoded()) |
1188 | 95 | { | 95 | { |
1193 | 96 | std::vector<char> encoded(lContent, lContent+lSize); | 96 | Base64::decode( lContent, lSize, &lResultString ); |
1190 | 97 | std::vector<char> decoded; | ||
1191 | 98 | Base64::decode(encoded, decoded); | ||
1192 | 99 | lResultString.insert(0, &decoded[0], decoded.size()); | ||
1194 | 100 | } | 97 | } |
1195 | 101 | else | 98 | else |
1196 | 102 | { | 99 | { |
1197 | @@ -156,8 +153,8 @@ | |||
1198 | 156 | // create a base64Binary item | 153 | // create a base64Binary item |
1199 | 157 | // the content is the non-encoded string | 154 | // the content is the non-encoded string |
1200 | 158 | GENV_ITEMFACTORY->createBase64Binary( | 155 | GENV_ITEMFACTORY->createBase64Binary( |
1203 | 159 | result, lTmpString.c_str(), lTmpString.size(), false | 156 | result, lTmpString.c_str(), lTmpString.size(), false |
1204 | 160 | ); | 157 | ); |
1205 | 161 | STACK_PUSH (true, state); | 158 | STACK_PUSH (true, state); |
1206 | 162 | } | 159 | } |
1207 | 163 | STACK_END (state); | 160 | STACK_END (state); |
1208 | 164 | 161 | ||
1209 | === modified file 'src/unit_tests/CMakeLists.txt' | |||
1210 | --- src/unit_tests/CMakeLists.txt 2012-06-18 10:06:47 +0000 | |||
1211 | +++ src/unit_tests/CMakeLists.txt 2012-06-26 01:34:26 +0000 | |||
1212 | @@ -13,6 +13,8 @@ | |||
1213 | 13 | # limitations under the License. | 13 | # limitations under the License. |
1214 | 14 | 14 | ||
1215 | 15 | SET(UNIT_TEST_SRCS | 15 | SET(UNIT_TEST_SRCS |
1216 | 16 | test_base64.cpp | ||
1217 | 17 | test_base64_streambuf.cpp | ||
1218 | 16 | string_instantiate.cpp | 18 | string_instantiate.cpp |
1219 | 17 | string.cpp | 19 | string.cpp |
1220 | 18 | test_uri.cpp | 20 | test_uri.cpp |
1221 | 19 | 21 | ||
1222 | === added file 'src/unit_tests/test_base64.cpp' | |||
1223 | --- src/unit_tests/test_base64.cpp 1970-01-01 00:00:00 +0000 | |||
1224 | +++ src/unit_tests/test_base64.cpp 2012-06-26 01:34:26 +0000 | |||
1225 | @@ -0,0 +1,286 @@ | |||
1226 | 1 | /* | ||
1227 | 2 | * Copyright 2006-2008 The FLWOR Foundation. | ||
1228 | 3 | * | ||
1229 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
1230 | 5 | * you may not use this file except in compliance with the License. | ||
1231 | 6 | * You may obtain a copy of the License at | ||
1232 | 7 | * | ||
1233 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
1234 | 9 | * | ||
1235 | 10 | * Unless required by applicable law or agreed to in writing, software | ||
1236 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
1237 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
1238 | 13 | * See the License for the specific language governing permissions and | ||
1239 | 14 | * limitations under the License. | ||
1240 | 15 | */ | ||
1241 | 16 | |||
1242 | 17 | #include "stdafx.h" | ||
1243 | 18 | #include <cstring> | ||
1244 | 19 | #include <iostream> | ||
1245 | 20 | #include <sstream> | ||
1246 | 21 | #include <stdexcept> | ||
1247 | 22 | #include <string> | ||
1248 | 23 | |||
1249 | 24 | #include "util/base64_util.h" | ||
1250 | 25 | |||
1251 | 26 | using namespace std; | ||
1252 | 27 | using namespace zorba; | ||
1253 | 28 | |||
1254 | 29 | struct test { | ||
1255 | 30 | char const *input; | ||
1256 | 31 | char const *expected; | ||
1257 | 32 | }; | ||
1258 | 33 | |||
1259 | 34 | /////////////////////////////////////////////////////////////////////////////// | ||
1260 | 35 | |||
1261 | 36 | static int failures; | ||
1262 | 37 | |||
1263 | 38 | static bool assert_true( int no, char const *expr, int line, bool result ) { | ||
1264 | 39 | if ( !result ) { | ||
1265 | 40 | cout << '#' << no << " FAILED, line " << line << ": " << expr << endl; | ||
1266 | 41 | ++failures; | ||
1267 | 42 | } | ||
1268 | 43 | return result; | ||
1269 | 44 | } | ||
1270 | 45 | |||
1271 | 46 | static void print_exception( int no, char const *expr, int line, | ||
1272 | 47 | std::exception const &e ) { | ||
1273 | 48 | assert_true( no, expr, line, false ); | ||
1274 | 49 | cout << "+ exception: " << e.what() << endl; | ||
1275 | 50 | } | ||
1276 | 51 | |||
1277 | 52 | #define ASSERT_TRUE( NO, EXPR ) assert_true( NO, #EXPR, __LINE__, !!(EXPR) ) | ||
1278 | 53 | |||
1279 | 54 | #define ASSERT_NO_EXCEPTION( NO, EXPR ) \ | ||
1280 | 55 | try { EXPR; } \ | ||
1281 | 56 | catch ( std::exception const &e ) { print_exception( NO, #EXPR, __LINE__, e ); } \ | ||
1282 | 57 | catch ( ... ) { assert_true( NO, #EXPR, __LINE__, false ); } | ||
1283 | 58 | |||
1284 | 59 | #define ASSERT_EXCEPTION( NO, EXPR, EXCEPTION ) \ | ||
1285 | 60 | try { EXPR; assert_true( NO, #EXPR, __LINE__, false ); } \ | ||
1286 | 61 | catch ( EXCEPTION const& ) { } | ||
1287 | 62 | |||
1288 | 63 | ///////////////////////////////////////////////////////////////////////////////} | ||
1289 | 64 | |||
1290 | 65 | static void test_decode_buf_to_buf( int no, string const &in, | ||
1291 | 66 | string const &expected ) { | ||
1292 | 67 | base64::size_type n; | ||
1293 | 68 | char out[ 1024 ]; | ||
1294 | 69 | ASSERT_NO_EXCEPTION( | ||
1295 | 70 | no, n = base64::decode( in.data(), in.size(), out, base64::dopt_any_len ) | ||
1296 | 71 | ); | ||
1297 | 72 | ASSERT_TRUE( no, n == expected.size() ); | ||
1298 | 73 | out[ n ] = '\0'; | ||
1299 | 74 | ASSERT_TRUE( no, out == expected ); | ||
1300 | 75 | } | ||
1301 | 76 | |||
1302 | 77 | static void test_decode_buf_to_string( int no, string const &in, | ||
1303 | 78 | string const &expected ) { | ||
1304 | 79 | base64::size_type n; | ||
1305 | 80 | string out; | ||
1306 | 81 | ASSERT_NO_EXCEPTION( | ||
1307 | 82 | no, | ||
1308 | 83 | n = base64::decode( in.data(), in.size(), &out, base64::dopt_any_len ) | ||
1309 | 84 | ); | ||
1310 | 85 | ASSERT_TRUE( no, n == expected.size() ); | ||
1311 | 86 | ASSERT_TRUE( no, out.size() == expected.size() ); | ||
1312 | 87 | ASSERT_TRUE( no, out == expected ); | ||
1313 | 88 | } | ||
1314 | 89 | |||
1315 | 90 | static void test_decode_buf_to_vector( int no, string const &in, | ||
1316 | 91 | string const &expected ) { | ||
1317 | 92 | base64::size_type n; | ||
1318 | 93 | vector<char> out; | ||
1319 | 94 | ASSERT_NO_EXCEPTION( | ||
1320 | 95 | no, | ||
1321 | 96 | n = base64::decode( in.data(), in.size(), &out, base64::dopt_any_len ) | ||
1322 | 97 | ); | ||
1323 | 98 | ASSERT_TRUE( no, n == expected.size() ); | ||
1324 | 99 | ASSERT_TRUE( no, out.size() == expected.size() ); | ||
1325 | 100 | ASSERT_TRUE( no, !strncmp( &out[0], expected.data(), expected.size() ) ); | ||
1326 | 101 | } | ||
1327 | 102 | |||
1328 | 103 | static void test_decode_stream_to_stream( int no, string const &in, | ||
1329 | 104 | string const &expected ) { | ||
1330 | 105 | base64::size_type n; | ||
1331 | 106 | istringstream sin( in ); | ||
1332 | 107 | ostringstream sout; | ||
1333 | 108 | ASSERT_NO_EXCEPTION( | ||
1334 | 109 | no, n = base64::decode( sin, sout, base64::dopt_any_len ) | ||
1335 | 110 | ); | ||
1336 | 111 | ASSERT_TRUE( no, n == expected.size() ); | ||
1337 | 112 | ASSERT_TRUE( no, sout.str().size() == expected.size() ); | ||
1338 | 113 | ASSERT_TRUE( no, sout.str() == expected ); | ||
1339 | 114 | } | ||
1340 | 115 | |||
1341 | 116 | static void test_decode_stream_to_string( int no, string const &in, | ||
1342 | 117 | string const &expected ) { | ||
1343 | 118 | base64::size_type n; | ||
1344 | 119 | istringstream sin( in ); | ||
1345 | 120 | string out; | ||
1346 | 121 | ASSERT_NO_EXCEPTION( | ||
1347 | 122 | no, n = base64::decode( sin, &out, base64::dopt_any_len ) | ||
1348 | 123 | ); | ||
1349 | 124 | ASSERT_TRUE( no, n == expected.size() ); | ||
1350 | 125 | ASSERT_TRUE( no, out.size() == expected.size() ); | ||
1351 | 126 | ASSERT_TRUE( no, out == expected ); | ||
1352 | 127 | } | ||
1353 | 128 | |||
1354 | 129 | static void test_decode_stream_to_vector( int no, string const &in, | ||
1355 | 130 | string const &expected ) { | ||
1356 | 131 | base64::size_type n; | ||
1357 | 132 | istringstream sin( in ); | ||
1358 | 133 | vector<char> out; | ||
1359 | 134 | ASSERT_NO_EXCEPTION( | ||
1360 | 135 | no, n = base64::decode( sin, &out, base64::dopt_any_len ) | ||
1361 | 136 | ); | ||
1362 | 137 | ASSERT_TRUE( no, n == expected.size() ); | ||
1363 | 138 | ASSERT_TRUE( no, out.size() == expected.size() ); | ||
1364 | 139 | ASSERT_TRUE( no, !strncmp( &out[0], expected.data(), expected.size() ) ); | ||
1365 | 140 | } | ||
1366 | 141 | |||
1367 | 142 | static void test_decode_exception( int no, string const &in ) { | ||
1368 | 143 | char out[ 1024 ]; | ||
1369 | 144 | ASSERT_EXCEPTION( | ||
1370 | 145 | no, base64::decode( in.data(), in.size(), out ), invalid_argument | ||
1371 | 146 | ); | ||
1372 | 147 | } | ||
1373 | 148 | |||
1374 | 149 | /////////////////////////////////////////////////////////////////////////////// | ||
1375 | 150 | |||
1376 | 151 | static void test_encode_buf_to_buf( int no, string const &in, | ||
1377 | 152 | string const &expected ) { | ||
1378 | 153 | char out[ 1024 ]; | ||
1379 | 154 | base64::size_type const n = base64::encode( in.data(), in.size(), out ); | ||
1380 | 155 | ASSERT_TRUE( no, n == expected.size() ); | ||
1381 | 156 | out[ n ] = '\0'; | ||
1382 | 157 | ASSERT_TRUE( no, out == expected ); | ||
1383 | 158 | } | ||
1384 | 159 | |||
1385 | 160 | static void test_encode_buf_to_string( int no, string const &in, | ||
1386 | 161 | string const &expected ) { | ||
1387 | 162 | base64::size_type n; | ||
1388 | 163 | string out; | ||
1389 | 164 | ASSERT_NO_EXCEPTION( no, n = base64::encode( in.data(), in.size(), &out ) ); | ||
1390 | 165 | ASSERT_TRUE( no, n == expected.size() ); | ||
1391 | 166 | ASSERT_TRUE( no, out.size() == expected.size() ); | ||
1392 | 167 | ASSERT_TRUE( no, out == expected ); | ||
1393 | 168 | } | ||
1394 | 169 | |||
1395 | 170 | static void test_encode_buf_to_vector( int no, string const &in, | ||
1396 | 171 | string const &expected ) { | ||
1397 | 172 | base64::size_type n; | ||
1398 | 173 | vector<char> out; | ||
1399 | 174 | ASSERT_NO_EXCEPTION( no, n = base64::encode( in.data(), in.size(), &out ) ); | ||
1400 | 175 | ASSERT_TRUE( no, n == expected.size() ); | ||
1401 | 176 | ASSERT_TRUE( no, out.size() == expected.size() ); | ||
1402 | 177 | ASSERT_TRUE( no, !strncmp( &out[0], expected.data(), expected.size() ) ); | ||
1403 | 178 | } | ||
1404 | 179 | |||
1405 | 180 | static void test_encode_stream_to_stream( int no, string const &in, | ||
1406 | 181 | string const &expected ) { | ||
1407 | 182 | base64::size_type n; | ||
1408 | 183 | istringstream sin( in ); | ||
1409 | 184 | ostringstream sout; | ||
1410 | 185 | ASSERT_NO_EXCEPTION( no, n = base64::encode( sin, sout ) ); | ||
1411 | 186 | ASSERT_TRUE( no, n == expected.size() ); | ||
1412 | 187 | ASSERT_TRUE( no, sout.str().size() == expected.size() ); | ||
1413 | 188 | ASSERT_TRUE( no, sout.str() == expected ); | ||
1414 | 189 | } | ||
1415 | 190 | |||
1416 | 191 | static void test_encode_stream_to_string( int no, string const &in, | ||
1417 | 192 | string const &expected ) { | ||
1418 | 193 | base64::size_type n; | ||
1419 | 194 | istringstream sin( in ); | ||
1420 | 195 | string out; | ||
1421 | 196 | ASSERT_NO_EXCEPTION( no, n = base64::encode( sin, &out ) ); | ||
1422 | 197 | ASSERT_TRUE( no, n == expected.size() ); | ||
1423 | 198 | ASSERT_TRUE( no, out.size() == expected.size() ); | ||
1424 | 199 | ASSERT_TRUE( no, out == expected ); | ||
1425 | 200 | } | ||
1426 | 201 | |||
1427 | 202 | static void test_encode_stream_to_vector( int no, string const &in, | ||
1428 | 203 | string const &expected ) { | ||
1429 | 204 | base64::size_type n; | ||
1430 | 205 | istringstream sin( in ); | ||
1431 | 206 | vector<char> out; | ||
1432 | 207 | ASSERT_NO_EXCEPTION( no, n = base64::encode( sin, &out ) ); | ||
1433 | 208 | ASSERT_TRUE( no, n == expected.size() ); | ||
1434 | 209 | ASSERT_TRUE( no, out.size() == expected.size() ); | ||
1435 | 210 | ASSERT_TRUE( no, !strncmp( &out[0], expected.data(), expected.size() ) ); | ||
1436 | 211 | } | ||
1437 | 212 | |||
1438 | 213 | /////////////////////////////////////////////////////////////////////////////// | ||
1439 | 214 | |||
1440 | 215 | static test const encode_tests[] = { | ||
1441 | 216 | /* 0 */ { "Now is the time", "Tm93IGlzIHRoZSB0aW1l" }, | ||
1442 | 217 | /* 1 */ { "Now is the time.", "Tm93IGlzIHRoZSB0aW1lLg==" }, | ||
1443 | 218 | /* 2 */ { "Now is the time..", "Tm93IGlzIHRoZSB0aW1lLi4=" }, | ||
1444 | 219 | |||
1445 | 220 | { 0, 0 } | ||
1446 | 221 | }; | ||
1447 | 222 | |||
1448 | 223 | static test const decode_tests[] = { | ||
1449 | 224 | /* 3 */ { "Tm93IGlzIHRoZSB0aW1l", "Now is the time" }, | ||
1450 | 225 | /* 4 */ { "Tm93IGlzIHRoZSB0aW1lLg==", "Now is the time." }, | ||
1451 | 226 | /* 5 */ { "Tm93IGlzIHRoZSB0aW1lLi4=", "Now is the time.." }, | ||
1452 | 227 | |||
1453 | 228 | // incomplete Base64 encodings | ||
1454 | 229 | /* 6 */ { "Tm93IGlzIHRoZSB0aW1", "Now is the tim" }, | ||
1455 | 230 | /* 7 */ { "Tm93IGlzIHRoZSB0aW", "Now is the ti" }, | ||
1456 | 231 | /* 8 */ { "Tm93IGlzIHRoZSB0a", "Now is the t" }, | ||
1457 | 232 | |||
1458 | 233 | { 0, 0 } | ||
1459 | 234 | }; | ||
1460 | 235 | |||
1461 | 236 | static char const *const decode_exception_tests[] = { | ||
1462 | 237 | "=", | ||
1463 | 238 | "_m93", | ||
1464 | 239 | "T_93", | ||
1465 | 240 | "Tm_3", | ||
1466 | 241 | "Tm9_", | ||
1467 | 242 | "=m93", | ||
1468 | 243 | "T=93", | ||
1469 | 244 | "Tm=3", | ||
1470 | 245 | "Tm93=", | ||
1471 | 246 | "ZmX=", | ||
1472 | 247 | "ZX==", | ||
1473 | 248 | "ZX===", | ||
1474 | 249 | 0 | ||
1475 | 250 | }; | ||
1476 | 251 | |||
1477 | 252 | namespace zorba { | ||
1478 | 253 | namespace UnitTests { | ||
1479 | 254 | |||
1480 | 255 | int test_base64( int, char*[] ) { | ||
1481 | 256 | int test_no = 0; | ||
1482 | 257 | |||
1483 | 258 | for ( test const *t = encode_tests; t->input; ++t, ++test_no ) { | ||
1484 | 259 | test_encode_buf_to_buf( test_no, t->input, t->expected ); | ||
1485 | 260 | test_encode_buf_to_string( test_no, t->input, t->expected ); | ||
1486 | 261 | test_encode_buf_to_vector( test_no, t->input, t->expected ); | ||
1487 | 262 | test_encode_stream_to_stream( test_no, t->input, t->expected ); | ||
1488 | 263 | test_encode_stream_to_string( test_no, t->input, t->expected ); | ||
1489 | 264 | test_encode_stream_to_vector( test_no, t->input, t->expected ); | ||
1490 | 265 | } | ||
1491 | 266 | |||
1492 | 267 | for ( test const *t = decode_tests; t->input; ++t, ++test_no ) { | ||
1493 | 268 | test_decode_buf_to_buf( test_no, t->input, t->expected ); | ||
1494 | 269 | test_decode_buf_to_string( test_no, t->input, t->expected ); | ||
1495 | 270 | test_decode_buf_to_vector( test_no, t->input, t->expected ); | ||
1496 | 271 | test_decode_stream_to_stream( test_no, t->input, t->expected ); | ||
1497 | 272 | test_decode_stream_to_string( test_no, t->input, t->expected ); | ||
1498 | 273 | test_decode_stream_to_vector( test_no, t->input, t->expected ); | ||
1499 | 274 | } | ||
1500 | 275 | |||
1501 | 276 | for ( char const *const *t = decode_exception_tests; *t; ++t, ++test_no ) | ||
1502 | 277 | test_decode_exception( test_no, *t ); | ||
1503 | 278 | |||
1504 | 279 | cout << failures << " test(s) failed\n"; | ||
1505 | 280 | return failures ? 1 : 0; | ||
1506 | 281 | } | ||
1507 | 282 | |||
1508 | 283 | } // namespace UnitTests | ||
1509 | 284 | } // namespace zorba | ||
1510 | 285 | |||
1511 | 286 | /* vim:set et sw=2 ts=2: */ | ||
1512 | 0 | 287 | ||
1513 | === added file 'src/unit_tests/test_base64_streambuf.cpp' | |||
1514 | --- src/unit_tests/test_base64_streambuf.cpp 1970-01-01 00:00:00 +0000 | |||
1515 | +++ src/unit_tests/test_base64_streambuf.cpp 2012-06-26 01:34:26 +0000 | |||
1516 | @@ -0,0 +1,141 @@ | |||
1517 | 1 | /* | ||
1518 | 2 | * Copyright 2006-2008 The FLWOR Foundation. | ||
1519 | 3 | * | ||
1520 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
1521 | 5 | * you may not use this file except in compliance with the License. | ||
1522 | 6 | * You may obtain a copy of the License at | ||
1523 | 7 | * | ||
1524 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
1525 | 9 | * | ||
1526 | 10 | * Unless required by applicable law or agreed to in writing, software | ||
1527 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
1528 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
1529 | 13 | * See the License for the specific language governing permissions and | ||
1530 | 14 | * limitations under the License. | ||
1531 | 15 | */ | ||
1532 | 16 | |||
1533 | 17 | #include "stdafx.h" | ||
1534 | 18 | #include <fstream> | ||
1535 | 19 | #include <iostream> | ||
1536 | 20 | #include <sstream> | ||
1537 | 21 | |||
1538 | 22 | #include <zorba/base64_stream.h> | ||
1539 | 23 | |||
1540 | 24 | using namespace std; | ||
1541 | 25 | using namespace zorba; | ||
1542 | 26 | |||
1543 | 27 | struct test { | ||
1544 | 28 | char const *raw_str; | ||
1545 | 29 | char const *b64_str; | ||
1546 | 30 | }; | ||
1547 | 31 | |||
1548 | 32 | /////////////////////////////////////////////////////////////////////////////// | ||
1549 | 33 | |||
1550 | 34 | static int failures; | ||
1551 | 35 | |||
1552 | 36 | static bool assert_true( int no, char const *expr, int line, bool result ) { | ||
1553 | 37 | if ( !result ) { | ||
1554 | 38 | cout << '#' << no << " FAILED, line " << line << ": " << expr << endl; | ||
1555 | 39 | ++failures; | ||
1556 | 40 | } | ||
1557 | 41 | return result; | ||
1558 | 42 | } | ||
1559 | 43 | |||
1560 | 44 | static void print_exception( int no, char const *expr, int line, | ||
1561 | 45 | std::exception const &e ) { | ||
1562 | 46 | assert_true( no, expr, line, false ); | ||
1563 | 47 | cout << "+ exception: " << e.what() << endl; | ||
1564 | 48 | } | ||
1565 | 49 | |||
1566 | 50 | #define ASSERT_TRUE( NO, EXPR ) assert_true( NO, #EXPR, __LINE__, !!(EXPR) ) | ||
1567 | 51 | |||
1568 | 52 | #define ASSERT_TRUE_AND_NO_EXCEPTION( NO, EXPR ) \ | ||
1569 | 53 | try { ASSERT_TRUE( NO, EXPR ); } \ | ||
1570 | 54 | catch ( std::exception const &e ) { print_exception( NO, #EXPR, __LINE__, e ); } | ||
1571 | 55 | |||
1572 | 56 | /////////////////////////////////////////////////////////////////////////////// | ||
1573 | 57 | |||
1574 | 58 | static bool test_getline( test const *t ) { | ||
1575 | 59 | string const b64_str( t->b64_str ); | ||
1576 | 60 | istringstream iss( b64_str ); | ||
1577 | 61 | base64::streambuf b64_sbuf( iss.rdbuf() ); | ||
1578 | 62 | iss.ios::rdbuf( &b64_sbuf ); | ||
1579 | 63 | |||
1580 | 64 | char raw_buf[ 1024 ]; | ||
1581 | 65 | iss.getline( raw_buf, sizeof raw_buf ); | ||
1582 | 66 | if ( iss.gcount() ) { | ||
1583 | 67 | string const raw_str( raw_buf ); | ||
1584 | 68 | return raw_str == t->raw_str; | ||
1585 | 69 | } | ||
1586 | 70 | return false; | ||
1587 | 71 | } | ||
1588 | 72 | |||
1589 | 73 | static bool test_read( test const *t ) { | ||
1590 | 74 | string const b64_str( t->b64_str ); | ||
1591 | 75 | istringstream iss( b64_str ); | ||
1592 | 76 | base64::streambuf b64_sbuf( iss.rdbuf() ); | ||
1593 | 77 | iss.ios::rdbuf( &b64_sbuf ); | ||
1594 | 78 | |||
1595 | 79 | char raw_buf[ 1024 ]; | ||
1596 | 80 | iss.read( raw_buf, sizeof raw_buf ); | ||
1597 | 81 | if ( iss.gcount() ) { | ||
1598 | 82 | string const raw_str( raw_buf, iss.gcount() ); | ||
1599 | 83 | return raw_str == t->raw_str; | ||
1600 | 84 | } | ||
1601 | 85 | return false; | ||
1602 | 86 | } | ||
1603 | 87 | |||
1604 | 88 | static bool test_insertion( test const *t ) { | ||
1605 | 89 | ostringstream oss; | ||
1606 | 90 | base64::streambuf b64_sbuf( oss.rdbuf() ); | ||
1607 | 91 | oss.ios::rdbuf( &b64_sbuf ); | ||
1608 | 92 | |||
1609 | 93 | oss << t->raw_str << flush; | ||
1610 | 94 | string const b64_str( oss.str() ); | ||
1611 | 95 | |||
1612 | 96 | string const expected_b64_str( t->b64_str ); | ||
1613 | 97 | return b64_str == expected_b64_str; | ||
1614 | 98 | } | ||
1615 | 99 | |||
1616 | 100 | static bool test_put( test const *t ) { | ||
1617 | 101 | ostringstream oss; | ||
1618 | 102 | { // local scope | ||
1619 | 103 | base64::auto_attach<ostringstream> const raii( oss ); | ||
1620 | 104 | |||
1621 | 105 | for ( char const *c = t->raw_str; *c; ++c ) | ||
1622 | 106 | oss.put( *c ); | ||
1623 | 107 | } // local scope | ||
1624 | 108 | string const b64_str( oss.str() ); | ||
1625 | 109 | |||
1626 | 110 | string const expected_b64_str( t->b64_str ); | ||
1627 | 111 | return b64_str == expected_b64_str; | ||
1628 | 112 | } | ||
1629 | 113 | |||
1630 | 114 | /////////////////////////////////////////////////////////////////////////////// | ||
1631 | 115 | |||
1632 | 116 | static test const tests[] = { | ||
1633 | 117 | /* 0 */ { "Now ", "Tm93IA==" }, | ||
1634 | 118 | /* 1 */ { "Now is the time", "Tm93IGlzIHRoZSB0aW1l" }, | ||
1635 | 119 | /* 2 */ { "Now is the time.", "Tm93IGlzIHRoZSB0aW1lLg==" }, | ||
1636 | 120 | /* 3 */ { "Now is the time..", "Tm93IGlzIHRoZSB0aW1lLi4=" }, | ||
1637 | 121 | { 0, 0 } | ||
1638 | 122 | }; | ||
1639 | 123 | |||
1640 | 124 | namespace zorba { | ||
1641 | 125 | namespace UnitTests { | ||
1642 | 126 | |||
1643 | 127 | int test_base64_streambuf( int, char*[] ) { | ||
1644 | 128 | int test_no = 0; | ||
1645 | 129 | for ( test const *t = tests; t->raw_str; ++t, ++test_no ) { | ||
1646 | 130 | ASSERT_TRUE_AND_NO_EXCEPTION( test_no, test_getline( t ) ); | ||
1647 | 131 | ASSERT_TRUE_AND_NO_EXCEPTION( test_no, test_read( t ) ); | ||
1648 | 132 | ASSERT_TRUE_AND_NO_EXCEPTION( test_no, test_insertion( t ) ); | ||
1649 | 133 | ASSERT_TRUE_AND_NO_EXCEPTION( test_no, test_put( t ) ); | ||
1650 | 134 | } | ||
1651 | 135 | cout << failures << " test(s) failed\n"; | ||
1652 | 136 | return failures ? 1 : 0; | ||
1653 | 137 | } | ||
1654 | 138 | |||
1655 | 139 | } // namespace UnitTests | ||
1656 | 140 | } // namespace zorba | ||
1657 | 141 | /* vim:set et sw=2 ts=2: */ | ||
1658 | 0 | 142 | ||
1659 | === modified file 'src/unit_tests/unit_test_list.h' | |||
1660 | --- src/unit_tests/unit_test_list.h 2012-06-18 10:06:47 +0000 | |||
1661 | +++ src/unit_tests/unit_test_list.h 2012-06-26 01:34:26 +0000 | |||
1662 | @@ -21,24 +21,21 @@ | |||
1663 | 21 | 21 | ||
1664 | 22 | #include <zorba/config.h> | 22 | #include <zorba/config.h> |
1665 | 23 | 23 | ||
1668 | 24 | namespace zorba | 24 | namespace zorba { |
1669 | 25 | { | 25 | namespace UnitTests { |
1670 | 26 | 26 | ||
1671 | 27 | namespace UnitTests | ||
1672 | 28 | { | ||
1673 | 29 | int runUriTest(int argc, char* argv[]); | 27 | int runUriTest(int argc, char* argv[]); |
1674 | 30 | int runDebuggerProtocolTest(int argc, char* argv[]); | 28 | int runDebuggerProtocolTest(int argc, char* argv[]); |
1675 | 29 | int test_base64( int, char*[] ); | ||
1676 | 30 | int test_base64_streambuf( int, char*[] ); | ||
1677 | 31 | int test_fs_iterator( int, char*[] ); | ||
1678 | 31 | int test_string( int, char*[] ); | 32 | int test_string( int, char*[] ); |
1679 | 32 | int test_unique_ptr( int, char*[] ); | 33 | int test_unique_ptr( int, char*[] ); |
1680 | 33 | int test_fs_iterator( int, char*[] ); | ||
1681 | 34 | #ifndef ZORBA_NO_FULL_TEXT | 34 | #ifndef ZORBA_NO_FULL_TEXT |
1682 | 35 | int test_stemmer( int, char*[] ); | 35 | int test_stemmer( int, char*[] ); |
1683 | 36 | int test_thesaurus( int, char*[] ); | 36 | int test_thesaurus( int, char*[] ); |
1684 | 37 | int test_tokenizer( int, char*[] ); | 37 | int test_tokenizer( int, char*[] ); |
1685 | 38 | #endif /* ZORBA_NO_FULL_TEXT */ | 38 | #endif /* ZORBA_NO_FULL_TEXT */ |
1686 | 39 | /** | ||
1687 | 40 | * ADD NEW UNIT TESTS HERE | ||
1688 | 41 | */ | ||
1689 | 42 | #ifndef ZORBA_NO_ICU | 39 | #ifndef ZORBA_NO_ICU |
1690 | 43 | int test_icu_streambuf( int, char*[] ); | 40 | int test_icu_streambuf( int, char*[] ); |
1691 | 44 | #endif /* ZORBA_NO_ICU */ | 41 | #endif /* ZORBA_NO_ICU */ |
1692 | @@ -46,9 +43,7 @@ | |||
1693 | 46 | 43 | ||
1694 | 47 | void initializeTestList(); | 44 | void initializeTestList(); |
1695 | 48 | 45 | ||
1700 | 49 | 46 | } // namespace UnitTests | |
1701 | 50 | }; | 47 | } // namespace zorba |
1698 | 51 | } /* namespace zorba */ | ||
1699 | 52 | |||
1702 | 53 | #endif /* ZORBA_UNIT_TEST_LIST_H */ | 48 | #endif /* ZORBA_UNIT_TEST_LIST_H */ |
1703 | 54 | /* vim:set et sw=2 ts=2: */ | 49 | /* vim:set et sw=2 ts=2: */ |
1704 | 55 | 50 | ||
1705 | === modified file 'src/unit_tests/unit_tests.cpp' | |||
1706 | --- src/unit_tests/unit_tests.cpp 2012-06-18 10:06:47 +0000 | |||
1707 | +++ src/unit_tests/unit_tests.cpp 2012-06-26 01:34:26 +0000 | |||
1708 | @@ -28,9 +28,7 @@ | |||
1709 | 28 | using namespace std; | 28 | using namespace std; |
1710 | 29 | 29 | ||
1711 | 30 | namespace zorba { | 30 | namespace zorba { |
1715 | 31 | 31 | namespace UnitTests { | |
1713 | 32 | namespace UnitTests | ||
1714 | 33 | { | ||
1716 | 34 | 32 | ||
1717 | 35 | map<string,libunittestfunc> libunittests; | 33 | map<string,libunittestfunc> libunittests; |
1718 | 36 | 34 | ||
1719 | @@ -39,14 +37,16 @@ | |||
1720 | 39 | */ | 37 | */ |
1721 | 40 | void initializeTestList() | 38 | void initializeTestList() |
1722 | 41 | { | 39 | { |
1723 | 40 | libunittests["base64"] = test_base64; | ||
1724 | 41 | libunittests["base64_streambuf"] = test_base64_streambuf; | ||
1725 | 42 | libunittests["fs_iterator"] = test_fs_iterator; | ||
1726 | 43 | libunittests["json_parser"] = json_parser; | ||
1727 | 42 | libunittests["string"] = test_string; | 44 | libunittests["string"] = test_string; |
1728 | 45 | libunittests["unique_ptr"] = test_unique_ptr; | ||
1729 | 43 | libunittests["uri"] = runUriTest; | 46 | libunittests["uri"] = runUriTest; |
1730 | 44 | libunittests["fs_iterator"] = test_fs_iterator; | ||
1731 | 45 | #ifndef ZORBA_NO_ICU | 47 | #ifndef ZORBA_NO_ICU |
1732 | 46 | libunittests["icu_streambuf"] = test_icu_streambuf; | 48 | libunittests["icu_streambuf"] = test_icu_streambuf; |
1733 | 47 | #endif /* ZORBA_NO_ICU */ | 49 | #endif /* ZORBA_NO_ICU */ |
1734 | 48 | libunittests["json_parser"] = json_parser; | ||
1735 | 49 | libunittests["unique_ptr"] = test_unique_ptr; | ||
1736 | 50 | #ifndef ZORBA_NO_FULL_TEXT | 50 | #ifndef ZORBA_NO_FULL_TEXT |
1737 | 51 | libunittests["stemmer"] = test_stemmer; | 51 | libunittests["stemmer"] = test_stemmer; |
1738 | 52 | libunittests["thesaurus"] = test_thesaurus; | 52 | libunittests["thesaurus"] = test_thesaurus; |
1739 | @@ -78,7 +78,6 @@ | |||
1740 | 78 | } | 78 | } |
1741 | 79 | 79 | ||
1742 | 80 | 80 | ||
1746 | 81 | } /* namespace UnitTests */ | 81 | } // namespace UnitTests |
1747 | 82 | } /* namespace zorba */ | 82 | } // namespace zorba |
1745 | 83 | |||
1748 | 84 | /* vim:set et sw=2 ts=2: */ | 83 | /* vim:set et sw=2 ts=2: */ |
1749 | 85 | 84 | ||
1750 | === modified file 'src/util/CMakeLists.txt' | |||
1751 | --- src/util/CMakeLists.txt 2012-06-18 10:06:47 +0000 | |||
1752 | +++ src/util/CMakeLists.txt 2012-06-26 01:34:26 +0000 | |||
1753 | @@ -14,6 +14,7 @@ | |||
1754 | 14 | 14 | ||
1755 | 15 | SET(UTIL_SRCS | 15 | SET(UTIL_SRCS |
1756 | 16 | ascii_util.cpp | 16 | ascii_util.cpp |
1757 | 17 | base64_util.cpp | ||
1758 | 17 | dynamic_bitset.cpp | 18 | dynamic_bitset.cpp |
1759 | 18 | error_util.cpp | 19 | error_util.cpp |
1760 | 19 | file.cpp | 20 | file.cpp |
1761 | 20 | 21 | ||
1762 | === modified file 'src/util/ascii_util.cpp' | |||
1763 | --- src/util/ascii_util.cpp 2012-06-18 10:06:47 +0000 | |||
1764 | +++ src/util/ascii_util.cpp 2012-06-26 01:34:26 +0000 | |||
1765 | @@ -15,6 +15,8 @@ | |||
1766 | 15 | */ | 15 | */ |
1767 | 16 | #include "stdafx.h" | 16 | #include "stdafx.h" |
1768 | 17 | 17 | ||
1769 | 18 | #include <cstring> | ||
1770 | 19 | |||
1771 | 18 | #include "ascii_util.h" | 20 | #include "ascii_util.h" |
1772 | 19 | 21 | ||
1773 | 20 | namespace zorba { | 22 | namespace zorba { |
1774 | @@ -30,6 +32,38 @@ | |||
1775 | 30 | return true; | 32 | return true; |
1776 | 31 | } | 33 | } |
1777 | 32 | 34 | ||
1778 | 35 | size_type remove_chars( char *s, size_type s_len, char const *chars ) { | ||
1779 | 36 | char *end = s + s_len; | ||
1780 | 37 | char *c; | ||
1781 | 38 | |||
1782 | 39 | // remove trailing chars first | ||
1783 | 40 | for ( c = end - 1; c >= s; --c ) | ||
1784 | 41 | if ( !std::strchr( chars, *c ) ) { | ||
1785 | 42 | end = c + 1; | ||
1786 | 43 | break; | ||
1787 | 44 | } | ||
1788 | 45 | if ( c < s ) // it was all chars | ||
1789 | 46 | return 0; | ||
1790 | 47 | |||
1791 | 48 | // remove all other chars | ||
1792 | 49 | char *first_char = nullptr; | ||
1793 | 50 | for ( c = s; c < end; ++c ) { | ||
1794 | 51 | if ( std::strchr( chars, *c ) ) { | ||
1795 | 52 | if ( !first_char ) | ||
1796 | 53 | first_char = c; | ||
1797 | 54 | } else { | ||
1798 | 55 | if ( first_char ) { | ||
1799 | 56 | std::memmove( first_char, c, end - c ); | ||
1800 | 57 | end -= c - first_char; | ||
1801 | 58 | c = first_char; | ||
1802 | 59 | first_char = nullptr; | ||
1803 | 60 | } | ||
1804 | 61 | } | ||
1805 | 62 | } | ||
1806 | 63 | |||
1807 | 64 | return end - s; | ||
1808 | 65 | } | ||
1809 | 66 | |||
1810 | 33 | char const* trim_start( char const *s, char const *chars ) { | 67 | char const* trim_start( char const *s, char const *chars ) { |
1811 | 34 | for ( ; *s; ++s ) { | 68 | for ( ; *s; ++s ) { |
1812 | 35 | if ( !std::strchr( chars, *s ) ) | 69 | if ( !std::strchr( chars, *s ) ) |
1813 | 36 | 70 | ||
1814 | === modified file 'src/util/ascii_util.h' | |||
1815 | --- src/util/ascii_util.h 2012-06-18 10:06:47 +0000 | |||
1816 | +++ src/util/ascii_util.h 2012-06-26 01:34:26 +0000 | |||
1817 | @@ -649,6 +649,29 @@ | |||
1818 | 649 | } | 649 | } |
1819 | 650 | 650 | ||
1820 | 651 | /** | 651 | /** |
1821 | 652 | * Removes all specified characters by shifting the contents of the buffer to | ||
1822 | 653 | * the left. | ||
1823 | 654 | * | ||
1824 | 655 | * @param s The string. | ||
1825 | 656 | * @param s_len The length of \a s. | ||
1826 | 657 | * @param chars The characters to remove. | ||
1827 | 658 | * @return Returns the new length of \a s with all \a chars removed. | ||
1828 | 659 | */ | ||
1829 | 660 | size_type remove_chars( char *s, size_type s_len, char const *chars ); | ||
1830 | 661 | |||
1831 | 662 | /** | ||
1832 | 663 | * Removes all whitespace characters by shifting the contents of the buffer to | ||
1833 | 664 | * the left. | ||
1834 | 665 | * | ||
1835 | 666 | * @param s The string. | ||
1836 | 667 | * @param s_len The length of \a s. | ||
1837 | 668 | * @return Returns the new length of \a s with all whitespace removed. | ||
1838 | 669 | */ | ||
1839 | 670 | inline size_type remove_whitespace( char *s, size_type s_len ) { | ||
1840 | 671 | return remove_chars( s, s_len, whitespace ); | ||
1841 | 672 | } | ||
1842 | 673 | |||
1843 | 674 | /** | ||
1844 | 652 | * Removes all leading and trailing specified characters. | 675 | * Removes all leading and trailing specified characters. |
1845 | 653 | * | 676 | * |
1846 | 654 | * @tparam InputStringType The input string type. | 677 | * @tparam InputStringType The input string type. |
1847 | 655 | 678 | ||
1848 | === added file 'src/util/base64_util.cpp' | |||
1849 | --- src/util/base64_util.cpp 1970-01-01 00:00:00 +0000 | |||
1850 | +++ src/util/base64_util.cpp 2012-06-26 01:34:26 +0000 | |||
1851 | @@ -0,0 +1,359 @@ | |||
1852 | 1 | /* | ||
1853 | 2 | * Copyright 2006-2008 The FLWOR Foundation. | ||
1854 | 3 | * | ||
1855 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
1856 | 5 | * you may not use this file except in compliance with the License. | ||
1857 | 6 | * You may obtain a copy of the License at | ||
1858 | 7 | * | ||
1859 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
1860 | 9 | * | ||
1861 | 10 | * Unless required by applicable law or agreed to in writing, software | ||
1862 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
1863 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
1864 | 13 | * See the License for the specific language governing permissions and | ||
1865 | 14 | * limitations under the License. | ||
1866 | 15 | */ | ||
1867 | 16 | |||
1868 | 17 | #include <algorithm> | ||
1869 | 18 | #include <cstring> | ||
1870 | 19 | |||
1871 | 20 | #include "ascii_util.h" | ||
1872 | 21 | #include "base64_util.h" | ||
1873 | 22 | #include "string_util.h" | ||
1874 | 23 | |||
1875 | 24 | using namespace std; | ||
1876 | 25 | |||
1877 | 26 | namespace zorba { | ||
1878 | 27 | namespace base64 { | ||
1879 | 28 | |||
1880 | 29 | /////////////////////////////////////////////////////////////////////////////// | ||
1881 | 30 | |||
1882 | 31 | static char const alphabet[] = | ||
1883 | 32 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | ||
1884 | 33 | "abcdefghijklmnopqrstuvwxyz" | ||
1885 | 34 | "0123456789+/"; | ||
1886 | 35 | |||
1887 | 36 | /** | ||
1888 | 37 | * Base64 decoding table. A value of -1 means "invalid"; a value of -2 means | ||
1889 | 38 | * "skip" (for newlines and carriage returns). | ||
1890 | 39 | */ | ||
1891 | 40 | static signed char const decode_table[] = { | ||
1892 | 41 | /* 00-07 */ -1, -1, -1, -1, -1, -1, -1, -1, | ||
1893 | 42 | /* 08-0F */ -1, -1, -2, -1, -1, -2, -1, -1, // . .\n . .\r . . | ||
1894 | 43 | /* 10-17 */ -1, -1, -1, -1, -1, -1, -1, -1, | ||
1895 | 44 | /* 18-1F */ -1, -1, -1, -1, -1, -1, -1, -1, | ||
1896 | 45 | /* 20-27 */ -1, -1, -1, -1, -1, -1, -1, -1, | ||
1897 | 46 | /* 28-2F */ -1, -1, -1, 62, -1, -1, -1, 63, // . . . + . . . / | ||
1898 | 47 | /* 30-37 */ 52, 53, 54, 55, 56, 57, 58, 59, // 0 1 2 3 4 5 6 7 | ||
1899 | 48 | /* 38-3F */ 60, 61, -1, -1, -1, -1, -1, -1, // 8 9 . . . . . . | ||
1900 | 49 | /* 40-47 */ -1, 0, 1, 2, 3, 4, 5, 6, // . A B C D E F G | ||
1901 | 50 | /* 48-4F */ 7, 8, 9, 10, 11, 12, 13, 14, // H I J K L M N O | ||
1902 | 51 | /* 50-57 */ 15, 16, 17, 18, 19, 20, 21, 22, // P Q R S T U V W | ||
1903 | 52 | /* 58-5F */ 23, 24, 25, -1, -1, -1, -1, -1, // X Y Z . . . . . | ||
1904 | 53 | /* 60-67 */ -1, 26, 27, 28, 29, 30, 31, 32, // . a b c d e f g | ||
1905 | 54 | /* 68-6F */ 33, 34, 35, 36, 37, 38, 39, 40, // h i j k l m n o | ||
1906 | 55 | /* 70-77 */ 41, 42, 43, 44, 45, 46, 47, 48, // p q r s t u v w | ||
1907 | 56 | /* 78-7F */ 49, 50, 51, -1, -1, -1, -1, -1, // x y z . . . . . | ||
1908 | 57 | /* 80-87 */ -1, -1, -1, -1, -1, -1, -1, -1, | ||
1909 | 58 | /* 88-8F */ -1, -1, -1, -1, -1, -1, -1, -1, | ||
1910 | 59 | /* 90-97 */ -1, -1, -1, -1, -1, -1, -1, -1, | ||
1911 | 60 | /* 98-9F */ -1, -1, -1, -1, -1, -1, -1, -1, | ||
1912 | 61 | /* A0-A7 */ -1, -1, -1, -1, -1, -1, -1, -1, | ||
1913 | 62 | /* A8-AF */ -1, -1, -1, -1, -1, -1, -1, -1, | ||
1914 | 63 | /* B0-B7 */ -1, -1, -1, -1, -1, -1, -1, -1, | ||
1915 | 64 | /* B8-BF */ -1, -1, -1, -1, -1, -1, -1, -1, | ||
1916 | 65 | /* C0-C7 */ -1, -1, -1, -1, -1, -1, -1, -1, | ||
1917 | 66 | /* C8-CF */ -1, -1, -1, -1, -1, -1, -1, -1, | ||
1918 | 67 | /* D0-D7 */ -1, -1, -1, -1, -1, -1, -1, -1, | ||
1919 | 68 | /* D8-DF */ -1, -1, -1, -1, -1, -1, -1, -1, | ||
1920 | 69 | /* E0-E7 */ -1, -1, -1, -1, -1, -1, -1, -1, | ||
1921 | 70 | /* E8-EF */ -1, -1, -1, -1, -1, -1, -1, -1, | ||
1922 | 71 | /* F0-F7 */ -1, -1, -1, -1, -1, -1, -1, -1, | ||
1923 | 72 | /* F8-FF */ -1, -1, -1, -1, -1, -1, -1, -1, | ||
1924 | 73 | }; | ||
1925 | 74 | |||
1926 | 75 | inline void decode_chunk( char const *from, char *to ) { | ||
1927 | 76 | // | ||
1928 | 77 | // | INPUT BYTES | ||
1929 | 78 | // +-----------+-----------+-----------+-----------+ | ||
1930 | 79 | // | 0 | 1 | 2 | 3 | | ||
1931 | 80 | // +-----------+-----------+-----------+-----------+ | ||
1932 | 81 | // | | | | | | ||
1933 | 82 | // | | | | | | | | | | | | | | | | | | | | | | | | | | ||
1934 | 83 | // | | | | | ||
1935 | 84 | // +---------------+---------------+---------------+ | ||
1936 | 85 | // | 0 | 1 | 2 | | ||
1937 | 86 | // +---------------+---------------+---------------+ | ||
1938 | 87 | // | OUTPUT BYTES | ||
1939 | 88 | // | ||
1940 | 89 | unsigned char const *const u = reinterpret_cast<unsigned char const*>( from ); | ||
1941 | 90 | to[0] = (u[0] << 2) | (u[1] >> 4); | ||
1942 | 91 | to[1] = (u[1] << 4) | (u[2] >> 2); | ||
1943 | 92 | to[2] = ((u[2] << 6) & 0xC0) | u[3] ; | ||
1944 | 93 | } | ||
1945 | 94 | |||
1946 | 95 | inline void encode_chunk( char const *from, char *to ) { | ||
1947 | 96 | // | ||
1948 | 97 | // | INPUT BYTES | ||
1949 | 98 | // +---------------+---------------+---------------+ | ||
1950 | 99 | // | 0 | 1 | 2 | | ||
1951 | 100 | // +---------------+---------------+---------------+ | ||
1952 | 101 | // | | | | | ||
1953 | 102 | // | | | | | | | | | | | | | | | | | | | | | | | | | | ||
1954 | 103 | // | | | | | | ||
1955 | 104 | // +-----------+-----------+-----------+-----------+ | ||
1956 | 105 | // | 0 | 1 | 2 | 3 | | ||
1957 | 106 | // +-----------+-----------+-----------+-----------+ | ||
1958 | 107 | // | OUTPUT BYTES | ||
1959 | 108 | // | ||
1960 | 109 | unsigned char const *const u = reinterpret_cast<unsigned char const*>( from ); | ||
1961 | 110 | to[0] = alphabet[ u[0] >> 2 ]; | ||
1962 | 111 | to[1] = alphabet[ ((u[0] & 0x03) << 4) | (u[1] >> 4) ]; | ||
1963 | 112 | to[2] = alphabet[ ((u[1] & 0x0F) << 2) | (u[2] >> 6) ]; | ||
1964 | 113 | to[3] = alphabet[ u[2] & 0x3F ]; | ||
1965 | 114 | } | ||
1966 | 115 | |||
1967 | 116 | streamsize read_without_whitespace( istream &is, char *buf, streamsize n ) { | ||
1968 | 117 | char const *const buf_orig = buf; | ||
1969 | 118 | char const *const buf_end = buf + n; | ||
1970 | 119 | |||
1971 | 120 | while ( buf < buf_end ) { | ||
1972 | 121 | is.read( buf, n ); | ||
1973 | 122 | if ( streamsize read = is.gcount() ) { | ||
1974 | 123 | read = ascii::remove_whitespace( buf, read ); | ||
1975 | 124 | buf += read, n -= read; | ||
1976 | 125 | } else | ||
1977 | 126 | break; | ||
1978 | 127 | } | ||
1979 | 128 | return buf - buf_orig; | ||
1980 | 129 | } | ||
1981 | 130 | |||
1982 | 131 | /////////////////////////////////////////////////////////////////////////////// | ||
1983 | 132 | |||
1984 | 133 | size_type decode( char const *from, size_type from_len, char *to, | ||
1985 | 134 | int options ) { | ||
1986 | 135 | char chunk[4]; | ||
1987 | 136 | int chunk_len = 0; | ||
1988 | 137 | bool const ignore_ws = options & dopt_ignore_ws; | ||
1989 | 138 | int pads = 0; | ||
1990 | 139 | char const *const to_orig = to; | ||
1991 | 140 | |||
1992 | 141 | for ( size_type pos = 0; pos < from_len; ++pos, ++from ) { | ||
1993 | 142 | char const c = *from; | ||
1994 | 143 | signed char value; | ||
1995 | 144 | if ( c == '=' ) { | ||
1996 | 145 | switch ( pos % 4 ) { | ||
1997 | 146 | // | ||
1998 | 147 | // Ensure '=' occurs only in the 3rd or 4th bytes of a 4-byte chunk | ||
1999 | 148 | // and that the byte preceding '=' is valid. | ||
2000 | 149 | // | ||
2001 | 150 | case 2: | ||
2002 | 151 | if ( !strchr( "AQgw", from[-1] ) ) | ||
2003 | 152 | throw base64::exception( | ||
2004 | 153 | c, pos, BUILD_STRING( '\'', c, "': invalid character before '='" ) | ||
2005 | 154 | ); | ||
2006 | 155 | break; | ||
2007 | 156 | case 3: | ||
2008 | 157 | if ( !strchr( "=048AEIMQUYcgkosw", from[-1] ) ) | ||
2009 | 158 | throw base64::exception( | ||
2010 | 159 | c, pos, BUILD_STRING( '\'', c, "': invalid character before '='" ) | ||
2011 | 160 | ); | ||
2012 | 161 | break; | ||
2013 | 162 | default: | ||
2014 | 163 | throw base64::exception( c, pos, "'=' encountered unexpectedly" ); | ||
2015 | 164 | } | ||
2016 | 165 | ++pads; | ||
2017 | 166 | value = '\0'; | ||
2018 | 167 | } else { | ||
2019 | 168 | if ( pads ) | ||
2020 | 169 | throw base64::exception( | ||
2021 | 170 | c, pos, BUILD_STRING( '\'', c, "': invalid character after '='" ) | ||
2022 | 171 | ); | ||
2023 | 172 | value = decode_table[ static_cast<unsigned char>( c ) ]; | ||
2024 | 173 | } | ||
2025 | 174 | switch ( value ) { | ||
2026 | 175 | case -1: | ||
2027 | 176 | if ( ascii::is_space( c ) && ignore_ws ) | ||
2028 | 177 | continue; | ||
2029 | 178 | throw base64::exception( | ||
2030 | 179 | c, pos, BUILD_STRING( '\'', c, "': invalid character" ) | ||
2031 | 180 | ); | ||
2032 | 181 | case -2: // \n or \r | ||
2033 | 182 | continue; | ||
2034 | 183 | default: | ||
2035 | 184 | if ( chunk_len == 4 ) | ||
2036 | 185 | chunk_len = 0; | ||
2037 | 186 | if ( to ) { | ||
2038 | 187 | chunk[ chunk_len ] = value; | ||
2039 | 188 | if ( ++chunk_len == 4 ) { | ||
2040 | 189 | decode_chunk( chunk, to ); | ||
2041 | 190 | to += 3; | ||
2042 | 191 | } | ||
2043 | 192 | } else | ||
2044 | 193 | ++chunk_len; | ||
2045 | 194 | } | ||
2046 | 195 | } // for | ||
2047 | 196 | |||
2048 | 197 | if ( (chunk_len % 4) && !(options & dopt_any_len) ) | ||
2049 | 198 | throw invalid_argument( "Base64 length is not a multiple of 4" ); | ||
2050 | 199 | |||
2051 | 200 | if ( !to ) | ||
2052 | 201 | return 0; | ||
2053 | 202 | |||
2054 | 203 | if ( chunk_len > 1 && chunk_len < 4 ) { | ||
2055 | 204 | // | ||
2056 | 205 | // The number of non-whitespace bytes was not a multiple of 4, hence the | ||
2057 | 206 | // Base64 encoding is incomplete: salvage 1 or 2 characters. | ||
2058 | 207 | // | ||
2059 | 208 | int const salvageable = chunk_len - 1; | ||
2060 | 209 | chunk[3] = '\0'; | ||
2061 | 210 | if ( salvageable == 1 ) | ||
2062 | 211 | chunk[2] = '\0'; | ||
2063 | 212 | decode_chunk( chunk, to ); | ||
2064 | 213 | to += salvageable; | ||
2065 | 214 | } | ||
2066 | 215 | |||
2067 | 216 | return to - to_orig - pads; | ||
2068 | 217 | } | ||
2069 | 218 | |||
2070 | 219 | size_type decode( char const *from, size_type from_len, std::vector<char> *to, | ||
2071 | 220 | int options ) { | ||
2072 | 221 | size_type total_decoded = 0; | ||
2073 | 222 | if ( from_len ) { | ||
2074 | 223 | std::vector<char>::size_type const orig_size = to->size(); | ||
2075 | 224 | to->resize( orig_size + decoded_size( from_len ) ); | ||
2076 | 225 | total_decoded = decode( from, from_len, &(*to)[ orig_size ], options ); | ||
2077 | 226 | to->resize( orig_size + total_decoded ); | ||
2078 | 227 | } | ||
2079 | 228 | return total_decoded; | ||
2080 | 229 | } | ||
2081 | 230 | |||
2082 | 231 | size_type decode( istream &from, ostream &to, int options ) { | ||
2083 | 232 | size_type total_decoded = 0; | ||
2084 | 233 | while ( !from.eof() ) { | ||
2085 | 234 | char from_buf[ 1024 * 4 ], to_buf[ 1024 * 3 ]; | ||
2086 | 235 | streamsize gcount; | ||
2087 | 236 | if ( options & dopt_ignore_ws ) | ||
2088 | 237 | gcount = read_without_whitespace( from, from_buf, sizeof from_buf ); | ||
2089 | 238 | else { | ||
2090 | 239 | from.read( from_buf, sizeof from_buf ); | ||
2091 | 240 | gcount = from.gcount(); | ||
2092 | 241 | } | ||
2093 | 242 | if ( gcount ) { | ||
2094 | 243 | size_type const decoded = decode( from_buf, gcount, to_buf, options ); | ||
2095 | 244 | to.write( to_buf, decoded ); | ||
2096 | 245 | total_decoded += decoded; | ||
2097 | 246 | } else | ||
2098 | 247 | break; | ||
2099 | 248 | } | ||
2100 | 249 | return total_decoded; | ||
2101 | 250 | } | ||
2102 | 251 | |||
2103 | 252 | size_type decode( istream &from, vector<char> *to, int options ) { | ||
2104 | 253 | vector<char>::size_type const orig_size = to->size(); | ||
2105 | 254 | size_type total_decoded = 0; | ||
2106 | 255 | while ( !from.eof() ) { | ||
2107 | 256 | char from_buf[ 1024 * 4 ]; | ||
2108 | 257 | streamsize gcount; | ||
2109 | 258 | if ( options & dopt_ignore_ws ) | ||
2110 | 259 | gcount = read_without_whitespace( from, from_buf, sizeof from_buf ); | ||
2111 | 260 | else { | ||
2112 | 261 | from.read( from_buf, sizeof from_buf ); | ||
2113 | 262 | gcount = from.gcount(); | ||
2114 | 263 | } | ||
2115 | 264 | if ( gcount ) { | ||
2116 | 265 | to->resize( to->size() + decoded_size( gcount ) ); | ||
2117 | 266 | total_decoded += | ||
2118 | 267 | decode( from_buf, gcount, &(*to)[ total_decoded ], options ); | ||
2119 | 268 | } else | ||
2120 | 269 | break; | ||
2121 | 270 | } | ||
2122 | 271 | to->resize( orig_size + total_decoded ); | ||
2123 | 272 | return total_decoded; | ||
2124 | 273 | } | ||
2125 | 274 | |||
2126 | 275 | /////////////////////////////////////////////////////////////////////////////// | ||
2127 | 276 | |||
2128 | 277 | size_type encode( char const *from, size_type from_len, char *to ) { | ||
2129 | 278 | char const *const to_orig = to; | ||
2130 | 279 | int chunk_len = 0; | ||
2131 | 280 | |||
2132 | 281 | while ( from_len-- ) { | ||
2133 | 282 | if ( ++chunk_len == 3 ) { | ||
2134 | 283 | encode_chunk( from, to ); | ||
2135 | 284 | from += 3, to += 4; | ||
2136 | 285 | chunk_len = 0; | ||
2137 | 286 | } | ||
2138 | 287 | } | ||
2139 | 288 | |||
2140 | 289 | if ( chunk_len ) { // must be either 1 or 2 | ||
2141 | 290 | // | ||
2142 | 291 | // Handle the special-case of from_len not being a multiple of 3. First, | ||
2143 | 292 | // copy what's left over from "from" to a temporary buffer that's 3 bytes | ||
2144 | 293 | // long and encode that buffer so encode_chunk() remains special-case-free | ||
2145 | 294 | // (and thus faster) for most of the encoding. | ||
2146 | 295 | // | ||
2147 | 296 | char from_temp[3]; | ||
2148 | 297 | from_temp[1] = from_temp[2] = '\0'; | ||
2149 | 298 | std::copy( from, from + chunk_len, from_temp ); | ||
2150 | 299 | encode_chunk( from_temp, to ); | ||
2151 | 300 | // | ||
2152 | 301 | // Second, overwrite the trailing byte(s) with Base64 padding characters. | ||
2153 | 302 | // | ||
2154 | 303 | to[3] = '='; | ||
2155 | 304 | if ( chunk_len == 1 ) | ||
2156 | 305 | to[2] = '='; | ||
2157 | 306 | to += 4; | ||
2158 | 307 | } | ||
2159 | 308 | |||
2160 | 309 | return to - to_orig; | ||
2161 | 310 | } | ||
2162 | 311 | |||
2163 | 312 | size_type encode( char const *from, size_type from_len, | ||
2164 | 313 | std::vector<char> *to ) { | ||
2165 | 314 | size_type encoded = 0; | ||
2166 | 315 | if ( from_len ) { | ||
2167 | 316 | std::vector<char>::size_type const orig_size = to->size(); | ||
2168 | 317 | to->resize( orig_size + encoded_size( from_len ) ); | ||
2169 | 318 | encoded = encode( from, from_len, &(*to)[ orig_size ] ); | ||
2170 | 319 | to->resize( orig_size + encoded ); | ||
2171 | 320 | } | ||
2172 | 321 | return encoded; | ||
2173 | 322 | } | ||
2174 | 323 | |||
2175 | 324 | size_type encode( istream &from, ostream &to ) { | ||
2176 | 325 | size_type total_encoded = 0; | ||
2177 | 326 | while ( !from.eof() ) { | ||
2178 | 327 | char from_buf[ 1024 * 3 ], to_buf[ 1024 * 4 ]; | ||
2179 | 328 | from.read( from_buf, sizeof from_buf ); | ||
2180 | 329 | if ( streamsize const gcount = from.gcount() ) { | ||
2181 | 330 | size_type const encoded = encode( from_buf, gcount, to_buf ); | ||
2182 | 331 | to.write( to_buf, encoded ); | ||
2183 | 332 | total_encoded += encoded; | ||
2184 | 333 | } else | ||
2185 | 334 | break; | ||
2186 | 335 | } | ||
2187 | 336 | return total_encoded; | ||
2188 | 337 | } | ||
2189 | 338 | |||
2190 | 339 | size_type encode( istream &from, vector<char> *to ) { | ||
2191 | 340 | vector<char>::size_type const orig_size = to->size(); | ||
2192 | 341 | size_type total_encoded = 0; | ||
2193 | 342 | while ( !from.eof() ) { | ||
2194 | 343 | char from_buf[ 1024 * 3 ]; | ||
2195 | 344 | from.read( from_buf, sizeof from_buf ); | ||
2196 | 345 | if ( streamsize const gcount = from.gcount() ) { | ||
2197 | 346 | to->resize( to->size() + encoded_size( gcount ) ); | ||
2198 | 347 | total_encoded += encode( from_buf, gcount, &(*to)[ total_encoded ] ); | ||
2199 | 348 | } else | ||
2200 | 349 | break; | ||
2201 | 350 | } | ||
2202 | 351 | to->resize( orig_size + total_encoded ); | ||
2203 | 352 | return total_encoded; | ||
2204 | 353 | } | ||
2205 | 354 | |||
2206 | 355 | /////////////////////////////////////////////////////////////////////////////// | ||
2207 | 356 | |||
2208 | 357 | } // namespace base64 | ||
2209 | 358 | } // namespace zorba | ||
2210 | 359 | /* vim:set et sw=2 ts=2: */ | ||
2211 | 0 | 360 | ||
2212 | === added file 'src/util/base64_util.h' | |||
2213 | --- src/util/base64_util.h 1970-01-01 00:00:00 +0000 | |||
2214 | +++ src/util/base64_util.h 2012-06-26 01:34:26 +0000 | |||
2215 | @@ -0,0 +1,361 @@ | |||
2216 | 1 | /* | ||
2217 | 2 | * Copyright 2006-2008 The FLWOR Foundation. | ||
2218 | 3 | * | ||
2219 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
2220 | 5 | * you may not use this file except in compliance with the License. | ||
2221 | 6 | * You may obtain a copy of the License at | ||
2222 | 7 | * | ||
2223 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
2224 | 9 | * | ||
2225 | 10 | * Unless required by applicable law or agreed to in writing, software | ||
2226 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
2227 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
2228 | 13 | * See the License for the specific language governing permissions and | ||
2229 | 14 | * limitations under the License. | ||
2230 | 15 | */ | ||
2231 | 16 | |||
2232 | 17 | #pragma once | ||
2233 | 18 | #ifndef ZORBA_BASE64_UTIL_H | ||
2234 | 19 | #define ZORBA_BASE64_UTIL_H | ||
2235 | 20 | |||
2236 | 21 | #include <algorithm> | ||
2237 | 22 | #include <iostream> | ||
2238 | 23 | #include <stdexcept> | ||
2239 | 24 | #include <sys/types.h> /* for size_t */ | ||
2240 | 25 | #include <vector> | ||
2241 | 26 | |||
2242 | 27 | #include "cxx_util.h" | ||
2243 | 28 | |||
2244 | 29 | namespace zorba { | ||
2245 | 30 | namespace base64 { | ||
2246 | 31 | |||
2247 | 32 | ////////// Types ////////////////////////////////////////////////////////////// | ||
2248 | 33 | |||
2249 | 34 | typedef size_t size_type; | ||
2250 | 35 | |||
2251 | 36 | /** | ||
2252 | 37 | * Options to use for decoding. | ||
2253 | 38 | */ | ||
2254 | 39 | enum decode_options { | ||
2255 | 40 | dopt_none = 0x00, ///< No options. | ||
2256 | 41 | dopt_any_len = 0x01, ///< Input length may be non-multiple of 4. | ||
2257 | 42 | dopt_ignore_ws = 0x02, ///< Ignore all whitespace. | ||
2258 | 43 | }; | ||
2259 | 44 | |||
2260 | 45 | ////////// Exception ////////////////////////////////////////////////////////// | ||
2261 | 46 | |||
2262 | 47 | /** | ||
2263 | 48 | * A %base64::exception is-an invalid_argument that contains additional details | ||
2264 | 49 | * about the exception such as the invalid character and its offset. | ||
2265 | 50 | */ | ||
2266 | 51 | class exception : public std::invalid_argument { | ||
2267 | 52 | public: | ||
2268 | 53 | exception( char c, size_type offset, std::string const &msg ) : | ||
2269 | 54 | std::invalid_argument( msg ), char_( c ), offset_( offset ) { } | ||
2270 | 55 | |||
2271 | 56 | char invalid_char() const { | ||
2272 | 57 | return char_; | ||
2273 | 58 | } | ||
2274 | 59 | |||
2275 | 60 | size_type char_offset() const { | ||
2276 | 61 | return offset_; | ||
2277 | 62 | } | ||
2278 | 63 | |||
2279 | 64 | private: | ||
2280 | 65 | char char_; | ||
2281 | 66 | size_type offset_; | ||
2282 | 67 | }; | ||
2283 | 68 | |||
2284 | 69 | ////////// Decoding /////////////////////////////////////////////////////////// | ||
2285 | 70 | |||
2286 | 71 | /** | ||
2287 | 72 | * \internal | ||
2288 | 73 | * Reads from the given istream until \a n non-whitespace characters are read | ||
2289 | 74 | * or until EOF is encountered. | ||
2290 | 75 | * | ||
2291 | 76 | * @param is The istream to read from. | ||
2292 | 77 | * @param buf A pointer to the start of a buffer to read into. | ||
2293 | 78 | * @param n The number of non-whitespace characters to read. | ||
2294 | 79 | * @return Returns the number of non-whitespace characters read. | ||
2295 | 80 | */ | ||
2296 | 81 | std::streamsize read_without_whitespace( std::istream &is, char *buf, | ||
2297 | 82 | std::streamsize n ); | ||
2298 | 83 | |||
2299 | 84 | /** | ||
2300 | 85 | * Calculates the number of bytes required to decode \a n Base64-encoded bytes. | ||
2301 | 86 | * | ||
2302 | 87 | * @param n The number of bytes to decode. | ||
2303 | 88 | * @return Returns the number of bytes needed for Base64 decoding. | ||
2304 | 89 | */ | ||
2305 | 90 | inline size_type decoded_size( size_type n ) { | ||
2306 | 91 | return ((n / 4) + !!(n % 4)) * 3; | ||
2307 | 92 | } | ||
2308 | 93 | |||
2309 | 94 | /** | ||
2310 | 95 | * Decodes a Base64-encoded buffer. Embedded newlines and carriage-returns are | ||
2311 | 96 | * skipped. | ||
2312 | 97 | * | ||
2313 | 98 | * @param from A pointer to the Base64 buffer to be decoded. | ||
2314 | 99 | * @param from_len The number of bytes to decode. | ||
2315 | 100 | * @paran to A pointer to the buffer to receive the decoded bytes. The buffer | ||
2316 | 101 | * must be large enough to contain them. Note that the buffer is \e not null | ||
2317 | 102 | * terminated. | ||
2318 | 103 | * @param options The decoding options to use. | ||
2319 | 104 | * @return Returns the number of decoded bytes. | ||
2320 | 105 | * @throws invalid_argument if \a options does not have the \c dtop_any_len bit | ||
2321 | 106 | * set and \a from_len is not a multiple of 4. | ||
2322 | 107 | * @throws base64::exception if an \c = is encountered unexpectedly or an | ||
2323 | 108 | * invalid byte is encountered. | ||
2324 | 109 | * @see decoded_size() | ||
2325 | 110 | */ | ||
2326 | 111 | size_type decode( char const *from, size_type from_len, char *to, | ||
2327 | 112 | int options = dopt_none ); | ||
2328 | 113 | |||
2329 | 114 | /** | ||
2330 | 115 | * Decodes a Base64-encoded buffer and appends the decoded bytes onto a | ||
2331 | 116 | * vector<char>. Embedded newlines and carriage-returns are skipped. | ||
2332 | 117 | * | ||
2333 | 118 | * @param from A pointer to the buffer to be encoded. | ||
2334 | 119 | * @param from_len The number of bytes to encode. | ||
2335 | 120 | * @param to A pointer to the vector to append the encoded bytes appended onto. | ||
2336 | 121 | * The vector is made large enough to contain the additional bytes. | ||
2337 | 122 | * @param options The decoding options to use. | ||
2338 | 123 | * @return Returns the number of decoded bytes. | ||
2339 | 124 | * @throws invalid_argument if \a options does not have the \c dopt_any_len bit | ||
2340 | 125 | * set and the number of Base64 bytes decoded is not a multiple of 4. | ||
2341 | 126 | * @throws base64::exception if an \c = is encountered unexpectedly or an | ||
2342 | 127 | * invalid byte is encountered. | ||
2343 | 128 | */ | ||
2344 | 129 | size_type decode( char const *from, size_type from_len, std::vector<char> *to, | ||
2345 | 130 | int options = dopt_none ); | ||
2346 | 131 | |||
2347 | 132 | /** | ||
2348 | 133 | * Decodes a Base64-encoded buffer and appends the decoded bytes onto a string. | ||
2349 | 134 | * Embedded newlines and carriage-returns are skipped. | ||
2350 | 135 | * | ||
2351 | 136 | * @tparam ToStringType The string type. | ||
2352 | 137 | * @param from A pointer to the Base64 buffer to be decoded. | ||
2353 | 138 | * @param from_len The number of bytes to decode. | ||
2354 | 139 | * @param to The string to append the decoded bytes to. | ||
2355 | 140 | * @param options The options to use. | ||
2356 | 141 | * @return Returns the number of decoded bytes. | ||
2357 | 142 | * @throws invalid_argument if \a options does not have the \c dopt_any_len bit | ||
2358 | 143 | * set and the number of Base64 bytes decoded is not a multiple of 4. | ||
2359 | 144 | * @throws base64::exception if an \c = is encountered unexpectedly or an | ||
2360 | 145 | * invalid byte is encountered. | ||
2361 | 146 | */ | ||
2362 | 147 | template<class ToStringType> | ||
2363 | 148 | size_type decode( char const *from, size_type from_len, ToStringType *to, | ||
2364 | 149 | int options = dopt_none ) { | ||
2365 | 150 | size_type total_decoded = 0; | ||
2366 | 151 | if ( from_len ) { | ||
2367 | 152 | typename ToStringType::size_type const orig_size = to->size(); | ||
2368 | 153 | to->resize( orig_size + decoded_size( from_len ) ); | ||
2369 | 154 | total_decoded = decode( from, from_len, &to->at( orig_size ), options ); | ||
2370 | 155 | to->resize( orig_size + total_decoded ); | ||
2371 | 156 | } | ||
2372 | 157 | return total_decoded; | ||
2373 | 158 | } | ||
2374 | 159 | |||
2375 | 160 | /** | ||
2376 | 161 | * Decodes a Base64-encoded istream. Embedded newlines and carriage-returns | ||
2377 | 162 | * are skipped. | ||
2378 | 163 | * | ||
2379 | 164 | * @param from The istream to read from until EOF is reached. | ||
2380 | 165 | * @param to The ostream to write the decoded bytes to. | ||
2381 | 166 | * @param options The options to use. | ||
2382 | 167 | * 4 otherwise an exception is thrown; if \a false, missing trailing bytes are | ||
2383 | 168 | * assumed to be padding. | ||
2384 | 169 | * @return Returns the number of decoded bytes. | ||
2385 | 170 | * @throws invalid_argument if \a options does not have the \c dopt_any_len bit | ||
2386 | 171 | * set and the number of Base64 bytes decoded is not a multiple of 4. | ||
2387 | 172 | * @throws base64::exception if an \c = is encountered unexpectedly or an | ||
2388 | 173 | * invalid byte is encountered. | ||
2389 | 174 | */ | ||
2390 | 175 | size_type decode( std::istream &from, std::ostream &to, | ||
2391 | 176 | int options = dopt_none ); | ||
2392 | 177 | |||
2393 | 178 | /** | ||
2394 | 179 | * Decodes a Base64-encoded istream and appends the decoded bytes to a string. | ||
2395 | 180 | * Embedded newlines and carriage-returns are skipped. | ||
2396 | 181 | * | ||
2397 | 182 | * @tparam ToStringType The string type. | ||
2398 | 183 | * @param from The istream to read from until EOF is reached. | ||
2399 | 184 | * @param to The string to append the decoded bytes to. | ||
2400 | 185 | * @param options The options to use. | ||
2401 | 186 | * 4 otherwise an exception is thrown; if \a false, missing trailing bytes are | ||
2402 | 187 | * assumed to be padding. | ||
2403 | 188 | * @return Returns the number of decoded bytes. | ||
2404 | 189 | * @throws invalid_argument if \a options does not have the \c dopt_any_len bit | ||
2405 | 190 | * set and the number of Base64 bytes decoded is not a multiple of 4. | ||
2406 | 191 | * @throws base64::exception if an \c = is encountered unexpectedly or an | ||
2407 | 192 | * invalid byte is encountered. | ||
2408 | 193 | */ | ||
2409 | 194 | template<class ToStringType> | ||
2410 | 195 | size_type decode( std::istream &from, ToStringType *to, | ||
2411 | 196 | int options = dopt_none ) { | ||
2412 | 197 | size_type total_decoded = 0; | ||
2413 | 198 | while ( !from.eof() ) { | ||
2414 | 199 | char from_buf[ 1024 * 4 ], to_buf[ 1024 * 3 ]; | ||
2415 | 200 | std::streamsize gcount; | ||
2416 | 201 | if ( options & dopt_ignore_ws ) | ||
2417 | 202 | gcount = read_without_whitespace( from, from_buf, sizeof from_buf ); | ||
2418 | 203 | else { | ||
2419 | 204 | from.read( from_buf, sizeof from_buf ); | ||
2420 | 205 | gcount = from.gcount(); | ||
2421 | 206 | } | ||
2422 | 207 | if ( gcount ) { | ||
2423 | 208 | size_type const decoded = decode( from_buf, gcount, to_buf, options ); | ||
2424 | 209 | to->append( to_buf, decoded ); | ||
2425 | 210 | total_decoded += decoded; | ||
2426 | 211 | } else | ||
2427 | 212 | break; | ||
2428 | 213 | } | ||
2429 | 214 | return total_decoded; | ||
2430 | 215 | } | ||
2431 | 216 | |||
2432 | 217 | /** | ||
2433 | 218 | * Decodes a Base64-encoded stream and appends the decoded bytes onto a | ||
2434 | 219 | * vector<char;>. | ||
2435 | 220 | * | ||
2436 | 221 | * @param from The istream to read from until EOF is reached. | ||
2437 | 222 | * @param to The string to append the decoded bytes to. | ||
2438 | 223 | * @param options The options to use. | ||
2439 | 224 | * @param Returns the number of decoded bytes. | ||
2440 | 225 | * @throws invalid_argument if \a options does not have the \c dopt_any_len bit | ||
2441 | 226 | * set and the number of Base64 bytes decoded is not a multiple of 4. | ||
2442 | 227 | * @throws base64::exception if an \c = is encountered unexpectedly or an | ||
2443 | 228 | * invalid byte is encountered. | ||
2444 | 229 | */ | ||
2445 | 230 | size_type decode( std::istream &from, std::vector<char> *to, | ||
2446 | 231 | int options = dopt_none ); | ||
2447 | 232 | |||
2448 | 233 | /** | ||
2449 | 234 | * Validates a Base64-encoded buffer. Embedded newlines and carriage-returns | ||
2450 | 235 | * are skipped. | ||
2451 | 236 | * | ||
2452 | 237 | * @param buf A pointer to the Base64 buffer to be validated. | ||
2453 | 238 | * @param buf_len The number of bytes to validate. | ||
2454 | 239 | * @param options The options to use. | ||
2455 | 240 | * @throws invalid_argument if \a options does not have the \c dopt_any_len bit | ||
2456 | 241 | * set and the number of Base64 bytes validated is not a multiple of 4. | ||
2457 | 242 | * @throws base64::exception if an \c = is encountered unexpectedly or an | ||
2458 | 243 | * invalid byte is encountered. | ||
2459 | 244 | * @see decoded_size() | ||
2460 | 245 | */ | ||
2461 | 246 | inline void validate( char const *buf, size_type buf_len, | ||
2462 | 247 | int options = dopt_none ) { | ||
2463 | 248 | decode( buf, buf_len, static_cast<char*>( nullptr ), options ); | ||
2464 | 249 | } | ||
2465 | 250 | |||
2466 | 251 | ////////// Encoding /////////////////////////////////////////////////////////// | ||
2467 | 252 | |||
2468 | 253 | /** | ||
2469 | 254 | * Calculates the number of bytes required to Base64-encode \a n bytes. | ||
2470 | 255 | * | ||
2471 | 256 | * @param n The number of bytes to encode. | ||
2472 | 257 | * @return Returns the number of bytes needed for Base64 encoding. | ||
2473 | 258 | */ | ||
2474 | 259 | inline size_type encoded_size( size_type n ) { | ||
2475 | 260 | return (n + 2) / 3 * 4; | ||
2476 | 261 | } | ||
2477 | 262 | |||
2478 | 263 | /** | ||
2479 | 264 | * Base64-encodes a buffer. | ||
2480 | 265 | * | ||
2481 | 266 | * @param from A pointer to the buffer to be encoded. | ||
2482 | 267 | * @param from_len The number of bytes to encode. | ||
2483 | 268 | * @param to A pointer to the buffer to receive the encoded bytes. The buffer | ||
2484 | 269 | * must be large enough to contain them. Note that the buffer is \e not null | ||
2485 | 270 | * terminated. | ||
2486 | 271 | * @return Returns the number of encoded bytes. | ||
2487 | 272 | * @see encoded_size() | ||
2488 | 273 | */ | ||
2489 | 274 | size_type encode( char const *from, size_type from_len, char *to ); | ||
2490 | 275 | |||
2491 | 276 | /** | ||
2492 | 277 | * Base64-encodes a buffer and appends the encoded bytes onto a | ||
2493 | 278 | * vector<char>. | ||
2494 | 279 | * | ||
2495 | 280 | * @param from A pointer to the buffer to be encoded. | ||
2496 | 281 | * @param from_len The number of bytes to encode. | ||
2497 | 282 | * @param to A pointer to the vector to append the encoded bytes appended onto. | ||
2498 | 283 | * The vector is made large enough to contain the additional bytes. | ||
2499 | 284 | */ | ||
2500 | 285 | size_type encode( char const *from, size_type from_len, std::vector<char> *to ); | ||
2501 | 286 | |||
2502 | 287 | /** | ||
2503 | 288 | * Base64-encodes a buffer and appends the encoded bytes onto a string. | ||
2504 | 289 | * | ||
2505 | 290 | * @tparam ToStringType The string type. | ||
2506 | 291 | * @param from A pointer to the Base64 buffer to be encoded. | ||
2507 | 292 | * @param from_len The number of bytes to encode. | ||
2508 | 293 | * @param to A pointer to the string to append the encoded bytes onto. | ||
2509 | 294 | * @return Returns the number of encoded bytes. | ||
2510 | 295 | */ | ||
2511 | 296 | template<class ToStringType> | ||
2512 | 297 | size_type encode( char const *from, size_type from_len, ToStringType *to ) { | ||
2513 | 298 | size_type total_encoded = 0; | ||
2514 | 299 | if ( from_len ) { | ||
2515 | 300 | typename ToStringType::size_type const orig_size = to->size(); | ||
2516 | 301 | to->resize( orig_size + encoded_size( from_len ) ); | ||
2517 | 302 | total_encoded = encode( from, from_len, &to->at( orig_size ) ); | ||
2518 | 303 | to->resize( orig_size + total_encoded ); | ||
2519 | 304 | } | ||
2520 | 305 | return total_encoded; | ||
2521 | 306 | } | ||
2522 | 307 | |||
2523 | 308 | /** | ||
2524 | 309 | * Base64-encodes one stream and write the encoded bytes to another. | ||
2525 | 310 | * | ||
2526 | 311 | * @param from The istream to read from until EOF is reached. | ||
2527 | 312 | * @param to The ostream to write the encoded bytes to. | ||
2528 | 313 | */ | ||
2529 | 314 | size_type encode( std::istream &from, std::ostream &to ); | ||
2530 | 315 | |||
2531 | 316 | /** | ||
2532 | 317 | * Encodes a stream to Base64 and appends the encoded bytes to a string. | ||
2533 | 318 | * | ||
2534 | 319 | * @tparam ToStringType The string type. | ||
2535 | 320 | * @param from The istream to read from until EOF is reached. | ||
2536 | 321 | * @param to The string to append the encoded bytes to. | ||
2537 | 322 | * @return Returns the number of encoded bytes. | ||
2538 | 323 | */ | ||
2539 | 324 | template<class ToStringType> | ||
2540 | 325 | size_type encode( std::istream &from, ToStringType *to ) { | ||
2541 | 326 | size_type total_encoded = 0; | ||
2542 | 327 | while ( !from.eof() ) { | ||
2543 | 328 | char from_buf[ 1024 * 3 ], to_buf[ 1024 * 4 ]; | ||
2544 | 329 | from.read( from_buf, sizeof from_buf ); | ||
2545 | 330 | if ( std::streamsize const gcount = from.gcount() ) { | ||
2546 | 331 | size_type const encoded = encode( from_buf, gcount, to_buf ); | ||
2547 | 332 | to->append( to_buf, encoded ); | ||
2548 | 333 | total_encoded += encoded; | ||
2549 | 334 | } else | ||
2550 | 335 | break; | ||
2551 | 336 | } | ||
2552 | 337 | return total_encoded; | ||
2553 | 338 | } | ||
2554 | 339 | |||
2555 | 340 | /** | ||
2556 | 341 | * Base64-encodes a stream and appends the encoded bytes onto a | ||
2557 | 342 | * vector<char;>. | ||
2558 | 343 | * | ||
2559 | 344 | * @param from The istream to read from until EOF is reached. | ||
2560 | 345 | * @param to The string to append the encoded bytes to. | ||
2561 | 346 | * @param Returns the number of encoded bytes. | ||
2562 | 347 | */ | ||
2563 | 348 | size_type encode( std::istream &from, std::vector<char> *to ); | ||
2564 | 349 | |||
2565 | 350 | /////////////////////////////////////////////////////////////////////////////// | ||
2566 | 351 | |||
2567 | 352 | } // namespace base64 | ||
2568 | 353 | } // namespace zorba | ||
2569 | 354 | |||
2570 | 355 | #endif /* ZORBA_BASE64_UTIL_H */ | ||
2571 | 356 | /* | ||
2572 | 357 | * Local variables: | ||
2573 | 358 | * mode: c++ | ||
2574 | 359 | * End: | ||
2575 | 360 | */ | ||
2576 | 361 | /* vim:set et sw=2 ts=2: */ | ||
2577 | 0 | 362 | ||
2578 | === modified file 'src/util/icu_streambuf.cpp' | |||
2579 | --- src/util/icu_streambuf.cpp 2012-06-18 10:06:47 +0000 | |||
2580 | +++ src/util/icu_streambuf.cpp 2012-06-26 01:34:26 +0000 | |||
2581 | @@ -15,8 +15,8 @@ | |||
2582 | 15 | */ | 15 | */ |
2583 | 16 | 16 | ||
2584 | 17 | #include "stdafx.h" | 17 | #include "stdafx.h" |
2585 | 18 | #define ZORBA_DEBUG_ICU_STREAMBUF 0 | ||
2586 | 19 | 18 | ||
2587 | 19 | // #define ZORBA_DEBUG_ICU_STREAMBUF | ||
2588 | 20 | #ifdef ZORBA_DEBUG_ICU_STREAMBUF | 20 | #ifdef ZORBA_DEBUG_ICU_STREAMBUF |
2589 | 21 | # include <stdio.h> | 21 | # include <stdio.h> |
2590 | 22 | #endif | 22 | #endif |
2591 | 23 | 23 | ||
2592 | === modified file 'src/util/string/rstring.h' | |||
2593 | --- src/util/string/rstring.h 2012-06-18 10:06:47 +0000 | |||
2594 | +++ src/util/string/rstring.h 2012-06-26 01:34:26 +0000 | |||
2595 | @@ -1884,7 +1884,7 @@ | |||
2596 | 1884 | } | 1884 | } |
2597 | 1885 | 1885 | ||
2598 | 1886 | /** | 1886 | /** |
2600 | 1887 | * Attemts to pre-allocated enough memory to contain the given number of | 1887 | * Attemts to pre-allocate enough memory to contain the given number of |
2601 | 1888 | * bytes. | 1888 | * bytes. |
2602 | 1889 | * | 1889 | * |
2603 | 1890 | * @param n The number of bytes. | 1890 | * @param n The number of bytes. |
2604 | 1891 | 1891 | ||
2605 | === modified file 'src/zorbatypes/binary.cpp' | |||
2606 | --- src/zorbatypes/binary.cpp 2012-06-18 10:06:47 +0000 | |||
2607 | +++ src/zorbatypes/binary.cpp 2012-06-26 01:34:26 +0000 | |||
2608 | @@ -25,32 +25,44 @@ | |||
2609 | 25 | #include "diagnostics/xquery_diagnostics.h" | 25 | #include "diagnostics/xquery_diagnostics.h" |
2610 | 26 | 26 | ||
2611 | 27 | #include "util/ascii_util.h" | 27 | #include "util/ascii_util.h" |
2612 | 28 | #include "util/base64_util.h" | ||
2613 | 28 | #include "util/stl_util.h" | 29 | #include "util/stl_util.h" |
2614 | 29 | 30 | ||
2615 | 31 | #define CATCH_BASE64_EXCEPTION() \ | ||
2616 | 32 | catch ( base64::exception const &e ) { \ | ||
2617 | 33 | throw XQUERY_EXCEPTION( \ | ||
2618 | 34 | err::FORG0001, ERROR_PARAMS( e.invalid_char(), ZED( Base64BadChar ) ) \ | ||
2619 | 35 | ); \ | ||
2620 | 36 | } \ | ||
2621 | 37 | catch ( std::invalid_argument const& ) { \ | ||
2622 | 38 | throw XQUERY_EXCEPTION( \ | ||
2623 | 39 | err::FORG0001, ERROR_PARAMS( "", ZED( Base64Multiple4 ) ) \ | ||
2624 | 40 | ); \ | ||
2625 | 41 | } | ||
2626 | 42 | |||
2627 | 30 | using namespace std; | 43 | using namespace std; |
2628 | 31 | 44 | ||
2642 | 32 | namespace zorba | 45 | namespace zorba { |
2643 | 33 | { | 46 | |
2644 | 34 | 47 | static size_t copy_without_ws( char const *from, size_t len, char *to ) { | |
2645 | 35 | 48 | char const *const end = from + len; | |
2646 | 36 | static const string base64_chars = | 49 | char const *const to_orig = to; |
2647 | 37 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | 50 | for ( ; from < end; ++from ) |
2648 | 38 | "abcdefghijklmnopqrstuvwxyz" | 51 | if ( !ascii::is_space( *from ) ) |
2649 | 39 | "0123456789+/"; | 52 | *to++ = *from; |
2650 | 40 | 53 | return to - to_orig; | |
2638 | 41 | |||
2639 | 42 | inline bool is_base64(char c) | ||
2640 | 43 | { | ||
2641 | 44 | return (isalnum(c) || (c == '+') || (c == '/')); | ||
2651 | 45 | } | 54 | } |
2652 | 46 | 55 | ||
2653 | 47 | 56 | ||
2654 | 48 | bool Base64::parseString(const char* aString, size_t aLength, Base64& aBase64) | 57 | bool Base64::parseString(const char* aString, size_t aLength, Base64& aBase64) |
2655 | 49 | { | 58 | { |
2656 | 50 | aBase64.theData.clear(); | ||
2657 | 51 | try | 59 | try |
2658 | 52 | { | 60 | { |
2660 | 53 | aBase64.insertData(aString, aLength); | 61 | base64::validate( aString, aLength, base64::dopt_ignore_ws ); |
2661 | 62 | aBase64.theData.resize( aLength ); | ||
2662 | 63 | aBase64.theData.resize( | ||
2663 | 64 | copy_without_ws( aString, aLength, &aBase64.theData[0] ) | ||
2664 | 65 | ); | ||
2665 | 54 | } | 66 | } |
2666 | 55 | catch (...) | 67 | catch (...) |
2667 | 56 | { | 68 | { |
2668 | @@ -66,10 +78,13 @@ | |||
2669 | 66 | Base64& aBase64, | 78 | Base64& aBase64, |
2670 | 67 | string& lErrorMessage) | 79 | string& lErrorMessage) |
2671 | 68 | { | 80 | { |
2672 | 69 | aBase64.theData.clear(); | ||
2673 | 70 | try | 81 | try |
2674 | 71 | { | 82 | { |
2676 | 72 | aBase64.insertData(aString, aLength); | 83 | base64::validate( aString, aLength, base64::dopt_ignore_ws ); |
2677 | 84 | aBase64.theData.resize( aLength ); | ||
2678 | 85 | aBase64.theData.resize( | ||
2679 | 86 | copy_without_ws( aString, aLength, &aBase64.theData[0] ) | ||
2680 | 87 | ); | ||
2681 | 73 | } | 88 | } |
2682 | 74 | catch (ZorbaException const& e) | 89 | catch (ZorbaException const& e) |
2683 | 75 | { | 90 | { |
2684 | @@ -82,102 +97,27 @@ | |||
2685 | 82 | 97 | ||
2686 | 83 | void Base64::encode(const zstring& aString, Base64& aResult) | 98 | void Base64::encode(const zstring& aString, Base64& aResult) |
2687 | 84 | { | 99 | { |
2696 | 85 | vector<char> source; | 100 | base64::encode( aString.data(), aString.size(), &aResult.theData ); |
2689 | 86 | source.reserve(aString.size()); | ||
2690 | 87 | |||
2691 | 88 | FOR_EACH( zstring, i, aString ) | ||
2692 | 89 | source.push_back( *i ); | ||
2693 | 90 | |||
2694 | 91 | aResult.theData.clear(); | ||
2695 | 92 | encode(source, aResult.theData); | ||
2697 | 93 | } | 101 | } |
2698 | 94 | 102 | ||
2699 | 95 | 103 | ||
2700 | 96 | void Base64::encode(istream& aStream, Base64& aResult) | 104 | void Base64::encode(istream& aStream, Base64& aResult) |
2701 | 97 | { | 105 | { |
2716 | 98 | vector<char> source; | 106 | base64::encode( aStream, &aResult.theData ); |
2703 | 99 | |||
2704 | 100 | char lC; | ||
2705 | 101 | while (aStream.good()) | ||
2706 | 102 | { | ||
2707 | 103 | aStream.get(lC); | ||
2708 | 104 | if (!aStream.good()) | ||
2709 | 105 | { | ||
2710 | 106 | break; | ||
2711 | 107 | } | ||
2712 | 108 | source.push_back(lC); | ||
2713 | 109 | } | ||
2714 | 110 | |||
2715 | 111 | encode(source, aResult.theData); | ||
2717 | 112 | } | 107 | } |
2718 | 113 | 108 | ||
2719 | 114 | 109 | ||
2720 | 115 | zstring Base64::encode(istream& aStream) | 110 | zstring Base64::encode(istream& aStream) |
2721 | 116 | { | 111 | { |
2722 | 117 | vector<char> source; | ||
2723 | 118 | vector<char> dest; | ||
2724 | 119 | |||
2725 | 120 | char buf[1024]; | ||
2726 | 121 | while (!aStream.eof()) | ||
2727 | 122 | { | ||
2728 | 123 | aStream.read(buf, 1024); | ||
2729 | 124 | source.insert(source.end(), buf, buf + aStream.gcount()); | ||
2730 | 125 | } | ||
2731 | 126 | |||
2732 | 127 | encode(source, dest); | ||
2733 | 128 | |||
2734 | 129 | zstring result; | 112 | zstring result; |
2740 | 130 | result.reserve(dest.size()); | 113 | base64::encode( aStream, &result ); |
2736 | 131 | |||
2737 | 132 | FOR_EACH( vector<char>, i, dest ) | ||
2738 | 133 | result.push_back( *i ); | ||
2739 | 134 | |||
2741 | 135 | return result; | 114 | return result; |
2742 | 136 | } | 115 | } |
2743 | 137 | 116 | ||
2744 | 138 | 117 | ||
2745 | 139 | void Base64::encode(const vector<char>& aSource, vector<char>& aResult) | 118 | void Base64::encode(const vector<char>& aSource, vector<char>& aResult) |
2746 | 140 | { | 119 | { |
2787 | 141 | size_t in_len = aSource.size(); | 120 | base64::encode( &aSource[0], aSource.size(), &aResult ); |
2748 | 142 | size_t lCurPos = 0; | ||
2749 | 143 | int i = 0; | ||
2750 | 144 | int j = 0; | ||
2751 | 145 | char char_array_3[3] = {'\0','\0','\0'}; | ||
2752 | 146 | char char_array_4[4] = {'\0','\0','\0','\0'}; | ||
2753 | 147 | |||
2754 | 148 | while (in_len--) | ||
2755 | 149 | { | ||
2756 | 150 | char_array_3[i++] = aSource[lCurPos++]; | ||
2757 | 151 | if (i == 3) | ||
2758 | 152 | { | ||
2759 | 153 | char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; | ||
2760 | 154 | char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); | ||
2761 | 155 | char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); | ||
2762 | 156 | char_array_4[3] = char_array_3[2] & 0x3f; | ||
2763 | 157 | |||
2764 | 158 | for(i = 0; (i <4) ; i++) | ||
2765 | 159 | aResult.push_back(base64_chars[char_array_4[i]]); | ||
2766 | 160 | i = 0; | ||
2767 | 161 | } | ||
2768 | 162 | } | ||
2769 | 163 | |||
2770 | 164 | if (i) | ||
2771 | 165 | { | ||
2772 | 166 | for(j = i; j < 3; j++) | ||
2773 | 167 | char_array_3[j] = '\0'; | ||
2774 | 168 | |||
2775 | 169 | char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; | ||
2776 | 170 | char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); | ||
2777 | 171 | char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); | ||
2778 | 172 | char_array_4[3] = char_array_3[2] & 0x3f; | ||
2779 | 173 | |||
2780 | 174 | for (j = 0; (j < i + 1); j++) | ||
2781 | 175 | aResult.push_back(base64_chars[char_array_4[j]]); | ||
2782 | 176 | |||
2783 | 177 | while((i++ < 3)) | ||
2784 | 178 | aResult.push_back('='); | ||
2785 | 179 | |||
2786 | 180 | } | ||
2788 | 181 | } | 121 | } |
2789 | 182 | 122 | ||
2790 | 183 | 123 | ||
2791 | @@ -186,110 +126,38 @@ | |||
2792 | 186 | unsigned int in_len, | 126 | unsigned int in_len, |
2793 | 187 | Base64& aResult) | 127 | Base64& aResult) |
2794 | 188 | { | 128 | { |
2835 | 189 | size_t lCurPos = 0; | 129 | base64::encode( (char*)aSource, in_len, &aResult.theData ); |
2796 | 190 | int i = 0; | ||
2797 | 191 | int j = 0; | ||
2798 | 192 | char char_array_3[3] = {'\0','\0','\0'}; | ||
2799 | 193 | char char_array_4[4] = {'\0','\0','\0','\0'}; | ||
2800 | 194 | |||
2801 | 195 | aResult.theData.reserve(in_len * 8 / 6 + 10); | ||
2802 | 196 | while (in_len--) | ||
2803 | 197 | { | ||
2804 | 198 | char_array_3[i++] = aSource[lCurPos++]; | ||
2805 | 199 | if (i == 3) | ||
2806 | 200 | { | ||
2807 | 201 | char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; | ||
2808 | 202 | char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); | ||
2809 | 203 | char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); | ||
2810 | 204 | char_array_4[3] = char_array_3[2] & 0x3f; | ||
2811 | 205 | |||
2812 | 206 | for(i = 0; (i <4) ; i++) | ||
2813 | 207 | aResult.theData.push_back(base64_chars[char_array_4[i]]); | ||
2814 | 208 | i = 0; | ||
2815 | 209 | } | ||
2816 | 210 | } | ||
2817 | 211 | |||
2818 | 212 | if (i) | ||
2819 | 213 | { | ||
2820 | 214 | for(j = i; j < 3; j++) | ||
2821 | 215 | char_array_3[j] = '\0'; | ||
2822 | 216 | |||
2823 | 217 | char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; | ||
2824 | 218 | char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); | ||
2825 | 219 | char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); | ||
2826 | 220 | char_array_4[3] = char_array_3[2] & 0x3f; | ||
2827 | 221 | |||
2828 | 222 | for (j = 0; (j < i + 1); j++) | ||
2829 | 223 | aResult.theData.push_back(base64_chars[char_array_4[j]]); | ||
2830 | 224 | |||
2831 | 225 | while((i++ < 3)) | ||
2832 | 226 | aResult.theData.push_back('='); | ||
2833 | 227 | |||
2834 | 228 | } | ||
2836 | 229 | } | 130 | } |
2837 | 230 | 131 | ||
2838 | 231 | 132 | ||
2840 | 232 | zstring Base64::decode(istream& aStream) | 133 | void Base64::decode(istream& aStream, zstring *result) |
2841 | 233 | { | 134 | { |
2850 | 234 | vector<char> source; | 135 | try { |
2851 | 235 | vector<char> dest; | 136 | base64::decode( |
2852 | 236 | 137 | aStream, result, base64::dopt_any_len | base64::dopt_ignore_ws | |
2853 | 237 | char buf[1024]; | 138 | ); |
2846 | 238 | while (!aStream.eof()) | ||
2847 | 239 | { | ||
2848 | 240 | aStream.read(buf, 1024); | ||
2849 | 241 | source.insert(source.end(), buf, buf + aStream.gcount()); | ||
2854 | 242 | } | 139 | } |
2865 | 243 | 140 | CATCH_BASE64_EXCEPTION() | |
2856 | 244 | decode(source, dest); | ||
2857 | 245 | |||
2858 | 246 | zstring result; | ||
2859 | 247 | result.reserve(dest.size()); | ||
2860 | 248 | |||
2861 | 249 | FOR_EACH( vector<char>, i, dest ) | ||
2862 | 250 | result.push_back( *i ); | ||
2863 | 251 | |||
2864 | 252 | return result; | ||
2866 | 253 | } | 141 | } |
2867 | 254 | 142 | ||
2868 | 255 | |||
2869 | 256 | void Base64::decode(const vector<char>& aSource, vector<char>& aResult) | 143 | void Base64::decode(const vector<char>& aSource, vector<char>& aResult) |
2870 | 257 | { | 144 | { |
2906 | 258 | size_t in_len = aSource.size(); | 145 | try { |
2907 | 259 | int i = 0; | 146 | base64::decode( |
2908 | 260 | int j = 0; | 147 | &aSource[0], aSource.size(), &aResult, |
2909 | 261 | int in_ = 0; | 148 | base64::dopt_any_len | base64::dopt_ignore_ws |
2910 | 262 | char char_array_4[4], char_array_3[3]; | 149 | ); |
2911 | 263 | 150 | } | |
2912 | 264 | while (in_len-- && ( aSource[in_] != '=') && is_base64(aSource[in_])) { | 151 | CATCH_BASE64_EXCEPTION() |
2913 | 265 | char_array_4[i++] = aSource[in_]; in_++; | 152 | } |
2914 | 266 | if (i ==4) { | 153 | |
2915 | 267 | for (i = 0; i <4; i++) | 154 | void Base64::decode( char const *from, size_t from_len, zstring *to ) { |
2916 | 268 | char_array_4[i] = (char)base64_chars.find(char_array_4[i]); | 155 | try { |
2917 | 269 | 156 | base64::decode( | |
2918 | 270 | char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); | 157 | from, from_len, to, base64::dopt_any_len | base64::dopt_ignore_ws |
2919 | 271 | char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); | 158 | ); |
2920 | 272 | char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; | 159 | } |
2921 | 273 | 160 | CATCH_BASE64_EXCEPTION() | |
2887 | 274 | for (i = 0; (i < 3); i++) | ||
2888 | 275 | aResult.push_back(char_array_3[i]); | ||
2889 | 276 | i = 0; | ||
2890 | 277 | } | ||
2891 | 278 | } | ||
2892 | 279 | |||
2893 | 280 | if (i) { | ||
2894 | 281 | for (j = i; j <4; j++) | ||
2895 | 282 | char_array_4[j] = 0; | ||
2896 | 283 | |||
2897 | 284 | for (j = 0; j <4; j++) | ||
2898 | 285 | char_array_4[j] = (char)base64_chars.find(char_array_4[j]); | ||
2899 | 286 | |||
2900 | 287 | char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); | ||
2901 | 288 | char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); | ||
2902 | 289 | char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; | ||
2903 | 290 | |||
2904 | 291 | for (j = 0; (j < i - 1); j++) aResult.push_back(char_array_3[j]); | ||
2905 | 292 | } | ||
2922 | 293 | } | 161 | } |
2923 | 294 | 162 | ||
2924 | 295 | 163 | ||
2925 | @@ -303,88 +171,12 @@ | |||
2926 | 303 | 171 | ||
2927 | 304 | Base64::Base64(const unsigned char *bin_data, size_t len) | 172 | Base64::Base64(const unsigned char *bin_data, size_t len) |
2928 | 305 | { | 173 | { |
3011 | 306 | std::vector<char> tmp; | 174 | try { |
3012 | 307 | tmp.reserve(len); | 175 | base64::encode( (char const*)bin_data, len, &theData ); |
3013 | 308 | tmp.insert(tmp.begin(), (const char*)bin_data, ((const char*)bin_data) + len); | 176 | } |
3014 | 309 | theData.reserve(len); | 177 | CATCH_BASE64_EXCEPTION() |
3015 | 310 | encode(tmp, theData); | 178 | } |
3016 | 311 | } | 179 | |
2935 | 312 | |||
2936 | 313 | |||
2937 | 314 | void Base64::insertData(const char* str, size_t len) | ||
2938 | 315 | { | ||
2939 | 316 | ascii::size_type pos = 0; | ||
2940 | 317 | |||
2941 | 318 | ascii::skip_whitespace(str, len, &pos); | ||
2942 | 319 | |||
2943 | 320 | for (size_t i = pos; i < len; ++i) | ||
2944 | 321 | { | ||
2945 | 322 | char lChar = str[i]; | ||
2946 | 323 | |||
2947 | 324 | if (lChar == ' ') | ||
2948 | 325 | { | ||
2949 | 326 | // do nothing | ||
2950 | 327 | } | ||
2951 | 328 | else if ((lChar >= 65 && lChar <= 90) // A-Z | ||
2952 | 329 | || (lChar >= 97 && lChar <= 122) // a-z | ||
2953 | 330 | || (lChar >= 48 && lChar <= 57) // 0-9 | ||
2954 | 331 | || (lChar == 43) // + | ||
2955 | 332 | || (lChar == 47)) // / | ||
2956 | 333 | { | ||
2957 | 334 | theData.push_back(lChar); | ||
2958 | 335 | } | ||
2959 | 336 | else if (lChar == '=' && i > 0 && i == (len-2) && str[i+1] == '=' ) | ||
2960 | 337 | { | ||
2961 | 338 | if (str[i-1] == 'A' || | ||
2962 | 339 | str[i-1] == 'Q' || | ||
2963 | 340 | str[i-1] == 'g' || | ||
2964 | 341 | str[i-1] == 'w') | ||
2965 | 342 | { | ||
2966 | 343 | theData.push_back('='); | ||
2967 | 344 | theData.push_back('='); | ||
2968 | 345 | ++i; | ||
2969 | 346 | } | ||
2970 | 347 | else | ||
2971 | 348 | { | ||
2972 | 349 | throw XQUERY_EXCEPTION( | ||
2973 | 350 | err::FORG0001, ERROR_PARAMS( "==", ZED( Base64EqualsEquals ) ) | ||
2974 | 351 | ); | ||
2975 | 352 | } | ||
2976 | 353 | } | ||
2977 | 354 | else if (lChar == '=' && i > 0 && i == (len-1)) | ||
2978 | 355 | { | ||
2979 | 356 | switch(str[i-1]) | ||
2980 | 357 | { | ||
2981 | 358 | case 'A': case 'E': case 'I': case 'M': case 'Q': case 'U': case 'Y': | ||
2982 | 359 | case 'c': case 'g': case 'k': case 'o': case 's': case 'w': case '0': | ||
2983 | 360 | case '4': case '8': | ||
2984 | 361 | theData.push_back('='); | ||
2985 | 362 | break; | ||
2986 | 363 | default: | ||
2987 | 364 | throw XQUERY_EXCEPTION( | ||
2988 | 365 | err::FORG0001, ERROR_PARAMS( '=', ZED( Base64Equals ) ) | ||
2989 | 366 | ); | ||
2990 | 367 | } | ||
2991 | 368 | } | ||
2992 | 369 | else if ( ascii::is_space(lChar) ) | ||
2993 | 370 | { | ||
2994 | 371 | // ignore it | ||
2995 | 372 | } | ||
2996 | 373 | else | ||
2997 | 374 | { | ||
2998 | 375 | throw XQUERY_EXCEPTION( | ||
2999 | 376 | err::FORG0001, ERROR_PARAMS( str[i], ZED( Base64BadChar ) ) | ||
3000 | 377 | ); | ||
3001 | 378 | } | ||
3002 | 379 | } | ||
3003 | 380 | |||
3004 | 381 | if (theData.size() % 4 != 0) | ||
3005 | 382 | { | ||
3006 | 383 | throw XQUERY_EXCEPTION( | ||
3007 | 384 | err::FORG0001, ERROR_PARAMS( "", ZED( Base64Multiple4 ) ) | ||
3008 | 385 | ); | ||
3009 | 386 | } | ||
3010 | 387 | } | ||
3017 | 388 | 180 | ||
3018 | 389 | 181 | ||
3019 | 390 | bool Base64::equal(const Base64& aBase64) const | 182 | bool Base64::equal(const Base64& aBase64) const |
3020 | @@ -396,7 +188,7 @@ | |||
3021 | 396 | vector<char>::const_iterator lEnd0 = theData.end(); | 188 | vector<char>::const_iterator lEnd0 = theData.end(); |
3022 | 397 | vector<char>::const_iterator lIter1 = aBase64.theData.begin(); | 189 | vector<char>::const_iterator lIter1 = aBase64.theData.begin(); |
3023 | 398 | 190 | ||
3025 | 399 | for (; lIter0 != lEnd0 ; ) | 191 | while ( lIter0 != lEnd0 ) |
3026 | 400 | { | 192 | { |
3027 | 401 | if (*lIter0 != *lIter1) | 193 | if (*lIter0 != *lIter1) |
3028 | 402 | return false; | 194 | return false; |
3029 | @@ -408,31 +200,28 @@ | |||
3030 | 408 | 200 | ||
3031 | 409 | zstring Base64::str() const | 201 | zstring Base64::str() const |
3032 | 410 | { | 202 | { |
3036 | 411 | stringstream lStream; | 203 | zstring result; |
3037 | 412 | lStream << *this; | 204 | vector<char>::const_iterator lIter = theData.begin(); |
3038 | 413 | return zstring(lStream.str()); | 205 | vector<char>::const_iterator lEnd = theData.end(); |
3039 | 206 | for( ; lIter != lEnd ; ++lIter) | ||
3040 | 207 | { | ||
3041 | 208 | result.push_back( *lIter ); | ||
3042 | 209 | } | ||
3043 | 210 | return result; | ||
3044 | 414 | } | 211 | } |
3045 | 415 | 212 | ||
3046 | 416 | 213 | ||
3047 | 417 | zstring Base64::decode() const | 214 | zstring Base64::decode() const |
3048 | 418 | { | 215 | { |
3049 | 419 | vector<char> lDecodedData; | ||
3050 | 420 | |||
3051 | 421 | Base64::decode(theData, lDecodedData); | ||
3052 | 422 | |||
3053 | 423 | zstring result; | 216 | zstring result; |
3059 | 424 | result.reserve( lDecodedData.size() ); | 217 | base64::decode( &theData[0], theData.size(), &result ); |
3055 | 425 | |||
3056 | 426 | FOR_EACH( vector<char>, i, lDecodedData ) | ||
3057 | 427 | result.push_back( *i ); | ||
3058 | 428 | |||
3060 | 429 | return result; | 218 | return result; |
3061 | 430 | } | 219 | } |
3062 | 431 | 220 | ||
3063 | 432 | 221 | ||
3064 | 433 | void Base64::decode(vector<char>& aResult) | 222 | void Base64::decode(vector<char>& aResult) |
3065 | 434 | { | 223 | { |
3067 | 435 | Base64::decode(theData, aResult); | 224 | base64::decode( &theData[0], theData.size(), &aResult ); |
3068 | 436 | } | 225 | } |
3069 | 437 | 226 | ||
3070 | 438 | 227 | ||
3071 | @@ -466,6 +255,7 @@ | |||
3072 | 466 | return os; | 255 | return os; |
3073 | 467 | } | 256 | } |
3074 | 468 | 257 | ||
3075 | 258 | /////////////////////////////////////////////////////////////////////////////// | ||
3076 | 469 | 259 | ||
3077 | 470 | const char* Base16::ENCODE_TABLE = "0123456789ABCDEF"; | 260 | const char* Base16::ENCODE_TABLE = "0123456789ABCDEF"; |
3078 | 471 | 261 | ||
3079 | @@ -662,6 +452,7 @@ | |||
3080 | 662 | return os; | 452 | return os; |
3081 | 663 | } | 453 | } |
3082 | 664 | 454 | ||
3083 | 455 | /////////////////////////////////////////////////////////////////////////////// | ||
3084 | 665 | 456 | ||
3085 | 666 | } // namespace zorba | 457 | } // namespace zorba |
3086 | 667 | /* vim:set et sw=2 ts=2: */ | 458 | /* vim:set et sw=2 ts=2: */ |
3087 | 668 | 459 | ||
3088 | === modified file 'src/zorbatypes/binary.h' | |||
3089 | --- src/zorbatypes/binary.h 2012-06-18 10:06:47 +0000 | |||
3090 | +++ src/zorbatypes/binary.h 2012-06-26 01:34:26 +0000 | |||
3091 | @@ -76,7 +76,9 @@ | |||
3092 | 76 | 76 | ||
3093 | 77 | static void decode(const std::vector<char>&, std::vector<char>&); | 77 | static void decode(const std::vector<char>&, std::vector<char>&); |
3094 | 78 | 78 | ||
3096 | 79 | static zstring decode(std::istream& aStream); | 79 | static void decode(std::istream& aStream, zstring*); |
3097 | 80 | |||
3098 | 81 | static void decode(char const*, size_t, zstring*); | ||
3099 | 80 | 82 | ||
3100 | 81 | public: | 83 | public: |
3101 | 82 | Base64(const Base64& aBase64) | 84 | Base64(const Base64& aBase64) |
3102 | @@ -90,8 +92,6 @@ | |||
3103 | 90 | 92 | ||
3104 | 91 | Base64() {} | 93 | Base64() {} |
3105 | 92 | 94 | ||
3106 | 93 | virtual ~Base64() {} | ||
3107 | 94 | |||
3108 | 95 | const std::vector<char>& getData() const { return theData; } | 95 | const std::vector<char>& getData() const { return theData; } |
3109 | 96 | 96 | ||
3110 | 97 | size_t size() const { return theData.size(); } | 97 | size_t size() const { return theData.size(); } |
3111 | @@ -105,9 +105,6 @@ | |||
3112 | 105 | void decode(std::vector<char>&); | 105 | void decode(std::vector<char>&); |
3113 | 106 | 106 | ||
3114 | 107 | uint32_t hash() const; | 107 | uint32_t hash() const; |
3115 | 108 | |||
3116 | 109 | private: | ||
3117 | 110 | void insertData(const char* aCharStar, size_t len); | ||
3118 | 111 | }; | 108 | }; |
3119 | 112 | 109 | ||
3120 | 113 | 110 |
Did the streambuf api (already released in 2.5) change?