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