﻿// Utf8_16.h
// Copyright (C) 2002 Scott Kirkwood
//
// Permission to use, copy, modify, distribute and sell this code
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies or
// any derived copies.  Scott Kirkwood makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
//
// Notes: Used the UTF information I found at:
//   http://www.cl.cam.ac.uk/~mgk25/unicode.html
////////////////////////////////////////////////////////////////////////////////
#ifndef UTF8_16_H
#define UTF8_16_H
#include "Forcelib.h"
#include <windows.h>
#include <stdio.h>
#include <assert.h>
#include <vector>
using namespace std;
const int blockSize = 65536*2+1;
//const int blockSize = 11;
enum UniMode {
    uni8Bit = 0, uni16BE = 1, uni16LE = 2, uniUTF8_bom = 3,
	uniUTF8 = 4, uniAnsi = 5, uniEuc =6, uniJis =7, uniCookie = 8
};


extern  UniMode SpecifiedEncoding;
class Utf8_16 {
public:
	Utf8_16(){
	  langId = GetSystemDefaultLangID();
	}
	~Utf8_16(){};
public:
	typedef unsigned short utf16; // 16 bits
	typedef unsigned char utf8; // 8 bits
	typedef unsigned char ubyte;
	enum encodingType {
		eUnknown = 0,
		eUtf16BigEndian,
		eUtf16LittleEndian,  // Default on Windows
		eUtf8_bom,
		eUtf8,
		eAnsi,
		eEuc,
		eJis,
		eLast
	};
	static const utf8 k_Boms[eLast][3];
	LANGID langId; 
};

// Reads UTF-16 and outputs UTF-8
class Utf16_Iter : public Utf8_16 {
public:
	Utf16_Iter();
	void reset();
	void set(const ubyte* pBuf, size_t _byteSize, encodingType eEncoding);
	utf8 get();
	bool canGet() const { return m_eReadState == eNull; }
	void operator++();
	operator bool() {
		return m_pRead < m_pEnd; 
	}

protected:
	enum eState {
		eNull,
		eStart,
		eSecondOf4Bytes,
		ePenultimate,
		eFinal
	};
protected:
	encodingType m_eEncoding;
	eState m_eReadState;
	eState m_eGetState;
	utf8 m_nCur;
	int m_nCur16;
	int trail;
	const ubyte* m_pBuf;
	const ubyte* m_pRead;
	const ubyte* m_pEnd;
};
// Reads UTF-16 and outputs UTF-16
//(LittleEndian -->BigEndian or BigEndian-->LittleEndian)
class Utf16_16Iter : public Utf8_16 {
public:
	Utf16_16Iter();
	void reset();
	void set(const ubyte* pBuf, size_t nLen);
	utf8 get();
	bool canGet() const { return m_eReadState == eNull; }
	void operator++();
	operator bool() {
		return m_pRead <= m_pEnd; 
	}

protected:
	enum eState {
		eNull,
		eStart,
		eSecondOf4Bytes,
		ePenultimate,
		eFinal
	};
protected:
	encodingType m_eEncoding;
	eState m_eReadState;
	eState m_eGetState;
	utf8 m_nCur;
	utf8 trail;
	const ubyte* m_pBuf;
	const ubyte* m_pRead;
	const ubyte* m_pEnd;
};

// Reads UTF-8 and outputs UTF-16
class Utf8_Iter : public Utf8_16 {
public:
	Utf8_Iter();
	void reset();
	void set(const ubyte* pBuf, size_t nLen, encodingType eEncoding);
	int get() const {
#ifdef _DEBUG
		assert(m_eState == eStart);
#endif
		return m_nCur;
	}
	bool canGet() const { return m_eState == eStart; }
	int CheckOnUTF8(unsigned char  * pcPos, size_t uiLen);
	void operator++();
	operator bool() const { return m_pRead <= m_pEnd; }

protected:
	void toStart(); // Put to start state
	enum eState {
	    eStart,
	    eSecondOf4Bytes,
	    ePenultimate,
	    eFinal
	};
protected:
	encodingType m_eEncoding;
	eState m_eState;
	int m_nCur;
	const ubyte* m_pBuf;
	const ubyte* m_pRead;
	const ubyte* m_pEnd;
};

// Reads UTF16 and outputs UTF8
class Utf8_16_Read : public Utf8_16 {
public:
	Utf8_16_Read();
	~Utf8_16_Read();

	size_t convert(char* buf, size_t len);
	char* getNewBuf() { return reinterpret_cast<char*>(m_pNewBuf); }

	encodingType getEncoding() const { return m_eEncoding; }
protected:
	int determineEncoding();
private:
	encodingType m_eEncoding;
	ubyte* m_pBuf;
	ubyte* m_pNewBuf;
	size_t m_nBufSize;
	bool m_bFirstRead;
	size_t m_nLen;
	Utf16_Iter m_Iter16;
};

// Read in a UTF-8 buffer and write out to UTF-16 or UTF-8
class Utf8_16_Write : public Utf8_16 {
public:
	Utf8_16_Write();
	~Utf8_16_Write();

	void setEncoding(encodingType eType);

	void setfile(FILE *pFile);
	size_t fwrite(const void* p, size_t _size);
	void fclose();
protected:
	encodingType m_eEncoding;
	FILE* m_pFile;
	utf16* m_pBuf;
	size_t m_nBufSize;
	bool m_bFirstWrite;
};

