1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
|
// Copyright (c) 1996 James Clark
// See the file COPYING for copying permission.
#ifdef __GNUG__
#pragma implementation
#endif
#include "splib.h"
#ifdef SP_MULTI_BYTE
#include <windows.h>
#include <io.h>
#include "Win32CodingSystem.h"
#include "Boolean.h"
#include "macros.h"
#ifdef SP_NAMESPACE
namespace SP_NAMESPACE {
#endif
class SingleByteWin32Decoder : public Decoder {
public:
SingleByteWin32Decoder(unsigned int codePage, Char defaultChar);
size_t decode(Char *to, const char *from, size_t fromLen,
const char **rest);
Boolean convertOffset(unsigned long &offset) const;
private:
Char map_[256];
};
class MultiByteWin32Decoder : public Decoder {
public:
MultiByteWin32Decoder(unsigned int codePage, Char defaultChar,
unsigned char *leadByte);
size_t decode(Char *to, const char *from, size_t fromLen,
const char **rest);
private:
unsigned int codePage_;
Char defaultChar_;
PackedBoolean isLeadByte_[256];
};
class Win32Encoder : public Encoder {
public:
Win32Encoder(unsigned int codePage);
~Win32Encoder();
void output(const Char *, size_t, OutputByteStream *);
private:
char *buf_;
size_t bufLen_;
unsigned int codePage_;
};
Win32CodingSystem::Win32CodingSystem(unsigned int codePage, Char defaultChar)
: codePage_(codePage), defaultChar_(defaultChar)
{
}
Win32CodingSystem::Win32CodingSystem(SpecialCodePage codePage,
Char defaultChar)
: defaultChar_(defaultChar)
{
if (codePage == codePageAnsi)
codePage_ = GetACP();
else
codePage_ = GetOEMCP();
}
Boolean Win32CodingSystem::isValid() const
{
return IsValidCodePage(codePage_);
}
Encoder *Win32CodingSystem::makeEncoder() const
{
return new Win32Encoder(codePage_);
}
Decoder *Win32CodingSystem::makeDecoder() const
{
CPINFO info;
if (GetCPInfo(codePage_, &info) && info.MaxCharSize > 1)
return new MultiByteWin32Decoder(codePage_, defaultChar_, info.LeadByte);
else
return new SingleByteWin32Decoder(codePage_, defaultChar_);
}
SingleByteWin32Decoder::SingleByteWin32Decoder(unsigned int codePage,
Char defaultChar)
{
for (int i = 0; i < 256; i++) {
char c = i;
wchar_t mapped;
if (MultiByteToWideChar(codePage, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
&c, 1, &mapped, 1) == 0)
map_[i] = defaultChar;
else
map_[i] = Char(mapped);
}
}
size_t SingleByteWin32Decoder::decode(Char *to, const char *from,
size_t fromLen, const char **rest)
{
for (size_t n = fromLen; n > 0; n--)
*to++ = map_[(unsigned char)*from++]; // zero extend
*rest = from;
return fromLen;
}
Boolean SingleByteWin32Decoder::convertOffset(unsigned long &) const
{
return 1;
}
MultiByteWin32Decoder::MultiByteWin32Decoder(unsigned int codePage,
Char defaultChar,
unsigned char *leadByte)
: defaultChar_(defaultChar), codePage_(codePage)
{
for (int i = 0; i < 256; i++)
isLeadByte_[i] = 0;
for (int i = 0; i < MAX_LEADBYTES; i += 2) {
if (leadByte[i] == 0 && leadByte[i + 1] == 0)
break;
int lim = leadByte[i + 1];
for (int j = leadByte[i]; j < lim; j++)
isLeadByte_[j] = 1;
}
}
size_t MultiByteWin32Decoder::decode(Char *to, const char *from,
size_t fromLen, const char **rest)
{
size_t i;
for (i = fromLen; i > 0; i--)
if (!isLeadByte_[(unsigned char)from[i - 1]])
break;
if ((fromLen - i) & 1)
fromLen--;
String<wchar_t> tow;
tow.resize(fromLen);
int count = MultiByteToWideChar(codePage_,
MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
from, fromLen, (wchar_t *)tow.data(), fromLen);
for (size_t i = 0; i < count; i++)
to[i] = Char(tow[i]);
if (count) {
*rest = from + fromLen;
return count;
}
Char *start = to;
// Try it character by character.
while (fromLen > 0) {
int nBytes = 1 + isLeadByte_[(unsigned char)*from];
ASSERT(nBytes <= fromLen);
wchar_t tow;
if (MultiByteToWideChar(codePage_, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
from, nBytes, &tow, 1) != 1)
*to = defaultChar_;
else
*to = Char(tow);
from += nBytes;
fromLen -= nBytes;
to++;
}
*rest = from;
return to - start;
}
Win32Encoder::Win32Encoder(unsigned int codePage)
: codePage_(codePage), buf_(0), bufLen_(0)
{
}
Win32Encoder::~Win32Encoder()
{
delete [] buf_;
}
void Win32Encoder::output(const Char *s, size_t n, OutputByteStream *sb)
{
if (n == 0)
return;
if (n*2 > bufLen_) {
delete [] buf_;
bufLen_ = n*2;
buf_ = new char[bufLen_];
}
String<wchar_t> ws;
ws.resize(n);
for (size_t i = 0; i < n; i++)
ws[i] = wchar_t(s[i]);
int nBytes = WideCharToMultiByte(codePage_,
0,
ws.data(),
n,
buf_,
bufLen_,
0,
0);
if (nBytes)
sb->sputn(buf_, nBytes);
}
#ifdef SP_NAMESPACE
}
#endif
#else /* not SP_MULTI_BYTE */
#ifndef __GNUG__
static char non_empty_translation_unit; // sigh
#endif
#endif /* not SP_MULTI_BYTE */
|