Initial upload
[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.  Mostly abstract.  Use one of the derived classes
21 or the function 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.  Codecs are able to determine if an encoded string could be 
26 */
27 class StringCodec
28 {
29 public:
30         /**
31         Base class for string encoder.  Each codec class should contain an Encoder
32         class derived from this.
33         */
34         class Encoder
35         {
36         public:
37                 /**
38                 Encodes a single character.  Derived classes should use the append
39                 function to put the result into the internal buffer.
40                 */
41                 virtual void encode_char(wchar_t) =0;
42                 
43                 /**
44                 Encodes a string.
45                 */
46                 virtual void encode(const std::wstring &s)
47                 { for(std::wstring::const_iterator i=s.begin(); i!=s.end(); ++i) encode_char(*i); }
48                 
49                 /**
50                 Brings the encoder back to its initial state.  This allows the encoded
51                 sequence to be extracted or flushed without loss of integrity.
52                 */
53                 virtual void sync() { }
54
55                 /**
56                 Returns a reference to the encoded sequence.  Call sync() first to make
57                 sure it's a valid encoded string by itself.
58                 */
59                 const std::string &get() const { return buffer_; }
60
61                 /**
62                 Returns the number of bytes in the output buffer.
63                 */
64                 unsigned size() const { return buffer_.size(); }
65                 
66                 /**
67                 Clears the encoded sequence.  Encoder state is left intact.
68                 */
69                 void flush() { buffer_.clear(); }
70
71                 virtual ~Encoder() { }
72         protected:
73                 Encoder() { }
74                 void append(char c) { buffer_+=c; }
75                 void append(const char *s, unsigned l) { buffer_.append(s, l); }
76                 void append(const std::string &s) { buffer_+=s; }
77         private:
78                 std::string buffer_;
79         };
80
81         /**
82         Base class for string decoder.  Each codec class should contain an Decoder
83         class derived from this.
84         */
85         class Decoder
86         {
87         public:
88                 virtual void decode_char(const std::string &, std::string::const_iterator &) =0;
89                 virtual void decode(const std::string &s)
90                 { for(std::string::const_iterator i=s.begin(); i!=s.end(); ) decode_char(s, i); }
91
92                 /**
93                 Ensures that all input has been processed.  An exception is thrown if
94                 this is not the case.
95                 */
96                 virtual void sync() { }
97
98                 const std::wstring &get() const { return buffer_; }
99                 unsigned size() const { return buffer_.size(); }
100                 void flush() { buffer_.clear(); }
101                 virtual ~Decoder() { }
102         protected:
103                 Decoder() { }
104                 void append(wchar_t c) { buffer_+=c; }
105                 void append(const std::wstring &s) { buffer_+=s; }
106         private:
107                 std::wstring buffer_;
108         };
109
110         virtual Encoder *create_encoder() const =0;
111         virtual Decoder *create_decoder() const =0;
112         virtual bool    detect(const std::string &) const;
113         virtual ~StringCodec() { }
114 protected:
115         StringCodec() { }
116 };
117
118 /**
119 Convenience function that decodes a string using the given codec. 
120 */
121 template<class C>
122 std::wstring decode(const std::string &s)
123 {
124         typename C::Decoder dec;
125         dec.decode(s);
126         dec.sync();
127         return dec.get();
128 }
129
130 template<class C>
131 std::string encode(const std::wstring &s)
132 {
133         typename C::Encoder enc;
134         enc.encode(s);
135         enc.sync();
136         return enc.get();
137 }
138
139 template<class F, class T>
140 std::string transcode(const std::string &s)
141 {
142         typename F::Decoder from;
143         typename T::Encoder to;
144         from.decode(s);
145         from.sync();
146         to.encode(from.get());
147         to.sync();
148         return to.get();
149 }
150
151 StringCodec *create_codec(const std::string &);
152
153 } // namespace Msp
154
155 #endif