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