#include "stdafx.h"

using namespace std;

#include "ImgUtil.h"


wstring g_ImageErrorStr[] =
{
	L"Успешно.",
	L"Недостаточно памяти.",
	L"Невозможно открыть файл образа.",
	L"Невозможно создать файл образа.",
	L"Файл образа не открыт.",
	L"Файл образа защищён от записи.",
	L"Ошибка позиционирования в файле образа.",
	L"Ошибка чтения файла образа.",
	L"Ошибка записи в файл образа.",
	L"Невозможно создать директорию.",
	L"Файл не найден.",
	L"Ошибки в формате файловой системы.",
	L"Файл с таким именем уже существует.",
	L"Директория с таким именем уже существует.",
	L"Директории с таким именем не существует.",
	L"Каталог заполнен.",
	L"Диск заполнен.",
	L"Диск сильно фрагментирован, нужно провести сквизирование.",
	L"Директория не пуста.",
	L"Нарушена структура каталога.",
	L"Это не директория.",
	L"Это не файл.",
	L"Файловая система не поддерживает директории.",
	L"Файл защищён от удаления.",
	L"" //на будущее
};

/*
преобразование имени файла из кои8 в юникод. с удалением запрещённых символов
*/
wstring BKToUNICODE(uint8_t *pBuff, int size, const wchar_t table[])
{
	wstring strRet = L"";

	for (int i = 0; i < size; ++i)
	{
		wchar_t tch = BKToUNICODE_Byte(pBuff[i], table);

		if (tch == 0)
		{
			break;
		}

		strRet += tch;
	}

	return strRet;
}

wchar_t BKToUNICODE_Byte(uint8_t b, const wchar_t table[])
{
	if (b == 0)
	{
		return 0;
	}

	if (b < 32)
	{
		return L' ';
	}
	else if (b >= 32 && b < 127)
	{
		return (wchar_t)b;
	}
	else if (b == 127)
	{
		return (wchar_t)0x25a0;
	}
	else if (b >= 128)
	{
		return table[b - 128];
	}

	return 0; //этот return не должен выполниться в принципе.
}


/*
преобразование юникодной строки в бкшный кои8.
вход:
ustr - преобразуемая строка
pBuff - буфер, куда выводится результат
bufSize - размер буфера
bFillBuf - флаг. если строка короче размера буфера, буфер до конца забивается пробелами. (конца строки - 0 нету.)
*/
void UNICODEtoBK(const wstring &ustr, uint8_t *pBuff, size_t bufSize, bool bFillBuf)
{
	uint8_t b;
	size_t bn = 0;
	size_t len = ustr.length();
	size_t n = 0;

	while (n < len)
	{
		wchar_t ch = ustr[n++]; //берём очередной символ

		if (ch < 32) //если символ меньше пробела,
		{
			b = 32;    //то будет пробел
		}
		else if ((32 <= ch) && (ch < 127)) //если буквы-цифры- знаки препинания
		{
			b = LOBYTE(ch); // то буквы-цифры- знаки препинания
		}
		else if (ch == 0x25a0) //если такое
		{
			b = 127; //то это. это единственное исключение в нижней половине аски кодов
		}
		else //если всякие другие символы
		{
			//то ищем в таблице нужный нам символ, а его номер - будет кодом кои8
			b = 32; //если такого символа нету в таблице - будет пробел

			for (int i = 0; i < 128; ++i)
			{
				if (ch == koi8tbl10[i])
				{
					b = LOBYTE(i) + 0200;
					break;
				}
			}
		}

		pBuff[bn++] = b;

		if (bn >= bufSize)
		{
			break;
		}
	}

	if (bFillBuf && (len < bufSize))
	{
		while (bn < bufSize)
		{
			pBuff[bn++] = 32;
		}
	}
}


//то же что и для дир + меняем страшные символы '\' и '/' на нестрашную '.'
void SetSafeName(wstring &str)
{
	SetSafeDir(str);
	replaceChars(&str, wstring(L"\\/"), L'.');
}
//меняем страшные символы '>','<',':','|','?','*' на нестрашную '_'
//и все коды меньше пробела - на '_'
void SetSafeDir(wstring &str)
{
	wchar_t rch = L'_';
	size_t l = str.length();

	if (l)
	{
		replaceChars(&str, wstring(L"><:|?*"), rch);

		//а теперь заменим все символы с кодом меньше 32
		for (size_t i = 0; i < l; ++i)
		{
			if (str[i] < 32)
			{
				str[i] = rch;
			}
		}
	}
}

//получим номер окончания слова в зависимости от числа num (предполагаем, что нет отрицательных чисел)
unsigned int GetWordEndIdx(unsigned int num)
{
	static const unsigned int nn[10] = { 2, 0, 1, 1, 1, 2, 2, 2, 2, 2 };

	//исключение 10..19, здесь всегда 2
	if ((num >= 10) && (num <= 19))
	{
		return 2;
	}

	//все остальные окончания определяются по одной крайней правой цифре.
	//вот её и получим
	num %= 10;
	return nn[num];
}

//тупой класс wstring не имеет многих нужных функций.

void trim(wstring *str, wchar_t trim_char)
{
	if (str == nullptr)
	{
		return;
	}

	trimLeft(str, trim_char);
	trimRight(str, trim_char);
}

void trimLeft(wstring *str, wchar_t trim_char)
{
	if (str == nullptr)
	{
		return;
	}

	while (!str->empty() && (str->front() == trim_char))
	{
		str->erase(str->begin());
	}
}

void trimRight(wstring *str, wchar_t trim_char)
{
	if (str == nullptr)
	{
		return;
	}

	while (!str->empty() && (str->back() == trim_char))
	{
		str->pop_back();
	}
}

void replaceChar(wstring *str, wchar_t src, wchar_t dst)
{
	if (str == nullptr)
	{
		return;
	}

	if (!str->empty())
	{
		for (wchar_t &n : *str)
		{
			if (n == src)
			{
				n = dst;
			}
		}
	}
}

void strToUpper(wstring *str)
{
	if (str == nullptr)
	{
		return;
	}

	if (!str->empty())
	{
		_locale_t loc = _create_locale(LC_ALL, "Russian");

		for (wchar_t &n : *str)
		{
			n = _toupper_l(n, loc);
		}

		_free_locale(loc);
	}
}

void strToLower(wstring *str)
{
	if (str == nullptr)
	{
		return;
	}

	if (!str->empty())
	{
		_locale_t loc = _create_locale(LC_ALL, "Russian");

		for (wchar_t &n : *str)
		{
			n = _tolower_l(n, loc);
		}

		_free_locale(loc);
	}
}


void replaceChars(wstring *str, wstring &src, wchar_t dst)
{
	if (str == nullptr)
	{
		return;
	}

	size_t l = src.length();

	if (!str->empty() && !src.empty())
	{
		for (wchar_t &n : *str)
		{
			for (size_t i = 0; i < l; ++i)
			{
				if (n == src[i])
				{
					n = dst;
					break;
				}
			}
		}
	}
}