//======================================
// Reads Euc and outputs UTF-8,Reads UTF-8 and outputs Euc
class Euc_Iter : public Utf8_16 {
public:
	Euc_Iter();
	~Euc_Iter();
	int CheckOnEUC(unsigned char  * pcPos, size_t uiLen);
	size_t EucJpToUtf8(unsigned char  *pcEucChar,size_t iEucLen, unsigned char  *pcUtf8Char, int *ipLeftChar);
	size_t Utf8ToEucJp(unsigned char  *pcUtf8Char,size_t iUtf8Len, unsigned char  *pcEucChar);
	size_t EucJpToUnicode(unsigned char  *pcEucChar,size_t iEucLen, wchar_t *pcUnicodeChar, int *ipLeftChar);
	size_t UnicodeToEucJp(wchar_t *pcUnicodeChar, size_t iUnicodeLen, char *pcEucChar);
protected:
	//void toStart(); // Put to start state
	enum eState {
	    eStart,
	    eSecondOf4Bytes,
	    ePenultimate,
	    eFinal
	};
protected:
	const ubyte* m_pRead;
	eState m_eState;
	int m_nCur;
	// for euc to utf8 
	int iFstOnTwo;
	int ihbyte;


};

typedef struct codeconvinfo {
	const char *Str;			/* 文字列 */
	size_t StrLen;			/* 文字列の長さ */
	//int KanaCnv;		/* 半角カタカナを全角に変換するかどうか (YES/NO) */
	char *Buf;			/* 変換後の文字列を格納するバッファ */
	size_t BufSize;		/* 変換後の文字列を格納するバッファのサイズ */
	size_t OutLen;			/* 変換後の文字列のサイズ */
	int KanjiMode;		/* 漢字モードフラグ(YES/NO) (内部処理用ワーク) */
	int EscProc;		/* エスケープシーケンス文字数 (0～) (内部処理用ワーク) */
	char EscCode[2];	/* エスケープシーケンス文字保存用 (内部処理用ワーク) */
	char KanjiFst;		/* 漢字コード１バイト目保存用 (内部処理用ワーク) */
	//char KanaPrev;		/* 半角カタカナ保存用 (内部処理用ワーク) */
	//funcptr KanaProc;	/* 半角カタカナ処理ルーチン (内部処理用ワーク) */
} CODECONVINFO;

//outputs UTF-8
class Utf8_Read : public Utf8_16 {
public:
	Utf8_Read();
	~Utf8_Read();

	void reset();
	size_t convert(char* buf, size_t len,bool Continue = false);
	char* getNewBuf() { return reinterpret_cast<char*>(m_pNewBuf); }

	encodingType getEncoding() const { return m_eEncoding; }
protected:
	void init();
	void free();
	int determineEncoding();
private:
	char ansi[2];
	char ansi_bk;
	encodingType m_eEncoding;
	ubyte* m_pBuf;
	ubyte* m_pNewBuf;
	size_t m_nBufSize;
	bool m_bFirstRead;
	size_t m_nLen;
	Utf8_Iter m_Iter8;
	Utf16_Iter m_Iter16;
	Euc_Iter   m_Ieuc;
	CODECONVINFO  m_ConvInfo;
	void CheckKanjiCode(char *Text, size_t Size);
};

// Read in a UTF-8 buffer and write out to xxx
class Utf8_Write : public Utf8_16 {
public:
	Utf8_Write();
	~Utf8_Write();

	void setEncoding(encodingType eType);

	void setfile(FILE *pFile);
	size_t fwrite(const void* p, size_t _size);
	void fclose();
protected:
	encodingType m_eEncoding;
	FILE* m_pFile;
	utf16* m_pBuf;
	size_t m_nBufSize;
	bool m_bFirstWrite;
private:
	Euc_Iter   m_Ieuc;
	CODECONVINFO  m_ConvInfo;

};

//---------for MyRegEditor--------------------start
//outputs UTF-16
class Utf16_Read : public Utf8_16 {
public:
	Utf16_Read();
	Utf16_Read(const wchar_t *file);
	~Utf16_Read();
	bool readFile(const wchar_t *file);
	int getline(wchar_t *line, size_t _len);
	size_t m_nFileSize;
	int	m_LineNum;

	void reset();
	size_t convert(const char* buf, size_t byteSize,bool Continue = false);
	const char* getNewBuf() { return reinterpret_cast<const char*>(m_pNewBuf); }

	encodingType getEncoding() const { return m_eEncoding; }
protected:
	void init();
	void free();
	int determineEncoding();
private:
	char *m_pFileContent;
	typedef struct _utf16_line_info {
		size_t   idx;
		size_t   len;
	}Utf16_Line_Info ;
	std::vector<Utf16_Line_Info>  m_LineInfo;

	char ansi[2];
	char ansi_bk;
	encodingType m_eEncoding;
	const ubyte* m_pBuf;
	ubyte* m_pNewBuf;
	size_t m_nBufSize;
	bool m_bFirstRead;
	size_t m_nLen;
	Utf8_Iter m_Iter8;
	Utf16_Iter m_Iter16;
	Utf16_16Iter m_Iter16_16;
	Euc_Iter   m_Ieuc;
	CODECONVINFO  m_ConvInfo;
	void CheckKanjiCode(char *Text, size_t Size);
};

// Read in a UTF-16 buffer and write out to xxx
class Utf16_Write : public Utf8_16 {
public:
	Utf16_Write();
	~Utf16_Write();

	void setEncoding(encodingType eType);

	void setfile(FILE *pFile);
	size_t fwrite(const void* p, size_t _wordSize);
	void fclose();
protected:
	encodingType m_eEncoding;
	FILE* m_pFile;
	utf16* m_pBuf;
	size_t m_nBufSize;
	bool m_bFirstWrite;
private:
	Euc_Iter   m_Ieuc;
	Utf16_Iter m_Iter16;
	Utf16_16Iter m_Iter16_16;
	CODECONVINFO  m_ConvInfo;

};
#endif
//---------for MyRegEditor--------------------end
