1/*
2 SPDX-FileCopyrightText: 2000-2001 Dawit Alemayehu <adawit@kde.org>
3 SPDX-FileCopyrightText: 2001 Rik Hemsley (rikkus) <rik@kde.org>
4 SPDX-FileCopyrightText: 2001-2002 Marc Mutz <mutz@kde.org>
5
6 SPDX-License-Identifier: LGPL-2.0-only
7
8 The quoted-printable codec as described in RFC 2045, section 6.7. is by
9 Rik Hemsley (C) 2001.
10*/
11
12#ifndef KCODECS_H
13#define KCODECS_H
14
15#include <kcodecs_export.h>
16
17#include <QString>
18
19#include <memory>
20
21class QByteArray;
22class QIODevice;
23
24/**
25 * A wrapper class for the most commonly used encoding and
26 * decoding algorithms. Currently there is support for encoding
27 * and decoding input using base64, uu and the quoted-printable
28 * specifications.
29 *
30 * \b Usage:
31 *
32 * \code
33 * QByteArray input = "Aladdin:open sesame";
34 * QByteArray result = KCodecs::base64Encode(input);
35 * cout << "Result: " << result.data() << endl;
36 * \endcode
37 *
38 * <pre>
39 * Output should be
40 * Result: QWxhZGRpbjpvcGVuIHNlc2FtZQ==
41 * </pre>
42 *
43 * The above example makes use of the convenience functions
44 * (ones that accept/return null-terminated strings) to encode/decode
45 * a string. If what you need is to encode or decode binary data, then
46 * it is highly recommended that you use the functions that take an input
47 * and output QByteArray as arguments. These functions are specifically
48 * tailored for encoding and decoding binary data.
49 *
50 * @short A collection of commonly used encoding and decoding algorithms.
51 * @author Dawit Alemayehu <adawit@kde.org>
52 * @author Rik Hemsley <rik@kde.org>
53 */
54namespace KCodecs
55{
56/**
57 * Encodes the given data using the quoted-printable algorithm.
58 *
59 * @param in data to be encoded.
60 * @param useCRLF if true the input data is expected to have
61 * CRLF line breaks and the output will have CRLF line
62 * breaks, too.
63 * @return quoted-printable encoded string.
64 */
65KCODECS_EXPORT QByteArray quotedPrintableEncode(QByteArrayView in, bool useCRLF = true);
66
67/**
68 * Encodes the given data using the quoted-printable algorithm.
69 *
70 * Use this function if you want the result of the encoding
71 * to be placed in another array which cuts down the number
72 * of copy operation that have to be performed in the process.
73 * This is also the preferred method for encoding binary data.
74 *
75 * NOTE: the output array is first reset and then resized
76 * appropriately before use, hence, all data stored in the
77 * output array will be lost.
78 *
79 * @param in data to be encoded.
80 * @param out encoded data.
81 * @param useCRLF if true the input data is expected to have
82 * CRLF line breaks and the output will have CRLF line
83 * breaks, too.
84 */
85KCODECS_EXPORT void quotedPrintableEncode(QByteArrayView in, QByteArray &out, bool useCRLF);
86
87/**
88 * Decodes a quoted-printable encoded data.
89 *
90 * Accepts data with CRLF or standard unix line breaks.
91 *
92 * @param in data to be decoded.
93 * @return decoded string.
94 * @since 5.5
95 */
96KCODECS_EXPORT QByteArray quotedPrintableDecode(QByteArrayView in);
97
98/**
99 * Decodes a quoted-printable encoded data.
100 *
101 * Accepts data with CRLF or standard unix line breaks.
102 * Use this function if you want the result of the decoding
103 * to be placed in another array which cuts down the number
104 * of copy operation that have to be performed in the process.
105 * This is also the preferred method for decoding an encoded
106 * binary data.
107 *
108 * NOTE: the output array is first reset and then resized
109 * appropriately before use, hence, all data stored in the
110 * output array will be lost.
111 *
112 * @param in data to be decoded.
113 * @param out decoded data.
114 */
115KCODECS_EXPORT void quotedPrintableDecode(QByteArrayView in, QByteArray &out);
116
117/**
118 * Decodes the given data using the uudecode algorithm.
119 *
120 * Any 'begin' and 'end' lines like those generated by
121 * the utilities in unix and unix-like OS will be
122 * automatically ignored.
123 *
124 * @param in data to be decoded.
125 * @return decoded string.
126 */
127KCODECS_EXPORT QByteArray uudecode(QByteArrayView in);
128
129/**
130 * Decodes the given data using the uudecode algorithm.
131 *
132 * Use this function if you want the result of the decoding
133 * to be placed in another array which cuts down the number
134 * of copy operation that have to be performed in the process.
135 * This is the preferred method for decoding binary data.
136 *
137 * Any 'begin' and 'end' lines like those generated by
138 * the utilities in unix and unix-like OS will be
139 * automatically ignored.
140 *
141 * NOTE: the output array is first reset and then resized
142 * appropriately before use, hence, all data stored in the
143 * output array will be lost.
144 *
145 * @param in data to be decoded.
146 * @param out uudecoded data.
147 */
148KCODECS_EXPORT void uudecode(QByteArrayView in, QByteArray &out);
149
150/**
151 * Encodes the given data using the base64 algorithm.
152 *
153 * The boolean argument determines if the encoded data is
154 * going to be restricted to 76 characters or less per line
155 * as specified by RFC 2045. If @p insertLFs is true, then
156 * there will be 76 characters or less per line.
157 *
158 * @param in data to be encoded.
159 * @param insertLFs limit the number of characters per line.
160 *
161 * @return base64 encoded string.
162 * @since 5.5
163 */
164KCODECS_EXPORT QByteArray base64Encode(QByteArrayView in);
165
166/**
167 * Encodes the given data using the base64 algorithm.
168 *
169 * Use this function if you want the result of the encoding
170 * to be placed in another array which cuts down the number
171 * of copy operation that have to be performed in the process.
172 * This is also the preferred method for encoding binary data.
173 *
174 * The boolean argument determines if the encoded data is going
175 * to be restricted to 76 characters or less per line as specified
176 * by RFC 2045. If @p insertLFs is true, then there will be 76
177 * characters or less per line.
178 *
179 * NOTE: the output array is first reset and then resized
180 * appropriately before use, hence, all data stored in the
181 * output array will be lost.
182 *
183 * @param in data to be encoded.
184 * @param out encoded data.
185 * @param insertLFs limit the number of characters per line.
186 */
187KCODECS_EXPORT void base64Encode(QByteArrayView in, QByteArray &out, bool insertLFs = false);
188
189/**
190 * Decodes the given data that was encoded using the
191 * base64 algorithm.
192 *
193 * @param in data to be decoded.
194 * @return decoded string.
195 */
196KCODECS_EXPORT QByteArray base64Decode(QByteArrayView in);
197
198/**
199 * Decodes the given data that was encoded with the base64
200 * algorithm.
201 *
202 * Use this function if you want the result of the decoding
203 * to be placed in another array which cuts down the number
204 * of copy operation that have to be performed in the process.
205 * This is also the preferred method for decoding an encoded
206 * binary data.
207 *
208 * NOTE: the output array is first reset and then resized
209 * appropriately before use, hence, all data stored in the
210 * output array will be lost.
211 *
212 * @param in data to be decoded.
213 * @param out decoded data.
214 */
215KCODECS_EXPORT void base64Decode(QByteArrayView in, QByteArray &out);
216
217/**
218 * Decodes string @p text according to RFC2047,
219 * i.e., the construct =?charset?[qb]?encoded?=
220 *
221 * @param text source string
222 * @returns the decoded string
223 */
224KCODECS_EXPORT QString decodeRFC2047String(QStringView text);
225
226/**
227 * Charset options for RFC2047 encoder
228 * @since 5.5
229 */
230enum CharsetOption {
231 NoOption = 0, /// No special option
232 ForceDefaultCharset = 1, /// Force use of the default charset
233};
234
235/**
236 * Decodes string @p src according to RFC2047, i.e. the construct
237 * =?charset?[qb]?encoded?=
238 *
239 * @param src source string.
240 * @param usedCS the name of any detected charset or, in case of multiple
241 * different ones, "UTF-8" as that of a super charset is
242 * returned here
243 * @param defaultCS the charset to use in case the detected
244 * one isn't known to us.
245 * @param option options for the encoder
246 *
247 * @return the decoded string.
248 * @since 5.5
249 */
250KCODECS_EXPORT QString decodeRFC2047String(QByteArrayView src, QByteArray *usedCS, const QByteArray &defaultCS = QByteArray(), CharsetOption option = NoOption);
251
252/**
253 * Encodes string @p src according to RFC2047 using charset @p charset.
254 *
255 * This function also makes commas, quotes and other characters part of the encoded name, for example
256 * the string "Jöhn Döe" <john@example.com"> would be encoded as <encoded word for "Jöhn Döe"> <john@example.com>,
257 * i.e. the opening and closing quote mark would be part of the encoded word.
258 * Therefore don't use this function for input strings that contain semantically meaningful characters,
259 * like the quoting marks in this example.
260 *
261 * @param src source string.
262 * @param charset charset to use. If it can't encode the string, UTF-8 will be used instead.
263 * @return the encoded string.
264 * @since 5.5
265 */
266KCODECS_EXPORT QByteArray encodeRFC2047String(QStringView src, const QByteArray &charset);
267
268/**
269 * Decodes the given data that was encoded using the
270 * base45 codec.
271 *
272 * @param in data to be decoded.
273 * @return decoded string.
274 * @since 5.84
275 * @see https://datatracker.ietf.org/doc/draft-faltstrom-base45/
276 */
277KCODECS_EXPORT QByteArray base45Decode(QByteArrayView in);
278
279class Encoder;
280class EncoderPrivate;
281class Decoder;
282class DecoderPrivate;
283
284/**
285 @class KCodecs::Codec kcodecs.h KCodecs
286
287 @glossary @anchor MIME @anchor mime @b MIME:
288 <b>Multipurpose Internet Mail Extensions</b> or @acronym MIME is an
289 Internet Standard that extends the format of e-mail to support text in
290 character sets other than US-ASCII, non-text attachments, multi-part message
291 bodies, and header information in non-ASCII character sets. Virtually all
292 human-written Internet e-mail and a fairly large proportion of automated
293 e-mail is transmitted via @acronym SMTP in MIME format. Internet e-mail is
294 so closely associated with the SMTP and MIME standards that it is sometimes
295 called SMTP/MIME e-mail. The content types defined by MIME standards are
296 also of growing importance outside of e-mail, such as in communication
297 protocols like @acronym HTTP for the World Wide Web. MIME is also a
298 fundamental component of communication protocols such as HTTP, which
299 requires that data be transmitted in the context of e-mail-like messages,
300 even though the data may not actually be e-mail.
301
302 @glossary @anchor codec @anchor codecs @anchor Codec @anchor Codecs @b codec:
303 a program capable of performing encoding and decoding on a digital data
304 stream. Codecs encode data for storage or encryption and decode it for
305 viewing or editing.
306
307 @glossary @anchor CRLF @b CRLF: a "Carriage Return (0x0D)" followed by a
308 "Line Feed (0x0A)", two ASCII control characters used to represent a
309 newline on some operating systems, notably DOS and Microsoft Windows.
310
311 @glossary @anchor LF @b LF: a "Line Feed (0x0A)" ASCII control character used
312 to represent a newline on some operating systems, notably Unix, Unix-like,
313 and Linux.
314
315 @brief An abstract base class of @ref codecs for common mail transfer encodings.
316
317 Provides an abstract base class of @ref codecs like base64 and quoted-printable.
318 Implemented as a singleton.
319
320 @authors Marc Mutz \<mutz@kde.org\>
321 @since 5.5
322*/
323class KCODECS_EXPORT Codec
324{
325public:
326 enum NewlineType {
327 NewlineLF,
328 NewlineCRLF,
329 };
330
331 /**
332 Returns a codec associated with the specified @p name.
333
334 @param name is a valid codec name.
335 */
336 static Codec *codecForName(QByteArrayView name);
337
338 /**
339 Computes the maximum size, in characters, needed for the encoding.
340
341 @param insize is the number of input characters to be encoded.
342 @param newline whether make new lines using @ref CRLF, or @ref LF (default is @ref LF).
343
344 @return the maximum number of characters in the encoding.
345 */
346 virtual qsizetype maxEncodedSizeFor(qsizetype insize, NewlineType newline = NewlineLF) const = 0;
347
348 /**
349 Computes the maximum size, in characters, needed for the deccoding.
350
351 @param insize is the number of input characters to be decoded.
352 @param newline whether make new lines using @ref CRLF, or @ref LF (default is @ref LF).
353
354 @return the maximum number of characters in the decoding.
355 */
356 virtual qsizetype maxDecodedSizeFor(qsizetype insize, NewlineType newline = NewlineLF) const = 0;
357
358 /**
359 Creates the encoder for the codec.
360
361 @param newline whether make new lines using @ref CRLF, or @ref LF (default is @ref LF).
362
363 @return a pointer to an instance of the codec's encoder.
364 */
365 virtual Encoder *makeEncoder(NewlineType newline = NewlineLF) const = 0;
366
367 /**
368 Creates the decoder for the codec.
369
370 @param newline whether make new lines using @ref CRLF, or @ref LF (default is @ref LF).
371
372 @return a pointer to an instance of the codec's decoder.
373 */
374 virtual Decoder *makeDecoder(NewlineType newline = NewlineLF) const = 0;
375
376 /**
377 Convenience wrapper that can be used for small chunks of data
378 when you can provide a large enough buffer. The default
379 implementation creates an Encoder and uses it.
380
381 Encodes a chunk of bytes starting at @p scursor and extending to
382 @p send into the buffer described by @p dcursor and @p dend.
383
384 This function doesn't support chaining of blocks. The returned
385 block cannot be added to, but you don't need to finalize it, too.
386
387 Example usage (@p in contains the input data):
388 <pre>
389 KCodecs::Codec *codec = KCodecs::Codec::codecForName("base64");
390 if (!codec) {
391 qFatal() << "no base64 codec found!?";
392 }
393 QByteArray out(in.size() * 1.4); // crude maximal size of b64 encoding
394 QByteArray::Iterator iit = in.begin();
395 QByteArray::Iterator oit = out.begin();
396 if (!codec->encode(iit, in.end(), oit, out.end())) {
397 qDebug() << "output buffer too small";
398 return;
399 }
400 qDebug() << "Size of encoded data:" << oit - out.begin();
401 </pre>
402
403 @param scursor is a pointer to the start of the input buffer.
404 @param send is a pointer to the end of the input buffer.
405 @param dcursor is a pointer to the start of the output buffer.
406 @param dend is a pointer to the end of the output buffer.
407 @param newline whether make new lines using @ref CRLF, or @ref LF (default is @ref LF).
408
409 @return false if the encoded data didn't fit into the output buffer;
410 true otherwise.
411 */
412 virtual bool encode(const char *&scursor, const char *const send, char *&dcursor, const char *const dend, NewlineType newline = NewlineLF) const;
413
414 /**
415 Convenience wrapper that can be used for small chunks of data
416 when you can provide a large enough buffer. The default
417 implementation creates a Decoder and uses it.
418
419 Decodes a chunk of bytes starting at @p scursor and extending to
420 @p send into the buffer described by @p dcursor and @p dend.
421
422 This function doesn't support chaining of blocks. The returned
423 block cannot be added to, but you don't need to finalize it, too.
424
425 Example usage (@p in contains the input data):
426 <pre>
427 KCodecs::Codec *codec = KCodecs::Codec::codecForName("base64");
428 if (!codec) {
429 qFatal() << "no base64 codec found!?";
430 }
431 QByteArray out(in.size()); // good guess for any encoding...
432 QByteArray::Iterator iit = in.begin();
433 QByteArray::Iterator oit = out.begin();
434 if (!codec->decode(iit, in.end(), oit, out.end())) {
435 qDebug() << "output buffer too small";
436 return;
437 }
438 qDebug() << "Size of decoded data:" << oit - out.begin();
439 </pre>
440
441 @param scursor is a pointer to the start of the input buffer.
442 @param send is a pointer to the end of the input buffer.
443 @param dcursor is a pointer to the start of the output buffer.
444 @param dend is a pointer to the end of the output buffer.
445 @param newline whether make new lines using @ref CRLF, or @ref LF (default is @ref LF).
446
447 @return false if the decoded data didn't fit into the output buffer;
448 true otherwise.
449 */
450 virtual bool decode(const char *&scursor, const char *const send, char *&dcursor, const char *const dend, NewlineType newline = NewlineLF) const;
451
452 /**
453 Even more convenient, but also a bit slower and more memory
454 intensive, since it allocates storage for the worst case and then
455 shrinks the result QByteArray to the actual size again.
456
457 For use with small @p src.
458
459 @param src is the data to encode.
460 @param newline whether make new lines using @ref CRLF, or @ref LF (default is @ref LF).
461 */
462 QByteArray encode(QByteArrayView src, NewlineType newline = NewlineLF) const;
463
464 /**
465 Even more convenient, but also a bit slower and more memory
466 intensive, since it allocates storage for the worst case and then
467 shrinks the result QByteArray to the actual size again.
468
469 For use with small @p src.
470
471 @param src is the data to decode.
472 @param newline whether make new lines using @ref CRLF, or @ref LF (default is @ref LF).
473 */
474 QByteArray decode(QByteArrayView src, NewlineType newline = NewlineLF) const;
475
476 /**
477 Returns the name of the encoding. Guaranteed to be lowercase.
478 */
479 virtual const char *name() const = 0;
480
481 /**
482 Destroys the codec.
483 */
484 virtual ~Codec()
485 {
486 }
487
488protected:
489 /**
490 Constructs the codec.
491 */
492 Codec()
493 {
494 }
495};
496
497/**
498 @class KCodecs::Decoder kcodecs.h KCodecs
499
500 @brief Stateful CTE decoder class
501
502 Stateful decoder class, modelled after QTextDecoder.
503
504 @section Overview
505
506 KCodecs decoders are designed to be able to process encoded data in
507 chunks of arbitrary size and to work with output buffers of also
508 arbitrary size. They maintain any state necessary to go on where
509 the previous call left off.
510
511 The class consists of only two methods of interest: see decode,
512 which decodes an input block and finalize, which flushes any
513 remaining data to the output stream.
514
515 Typically, you will create a decoder instance, call decode as
516 often as necessary, then call finalize (most often a single
517 call suffices, but it might be that during that call the output
518 buffer is filled, so you should be prepared to call finalize
519 as often as necessary, i.e. until it returns @p true).
520
521 @section Return Values
522
523 Both methods return @p true to indicate that they've finished their
524 job. For decode, a return value of @p true means that the
525 current input block has been finished (@p false most often means
526 that the output buffer is full, but that isn't required
527 behavior. The decode call is free to return at arbitrary
528 times during processing).
529
530 For finalize, a return value of @p true means that all data
531 implicitly or explicitly stored in the decoder instance has been
532 flushed to the output buffer. A @p false return value should be
533 interpreted as "check if the output buffer is full and call me
534 again", just as with decode.
535
536 @section Usage Pattern
537
538 Since the decoder maintains state, you can only use it once. After
539 a sequence of input blocks has been processed, you finalize
540 the output and then delete the decoder instance. If you want to
541 process another input block sequence, you create a new instance.
542
543 Typical usage (@p in contains the (base64-encoded) input data),
544 taking into account all the conventions detailed above:
545
546 <pre>
547 KCodecs::Codec *codec = KCodecs::Codec::codecForName("base64");
548 if (!codec) {
549 qFatal() << "No codec found for base64!";
550 }
551 KCodecs::Decoder *dec = codec->makeDecoder();
552 Q_ASSERT(dec); // should not happen
553 QByteArray out(256); // small buffer is enough ;-)
554 QByteArray::Iterator iit = in.begin();
555 QByteArray::Iterator oit = out.begin();
556 // decode the chunk
557 while (!dec->decode(iit, in.end(), oit, out.end()))
558 if (oit == out.end()) { // output buffer full, process contents
559 do_something_with(out);
560 oit = out.begin();
561 }
562 // repeat while loop for each input block
563 // ...
564 // finish (flush remaining data from decoder):
565 while (!dec->finish(oit, out.end()))
566 if (oit == out.end()) { // output buffer full, process contents
567 do_something_with(out);
568 oit = out.begin();
569 }
570 // now process last chunk:
571 out.resize(oit - out.begin());
572 do_something_with(out);
573 // _delete_ the decoder, but not the codec:
574 delete dec;
575 </pre>
576
577 @since 5.5
578*/
579class KCODECS_EXPORT Decoder
580{
581protected:
582 friend class Codec;
583 friend class DecoderPrivate;
584
585 /**
586 Protected constructor. Use KCodecs::Codec::makeDecoder to create an
587 instance.
588
589 @param newline whether make new lines using @ref CRLF, or @ref LF (default is @ref LF).
590 */
591 Decoder(Codec::NewlineType newline = Codec::NewlineLF);
592
593public:
594 /**
595 Destroys the decoder.
596 */
597 virtual ~Decoder();
598
599 /**
600 Decodes a chunk of data, maintaining state information between
601 calls. See class decumentation for calling conventions.
602
603 @param scursor is a pointer to the start of the input buffer.
604 @param send is a pointer to the end of the input buffer.
605 @param dcursor is a pointer to the start of the output buffer.
606 @param dend is a pointer to the end of the output buffer.
607 */
608 virtual bool decode(const char *&scursor, const char *const send, char *&dcursor, const char *const dend) = 0;
609
610 /**
611 Call this method to finalize the output stream. Writes all
612 remaining data and resets the decoder. See KCodecs::Codec for
613 calling conventions.
614
615 @param dcursor is a pointer to the start of the output buffer.
616 @param dend is a pointer to the end of the output buffer.
617 */
618 virtual bool finish(char *&dcursor, const char *const dend) = 0;
619
620protected:
621 //@cond PRIVATE
622 std::unique_ptr<DecoderPrivate> const d;
623 //@endcond
624};
625
626/**
627 @class KCodecs::Encoder kcodecs.h KCodecs
628
629 @brief Stateful encoder class.
630
631 Stateful encoder class, modeled after QTextEncoder.
632
633 @since 5.5
634*/
635class KCODECS_EXPORT Encoder
636{
637protected:
638 friend class Codec;
639 friend class EncoderPrivate;
640
641 /**
642 Protected constructor. Use KCodecs::Codec::makeEncoder if you want one.
643
644 @param newline whether make new lines using @ref CRLF, or @ref LF (default is @ref LF).
645 */
646 explicit Encoder(Codec::NewlineType newline = Codec::NewlineLF);
647
648public:
649 /**
650 Destroys the encoder.
651 */
652 virtual ~Encoder();
653
654 /**
655 Encodes a chunk of data, maintaining state information between
656 calls. See KCodecs::Codec for calling conventions.
657
658 @param scursor is a pointer to the start of the input buffer.
659 @param send is a pointer to the end of the input buffer.
660 @param dcursor is a pointer to the start of the output buffer.
661 @param dend is a pointer to the end of the output buffer.
662 */
663 virtual bool encode(const char *&scursor, const char *const send, char *&dcursor, const char *const dend) = 0;
664
665 /**
666 Call this method to finalize the output stream. Writes all remaining
667 data and resets the encoder. See KCodecs::Codec for calling conventions.
668
669 @param dcursor is a pointer to the start of the output buffer.
670 @param dend is a pointer to the end of the output buffer.
671 */
672 virtual bool finish(char *&dcursor, const char *const dend) = 0;
673
674protected:
675 /**
676 The maximum number of characters permitted in the output buffer.
677 */
678 enum {
679 maxBufferedChars = 8, /**< Eight */
680 };
681
682 /**
683 Writes character @p ch to the output stream or the output buffer,
684 depending on whether or not the output stream has space left.
685
686 @param ch is the character to write.
687 @param dcursor is a pointer to the start of the output buffer.
688 @param dend is a pointer to the end of the output buffer.
689
690 @return true if written to the output stream; else false if buffered.
691 */
692 bool write(char ch, char *&dcursor, const char *const dend);
693
694 /**
695 Writes characters from the output buffer to the output stream.
696 Implementations of encode and finish should call this
697 at the very beginning and for each iteration of the while loop.
698
699 @param dcursor is a pointer to the start of the output buffer.
700 @param dend is a pointer to the end of the output buffer.
701
702 @return true if all chars could be written, false otherwise
703 */
704 bool flushOutputBuffer(char *&dcursor, const char *const dend);
705
706 /**
707 Convenience function. Outputs @ref LF or @ref CRLF, based on the
708 state of mWithCRLF.
709
710 @param dcursor is a pointer to the start of the output buffer.
711 @param dend is a pointer to the end of the output buffer.
712 */
713 bool writeCRLF(char *&dcursor, const char *const dend);
714
715protected:
716 //@cond PRIVATE
717 std::unique_ptr<EncoderPrivate> const d;
718 //@endcond
719};
720
721} // namespace KCodecs
722
723#endif // KCODECS_H
724

source code of kcodecs/src/kcodecs.h