読者です 読者をやめる 読者になる 読者になる

きままにブログ

プログラミングを主とした私のメモ帳です。寂しいのでコメントください笑

S_JISの1文字ごと全文字読み取り

イテレータで全文字読み取ることを考えます。文字列返却のために、イテレータクラスのメモリを使っていますが、相当邪道だと思います。unique_ptrは使いたくないし、素直にポインタとサイズを返すのがいいのかもしれないが、簡単に使えないし困ったものです。

#include <stdio.h>
#include <memory>
#include <iterator>

class S_JIS_iterator;

class S_JIS {
	friend S_JIS_iterator;
public:
	S_JIS(const char* str) : str(str) {

	}
	S_JIS_iterator begin();
	S_JIS_iterator end();
private:
	// 2バイト・あるいは\0が必要
	static int getByteOfNextCharactor(const char* next) {
		const unsigned char next1 = next[0];
		
		if(next1 == '\0') {
			return 0;
		}
		
		const unsigned char next2 = next[1];

		if(next2 == '\0') {
			return 1;
		}
		else if(
			(
				(next1 >= 0x81 && next1 <= 0x9F) ||
				(next1 >= 0xE0 && next1 <= 0xEF)
			) && (
				(next2 >= 0x40 && next2 <= 0x7E) ||
				(next2 >= 0x80 && next2 <= 0xFC)
			)
			) {
			return 2;
		}
		else {
			return 1;
		}
	}

	std::string str;
};

class S_JIS_iterator : std::iterator<std::forward_iterator_tag, char*> {
	friend S_JIS;
public:
	S_JIS_iterator(S_JIS* self, int pos) : self(self), pos(pos) { }
	const char* operator*() const {
		const int n = self->getByteOfNextCharactor(&self->str[pos]);
		std::memcpy(moji, &self->str[pos], n);
		moji[n] = '\0';

		return moji;
	}
	bool operator==(const S_JIS_iterator& it) const {
		return pos == it.pos;
	}
	bool operator!=(const S_JIS_iterator& it) const {
		return pos != it.pos;
	}
	S_JIS_iterator& operator++() {
		pos += self->getByteOfNextCharactor(&self->str[pos]);
		return *this;
	}
	S_JIS_iterator operator++(int) {
		S_JIS_iterator ret = *this;
		operator++();
		return ret;
	}
private:
	S_JIS* self;
	mutable char moji[4]; // 返却用
	int pos;
};

S_JIS_iterator S_JIS::begin() {
	return S_JIS_iterator(this, 0);
}
S_JIS_iterator S_JIS::end() {
	return S_JIS_iterator(this, str.length());
}

int main() {
	S_JIS str("あAいBうCえDおE");

	for(const auto& it : str) {
		printf("%s\n", it);
	}

	getchar();
	return 0;
}