/*---------------------------------------------------------------------------*/
/*  ランレングス圧縮、展開関数
＜圧縮＞
	  書式：int rl_arc_b(source,dist,size);
	  引数：     char *source;     圧縮元のデータの先頭アドレス
				 char *dist;       圧縮先バッファの先頭アドレス
				 int  size;        圧縮元データのサイズ
	戻り値：int 圧縮後のサイズ
	  機能：バイト単位でランレングス圧縮を実行します。


	  書式：int rl_arc_w(source,dist,size);
	  引数：     short *source;     圧縮元のデータの先頭アドレス
				 short *dist;       圧縮先バッファの先頭アドレス
				 int   size;        圧縮元データのサイズ
	戻り値：int 圧縮後のサイズ
	  機能：ワード単位でランレングス圧縮を実行します。


	  書式：int rl_arc_l(source,dist,size);
	  引数：     int *source;     圧縮元のデータの先頭アドレス
				 int *dist;       圧縮先バッファの先頭アドレス
				 int  size;       圧縮元データのサイズ
	戻り値：int 圧縮後のサイズ
	  機能：ロングワード単位でランレングス圧縮を実行します。

＜展開＞
	  書式：int rl_ext_b(source,dist,size);
	  引数：     char *source;     展開元のデータの先頭アドレス
				 char *dist;       展開先バッファの先頭アドレス
				 int  size;        展開元のデータのサイズ
	戻り値：int 展開後のサイズ
	  機能：バイト単位でランレングス展開を実行します。


	  書式：int rl_ext_w(source,dist,size);
	  引数：     short *source;     展開元のデータの先頭アドレス
				 short *dist;       展開先バッファの先頭アドレス
				 int   size;        展開元のデータのサイズ
	戻り値：int 展開後のサイズ
	  機能：ワード単位でランレングス展開を実行します。


	  書式：int rl_ext_l(source,dist,size);
	  引数：     int *source;     展開元のデータの先頭アドレス
				 int *dist;       展開先バッファの先頭アドレス
				 int size;        展開元のデータのサイズ
	戻り値：int 展開後のサイズ
	  機能：ロングワード単位でランレングス展開を実行します。

  注）size が int 型のため、ファイルサイズは圧縮後、展開後共に
	  2147483648バイトまでしか扱えません.


  p.s.殆ど圧縮ききません(^^;;;    ・・・
	  というより、めったに元サイズ以下になることないです(^^;;;;;;
	  ほとんど「ランレングス膨張、復活関数」ｸｻｲ(笑ｴﾈｰ(ｫ
	  （試作時の gtn.a とのデータ互換以外には使い道なさそう(^^;）
*/
int rl_arc_b(char* source, char* dist, int size);
int rl_ext_b(char* source, char* dist, int size);
int rl_arc_w(short* source, short* dist, int size);
int rl_ext_w(short* source, short* dist, int size);
int rl_arc_l(int* source, int* dist, int* size);
int rl_ext_l(int* source, int* dist, int* size);

/*---------------------------------------------------------------  バイト単位で  ------*/
/*-----------------------------------  圧縮  --*/
int rl_arc_b(char* source, char* dist, int size)
{
	char keep;
	unsigned char contno = 0;
	int sizecount = 0;
	int sizechk = 0;

	while (1) {
		keep = *source++;
		contno = 0;
		sizechk += 1;

		if (sizechk == size) {
			*dist++ = keep;
			*dist++ = contno;
			sizecount += 2;
			return(sizecount);
		}

		while (1) {
			if (*source++ == keep) {
				contno += 1;
				if (sizechk > 524284) {
					int a = 1;
				}
				sizechk += 1;
				if (contno == 255) {
					*dist++ = keep;
					*dist++ = contno;
					sizecount += 2;
					break;
				}
				if (sizechk >= size) {
					*dist++ = keep;
					*dist++ = contno;
					sizecount += 2;
					return(sizecount);
					break;
				}
			}
			else {
				*dist++ = keep;
				*dist++ = contno;
				source--;
				sizecount += 2;
				break;
			}
		}
		if (sizechk >= size) {
			break;
		}
	}
	return(sizecount);
}

/*-----------------------------------  展開  --*/
int rl_ext_b(char* source, char* dist, int size)
{
	char keep;
	unsigned char cont;
	int i;
	int sizechk = 0;
	int extsize = 0;

	while (1) {
		keep = *source++;
		cont = *source++;
		for (i = 0; i <= cont; i++) {
			*dist++ = keep;
			extsize += 1;
		}
		sizechk += 2;
		if (size == sizechk)return(extsize);
	}
}


/*---------------------------------------------------------------  ワード単位で  ------*/
/*-----------------------------------  圧縮  --*/
int rl_arc_w(short* source, short* dist, int size)
{
	short keep;
	unsigned short contno = 0;
	int sizecount = 0;
	int sizechk = 0;

	while (1) {
		keep = *source++;
		contno = 0;
		sizechk += 2;

		if (sizechk >= size) {
			*dist++ = keep;
			*dist++ = contno;
			sizecount += 4;
			return(sizecount);
		}

		while (1) {
			if (*source++ == keep) {
				contno += 1;
				sizechk += 2;
				if (contno == 65535) {
					*dist++ = keep;
					*dist++ = contno;
					sizecount += 4;
					break;
				}
				if (sizechk >= size) {
					*dist++ = keep;
					*dist++ = contno;
					sizecount += 4;
					return(sizecount);
					break;
				}
			}
			else {
				*dist++ = keep;
				*dist++ = contno;
				source--;
				sizecount += 4;
				break;
			}
		}
	}
}

/*-----------------------------------  展開  --*/
int rl_ext_w(short* source, short* dist, int size)
{
	short keep;
	unsigned short cont;
	int i;
	int sizechk = 0;
	int extsize = 0;

	while (1) {
		keep = *source++;
		cont = *source++;
		for (i = 0; i <= cont; i++) {
			*dist++ = keep;
			extsize += 2;
		}
		sizechk += 4;
		if (size <= sizechk)return(extsize);
	}
}


/*---------------------------------------------------------  ロングワード単位で  ------*/
/*-----------------------------------  圧縮  --*/
int rl_arc_l(int* source, int* dist, int* size)
{
	int keep;
	unsigned int contno = 0;
	int sizecount = 0;
	int sizechk = 0;

	while (1) {
		keep = *source++;
		contno = 0;
		sizechk += 4;

		if (sizechk >= size) {
			*dist++ = keep;
			*dist++ = contno;
			sizecount += 8;
			return(sizecount);
		}

		while (1) {
			if (*source++ == keep) {
				contno += 1;
				sizechk += 4;
				if (contno == 0xFFFFFFFF) {
					*dist++ = keep;
					*dist++ = contno;
					sizecount += 8;
					break;
				}
				if (sizechk >= size) {
					*dist++ = keep;
					*dist++ = contno;
					sizecount += 8;
					return(sizecount);
					break;
				}
			}
			else {
				*dist++ = keep;
				*dist++ = contno;
				source--;
				sizecount += 8;
				break;
			}
		}
	}
}

/*-----------------------------------  展開  --*/
int rl_ext_l(int* source, int* dist, int* size)
{
	int keep;
	unsigned int cont;
	int i;
	int sizechk = 0;
	int extsize = 0;

	while (1) {
		keep = *source++;
		cont = *source++;
		for (i = 0; i <= cont; i++) {
			*dist++ = keep;
			extsize += 4;
		}
		sizechk += 8;
		if (size <= sizechk)return(extsize);
	}
}
