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