1"""
2Python 'utf-32' Codec
3"""
4import codecs, sys
5
6### Codec APIs
7
8encode = codecs.utf_32_encode
9
10def decode(input, errors='strict'):
11    return codecs.utf_32_decode(input, errors, True)
12
13class IncrementalEncoder(codecs.IncrementalEncoder):
14    def __init__(self, errors='strict'):
15        codecs.IncrementalEncoder.__init__(self, errors)
16        self.encoder = None
17
18    def encode(self, input, final=False):
19        if self.encoder is None:
20            result = codecs.utf_32_encode(input, self.errors)[0]
21            if sys.byteorder == 'little':
22                self.encoder = codecs.utf_32_le_encode
23            else:
24                self.encoder = codecs.utf_32_be_encode
25            return result
26        return self.encoder(input, self.errors)[0]
27
28    def reset(self):
29        codecs.IncrementalEncoder.reset(self)
30        self.encoder = None
31
32    def getstate(self):
33        # state info we return to the caller:
34        # 0: stream is in natural order for this platform
35        # 2: endianness hasn't been determined yet
36        # (we're never writing in unnatural order)
37        return (2 if self.encoder is None else 0)
38
39    def setstate(self, state):
40        if state:
41            self.encoder = None
42        else:
43            if sys.byteorder == 'little':
44                self.encoder = codecs.utf_32_le_encode
45            else:
46                self.encoder = codecs.utf_32_be_encode
47
48class IncrementalDecoder(codecs.BufferedIncrementalDecoder):
49    def __init__(self, errors='strict'):
50        codecs.BufferedIncrementalDecoder.__init__(self, errors)
51        self.decoder = None
52
53    def _buffer_decode(self, input, errors, final):
54        if self.decoder is None:
55            (output, consumed, byteorder) = \
56                codecs.utf_32_ex_decode(input, errors, 0, final)
57            if byteorder == -1:
58                self.decoder = codecs.utf_32_le_decode
59            elif byteorder == 1:
60                self.decoder = codecs.utf_32_be_decode
61            elif consumed >= 4:
62                raise UnicodeError("UTF-32 stream does not start with BOM")
63            return (output, consumed)
64        return self.decoder(input, self.errors, final)
65
66    def reset(self):
67        codecs.BufferedIncrementalDecoder.reset(self)
68        self.decoder = None
69
70    def getstate(self):
71        # additional state info from the base class must be None here,
72        # as it isn't passed along to the caller
73        state = codecs.BufferedIncrementalDecoder.getstate(self)[0]
74        # additional state info we pass to the caller:
75        # 0: stream is in natural order for this platform
76        # 1: stream is in unnatural order
77        # 2: endianness hasn't been determined yet
78        if self.decoder is None:
79            return (state, 2)
80        addstate = int((sys.byteorder == "big") !=
81                       (self.decoder is codecs.utf_32_be_decode))
82        return (state, addstate)
83
84    def setstate(self, state):
85        # state[1] will be ignored by BufferedIncrementalDecoder.setstate()
86        codecs.BufferedIncrementalDecoder.setstate(self, state)
87        state = state[1]
88        if state == 0:
89            self.decoder = (codecs.utf_32_be_decode
90                            if sys.byteorder == "big"
91                            else codecs.utf_32_le_decode)
92        elif state == 1:
93            self.decoder = (codecs.utf_32_le_decode
94                            if sys.byteorder == "big"
95                            else codecs.utf_32_be_decode)
96        else:
97            self.decoder = None
98
99class StreamWriter(codecs.StreamWriter):
100    def __init__(self, stream, errors='strict'):
101        self.encoder = None
102        codecs.StreamWriter.__init__(self, stream, errors)
103
104    def reset(self):
105        codecs.StreamWriter.reset(self)
106        self.encoder = None
107
108    def encode(self, input, errors='strict'):
109        if self.encoder is None:
110            result = codecs.utf_32_encode(input, errors)
111            if sys.byteorder == 'little':
112                self.encoder = codecs.utf_32_le_encode
113            else:
114                self.encoder = codecs.utf_32_be_encode
115            return result
116        else:
117            return self.encoder(input, errors)
118
119class StreamReader(codecs.StreamReader):
120
121    def reset(self):
122        codecs.StreamReader.reset(self)
123        try:
124            del self.decode
125        except AttributeError:
126            pass
127
128    def decode(self, input, errors='strict'):
129        (object, consumed, byteorder) = \
130            codecs.utf_32_ex_decode(input, errors, 0, False)
131        if byteorder == -1:
132            self.decode = codecs.utf_32_le_decode
133        elif byteorder == 1:
134            self.decode = codecs.utf_32_be_decode
135        elif consumed>=4:
136            raise UnicodeError,"UTF-32 stream does not start with BOM"
137        return (object, consumed)
138
139### encodings module API
140
141def getregentry():
142    return codecs.CodecInfo(
143        name='utf-32',
144        encode=encode,
145        decode=decode,
146        incrementalencoder=IncrementalEncoder,
147        incrementaldecoder=IncrementalDecoder,
148        streamreader=StreamReader,
149        streamwriter=StreamWriter,
150    )
151