]> git.tdb.fi Git - libs/core.git/blob - source/codec.h
More sophisticated error handling
[libs/core.git] / source / codec.h
1 #ifndef MSP_STRINGS_CODEC_H_
2 #define MSP_STRINGS_CODEC_H_
3
4 #include <string>
5 #include <msp/error.h>
6
7 namespace Msp {
8
9 /**
10 An exception thrown for all kinds of problems encountered while encoding or
11 decoding strings.
12 */
13 class CodecError: public Exception
14 {
15 public:
16         CodecError(const std::string &w_): Exception(w_) { }
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 For the purposes of this class, an std::wstring is considered to contain
24 Unicode characters and an std::string is considered to be an encoded sequence
25 of bytes.  A codec is able to determine if an encoded string could be decoded
26 with it.
27 */
28 class StringCodec
29 {
30 public:
31         enum ErrorMode
32         {
33                 THROW_ON_ERROR,
34                 IGNORE_ERRORS,
35                 REPLACE_ERRORS
36         };
37
38         /**
39         Base class for string encoder.  Each codec class should contain an Encoder
40         class derived from this.
41         */
42         class Encoder
43         {
44         public:
45                 /**
46                 Encodes a single character.  Derived classes should use the append
47                 function to put the result into the internal buffer.
48                 */
49                 virtual void encode_char(wchar_t) =0;
50
51                 /**
52                 Encodes a string.
53                 */
54                 virtual void encode(const std::wstring &s)
55                 { for(std::wstring::const_iterator i=s.begin(); i!=s.end(); ++i) encode_char(*i); }
56
57                 /**
58                 Brings the encoder back to its initial state.  This allows the encoded
59                 sequence to be extracted or flushed without loss of integrity.
60                 */
61                 virtual void sync() { }
62
63                 /**
64                 Returns a reference to the encoded sequence.  Call sync() first to make
65                 sure it's a valid encoded string by itself.
66                 */
67                 const std::string &get() const { return buffer_; }
68
69                 /**
70                 Returns the number of bytes in the output buffer.
71                 */
72                 unsigned size() const { return buffer_.size(); }
73
74                 /**
75                 Clears the encoded sequence.  Encoder state is left intact.
76                 */
77                 void flush() { buffer_.clear(); }
78
79                 virtual ~Encoder() { }
80         protected:
81                 Encoder(ErrorMode em=THROW_ON_ERROR): err_mode_(em) { }
82                 void append(char c) { buffer_+=c; }
83                 void append(const char *s, unsigned l) { buffer_.append(s, l); }
84                 void append(const std::string &s) { buffer_+=s; }
85                 void error(const std::string &);
86                 virtual void append_replacement() { }
87         private:
88                 ErrorMode err_mode_;
89                 std::string buffer_;
90         };
91
92         /**
93         Base class for string decoder.  Each codec class should contain an Decoder
94         class derived from this.
95         */
96         class Decoder
97         {
98         public:
99                 virtual void decode_char(const std::string &, std::string::const_iterator &) =0;
100                 virtual void decode(const std::string &s)
101                 { for(std::string::const_iterator i=s.begin(); i!=s.end(); ) decode_char(s, i); }
102
103                 /**
104                 Ensures that all input has been processed.  If this is not the case any
105                 buffers are cleared and an error is triggered.
106                 */
107                 virtual void sync() { }
108
109                 const std::wstring &get() const { return buffer_; }
110                 unsigned size() const { return buffer_.size(); }
111                 void flush() { buffer_.clear(); }
112                 virtual ~Decoder() { }
113         protected:
114                 Decoder(ErrorMode em): err_mode_(em) { }
115                 void append(wchar_t c) { buffer_+=c; }
116                 void append(const std::wstring &s) { buffer_+=s; }
117                 void error(const std::string &);
118         private:
119                 ErrorMode err_mode_;
120                 std::wstring buffer_;
121         };
122
123         virtual Encoder *create_encoder(ErrorMode =THROW_ON_ERROR) const =0;
124         virtual Decoder *create_decoder(ErrorMode =THROW_ON_ERROR) const =0;
125         virtual bool    detect(const std::string &) const;
126         virtual ~StringCodec() { }
127 protected:
128         StringCodec() { }
129 };
130
131 /**
132 Convenience function that decodes a string using the given codec.
133 */
134 template<class C>
135 std::wstring decode(const std::string &s)
136 {
137         typename C::Decoder dec;
138         dec.decode(s);
139         dec.sync();
140         return dec.get();
141 }
142
143 template<class C>
144 std::string encode(const std::wstring &s)
145 {
146         typename C::Encoder enc;
147         enc.encode(s);
148         enc.sync();
149         return enc.get();
150 }
151
152 template<class F, class T>
153 std::string transcode(const std::string &s)
154 {
155         typename F::Decoder from;
156         typename T::Encoder to;
157         from.decode(s);
158         from.sync();
159         to.encode(from.get());
160         to.sync();
161         return to.get();
162 }
163
164 StringCodec *create_codec(const std::string &);
165
166 } // namespace Msp
167
168 #endif