]> git.tdb.fi Git - libs/core.git/blob - source/codec.h
Further style and comment adjustments
[libs/core.git] / source / codec.h
1 /* $Id$
2
3 This file is part of libmspstrings
4 Copyright © 2006-2007 Mikko Rasa
5 Distributed under the LGPL
6 */
7
8 #ifndef MSP_STRINGS_CODEC_H_
9 #define MSP_STRINGS_CODEC_H_
10
11 #include <string>
12 #include <msp/core/except.h>
13
14 namespace Msp {
15 namespace Codecs {
16
17 typedef int UnicodeChar;
18
19 typedef std::basic_string<UnicodeChar> ustring;
20
21 enum ErrorMode
22 {
23         THROW_ON_ERROR,
24         IGNORE_ERRORS,
25         TRANSLITERATE
26 };
27
28 /**
29 An exception thrown for all kinds of problems encountered while encoding or
30 decoding strings.
31 */
32 class CodecError: public Exception
33 {
34 public:
35         CodecError(const std::string &w_): Exception(w_) { }
36 };
37
38 /**
39 Base class for string codecs.  Use one of the derived classes or the function
40 create_codec to create a specific codec.
41
42 Unicode strings are represented as ustrings.  An std::string is considered to
43 be an encoded sequence of bytes.  A codec is able to determine if an encoded
44 string could be decoded with it.
45 */
46 class Codec
47 {
48 public:
49         /**
50         Base class for string encoder.
51
52         Each codec class should contain an Encoder class derived from this.  The
53         encode_char and transliterate functions must be overloaded.  Some encoders
54         may find it useful or necessary to implement some other functions too
55         (particularly sync and reset for stateful codecs).
56         */
57         class Encoder
58         {
59         protected:
60                 ErrorMode err_mode;
61
62                 Encoder(ErrorMode em): err_mode(em) { }
63         public:
64                 virtual ~Encoder() { }
65
66                 /** Encodes a single unicode character.  If the character can't be
67                 represented in this encoding, error() should be called. */
68                 virtual void encode_char(UnicodeChar ch, std::string &buf) = 0;
69
70                 /** Encodes a unicode string.  This is equivalent to calling encode_char
71                 for each character in the string with the same buffer. */
72                 virtual void encode(const ustring &str, std::string &buf);
73
74                 std::string encode(const ustring &);
75
76                 /** Procuces a sequence of bytes that will bring the encoder back to the
77                 initial state. */
78                 virtual void sync(std::string &buf) { (void)buf; }
79
80                 /** Resets the encoder to the initial state without producing output. */
81                 virtual void reset() { }
82
83         protected:
84                 /** Handles an error depending on the error mode.
85
86                 THROW_ON_ERROR: throws CodecError(msg)
87                 IGNORE_ERRORS: does nothing
88                 TRANSLITERATE: calls transliterate(ch, buf) */
89                 void error(UnicodeChar ch, std::string &buf, const std::string &msg);
90
91                 /** Attempts to produce an alternative encoding for a unicode character.
92                 Typically this includes dropping accent marks or romanizing letters. */
93                 virtual void transliterate(UnicodeChar ch, std::string &buf) = 0;
94         };
95
96         /**
97         Base class for string decoder.
98
99         Each codec class should contain an Decoder class derived from this.
100         */
101         class Decoder
102         {
103         protected:
104                 ErrorMode err_mode;
105
106                 Decoder(ErrorMode em): err_mode(em) { }
107         public:
108                 virtual ~Decoder() { }
109
110                 /** Decodes a single character from a string.  The iterator is advanced
111                 to the next character.  For stateful codecs, -1 may be returned if a
112                 state change sequence was decoded but no character followed it.  If
113                 invalid input is encountered, the error() function should be called and
114                 the iterator advanced only if it doesn't throw. */
115                 virtual UnicodeChar decode_char(const std::string &str, std::string::const_iterator &i) = 0;
116
117                 /** Decodes a string. */
118                 virtual void decode(const std::string &str, ustring &buf);
119
120                 ustring decode(const std::string &);
121
122                 /** Resets the decoder to the initial state. */
123                 virtual void reset() { }
124
125         protected:
126                 /** Handles an error depending on the error mode.  The return value is
127                 suitable for returning from decode_char.
128                 
129                 THROW_ON_ERROR: throws CodecError(msg)
130                 IGNORE_ERRORS: returns -1
131                 TRANSLITERATE: return 0xFFFE */
132                 UnicodeChar error(const std::string &msg);
133         };
134
135 protected:
136         Codec() { }
137 public:
138         virtual ~Codec() { }
139
140         /** Returns the name of the encoding handled by this codec. */
141         virtual const char *get_name() const = 0;
142
143         /** Creates an encoder for this codec. */
144         virtual Encoder *create_encoder(ErrorMode err_mode = THROW_ON_ERROR) const = 0;
145
146         /** Creates a decoder for this codec. */
147         virtual Decoder *create_decoder(ErrorMode err_mode = THROW_ON_ERROR) const = 0;
148
149         /** Determines whether the given string can be successfully decoded with
150         this codec.  Note that this function returning true does not guarantee that
151         the string was actually encoded with this codec.  In particular, many 8-bit
152         encodings are indistinguishable. */
153         virtual bool detect(const std::string &) const;
154 };
155
156 typedef Codec::Encoder Encoder;
157 typedef Codec::Decoder Decoder;
158
159 /** Convenience function that decodes a string. */
160 template<class C>
161 ustring decode(const std::string &s)
162 {
163         typename C::Decoder dec;
164         ustring result;
165         dec.decode(s, result);
166         return result;
167 }
168
169 /** Convenience function that encodes a string. */
170 template<class C>
171 std::string encode(const ustring &s)
172 {
173         typename C::Encoder enc;
174         std::string result;
175         enc.encode(s, result);
176         enc.sync(result);
177         return result;
178 }
179
180 /** Convenience function that transcodes a string from one codec to another. */
181 template<class F, class T>
182 std::string transcode(const std::string &s)
183 {
184         typename F::Decoder from;
185         typename T::Encoder to;
186         ustring temp;
187         from.decode(s, temp);
188         std::string result;
189         to.encode(temp, result);
190         to.sync(result);
191         return result;
192 }
193
194 /** Creates a codec for an encoding by name.  The caller is responsible for
195 deleting the codec when it's no longer needed. */
196 Codec *create_codec(const std::string &);
197
198 /** Automatically detects the encoding of a string and creates a codec for it.
199 The codec must be deleted when it's no longer needed. */
200 Codec *detect_codec(const std::string &);
201
202 } // namespace Codecs
203 } // namespace Msp
204
205 #endif