#pragma once
#include <cstdint>
struct ShiftJIS {
static const uint32_t INVALID = (uint32_t) -1;
ShiftJIS(const char *c) : c_(c), index_(0) {}
uint32_t next() {
uint32_t j = (uint8_t)c_[index_++];
int row;
bool emojiAdjust = false;
switch (j >> 4) {
case 0x8:
if (j == 0x80) {
return INVALID;
}
[[fallthrough]];
case 0x9:
case 0xE:
row = ((j & 0x3F) << 1) - 0x01;
break;
case 0xF:
emojiAdjust = true;
if (j < 0xF4) {
row = ((j & 0x7F) << 1) - 0x59;
} else if (j < 0xFD) {
row = ((j & 0x7F) << 1) - 0x1B;
} else {
return j;
}
break;
default:
return j;
}
j = (uint8_t)c_[index_++];
if (j < 0x40 || j == 0x7F || j >= 0xFD) {
return INVALID;
}
if (j >= 0x9F) {
++row;
j -= 0x7E;
} else {
if (j >= 0x80) {
j -= 0x20;
} else {
j -= 0x20 - 1;
}
if (emojiAdjust) {
if (row == 0x87) {
row = 0x81;
} else if (row == 0x8B) {
row = 0x85;
} else if (row == 0xCD) {
row = 0x8F;
}
}
}
return ((row + 0x20) << 8) | j;
}
bool end() const {
return c_[index_] == 0;
}
int length() const {
int len = 0;
for (ShiftJIS dec(c_); !dec.end(); dec.next())
++len;
return len;
}
int byteIndex() const {
return index_;
}
static int encode(char *dest, uint32_t j) {
int row = (j >> 8) - 0x20;
int offsetCell = j & 0xFF;
if ((j & ~0xFF) == 0) {
*dest = j;
return 1;
}
if (row < 0x3F) {
*dest++ = 0x80 + ((row + 1) >> 1);
} else if (row < 0x5F) {
*dest++ = 0xE0 + ((row - 0x40 + 1) >> 1);
} else if (row >= 0x80) {
}
if (row & 1) {
if (offsetCell < 0x60) {
*dest++ = offsetCell + 0x20 - 1;
} else {
*dest++ = offsetCell + 0x20;
}
} else {
*dest++ = offsetCell + 0x7E;
}
return 2;
}
static int encodeUnits(uint32_t j) {
if ((j & ~0xFF) == 0) {
return 1;
}
return 2;
}
private:
const char *c_;
int index_;
};