]> git.tdb.fi Git - libs/core.git/blob - source/codec.h
Add convenience functions to Encoder and Decoder to process a string and return the...
[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         public:
60                 virtual ~Encoder() { }
61
62                 /**
63                 Encodes a single unicode character.  If the character can't be
64                 represented in this encoding, behavior depends on the error mode
65                 specified for the encoder:
66
67                 For THROW_ON_ERROR, an exception is thrown.
68
69                 For IGNORE_ERRORS, nothing is done.
70
71                 For TRANSLITERATE, the encoder attempts to select a character or a string
72                 or characters that closely approximates the non-representable character.
73                 */
74                 virtual void encode_char(UnicodeChar ch, std::string &buf) =0;
75
76                 /**
77                 Encodes a unicode string.  This is equivalent to callind encode_char for
78                 each character in the string with the same buffer.
79                 */
80                 virtual void encode(const ustring &str, std::string &buf);
81
82                 std::string encode(const ustring &);
83
84                 /**
85                 Procuces a sequence of bytes that will bring the encoder back to the
86                 initial state.
87                 */
88                 virtual void sync(std::string &buf) { (void)buf; }
89
90                 /**
91                 Resets the encoder to the initial state without producing output.
92                 */
93                 virtual void reset() { }
94         protected:
95                 ErrorMode err_mode;
96
97                 Encoder(ErrorMode em): err_mode(em) { }
98
99                 /**
100                 Handles an error depending on the error mode.
101
102                 For THROW_ON_ERROR, throws CodecError(msg).
103
104                 For IGNORE_ERROR, does nothing.
105
106                 For TRANSLITERATE, calls transliterate(ch, buf).
107                 */
108                 void error(UnicodeChar ch, std::string &buf, const std::string &msg);
109
110                 /**
111                 Attempts to produce an alternative encoding for a unicode character.
112                 Typically this includes dropping accent marks or romanizing letters.
113                 */
114                 virtual void transliterate(UnicodeChar ch, std::string &buf) =0;
115         };
116
117         /**
118         Base class for string decoder.
119
120         Each codec class should contain an Decoder class derived from this.
121         */
122         class Decoder
123         {
124         public:
125                 virtual ~Decoder() { }
126
127                 /**
128                 Decodes a single character from a string.  The iterator is advanced to
129                 the next character.  For stateful codecs, -1 may be returned if a state
130                 change sequence was decoded but no character followed it.  In case a
131                 decoding error occurs, behavior depends on the error mode specified for
132                 the decoder:
133
134                 For THROW_ON_ERROR, an exception is thrown and the iterator is left at
135                 the erroneous character.
136
137                 For IGNORE_ERRORS, -1 is returned and the iterator is advanced.
138
139                 For TRANSLITERATE, 0xFFFE is returned and the iterator is advanced.
140                 */
141                 virtual UnicodeChar decode_char(const std::string &str, std::string::const_iterator &i) =0;
142
143                 /**
144                 Decodes a string.
145                 */
146                 virtual void decode(const std::string &str, ustring &buf);
147
148                 ustring decode(const std::string &);
149
150                 /**
151                 Resets the decoder to the initial state.
152                 */
153                 virtual void reset() { }
154         protected:
155                 ErrorMode err_mode;
156
157                 Decoder(ErrorMode em): err_mode(em) { }
158
159                 /**
160                 Handles an error depending on the error mode.
161                 */
162                 UnicodeChar error(const std::string &);
163         };
164
165         virtual ~Codec() { }
166
167         /**
168         Returns the name of the encoding handled by this codec.
169         */
170         virtual const char *get_name() const =0;
171
172         /**
173         Creates an encoder for this codec.
174         */
175         virtual Encoder *create_encoder(ErrorMode err_mode=THROW_ON_ERROR) const =0;
176
177         /**
178         Creates a decoder for this codec.
179         */
180         virtual Decoder *create_decoder(ErrorMode err_mode=THROW_ON_ERROR) const =0;
181
182         /**
183         Determines whether the given string can be successfully decoded with this
184         codec.  Note that this function returning true does not guarantee that the
185         string was actually encoded with this codec.  In particular, many 8-bit
186         encodings are indistinguishable.
187         */
188         virtual bool detect(const std::string &) const;
189 protected:
190         Codec() { }
191 };
192
193 typedef Codec::Encoder Encoder;
194 typedef Codec::Decoder Decoder;
195
196 /**
197 Convenience function that decodes a string.
198 */
199 template<class C>
200 ustring decode(const std::string &s)
201 {
202         typename C::Decoder dec;
203         ustring result;
204         dec.decode(s, result);
205         return result;
206 }
207
208 /**
209 Convenience function that encodes a string.
210 */
211 template<class C>
212 std::string encode(const ustring &s)
213 {
214         typename C::Encoder enc;
215         std::string result;
216         enc.encode(s, result);
217         enc.sync(result);
218         return result;
219 }
220
221 /**
222 Convenience function that transcodes a string from one codec to another.
223 */
224 template<class F, class T>
225 std::string transcode(const std::string &s)
226 {
227         typename F::Decoder from;
228         typename T::Encoder to;
229         ustring temp;
230         from.decode(s, temp);
231         std::string result;
232         to.encode(temp, result);
233         to.sync(result);
234         return result;
235 }
236
237 /**
238 Creates a codec for an encoding by name.  The caller is responsible for
239 deleting the codec when it's no longer needed.
240 */
241 Codec *create_codec(const std::string &);
242
243 /**
244 Automatically detects the encoding of a string and creates a codec for it.
245 The codec must be deleted when it's no longer needed.
246 */
247 Codec *detect_codec(const std::string &);
248
249 } // namespace Codecs
250 } // namespace Msp
251
252 #endif