1 // Copyright (c) 2000 Matthias Clasen
2 // See the file COPYING for copying permission.
8 #include "Fixed4CodingSystem.h"
13 namespace SP_NAMESPACE {
16 class Fixed4Decoder : public Decoder {
18 Fixed4Decoder(Boolean lsbFirst, Boolean lswFirst);
19 size_t decode(Char *to, const char *from, size_t fromLen,
21 Boolean convertOffset(unsigned long &offset) const;
23 // value for encoding error
24 enum { invalid = 0xfffd };
29 class Fixed4Encoder : public Encoder {
33 void output(Char *, size_t, OutputByteStream *);
34 void output(const Char *, size_t, OutputByteStream *);
36 void allocBuf(size_t);
41 Decoder *Fixed4CodingSystem::makeDecoder(Boolean lsbFirst, Boolean lswFirst) const
43 return new Fixed4Decoder(lsbFirst, lswFirst);
46 Encoder *Fixed4CodingSystem::makeEncoder() const
48 return new Fixed4Encoder;
51 unsigned Fixed4CodingSystem::fixedBytesPerChar() const
56 Fixed4Decoder::Fixed4Decoder(Boolean lsbFirst, Boolean lswFirst)
57 : Decoder(4), lsbFirst_(lsbFirst), lswFirst_(lswFirst)
61 size_t Fixed4Decoder::decode(Char *to, const char *from, size_t fromLen,
65 // FIXME for this optimization I need autoconf macros that tell
66 // me the byte order in 32bit words: 1234, 4321, 2143 or 3412.
67 // Look at the corresponding optimization in Fixed2Decoder.
68 if (sizeof(Char) == 4 && from == (char *)to) {
69 *rest = from + (fromLen & ~3);
70 for (size_t n = 0; n < fromLen/4; n++)
77 *rest = from + fromLen;
78 // lsbFirst, lswFirst: 0123
79 // lsbFirst, !lswFirst: 2301
80 // !lsbFirst, lswFirst: 1032
81 // !lsbFirst, !lswFirst: 3210
82 size_t shift0 = 8*(!lsbFirst_ + 2*!lswFirst_);
83 size_t shift1 = 8*(lsbFirst_ + 2*!lswFirst_);
84 size_t shift2 = 8*(!lsbFirst_ + 2*lswFirst_);
85 size_t shift3 = 8*(lsbFirst_ + 2*lswFirst_);
86 for (size_t n = fromLen; n > 0; n -= 4) {
87 Unsigned32 c = ((unsigned char)from[0] << shift0)
88 + ((unsigned char)from[1] << shift1)
89 + ((unsigned char)from[2] << shift2)
90 + ((unsigned char)from[3] << shift3);
91 *to++ = charMax < c ? invalid : c;
97 Boolean Fixed4Decoder::convertOffset(unsigned long &n) const
103 Fixed4Encoder::Fixed4Encoder()
104 : buf_(0), bufSize_(0)
108 Fixed4Encoder::~Fixed4Encoder()
113 void Fixed4Encoder::allocBuf(size_t n)
117 buf_ = new char[bufSize_ = n];
121 void Fixed4Encoder::output(Char *s, size_t n, OutputByteStream *sb)
124 if (sizeof(Char) == 4) {
125 sb->sputn((char *)s, n*4);
129 ASSERT(sizeof(Char) >= 4);
131 for (size_t i = 0; i < n; i++) {
133 *p++ = (c >> 24) & 0xff;
134 *p++ = (c >> 16) & 0xff;
135 *p++ = (c >> 8) & 0xff;
138 sb->sputn((char *)s, n*4);
141 void Fixed4Encoder::output(const Char *s, size_t n, OutputByteStream *sb)
144 if (sizeof(Char) == 4) {
145 sb->sputn((char *)s, n*4);
150 for (size_t i = 0; i < n; i++) {
151 buf_[i*4] = (s[i] >> 24) & 0xff;
152 buf_[i*4 + 1] = (s[i] >> 16) & 0xff;
153 buf_[i*4 + 2] = (s[i] >> 8) & 0xff;
154 buf_[i*4 + 3] = s[i] & 0xff;
156 sb->sputn(buf_, n*4);
163 #else /* not SP_MULTI_BYTE */
166 static char non_empty_translation_unit; // sigh
169 #endif /* not SP_MULTI_BYTE */