//---------------------------------------------------------------------------
//#pragma hdrstop
//---------------------------------------------------------------------------
#define _CRT_SECURE_NO_WARNINGS
//---------------------------------------------------------------------------
#ifdef _WIN32
#define NOMINMAX
#endif // _WIN32
//---------------------------------------------------------------------------
#include "stdTools.h"
//#include "mathTools.h"
#include <cstdint>

//#include <Math.h>
#include <list>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <locale>
#include <codecvt>
#include <vector>
#include <stdexcept>
#include <algorithm>
#include <ctime>
#include <limits> //min max
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND) || defined(__BORLANDC__)
	#include <windows.h>
	//#include <minwinbase.h>
	#include <winnt.h>
	//#include <fileapi.h>

	#include <shlobj.h>
#else
	//#include <chrono>
	#include <sys/time.h>
	#include <pwd.h>
	#include <unistd.h>
	#include <sys/types.h>

	#include <dirent.h>
#endif
#include <sys/stat.h> //mkdir

#include <iostream>
#include <clocale>
#include <cstring>
#include <cstdlib>



namespace Utility
{

	//---------------------------------------------------------------------------
	std::string sp3()
	{
#if defined _WIN32 || defined __CYGWIN__
		return "\\";
#else
		return "/";
#endif
	}
	//------------------------------------------------------------------------------
	//Разделитель для директорий
	char separator()
	{
	#ifdef _WIN32
		return '\\';
	#else
		return '/';
	#endif
	}
	//---------------------------------------------------------------------------
	std::string base64_encode(const std::string &in) {
		std::string out;
#if defined(__BORLANDC__)
#else
		int val = 0, valb = -6;
		for (unsigned char c : in) {
			val = (val << 8) + c;
			valb += 8;
			while (valb >= 0) {
				out.push_back("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(val >> valb) & 0x3F]);
				valb -= 6;
			}
		}
		if (valb>-6) out.push_back("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[((val << 8) >> (valb + 8)) & 0x3F]);
		while (out.size() % 4) out.push_back('=');
#endif
		return out;
	}
	//---------------------------------------------------------------------------
	std::string base64_decode(const std::string &in) {

		std::string out;
#if defined(__BORLANDC__)
#else
		std::vector<int> T(256, -1);
		for (int i = 0; i<64; i++) T["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[i]] = i;

		int val = 0, valb = -8;
		for (unsigned char c : in) {
			if (T[c] == -1) break;
			val = (val << 6) + T[c];
			valb += 6;
			if (valb >= 0) {
				out.push_back(char((val >> valb) & 0xFF));
				valb -= 8;
			}
		}
#endif
		return out;
	}
	//------------------------------------------------------------------------------
	//Преобразовать HEX символ в число (вынужденный повтор чтобы не инклюдить большой файл)
	int hexCharToIntTMP(char input)
	{
	  if(input >= '0' && input <= '9')
	    return input - '0';
	  if(input >= 'A' && input <= 'F')
	    return input - 'A' + 10;
	  if(input >= 'a' && input <= 'f')
	    return input - 'a' + 10;
	  throw std::invalid_argument("Invalid input string");
	}
	//------------------------------------------------------------------------------
	uint16_t hexString2ToUint(std::string &str, int pos,bool cut)
	{
		uint16_t result;
		((uint8_t*)&result)[0] = hexCharToIntTMP(str[pos]) * 16 + hexCharToIntTMP(str[pos + 1]);
		((uint8_t*)&result)[1] = hexCharToIntTMP(str[pos + 2]) * 16 + hexCharToIntTMP(str[pos + 3]);
		if (cut)
		{
			str = str.substr(0, pos) + str.substr(pos+4);
		}
		return result;
	}
	//---------------------------------------------------------------------------
	uint32_t hexString4ToUint(std::string &str, int pos, bool cut)
	{
		uint32_t result=0;
		((uint8_t*)&result)[0] = hexCharToIntTMP(str[pos]) * 16 + hexCharToIntTMP(str[pos + 1]);
		((uint8_t*)&result)[1] = hexCharToIntTMP(str[pos + 2]) * 16 + hexCharToIntTMP(str[pos + 3]);
		((uint8_t*)&result)[2] = hexCharToIntTMP(str[pos + 4]) * 16 + hexCharToIntTMP(str[pos + 5]);
		((uint8_t*)&result)[3] = hexCharToIntTMP(str[pos + 6]) * 16 + hexCharToIntTMP(str[pos + 7]);
		if (cut)
		{
			str = str.substr(0, pos) + str.substr(pos + 8);
		}
		return result;
	}
	//---------------------------------------------------------------------------
	uint64_t hexString6ToUint(std::string &str, int pos, bool cut)
	{
		uint64_t result=0;
		((uint8_t*)&result)[0] = hexCharToIntTMP(str[pos]) * 16 + hexCharToIntTMP(str[pos+1]);
		((uint8_t*)&result)[1] = hexCharToIntTMP(str[pos + 2]) * 16 + hexCharToIntTMP(str[pos + 3]);
		((uint8_t*)&result)[2] = hexCharToIntTMP(str[pos + 4]) * 16 + hexCharToIntTMP(str[pos + 5]);
		((uint8_t*)&result)[3] = hexCharToIntTMP(str[pos + 6]) * 16 + hexCharToIntTMP(str[pos + 7]);
		((uint8_t*)&result)[4] = hexCharToIntTMP(str[pos + 8]) * 16 + hexCharToIntTMP(str[pos + 9]);
		((uint8_t*)&result)[5] = hexCharToIntTMP(str[pos + 10]) * 16 + hexCharToIntTMP(str[pos + 11]);
		if (cut)
		{
			str = str.substr(0, pos) + str.substr(pos + 12);
		}
		return result;
	}
	//---------------------------------------------------------------------------
	//Прочитать файл в строку
	std::string readFileToString(std::string fName){
		std::ifstream t(fName);
		std::stringstream buffer;
		buffer << t.rdbuf();
		return buffer.str();
	}
	//------------------------------------------------------------------------------
	bool deleteFile(std::string fileName)
	{
		bool result=false;
#ifdef __linux__
		if(unlink(fileName.c_str())==0)
		{
			result=true;
		}
#elif _WIN32
		if(remove(fileName.c_str())==0)
		{
			result=true;
		}
#endif
		return result;
	}
	//---------------------------------------------------------------------------
	//Получить дату последнего изменения файла
	long getFileDateModiff(std::string file)
	{
	#ifdef __linux__
		struct stat fStat;
		int rc = stat(file.c_str(), &fStat);
		if(rc==0)
		{
			return fStat.st_mtim.tv_sec;
		}
		return 0;
	#elif _WIN32
		return 0;
	#else
	#endif
	}
	//------------------------------------------------------------------------------
	//удалить старые файлы которые были созданы больше заданного количества дней
	bool deleteOldFiles(std::string path,int days)
	{
		bool result=true;
		std::list<std::string> fileList;
		Utility::getFiles(fileList,path);
		std::list<std::string>::const_iterator iterator;
		for (iterator = fileList.begin(); iterator != fileList.end(); ++iterator) {
			std::string fName = *iterator;
			long timeS = getFileDateModiff(fName);
			int tNow=std::time(NULL);
			int tDiff = tNow-timeS;
			if(tDiff > days*24*60*60) {
				if(!deleteFile(fName)) {
					result=result & false;
				}
			}
		}
		return result;
	}
	//---------------------------------------------------------------------------
	//Найти файлы в директории и под директории и добавить их в список
	void getFiles(std::list<std::string>& fileList, std::string directory)
	{
		if(directory.length()>0 && directory[directory.length()-1]!=separator()) directory+=separator();
#ifdef __linux__
		DIR *dir = opendir(directory.c_str());
		if(dir)
		{
			struct dirent *ent;
			while((ent = readdir(dir)) != NULL)
			{
				if(ent->d_type==0x04)
				{
					if ((strncmp(".", ent->d_name, 1) != 0) && (strncmp("..", ent->d_name, 2) != 0))
					{
						std::string newDir = directory + ent->d_name+"/";
						Utility::getFiles(fileList, newDir);
					}
				}
				else
				if(ent->d_type==0x08)
				{
					std::string fWName = ent->d_name;
					fWName = directory + fWName;
					fileList.push_back(fWName);
				}
			}
			closedir(dir);
		}
#elif _WIN32
		HANDLE hFind;
		WIN32_FIND_DATAA FindFileData;

		if ((hFind = FindFirstFileA((std::string(directory+"*.*")).c_str(), &FindFileData)) != INVALID_HANDLE_VALUE) {
			do {
				if (FILE_ATTRIBUTE_DIRECTORY & FindFileData.dwFileAttributes)
				{
					if ((strncmp(".", FindFileData.cFileName, 1) != 0) && (strncmp("..", FindFileData.cFileName, 2) != 0))
					{
						std::string newDir = directory + FindFileData.cFileName+"\\";
						Utility::getFiles(fileList, newDir);
					}
				}
				else
				{
					std::string fWName = FindFileData.cFileName;
					fWName = directory + fWName;
					fileList.push_back(fWName);
				}

			} while (FindNextFileA(hFind, &FindFileData));
			FindClose(hFind);
		}
#else

#endif
	}
	//---------------------------------------------------------------------------
	//Читаем до символа перехода на новую строку
	std::wstring readUTF16LEString(FILE* fp)
	{
		std::wstring result=L"";
		wchar_t ch;
		while( !feof( fp) )
		{
			size_t count = fread( &((char*)&ch)[0], 1, 1, fp);
			if(count==1)
			{
				count = fread( &((char*)&ch)[1], 1, 1, fp);
				if(count==1)
				{
					if(ch==10) break; //L'\n'
					if(ch!=13) //L'\r'
						result+=ch;
				}
			}
		}
		return result;
	}
	//---------------------------------------------------------------------------
	//Прочитать первый попавшийся UTF-16 (LE) FF FE во всём файле
	bool seekToLEBOM(FILE* fp)
	{
		bool result = false;
		unsigned char ch;
		while( !feof( fp) )
		{
			size_t count = fread( &ch, 1, 1, fp);
			if(count==1 && ch==0xFF)
			{
				count = fread( &ch, 1, 1, fp);
				if(count==1 && ch==0xFE)
				{
					result=true;
					break;
				}
			}
		}
		return result;
	}
	//---------------------------------------------------------------------------
	//Читать в строку до первого попавшегося символа (в результате этого символа не будет)
	std::string readString(FILE* fp,char ch)
	{
		std::string result="";
		char tmp;
		while( !feof( fp) )
		{
			size_t count = fread( &tmp, 1, 1, fp);
			if(count==1)
			{
				if(tmp==ch)
					break;
				result+=tmp;
			}
		}
		return result;
	}
	//---------------------------------------------------------------------------
	int readFile(FILE* fp,char* data,int len)
	{
		int result=0;
		while( !feof( fp) )
		{
			size_t count = fread( &data[result], 1, 1, fp);
			if(count==1)
			{
				result++;
				if(result>=len)
					break;
			}
		}
		return result;
	}
	//---------------------------------------------------------------------------
	std::string lowerCaseENG(std::string str)
	{
		std::string result;
		for(int i=0;i<(int)str.length();i++)
		{
			if(str[i]<='Z' && str[i]>='A')
				result += str[i]-('Z'-'z');
			else
			result += str[i];
		}
		return result;
	}
	//---------------------------------------------------------------------------
	/*char easytolower(char in){
	  if(in<='Z' && in>='A')
		return in-('Z'-'z');
	  return in;
	}*/
	//---------------------------------------------------------------------------
	//#include <atlbase.h> //Зло :-)
	//#include "stdafx.h"
	#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND) || defined(__BORLANDC__)
	#if defined( _VC )
		#include < ctime >
	#endif
	#if defined( _BORLAND )
		#include <vcl.h>
	#endif
		#include <Windows.h> //Для Windows
		#include <sys\types.h>
		#include <sys\stat.h>
	#else
		#include <iconv.h>
	#endif

	//#include <time.h> //Функция времени

	#include "tcDebug.h"
	//---------------------------------------------------------------------------
	//260 was taken from windef.h
	#ifndef MAX_PATH
		#define MAX_PATH 260
	#endif
	//---------------------------------------------------------------------------
	#define MIN(a,b) (((a)<(b))?(a):(b))
	#define MAX(a,b) (((a)>(b))?(a):(b))
	//---------------------------------------------------------------------------
	/*template <typename T>
	std::string toStdStr(T val)
	{
		std::ostringstream oss;
		oss << val;
		return oss.str();
	}*/
	//---------------------------------------------------------------------------
	//Большее из 2х
	/*int MaxI4(int v1,int v2)
	{	if(v1>v2) return v1; else return v2;
	}*/
	//---------------------------------------------------------------------------
	/*std::wstring s2ws(const std::string& str)
	{
	#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND)
		int len;
		int slength = (int)str.length();// + 1;
		if(slength==0) return L"";
		len = MultiByteToWideChar(CP_ACP, 0, str.c_str(), slength, 0, 0);
		std::wstring rez(len, L'\0');
		MultiByteToWideChar(CP_ACP, 0, str.c_str(), slength, &rez[0], len);

		//Каз. символы из ASCII в UTF16 в ручную переводим
		for(size_t i=0;i<str.length();i++)
		{
			switch ((char)str[i])
			{
				case (char)0xA3: rez[i]=L'Ә'; break;// Ә
				case (char)0xBC: rez[i]=L'ә'; break;// ә
				case (char)0xAA: rez[i]=L'Ғ'; break;// Ғ
				case (char)0xBA: rez[i]=L'ғ'; break;// ғ
				case (char)0x8D: rez[i]=L'Қ'; break;// Қ
				case (char)0x9D: rez[i]=L'қ'; break;// қ
				case (char)0xBD: rez[i]=L'Ң'; break;// Ң
				case (char)0xBE: rez[i]=L'ң'; break;// ң
				case (char)0xA5: rez[i]=L'Ө'; break;// Ө
				case (char)0xB4: rez[i]=L'ө'; break;// ө
				case (char)0xA1: rez[i]=L'Ұ'; break;// Ұ
				case (char)0xA2: rez[i]=L'ұ'; break;// ұ
				case (char)0xAF: rez[i]=L'Ү'; break;// Ү
				case (char)0xBF: rez[i]=L'ү'; break;// ү
				case (char)0x8E: rez[i]=L'Һ'; break;// Һ
				case (char)0x9E: rez[i]=L'һ'; break;// һ
				//case (char)0xB2: rez[i]=L'І'; break;// І
				//case (char)0xB3: rez[i]=L'i'; break;// i
				case (char)0xB9: rez[i]=L'№'; break;
			}
		}

		return rez;
	#else
		std::wstring result;
		const char* pt = s.c_str();
		size_t max = s.length();
		int length;
		wchar_t dest;
		mbtowc (NULL, NULL, 0);
		while (max>0)
		{
			length = mbtowc(&dest,pt,max);
			if (length<1) break;
			result+=dest;
			pt+=length; max-=length;
		}
		return result;
	#endif
		return L"";
	}*/
	//---------------------------------------------------------------------------
	//Размер файла в байтах
	long getFileSize(std::string filename)
	{
	//#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND)
	//	unsigned long FileSize = 0;
	//	HANDLE hF = CreateFile(
	//		filename.c_str(),			// file name
	//		GENERIC_READ,				// access mode
	//		0,							// share mode
	//		NULL,						// SD
	//		OPEN_EXISTING,				// how to create
	//		0,							// file attributes
	//		NULL						// handle to template file
	//	);
	//	FileSize = GetFileSize(hF, NULL);
	//	CloseHandle(hF);
	//	return FileSize;
	//#else
		std::ifstream in(filename.c_str(), std::ifstream::ate | std::ifstream::binary);
		return (long)in.tellg();

		//struct stat stat_buf;
		//int rc = stat(filename.c_str(), &stat_buf);
		//return rc == 0 ? stat_buf.st_size : -1;
	//#endif
	}
	//---------------------------------------------------------------------------
	//Размер файла в байтах
	long GetWFileSize(std::wstring filename)
	{
		std::string str = WStringToString(filename,std::locale(""));
		std::wifstream in(str.c_str(), std::wifstream::ate | std::wifstream::binary);
		return (long)in.tellg();
	}
	//---------------------------------------------------------------------------
	//Сохранение лог файла по 10 мегабайт (в 2 файлика)
	bool logrotateW(std::wstring fileName, std::wstring data)
	{
		long fileSize = GetWFileSize(fileName);
		//Переименовываем файл если он привысил размер
		if(fileSize>1024*1024*10)
		{
	#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND)
			//_wrename(fileName.c_str(),std::wstring(fileName+L".1").c_str());
			std::string str = WStringToString(fileName,std::locale(""),'?');
			std::rename(str.c_str(),std::string(str+".1").c_str());
	#else
			std::string str = WStringToString(fileName,std::locale(""));
			rename(str.c_str(),std::string(str+".1").c_str());
	#endif
		}
		//Записываем лог
		std::string str = WStringToString(fileName,std::locale(""));
		std::ofstream myfile(str.c_str(),std::fstream::app | std::fstream::out);
		if (myfile.is_open())
		{
			myfile << data.c_str();
			myfile.flush();
			myfile.close();
			return true;
		}
		return false;
	}
	//---------------------------------------------------------------------------
	bool logrotateUTF8(std::wstring fileName, std::wstring data)
	{
		long fileSize = GetWFileSize(fileName);
		//Переименовываем файл если он привысил размер
		if (fileSize>1024 * 1024 * 10)
		{
	#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND)
			//_wrename(fileName.c_str(),std::wstring(fileName+L".1").c_str());

			std::string str = WStringToString(fileName, std::locale(""));
			rename(str.c_str(), std::string(str + ".1").c_str());
	#else
			std::string str = WStringToString(fileName,std::locale(""));
			rename(str.c_str(),std::string(str+".1").c_str());
	#endif
		}
		else if (fileSize == 0 || fileSize == -1) //Записываю сигнатуру то что это UTF8
		{
			std::string str = WStringToString(fileName,std::locale(""));
			std::ofstream myfile(str.c_str(), std::fstream::app | std::fstream::out);
			if (myfile.is_open())
			{
				myfile << (char)0xEF << (char)0xBB << (char)0xBF;
				myfile.flush();
				myfile.close();
			}
		}

		//Записываем лог
		std::string str = WStringToString(fileName,std::locale(""));
		std::ofstream myfile(str.c_str(), std::fstream::app | std::fstream::out);
		if (myfile.is_open())
		{
			std::time_t result = std::time(0);
			std::string time = std::asctime(std::localtime(&result));
			time = time.substr(0, time.length() - 1);

			myfile << "[" << time << "] " << convUTF16ToUTF8(data).c_str() << std::endl;
			myfile.flush();
			myfile.close();
			return true;
		}
		return false;
	}
	//---------------------------------------------------------------------------
	std::string escape_json(const std::string& input) {
	    std::ostringstream oss;
	    for (char c : input) {
	        switch (c) {
	            case '"':  oss << "\\\""; break;
	            case '\\': oss << "\\\\"; break;
	            case '\b': oss << "\\b";  break;
	            case '\f': oss << "\\f";  break;
	            case '\n': oss << "\\n";  break;
	            case '\r': oss << "\\r";  break;
	            case '\t': oss << "\\t";  break;
	            default:
	                if (static_cast<unsigned char>(c) < 0x20 || c == 0x7F) {
	                    oss << "\\u" << std::hex << std::setw(4) << std::setfill('0') << static_cast<int>(c);
	                } else {
	                    oss << c;
	                }
	                break;
	        }
	    }
	    return oss.str();
	}
	//---------------------------------------------------------------------------
	//Сохранение лог файла по 10 мегабайт (в 2 файлика) Функция отрабатывает за 4 миллисекунды
	/*bool logrotate(std::string fileName, std::string data, bool cout, int size)
	{
		long fileSize = GetFileSize(fileName);
		//Переименовываем файл если он привысил размер
		if(fileSize>1024*1024* size)
		{
			remove(std::string(fileName + ".1").c_str()); //Пытаюсь удалить старый файл
			rename(fileName.c_str(),std::string(fileName+".1").c_str());
		}

		//Записываем лог
		std::ofstream myfile(fileName.c_str(), std::ofstream::binary | std::fstream::app);
		if (myfile.is_open())
		{
			std::stringstream str(std::stringstream::out | std::stringstream::binary);
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND)
			SYSTEMTIME st;
			GetLocalTime(&st);
			//LONG time_ms = (st.wSecond * 1000) + st.wMilliseconds;
			//для конвертиции в строку: https://www.technical-recipes.com/2014/converting-a-systemtime-to-a-stdstring-in-c/
			char buffer[256];
			memset(buffer, 0, sizeof(buffer));
			sprintf(buffer,
				"%d.%02d.%02d %02d:%02d:%02d.%03d",
				st.wYear,
				st.wMonth,
				st.wDay,
				st.wHour,
				st.wMinute,
				st.wSecond,
				st.wMilliseconds);
			str << "[" << buffer << "] " << data << std::endl;
#else
			timeval curTime;
			gettimeofday(&curTime, NULL);
			int milli = curTime.tv_usec / 1000;
			std::time_t utime = curTime.tv_sec;
			char buffer[80]; memset(buffer, 0, sizeof(buffer));
			std::strftime(buffer, sizeof(buffer), "%Y.%m.%d %H:%M:%S", std::localtime(&utime));
			str << "[" << buffer << ":" << milli << "] " << data << std::endl;
#endif
			if (cout)
				std::cout << "[" << buffer << "] " << data << std::endl; //Повтор лога в консоль

			myfile.write(str.str().c_str(), str.str().length());
			myfile.flush();
			myfile.close();
			return true;
		}else
		{
			std::cerr << "Error: " << strerror(errno) << " " << fileName << std::endl;
		}
		return true;
	}*/

	bool logrotate(std::string fileName, std::string thread, std::string level, std::string data, bool cout, int size)
	{
		long fileSize = getFileSize(fileName);
		//Переименовываем файл если он привысил размер
		if(fileSize>1024*1024* size)
		{
			remove(std::string(fileName + ".1").c_str()); //Пытаюсь удалить старый файл
			rename(fileName.c_str(),std::string(fileName+".1").c_str());
		}
		if(fileSize==-1){
			createFolder(BeforeFirst(fileName,separator()));
		}

		//Записываем лог
		std::ofstream myfile(fileName.c_str(), std::ofstream::binary | std::fstream::app);
		if (myfile.is_open())
		{
			std::stringstream str(std::stringstream::out | std::stringstream::binary);
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND)
			SYSTEMTIME st;
			GetLocalTime(&st);
			char buffer[256];
			memset(buffer, 0, sizeof(buffer));
			sprintf(buffer,
				"%d-%02d-%02d %02d:%02d:%02d.%03d",
				st.wYear,
				st.wMonth,
				st.wDay,
				st.wHour,
				st.wMinute,
				st.wSecond,
				st.wMilliseconds);
			str << "[" << buffer << "] " << data << std::endl;
#else
			timeval curTime;
			gettimeofday(&curTime, NULL);
			int milli = curTime.tv_usec / 1000;
			std::time_t utime = curTime.tv_sec;
			char buffer[80]; memset(buffer, 0, sizeof(buffer));
			std::strftime(buffer, sizeof(buffer), "%Y-%m-%dT%H:%M:%S", std::localtime(&utime));
			str << "{\"timestamp\":\"" << buffer << "." << std::setw(3) << std::setfill('0') << milli << "Z\", \"thread\":\"" <<thread<<"\", \"level\":\""<<level<<"\", \"message\":\"" << escape_json(data)<<"\"}" << std::endl;
#endif
			if (cout)
				std::cout << "[" << buffer << "] " << data << std::endl; //Повтор лога в консоль

			myfile.write(str.str().c_str(), str.str().length());
			myfile.flush();
			myfile.close();
			return true;
		}else
		{
			std::cerr << "Error: " << strerror(errno) << " " << fileName << std::endl;
		}
		return true;
	}
	//---------------------------------------------------------------------------
	bool fileExists(std::string name)
	{
		if (FILE *file = fopen(name.c_str(), "r")) {
			fclose(file);
			return true;
		} else {
			return false;
		}
	}
	//---------------------------------------------------------------------------
	std::string ws2s(const std::wstring& str)
	{
	#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND)
		int len;
		int slength = (int)str.length();// + 1;
		if(slength==0) return "";
		len = WideCharToMultiByte(CP_ACP, 0, str.c_str(), slength, 0, 0, 0, 0);
		std::string rez(len, '\0');
		WideCharToMultiByte(CP_ACP, 0, str.c_str(), slength, &rez[0], len, 0, 0);

		//Каз символы из UTF16 в ASCII в ручную переводим
		for(size_t i=0;i<str.length();i++)
		{
			switch (str[i])
			{
				case L'Ә': rez[i]=(char)0xA3; break;// Ә
				case L'ә': rez[i]=(char)0xBC; break;// ә
				case L'Ғ': rez[i]=(char)0xAA; break;// Ғ
				case L'ғ': rez[i]=(char)0xBA; break;// ғ
				case L'Қ': rez[i]=(char)0x8D; break;// Қ
				case L'қ': rez[i]=(char)0x9D; break;// қ
				case L'Ң': rez[i]=(char)0xBD; break;// Ң
				case L'ң': rez[i]=(char)0xBE; break;// ң
				case L'Ө': rez[i]=(char)0xA5; break;// Ө
				case L'ө': rez[i]=(char)0xB4; break;// ө
				case L'Ұ': rez[i]=(char)0xA1; break;// Ұ
				case L'ұ': rez[i]=(char)0xA2; break;// ұ
				case L'Ү': rez[i]=(char)0xAF; break;// Ү
				case L'ү': rez[i]=(char)0xBF; break;// ү
				case L'Һ': rez[i]=(char)0x8E; break;// Һ
				case L'һ': rez[i]=(char)0x9E; break;// һ
				//case L'І': rez[i]=(char)0xB2; break;// І
				//case L'i': rez[i]=(char)0xB3; break;// i
				case 10402: rez[i]=(char)0xB9; break;//L'№'
			}
		}

		return rez;
	#else
		std::string result( str.begin(), str.end() );
		return result;
	#endif
		return "";
	}
	//---------------------------------------------------------------------------
	//Конвертнуть Win1251 в utf8 //TRANSLIT//IGNORE
	std::string iConvert(const std::string& instr,const char* fromCode,const char* toCode)
	{
		std::string outstr;
	#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND)

	#else
		iconv_t cd = iconv_open(toCode, fromCode);

		if( cd == (iconv_t)(-1) )
							 throw std::runtime_error("Не удалось открыть дескриптор iconv");

		size_t in_size = instr.size();
		char* inPrt = (char*)instr.c_str();

		int BUF_SIZE=in_size*4;
		char* out_buf = new char[BUF_SIZE];
		char* outPtr;
		size_t out_size;

		size_t  rSize;

		while(in_size > 0)
		{
			outPtr = out_buf;
			out_size = BUF_SIZE;

			rSize = iconv(cd, &inPrt,  &in_size, &outPtr, &out_size );

			if(rSize == (size_t)-1 && errno)
			{
				switch (errno)
				{
				case EILSEQ:
					throw std::runtime_error("invalid multibyte chars");
				case EINVAL:
					throw std::runtime_error("invalid multibyte chars");
				default:
					throw std::runtime_error("unknown error");
				}
			}
			outstr.append(out_buf,BUF_SIZE-out_size);
		}

		 if(iconv_close(cd)!=0 )
				std::runtime_error("Не удается закрыть дескриптор iconv");

		 delete[] out_buf;

	#endif

		return outstr;
	}
	//---------------------------------------------------------------------------
	//Конвертим из Unicode в DOS 866 кодировку
	std::string UnicodeToDOS886(std::wstring str)
	{
		std::string rez;
		rez.reserve(str.length()); //Количество символов не должно измениться

		for(unsigned int i=0;i<str.length();i++)
		{
			switch(str[i])
			{
				case L'А': rez+=(char)0x80; break;
				case L'Б': rez+=(char)0x81; break;
				case L'В': rez+=(char)0x82; break;
				case L'Г': rez+=(char)0x83; break;
				case L'Д': rez+=(char)0x84; break;
				case L'Е': rez+=(char)0x85; break;
				case L'Ё': rez+=(char)0x85; break; //case L'Ё': rez+=(char)0xF0; break;
				case L'Ж': rez+=(char)0x86; break;
				case L'З': rez+=(char)0x87; break;
				case L'И': rez+=(char)0x88; break;
				case L'Й': rez+=(char)0x89; break;
				case L'К': rez+=(char)0x8A; break;
				case L'Л': rez+=(char)0x8B; break;
				case L'М': rez+=(char)0x8C; break;
				case L'Н': rez+=(char)0x8D; break;
				case L'О': rez+=(char)0x8E; break;
				case L'П': rez+=(char)0x8F; break;
				case L'Р': rez+=(char)0x90; break;
				case L'С': rez+=(char)0x91; break;
				case L'Т': rez+=(char)0x92; break;
				case L'У': rez+=(char)0x93; break;
				case L'Ф': rez+=(char)0x94; break;
				case L'Х': rez+=(char)0x95; break;
				case L'Ц': rez+=(char)0x96; break;
				case L'Ч': rez+=(char)0x97; break;
				case L'Ш': rez+=(char)0x98; break;
				case L'Щ': rez+=(char)0x99; break;
				case L'Ъ': rez+=(char)0x9A; break;
				case L'Ы': rez+=(char)0x9B; break;
				case L'Ь': rez+=(char)0x9C; break;
				case L'Э': rez+=(char)0x9D; break;
				case L'Ю': rez+=(char)0x9E; break;
				case L'Я': rez+=(char)0x9F; break;
				case L'а': rez+=(char)0xA0; break;
				case L'б': rez+=(char)0xA1; break;
				case L'в': rez+=(char)0xA2; break;
				case L'г': rez+=(char)0xA3; break;
				case L'д': rez+=(char)0xA4; break;
				case L'е': rez+=(char)0xA5; break;
				case L'ё': rez+=(char)0xA5; break; 	//case L'ё': rez+=(char)0xF1; break;
				case L'ж': rez+=(char)0xA6; break;
				case L'з': rez+=(char)0xA7; break;
				case L'и': rez+=(char)0xA8; break;
				case L'й': rez+=(char)0xA9; break;
				case L'к': rez+=(char)0xAA; break;
				case L'л': rez+=(char)0xAB; break;
				case L'м': rez+=(char)0xAC; break;
				case L'н': rez+=(char)0xAD; break;
				case L'о': rez+=(char)0xAE; break;
				case L'п': rez+=(char)0xAF; break;
				case L'р': rez+=(char)0xE0; break;
				case L'с': rez+=(char)0xE1; break;
				case L'т': rez+=(char)0xE2; break;
				case L'у': rez+=(char)0xE3; break;
				case L'ф': rez+=(char)0xE4; break;
				case L'х': rez+=(char)0xE5; break;
				case L'ц': rez+=(char)0xE6; break;
				case L'ч': rez+=(char)0xE7; break;
				case L'ш': rez+=(char)0xE8; break;
				case L'щ': rez+=(char)0xE9; break;
				case L'ъ': rez+=(char)0xEA; break;
				case L'ы': rez+=(char)0xEB; break;
				case L'ь': rez+=(char)0xEC; break;
				case L'э': rez+=(char)0xED; break;
				case L'ю': rez+=(char)0xEE; break;
				case L'я': rez+=(char)0xEF; break;
				//Каз-яз
	/*			case L'?': rez+=(char)0xDB; break;
				case L'?': rez+=(char)0xDC; break;
				case L'?': rez+=(char)0xDE; break;
				case L'?': rez+=(char)0xDF; break;
				case L'?': rez+=(char)0xF0; break;
				case L'?': rez+=(char)0xF1; break;
				case L'?': rez+=(char)0xF3; break;
				case L'?': rez+=(char)0xF4; break;
				case L'?': rez+=(char)0xF5; break;
				case L'?': rez+=(char)0xF6; break;
				case L'?': rez+=(char)0xF7; break;
				case L'?': rez+=(char)0xF8; break;
				case L'?': rez+=(char)0xFD; break;
				case L'?': rez+=(char)0xFE; break;
	 */
				default: rez+=(char)str[i]; break;
			}
		}
		return rez;
	}
	//---------------------------------------------------------------------------
	//Обратная конвертация из DOS886 в Unicode
	std::wstring DOS886ToUnicode(std::string str)
	{
		std::wstring rez;
		rez.reserve(str.length()); //Количество символов не должно измениться

		for(unsigned int i=0;i<str.length();i++)
		{
			switch(str[i])
			{
				case (char)0x80: rez+=L'А'; break;
				case (char)0x81: rez+=L'Б'; break;
				case (char)0x82: rez+=L'В'; break;
				case (char)0x83: rez+=L'Г'; break;
				case (char)0x84: rez+=L'Д'; break;
				case (char)0x85: rez+=L'Е'; break;
				//case (char)0xF0: rez+=L'Ё'; break; //В место "Ё" в принтере "?"
				case (char)0x86: rez+=L'Ж'; break;
				case (char)0x87: rez+=L'З'; break;
				case (char)0x88: rez+=L'И'; break;
				case (char)0x89: rez+=L'Й'; break;
				case (char)0x8A: rez+=L'К'; break;
				case (char)0x8B: rez+=L'Л'; break;
				case (char)0x8C: rez+=L'М'; break;
				case (char)0x8D: rez+=L'Н'; break;
				case (char)0x8E: rez+=L'О'; break;
				case (char)0x8F: rez+=L'П'; break;
				case (char)0x90: rez+=L'Р'; break;
				case (char)0x91: rez+=L'С'; break;
				case (char)0x92: rez+=L'Т'; break;
				case (char)0x93: rez+=L'У'; break;
				case (char)0x94: rez+=L'Ф'; break;
				case (char)0x95: rez+=L'Х'; break;
				case (char)0x96: rez+=L'Ц'; break;
				case (char)0x97: rez+=L'Ч'; break;
				case (char)0x98: rez+=L'Ш'; break;
				case (char)0x99: rez+=L'Щ'; break;
				case (char)0x9A: rez+=L'Ъ'; break;
				case (char)0x9B: rez+=L'Ы'; break;
				case (char)0x9C: rez+=L'Ь'; break;
				case (char)0x9D: rez+=L'Э'; break;
				case (char)0x9E: rez+=L'Ю'; break;
				case (char)0x9F: rez+=L'Я'; break;
				case (char)0xA0: rez+=L'а'; break;
				case (char)0xA1: rez+=L'б'; break;
				case (char)0xA2: rez+=L'в'; break;
				case (char)0xA3: rez+=L'г'; break;
				case (char)0xA4: rez+=L'д'; break;
				case (char)0xA5: rez+=L'е'; break;
				//case (char)0xF1: rez+=L'ё'; break; //В место "ё" в принтере "?"
				case (char)0xA6: rez+=L'ж'; break;
				case (char)0xA7: rez+=L'з'; break;
				case (char)0xA8: rez+=L'и'; break;
				case (char)0xA9: rez+=L'й'; break;
				case (char)0xAA: rez+=L'к'; break;
				case (char)0xAB: rez+=L'л'; break;
				case (char)0xAC: rez+=L'м'; break;
				case (char)0xAD: rez+=L'н'; break;
				case (char)0xAE: rez+=L'о'; break;
				case (char)0xAF: rez+=L'п'; break;
				case (char)0xE0: rez+=L'р'; break;
				case (char)0xE1: rez+=L'с'; break;
				case (char)0xE2: rez+=L'т'; break;
				case (char)0xE3: rez+=L'у'; break;
				case (char)0xE4: rez+=L'ф'; break;
				case (char)0xE5: rez+=L'х'; break;
				case (char)0xE6: rez+=L'ц'; break;
				case (char)0xE7: rez+=L'ч'; break;
				case (char)0xE8: rez+=L'ш'; break;
				case (char)0xE9: rez+=L'щ'; break;
				case (char)0xEA: rez+=L'ъ'; break;
				case (char)0xEB: rez+=L'ы'; break;
				case (char)0xEC: rez+=L'ь'; break;
				case (char)0xED: rez+=L'э'; break;
				case (char)0xEE: rez+=L'ю'; break;
				case (char)0xEF: rez+=L'я'; break;
				//Каз-яз
				case (char)0xDB: rez+=L'?'; break;
				case (char)0xDC: rez+=L'?'; break;
				case (char)0xDE: rez+=L'?'; break;
				case (char)0xDF: rez+=L'?'; break;
				case (char)0xF0: rez+=L'?'; break;
				case (char)0xF1: rez+=L'?'; break;
				case (char)0xF3: rez+=L'?'; break;
				case (char)0xF4: rez+=L'?'; break;
				case (char)0xF5: rez+=L'?'; break;
				case (char)0xF6: rez+=L'?'; break;
				case (char)0xF7: rez+=L'?'; break;
				case (char)0xF8: rez+=L'?'; break;
				case (char)0xFD: rez+=L'?'; break;
				case (char)0xFE: rez+=L'?'; break;

				default: rez+=(char)str[i]; break;
			}
		}
		return rez;
	}
	//---------------------------------------------------------------------------
	std::string UIntToStdStr(unsigned int val)
	{
		std::stringstream ss;
		ss << val;
		return ss.str();
	}
	//---------------------------------------------------------------------------
	std::string IntToStdStr(int val)
	{
		std::ostringstream oss;
		oss << val;
		return oss.str();
	}
	//---------------------------------------------------------------------------
	template <typename T>
	std::string toStringHex(T val)
	{
		std::ostringstream oss;
		oss << std::hex << val;
		return oss.str();
	}
	//---------------------------------------------------------------------------
	std::string toStringHex2(int val)
	{
		std::ostringstream oss;
		oss << std::hex << val;
		std::string result = oss.str(); 
		if (result.length() % 2 != 0)
			result = "0" + result;
		return result;
	}
	//---------------------------------------------------------------------------
	std::string toHexString(unsigned char* mas,int len)
	{
		std::string result="";
		for(int i=0;i<len;i++)
		{
			std::string str=toStringHex2(mas[i]);
			if(str.length()==1)
				result+="0"+str;
			else
				result+=str;
		}
		return result;
	}
	//---------------------------------------------------------------------------
	bool hexStringToArray(std::string data, char* mas)
	{
		int len = data.length() / 2;	
		for (int i = 0; i < len; i++) {
			std::string val;
			val += data[i * 2];
			val += data[i * 2 + 1];
			mas[i] = strtol(val.c_str(), NULL, 16);
		}
		return true;
	}
	//---------------------------------------------------------------------------
	//Преобразовать HEX строку в число
	template <typename T>
	T fromStringHex(std::string val)
	{
		T value;
		std::istringstream iss(val);
		iss >> std::hex >> value;
		return value;
	}
	//----------------------------------------------------------------------------
	//ord - менять порядок байт
	unsigned int  hexStringToInt(std::string val, bool ord)
	{
		if (ord)
		{
			return (unsigned int)strtol(val.c_str(), NULL, 16);
		}
		else
		{
			std::string tmp;
			for (unsigned int i = 0; i < val.size() / 2; i++)
			{
				tmp = val[i * 2 + 1] + tmp;
				tmp = val[i * 2] + tmp;
			}
			return (unsigned int)strtol(tmp.c_str(), NULL, 16);
		}
	}
	//---------------------------------------------------------------------------
	unsigned int hexStdStrToUInt(std::string& str)
	{
		unsigned int x;
		std::stringstream ss;
		ss << std::hex << str;
		ss >> x;
		return x;
	}
	//----------------------------------------------------------------------------
	//Закодировать двоично десятичное число
	//Преобразовать строку цифр в строку байт пример "1234" в 2 байта [12h,34h] если нечётное то 0 в начале
	std::string CodeBSD(std::string str)
	{
		if(str.length()%2!=0) str="0"+str;
		//Преобразуем 2 символа в 1 байт
		std::string rez;
		size_t len=str.length()/2;
		for(size_t i=0;i<len;i++)
		{
			std::string ch;
			ch+=str[i*2];
			ch+=str[i*2+1];
			unsigned char hch = fromStringHex<int>(ch);
			rez+=hch;
		}
		return rez;
	}
	//---------------------------------------------------------------------------
	//Закодировать двоично десятичное число
	//Преобразовать строку цифр в строку байт пример "1234" в 2 байта [12h,34h] если нечётное то 0 в начале
	//len - количество (байт)символов добавит нули в начале если получилось меньше
	std::string CodeBSD(int val,int len)
	{
		std::string str=CodeBSD(IntToStdStr(val));
		for(int i=str.length();i<len;i++) //Медленно
			str=(char)0x00+str;
		return str;
	}
	//---------------------------------------------------------------------------
	//Двоично десятичный символ в int
	int BSDToInt(char chr)
	{
		std::string data = DecodeBSD(chr);
		return StdStrToInt(data);
	}
	//---------------------------------------------------------------------------
	//Двоично десятичную строку в int
	int BSDToInt(std::string str, size_t start, size_t len)
	{
		std::string data = DecodeBSD(str,start,len);
		return StdStrToInt(data);
	}
	//---------------------------------------------------------------------------
	//Раскодировать двоично десятичное число 2 байта [12h,34h] преобразуются в строку "1234"
	std::string DecodeBSD(char chr)
	{
		std::string rez;
		unsigned char ch;

		ch=(chr >> 4) & 0x0F;
		if(ch<10) rez+=(char)(48+ch);
		else rez+='0';  //такого не должно быть

		ch=chr & 0x0F;
		if(ch<10) rez+=(char)(48+ch);
		else rez+='0';  //такого не должно быть

		return rez;
	}
	//---------------------------------------------------------------------------
	//Раскодировать двоично десятичное число 2 байта [12h,34h] преобразуются в строку "1234"
	std::string DecodeBSD(std::string str, size_t start, size_t len)
	{
		if(len==0) len=str.length();
		len=start+len;
		if(len>str.length()) len=str.length();
		std::string rez;
		for(size_t i=start;i<len;i++)
		{
			rez+=DecodeBSD(str[i]);
		}
		return rez;
	}
	//---------------------------------------------------------------------------
	//std::wstring StringToWString( const std::string& in, std::locale loc )
	std::wstring StringToWString(const std::string& in, const std::locale &loc)
	{
		std::wstring out;
		std::string::const_iterator i( in.begin() ), ie( in.end() );
		for( ; i!=ie; ++i )
			out += std::use_facet<std::ctype<wchar_t> > ( loc ).widen( *i );
		return out;
	}
	//---------------------------------------------------------------------------
	//Запись в строку line, align: 1 = лево, 2 = центр, 3 = право
	void printToPos(std::wstring& line, std::wstring data, char align) {
		switch (align) {
			case 1: {
				for (uint32_t i = 0; i < std::min(line.length(), data.length()); i++) //На min ругалось сделал std::min
				{
					line[i] = data[i];
				}
				break;
			}
			case 2: {
				int p1 = line.length() / 2.0f;
				int p2 = data.length() / 2.0f;
				int st = p1 - p2;
				for (uint32_t  i = st; i < st + data.length(); i++)
				{
					if (i > 0 && i < line.length()) {
						line[i] = data[i - st];
					}
				}
				break;
			}
			case 3: {
				for (uint32_t i = 0; i < std::min(line.length(), data.length()); i++)
				{
					line[line.length()-i-1] = data[data.length()-i-1];
				}
				break;
			}
		}
	}
	//---------------------------------------------------------------------------
	void replaseChars(std::string& str, char oldCh, char newCh)
	{
		int indexCh = str.find(oldCh);
		while (indexCh != -1)
		{
			str.replace(indexCh,1,1,newCh);
			indexCh = str.find(oldCh,indexCh);
		}
	}
	//---------------------------------------------------------------------------
	/*inline std::string replace(std::string text, std::string s, std::string d)
	{
		for(unsigned index=0; index=text.find(s, index), index!=std::string::npos;)
		{
			text.replace(index, s.length(), d);
			index+=d.length();
		}
		return text;
	}*/
	//---------------------------------------------------------------------------
	//Заменить подстроку на другую
	void replaceAll(std::wstring& str, const std::wstring from, const std::wstring to)
	{
		if (from.empty())
			return;
		size_t start_pos = 0;
		while ((start_pos = str.find(from, start_pos)) != std::string::npos)
		{
			str.replace(start_pos, from.length(), to);
			start_pos += to.length();
		}
	}
	//------------------------------------------------------------------------------
	//Заменить подстроку на другую
	void replaceAll(std::string& str, const std::string from, const std::string to)
	{
		if (from.empty())
			return;
		size_t start_pos = 0;
		while ((start_pos = str.find(from, start_pos)) != std::string::npos)
		{
			str.replace(start_pos, from.length(), to);
			start_pos += to.length();
		}
	}
	//------------------------------------------------------------------------------
	//Заменить все вхождения строки find в sors на repl (wxString::Replace)
	std::string replaceStrings(std::string sors,std::string find,std::string repl)
	{
		if(find==repl) return sors;
		std::string rez="";
		size_t p0=0;
		size_t p1 = sors.find(find,p0);
		while(p1!=std::string::npos)
		{
			rez.append(sors,p0,p1-p0);
			rez+=repl;
			p0=p1+find.length();
			p1=sors.find(find,p0);
		}
		rez.append(sors,p0,sors.length()-p0);
		return rez;
	}
	//---------------------------------------------------------------------------
	std::wstring replaceStrings(std::wstring sors,std::wstring find,std::wstring repl)
	{
		if(find==repl) return sors;
		std::wstring rez=L"";
		size_t p0=0;
		size_t p1 = sors.find(find,p0);
		while(p1!=std::wstring::npos)
		{
			rez.append(sors,p0,p1-p0);
			rez+=repl;
			p0=p1+find.length();
			p1=sors.find(find,p0);
		}
		rez.append(sors,p0,sors.length()-p0);
		return rez;
	}
	//---------------------------------------------------------------------------
	//Получить дату в виде ANSI строки в формате ddmmyyyy
	std::string getStrDate()
	{
		time_t t=time(NULL);
		tm* st=localtime(&t);

		std::string str1=IntToStdStr(st->tm_mday);
		if(str1.length()==1) str1="0"+str1;
		std::string str2=IntToStdStr(st->tm_mon+1);
		if(str2.length()==1) str2="0"+str2;
		std::string str3=IntToStdStr(st->tm_year+1900);
		if(str3.length()==1) str3="0"+str3;

		//delete st; Ошибка памяти будет если удалю
		return str1+str2+str3;
	}
	//---------------------------------------------------------------------------
	//Преобразую строку вида 02-10-18 20:51:40 в unix time
	unsigned int getTime1(std::string date)
	{
	#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND)
		std::string tmp;
		//struct tm {
		//int tm_sec;         // seconds
		//int tm_min;         // minutes
		//int tm_hour;        // hours
		//int tm_mday;        // day of the month
		//int tm_mon;         // month
		//int tm_year;        // year
		//int tm_wday;        // day of the week
		//int tm_yday;        // day in the year
		//int tm_isdst;       // daylight saving time
		//};
		struct tm tmd;
		memset(&tmd, 0, sizeof(struct tm));

		tmp=CutBeforeFirst(date, "-");
		tmd.tm_mday = StdStrToInt(tmp);
		tmp=CutBeforeFirst(date, "-");
		tmd.tm_mon = StdStrToInt(tmp);
		tmp=CutBeforeFirst(date, " ");
		tmd.tm_year = (2000 + StdStrToInt(tmp)) - 1900;

		tmp=CutBeforeFirst(date, ":");
		tmd.tm_hour = StdStrToInt(tmp);
		tmp=CutBeforeFirst(date, ":");
		tmd.tm_min = StdStrToInt(tmp);
		tmd.tm_sec = StdStrToInt(date);

		time_t time = mktime(&tmd);
		return (unsigned int)time;
	#else
		return 0;
	#endif
	}
	//---------------------------------------------------------------------------
	//Получить дату в виде Unicode строки в формате ddmmyyyy
	std::wstring getWStrDate()
	{
		return StringToWString(getStrDate(),std::locale(""));
	}
	//---------------------------------------------------------------------------
	//Дата и время в виде строки dd.mm.yyyy hh:mm:ss пример 24.05.2010 15:20:26
	std::string getDateTime()
	{
	/*
	#if defined( _VC )
		//Для проекта с ATL библиотекой
		std::string tmp,res="";
		SYSTEMTIME st;
		GetLocalTime(&st);
		//Дата
		tmp=toStdStr(st.wDay);
		if(tmp.length()==1) res+="0"+tmp+"."; else res+=tmp+".";
		tmp=toStdStr(st.wMonth);
		if(tmp.length()==1) res+="0"+tmp+"."; else res+=tmp+".";
		res+=toStdStr(st.wYear)+" ";

		//Время
		tmp=toStdStr(st.wHour);
		if(tmp.length()==1) res+="0"+tmp+":"; else res+=tmp+":";
		tmp=toStdStr(st.wMinute);
		if(tmp.length()==1) res+="0"+tmp+":"; else res+=tmp+":";
		tmp=toStdStr(st.wSecond);
		if(tmp.length()==1) res+="0"+tmp; else res+=tmp;

		return res;
	#endif
	#if defined( _WX )
		//Для кросплатформенного проекта wxWidgets
		return "";
	#endif
	*/
		std::string tmp,res="";

		time_t t=time(NULL);
		tm* st=localtime(&t);

		//Дата
		tmp=IntToStdStr(st->tm_mday);
		if(tmp.length()==1) res+="0"+tmp+"."; else res+=tmp+".";
		tmp=IntToStdStr(st->tm_mon+1);
		if(tmp.length()==1) res+="0"+tmp+"."; else res+=tmp+".";
		res+=IntToStdStr(st->tm_year+1900)+" ";

		//Время
		tmp=IntToStdStr(st->tm_hour);
		if(tmp.length()==1) res+="0"+tmp+":"; else res+=tmp+":";
		tmp=IntToStdStr(st->tm_min);
		if(tmp.length()==1) res+="0"+tmp+":"; else res+=tmp+":";
		tmp=IntToStdStr(st->tm_sec);
		if(tmp.length()==1) res+="0"+tmp; else res+=tmp;

		//delete st; //Ошибка памяти будет если удалю
		return res;
	}
	//---------------------------------------------------------------------------
	//Float в строку
	/*std::string FloatToStdStr(float val)
	{
		std::ostringstream oss;
		oss << val;
		return oss.str();
	}*/
	//---------------------------------------------------------------------------
	//Преобразовать в строку (Разделитель всегда точка)
	//digits - Сколько цифр после запятой оставлять если -1 то по полной
	std::string FloatToStdStr(double val, int digits,char sep)
	{
		std::ostringstream oss;
		if(digits >= 0)
			oss << std::fixed << std::setprecision( digits ) << val;
		else oss << std::fixed << val;

		std::string str=oss.str();
		if(sep=='.')
			std::replace( str.begin(), str.end(), ',', '.');
		if(sep==',')
			std::replace( str.begin(), str.end(), '.', ',');

		int pos=MAX(str.find('.'),str.find(',')); //Позиция запятой в строке (TODO взять разделитель из системных параметров)
		//Обрезаем строку
		if(digits>=0 && pos>=0)
		{	if(digits==0) digits=-1; //Чтоб убрать запятую

			std::string result="";
			result.append(str,0,pos+digits+1);
			return result;
		}else return str;
	}
	//---------------------------------------------------------------------------
	std::wstring FloatToStdWStr(double val, int digits)
	{
		std::string str = FloatToStdStr(val,digits);
		std::wstring wsTmp(str.begin(), str.end());
		return wsTmp;
		//return s2ws(str);
	}
	//---------------------------------------------------------------------------
	template <typename T>
	std::wstring toStdWStr(T val)
	{
		std::ostringstream oss;
		oss << val;

		std::string str=oss.str();
		return StringToWString( str, std::locale(""));
	}
	//---------------------------------------------------------------------------
	std::wstring IntToStdWStr(int val)
	{
		return toStdWStr(val);
	}
	//---------------------------------------------------------------------------
	template<typename T>
	T fromString(const std::string& s)
	{
		std::istringstream iss(s);
		T res;
		iss >> res;
		return res;
	}
	//---------------------------------------------------------------------------
	//Преобразовать строку в число
	//str - Исходная строка с числом
	//cutInt - вырезать из строки только цифры
	int StdStrToInt(std::string& str, bool cutInt, int def)
	{
		if(cutInt)
		{
			std::string val="";
			for(unsigned int i=0;i<str.length();i++)
			{
				if((str[i]=='-' && (val.length()==0 || val[0]!='-'))  || str[i]=='0' || str[i]=='1' || str[i]=='2' || str[i]=='3' || str[i]=='4' || str[i]=='5' || str[i]=='6' || str[i]=='7' || str[i]=='8' || str[i]=='9')
					val+=str[i];
			}
			if(val=="") return def;
			return fromString<int>(val);
		}
		if(str=="") return def;
		return fromString<int>(str);
	}
	//---------------------------------------------------------------------------
	//Преобразовать строку в число
	//str - Исходная строка с числом
	//cutInt - вырезать из строки только цифры
	uint32_t StdStrToUInt(std::string& str, bool cutInt, uint32_t def)
	{
		if(cutInt)
		{
			std::string val="";
			for(unsigned int i=0;i<str.length();i++)
			{
				if(str[i]=='0' || str[i]=='1' || str[i]=='2' || str[i]=='3' || str[i]=='4' || str[i]=='5' || str[i]=='6' || str[i]=='7' || str[i]=='8' || str[i]=='9')
					val+=str[i];
			}
			if(val=="") return def;
			return fromString<int>(val);
		}
		if(str=="") return def;
		return fromString<int>(str);
	}
	//---------------------------------------------------------------------------
	float StdStrToFloat(std::string& str)
	{
		if(str=="") return 0;
		return fromString<float>(str);
	}
	//---------------------------------------------------------------------------
	double StdStrToDouble(std::string& str,double defval)
	{
		if(str=="") return defval;
		return fromString<double>(str);
	}
	//---------------------------------------------------------------------------
	double StdWStrToDouble(std::wstring str, double defval)
	{
		if (str == L"") return defval;
		return fromWString<double>(str);
	}
	//---------------------------------------------------------------------------
	template<typename T>
	T fromWString(const std::wstring& s)
	{
		std::string str=WStringToString(s, std::locale(""));

		std::istringstream iss(str);
		T res;
		iss >> res;
		return res;
	}
	//---------------------------------------------------------------------------
	int StdWStrToInt(const std::wstring& str, bool cutInt)
	{
		if(cutInt)
		{
			std::wstring val=L"";
			for(unsigned int i=0;i<str.length();i++)
			{
				if((str[i]==L'-' && (val.length()==0 || val[0]!=L'-'))  || str[i]==L'0' || str[i]==L'1' || str[i]==L'2' || str[i]==L'3' || str[i]==L'4' || str[i]==L'5' || str[i]==L'6' || str[i]==L'7' || str[i]==L'8' || str[i]==L'9')
					val+=str[i];
			}
			if(val==L"") return 0;
			return fromWString<int>(val);
		}
		if(str==L"") return 0;

		return fromWString<int>(str);
	}
	//---------------------------------------------------------------------------
	int StdWStrToUInt(const std::wstring& str, bool cutInt)
	{
		if(cutInt)
		{
			std::wstring val=L"";
			for(unsigned int i=0;i<str.length();i++)
			{
				if(str[i]==L'0' || str[i]==L'1' || str[i]==L'2' || str[i]==L'3' || str[i]==L'4' || str[i]==L'5' || str[i]==L'6' || str[i]==L'7' || str[i]==L'8' || str[i]==L'9')
					val+=str[i];
			}
			if(val==L"") return 0;
			return fromWString<int>(val);
		}
		if(str==L"") return 0;
		return fromWString<int>(str);
	}
	//---------------------------------------------------------------------------
	///К верхнему регистру строку
	std::wstring UpperCase(const std::wstring& str)
	{
		std::wstring res=L""; //TODO Надо выделить память
		for(unsigned int i=0;i<str.length();i++)
		{
			switch( str[i] )
			{
				case L'a': res+=L'A'; break;
				case L'b': res+=L'B'; break;
				case L'c': res+=L'C'; break;
				case L'd': res+=L'D'; break;
				case L'e': res+=L'E'; break;
				case L'f': res+=L'F'; break;
				case L'g': res+=L'G'; break;
				case L'h': res+=L'H'; break;
				case L'i': res+=L'I'; break;
				case L'j': res+=L'J'; break;
				case L'k': res+=L'K'; break;
				case L'l': res+=L'L'; break;
				case L'm': res+=L'M'; break;
				case L'n': res+=L'N'; break;
				case L'o': res+=L'O'; break;
				case L'p': res+=L'P'; break;
				case L'q': res+=L'Q'; break;
				case L'r': res+=L'R'; break;
				case L's': res+=L'S'; break;
				case L't': res+=L'T'; break;
				case L'u': res+=L'U'; break;
				case L'v': res+=L'V'; break;
				case L'w': res+=L'W'; break;
				case L'x': res+=L'X'; break;
				case L'y': res+=L'Y'; break;
				case L'z': res+=L'Z'; break;

				case L'а': res+=L'А'; break;
				case L'б': res+=L'Б'; break;
				case L'в': res+=L'В'; break;
				case L'г': res+=L'Г'; break;
				case L'д': res+=L'Д'; break;
				case L'е': res+=L'Е'; break;
				case L'ё': res+=L'Ё'; break;
				case L'ж': res+=L'Ж'; break;
				case L'з': res+=L'З'; break;
				case L'и': res+=L'И'; break;
				case L'к': res+=L'К'; break;
				case L'л': res+=L'Л'; break;
				case L'м': res+=L'М'; break;
				case L'н': res+=L'Н'; break;
				case L'о': res+=L'О'; break;
				case L'п': res+=L'П'; break;
				case L'р': res+=L'Р'; break;
				case L'с': res+=L'С'; break;
				case L'т': res+=L'Т'; break;
				case L'у': res+=L'У'; break;
				case L'ф': res+=L'Ф'; break;
				case L'х': res+=L'Х'; break;
				case L'ц': res+=L'Ц'; break;
				case L'ч': res+=L'Ч'; break;
				case L'ш': res+=L'Ш'; break;
				case L'щ': res+=L'Щ'; break;
				case L'ъ': res+=L'Ъ'; break;
				case L'ы': res+=L'Ы'; break;
				case L'ь': res+=L'Ь'; break;
				case L'э': res+=L'Э'; break;
				case L'ю': res+=L'Ю'; break;
				case L'я': res+=L'Я'; break;
				default:
					res+=str[i];
			}
		}
		return res;
	}
	//---------------------------------------------------------------------------
	///Получить строку до указанного символа если символа нет то вернёт всю строку.
	std::string BeforeLast(std::string str,char ch)
	{
		int pos=0;
		for(uint32_t i=0;i<str.length();i++)
		{
			if(str[i]==ch) pos=i;
		}
		if(pos==0) pos=str.length();

		std::string result="";
		result.append(str,0,pos);
		return result;
	}
	//---------------------------------------------------------------------------
	///Получить строку до указанного символа если символа нет то вернёт всю строку.
	std::wstring BeforeWLast(std::wstring str,wchar_t ch)
	{
		int pos=0;
		for(uint32_t i=0;i<str.length();i++)
		{
			if(str[i]==ch) pos=i;
		}
		if(pos==0) pos=str.length();

		std::wstring result=L"";
		result.append(str,0,pos);
		return result;
	}
	//---------------------------------------------------------------------------
	std::string BeforeFirst(std::string str,const unsigned char ch)
	{
		unsigned int pos=str.find(ch);
		std::string result="";
		result.append(str,0,pos);
		return result;
	}
	//---------------------------------------------------------------------------
	std::string BeforeFirst(std::string str,const char ch)
	{
		unsigned int pos=str.find(ch);
		std::string result="";
		result.append(str,0,pos);
		return result;
	}
	//---------------------------------------------------------------------------
	std::wstring BeforeWFirst(std::wstring str,const wchar_t ch)
	{
		unsigned int pos=str.find(ch);
		std::wstring result=L"";
		result.append(str,0,pos);
		return result;
	}
	//---------------------------------------------------------------------------
	std::string CutAfterFirst(std::string& str,std::string br)
	{
		size_t pos=str.find(br);
		std::string result="";
		if(pos==std::string::npos)
		{
			result.append(str);
			str.erase();
		}else
		{
			result.append(str,pos + br.size(),str.length() - pos - br.size());
			str.erase(pos);
		}
		return result;
	}
	//---------------------------------------------------------------------------
	//Если не найдёт нужный символ то вернёт всю строку
	std::string CutAfterLast(std::string& str,const unsigned char ch)
	{
		std::string result="";
		size_t pos=str.find_last_of(ch);
		if(pos!=std::string::npos)
		{
			result.append(str,pos+1,str.length()-pos-1);
			str.erase(pos);
		}else
		{
			result.append(str);
			str.erase();
		}
		return result;
	}
	//---------------------------------------------------------------------------
	//Отрезать от строки до указанного символа если не найден символ отрезается вся строка
	std::string CutBeforeFirst(std::string& str,const char ch)
	{
		int pos=str.find(ch);
		std::string result="";
		if(pos==-1)
		{
			result.append(str);
			str.erase();
		}else
		{
			result.append(str,0,pos);
			str.erase(0,pos+1);
		}
		return result;
	}
	//---------------------------------------------------------------------------
	//Отрезать от строки до указанного символа если не найден символ отрезается вся строка
	std::string CutBeforeFirst(std::string& str,const std::string br)
	{
		int pos=str.find(br);
		std::string result="";
		if(pos==-1)
		{
			result.append(str);
			str.erase();
		}else
		{
			if(pos>0)
				result.append(str,0,pos);
			str.erase(0,pos+br.size());
		}
		return result;
	}
	//---------------------------------------------------------------------------
	//Отрезать от строки до указанного символа если не найден символ отрезается вся строка
	std::wstring CutBeforeWFirst(std::wstring& str,const wchar_t ch)
	{
		int pos=str.find(ch);
		std::wstring result=L"";
		if(pos==-1)
		{
			result.append(str);
			str.erase();
		}else
		{
			result.append(str,0,pos);
			str.erase(0,pos+1);
		}
		return result;
	}
	//---------------------------------------------------------------------------
	std::string AfterFirst(std::string str,const char ch)
	{
		unsigned int pos=str.find(ch);
		std::string result="";
		result.append(str,pos+1,str.size());
		return result;
	}
	//---------------------------------------------------------------------------
	std::wstring AfterWFirst(std::wstring str,const wchar_t ch)
	{
		unsigned int pos=str.find(ch);
		std::wstring result=L"";
		result.append(str,pos+1,str.size());
		return result;
	}
	//---------------------------------------------------------------------------
	//Всё после заданного разделителя, если разделитель не найден то сначала строки
	std::string AfterLast(std::string str,const char ch)
	{
		int pos=str.find_last_of(ch)+1;
		int len=str.length()-pos;
		return str.substr(pos,len);
	}
	//---------------------------------------------------------------------------
	std::string WStringToString(const std::wstring &wstr, const std::locale &loc, char default_char)
	{
		//std::wcout << L"wstr=" << wstr<< std::endl;;

		if (wstr.empty())
			return std::string();

 	 	//закоментил потому что маленькую букву я не преобразует
		std::string ret;
		ret.resize(wstr.length());
		std::use_facet<std::ctype<wchar_t> >(loc).narrow(&wstr[0], &wstr[0] + wstr.length(), '?', &ret[0]);
		return ret;


/*
		std::ctype<wchar_t> const &facet = std::use_facet<std::ctype<wchar_t> >(loc);
		wchar_t const *first = wstr.c_str();
		wchar_t const *last = first + wstr.size();
		std::vector<char> result(wstr.size());

		facet.narrow(first, last, default_char, &result[0]);

		return std::string(result.begin(), result.end());
*/

/*
		//setup converter
		using convert_type = std::codecvt_utf8<wchar_t>;
		std::wstring_convert<convert_type, wchar_t> converter;
		//use converter (.to_bytes: wstr->str, .from_bytes: str->wstr)
		std::string converted_str = converter.to_bytes( wstr );
		return converted_str;
*/

/*
	    using convert_typeX = std::codecvt_utf8<wchar_t>;
	    std::wstring_convert<convert_typeX, wchar_t> converterX;
	    return converterX.to_bytes(wstr);*/
/*
		static std::wstring_convert< std::codecvt_utf8<wchar_t>, wchar_t > converter ;
	    return converter.to_bytes(wstr) ;
*/
	}
	//---------------------------------------------------------------------------
	//Получить полный путь к текущему EXE файлу
	std::wstring getExePathW(bool add)
	{
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND)
		std::wstring str;
		wchar_t pathBuf[MAX_PATH] = { 0 };
		GetModuleFileNameW(NULL, pathBuf, MAX_PATH);
		str = pathBuf;
		str = BeforeWLast(str, L'\\');
		if (add) str += L'\\';
		return str;
#else
		std::wstring str = L".";
		if (add) str += L'\\';
		return str;
#endif
		return L"";
/*
это к DLL делал но не пригодилось (по хенделу)
		std::wstring str;
	#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND)
		wchar_t pathBuf[MAX_PATH] = {0};
		HMODULE thisModule = 0;
		BOOL ret = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)&__FUNCTION__, &thisModule);
		DWORD nLen = GetModuleFileName(thisModule, pathBuf, MAX_PATH);
		str=pathBuf;
		if(!add) str=BeforeWLast(str,L'\\')+L'\\';
	#endif
		return str;
*/
	}
	//---------------------------------------------------------------------------
	/*std::string getExePath()
	{
	//если EXE то
	//return ExtractFilePath(ParamStr(0)).c_str();
	//Если DLL то
	return "";
	}*/
	//---------------------------------------------------------------------------
	//Получить полный путь к текущему EXE файлу
	std::string getExePathA(bool add)
	{
	#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND)
		std::string str;
		char pathBuf[MAX_PATH] = {0};
		GetModuleFileNameA(NULL,pathBuf,MAX_PATH);
		str=pathBuf;
		str=BeforeLast(str,'\\');
		if (add) str += '\\';
		return str;
	#else
		std::string str=".";
		if (add) str += '\\';
		return str;
	#endif
		return "";
	}
	//---------------------------------------------------------------------------
	//Путь к дирректории приложений, для хранения настроек (если линукс то к томайней директории пользователя) без завершающего слеша
	std::string getAppPath()
	{
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND)
		std::string path;
		char szPath[MAX_PATH];
		memset(szPath,0,MAX_PATH);
		if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_COMMON_APPDATA, NULL, 0, szPath)))
		//if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, szPath)))
		{
			path=szPath;
		}
		return path;
#else
		struct passwd *pw = getpwuid(getuid());
		return pw->pw_dir;
#endif
	}
	//---------------------------------------------------------------------------
	//Добавить 0 в начало строоки если 1 символ для даты нужно
	std::string add0(std::string str)
	{
		if(str.length()==1) return "0"+str;
		else return str;
	}
	//---------------------------------------------------------------------------
	//Конвертация из UTF16LE в UTF8
	std::string convUTF16ToUTF8(const std::wstring& widestring)
	{
		unsigned int len8=0;
		unsigned int len16=widestring.length();
		const wchar_t* p16=widestring.data();
		for(unsigned int i=0;i<len16;i++) //Подсчитываем размер буфера
		{
			if(p16[i]<=0x7f) len8++; else
			if(p16[i]<=0x7ff) len8+=2; else
			if(p16[i]<=0xffff) len8+=3; else
			if(p16[i]<=0x10ffff) len8+=4;
		}
		unsigned char * p8=new unsigned char[len8];
		unsigned int pos=0;
		for(unsigned int i=0;i<len16;i++)
		{
			if(p16[i]<=0x7f)
			{
				p8[pos]=(unsigned char)p16[i];
				pos++;
			}else
			if(p16[i]<=0x7ff) //110xxxxx, 10xxxxxx
			{
				p8[pos]=(p16[i]>>6 | 192) & 223;
				pos++;
				p8[pos]=(p16[i] | 128) & 191;
				pos++;
			}else
			if(p16[i]<=0xffff) //1110xxxx 10xxxxxx 10xxxxxx
			{
				p8[pos]=(p16[i]>>12 | 224) & 239;
				pos++;
				p8[pos]=(p16[i]>>6 | 128) & 191;
				pos++;
				p8[pos]=(p16[i] | 128) & 191;
				pos++;
			}else
			if(p16[i]<=0x10ffff) //11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
			{
				p8[pos]=(p16[i]>>18 | 240) & 247;
				pos++;
				p8[pos]=(p16[i]>>12 | 128) & 191;
				pos++;
				p8[pos]=(p16[i]>>6 | 128) & 191;
				pos++;
				p8[pos]=(p16[i] | 128) & 191;
				pos++;
			}
		}
		std::string str;
		str.append((char*)p8,len8);
		delete[] p8;
		return str;
	}
	//---------------------------------------------------------------------------
	//Конвертация из UTF8 в UTF16LE
	std::wstring convUTF8ToUTF16(const std::string& str)
	{
		unsigned int len16=0;
		unsigned int len8=str.length();
		const char* p8=str.data();

		unsigned int i=0;
		while(i<len8) //Подсчитываем сколько символов в строке
		{
			if((p8[i] & 0x80)==0) i++; else //0 в начале знач 1 символ
			if((p8[i] & 0xF0)==0xF0) i+=4; else //11110xxx
			if((p8[i] & 0xE0)==0xE0) i+=3; else //1110xxxx
			if((p8[i] & 0xC0)==0xC0) i+=2; //110xxxxx
			len16++;
		}
		wchar_t* p16=new wchar_t[len16];
		unsigned int pos=0;
		i=0;
		while(i<len8)
		{
			if((p8[i] & 0x80)==0) //0xxxxxxx (0 в начале знач 1 символ)
			{
				p16[pos]=p8[i];
				pos++; i++;
			}else
			if((p8[i] & 0xF0)==0xF0) //11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
			{
				p16[pos]=((p8[i] & 0x7) << 18) | ((p8[i+1] & 0x3F) << 12) | ((p8[i+2] & 0x3F) << 6) | (p8[i+3] & 0x3F);
				pos++; i+=4;
			}else
			if((p8[i] & 0xE0)==0xE0) //1110xxxx 10xxxxxx 10xxxxxx
			{
				p16[pos]=((p8[i] & 0xf) << 12) | ((p8[i+1] & 0x3F) << 6) | (p8[i+2] & 0x3F);
				pos++; i+=3;
			} else
			if((p8[i] & 0xC0)==0xC0) //110xxxxx 10xxxxxx
			{
				p16[pos]=((p8[i] & 0x1F) << 6) | (p8[i+1] & 0x3F);
				pos++; i+=2;
			}else i++; //если дошло до сюда то ошибка
		}

		std::wstring wstr;
		wstr.append(p16,len16);
		delete[] p16;
		return wstr;
	}
	//---------------------------------------------------------------------------
	//Убрать начальные и конечные пробелы \t\r
	void Trim(std::string& s)
	{
		TrimLeft(s);
		TrimRight(s);
	}
	//---------------------------------------------------------------------------
	std::string trim(const std::string & s)
	{
		size_t startPos = s.find_first_not_of(" \t\r");
		if (startPos == std::string::npos)
			return "";
		size_t endPos = s.find_last_not_of(" \t\r");
		return s.substr(startPos, endPos - startPos + 1);
	}
	//---------------------------------------------------------------------------
	void TrimW(std::wstring& s)
	{
		TrimWLeft(s);
		TrimWRight(s);
	}
	//---------------------------------------------------------------------------
	void TrimWLeft(std::wstring& str)
	{
		size_t startpos = str.find_first_not_of(L" \t\f\n\r");
		if (startpos != std::string::npos)
		{
			str = str.substr(startpos);
		}
		else
		{
			str.clear(); //Вся строка из спец символов
		}
	}
	//---------------------------------------------------------------------------
	void TrimWRight(std::wstring& str)
	{
		std::wstring::size_type endpos = str.find_last_not_of(L" \t\f\n\r");
		if (endpos != std::string::npos)
		{
			str = str.substr(0, endpos + 1);
		}
		else
		{
			str.clear(); //Вся строка из спец символов
		}
	}
	//---------------------------------------------------------------------------
	void TrimLeft(std::string& str)
	{
		size_t startpos = str.find_first_not_of(" \t\f\n\r");
		if(startpos != std::string::npos)
		{
			str = str.substr( startpos );
		}else
		{
			str.clear(); //Вся строка из спец символов
		}
	}
	//---------------------------------------------------------------------------
	void TrimRight(std::string& str)
	{
		 std::string::size_type endpos = str.find_last_not_of(" \t\f\n\r");
		if( endpos != std::string::npos )
		{
			str = str.substr( 0, endpos+1 );
		}else
		{
			str.clear(); //Вся строка из спец символов
		}
	}
	//---------------------------------------------------------------------------
	//Заменить текст str на тот что из txt
	std::string printToPos(std::string str, int pos, std::string txt)
	{
		//Дополняю длину строки
		if (str.length() < pos + txt.length()) {
			str.append(std::string(pos + txt.length() - str.length(), ' '));
		}
		//Переписываю строку
		for(long unsigned int i = 0; i < txt.length();i++) {
			str[pos + i] = txt[i];
		}
		return str;
	}
	//---------------------------------------------------------------------------
	//Разделить текст по разделителю на слова
	std::vector<std::wstring> split(const std::wstring& str, wchar_t delimiter)
	{
		std::wstring temp;
		std::vector<std::wstring> parts;
		std::wstringstream wss(str);
		while(std::getline(wss, temp, delimiter))
		parts.push_back(temp);
		return parts;
	}
	//---------------------------------------------------------------------------
	void killProcessByName(const wchar_t *filename)
	{
	#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND)
	/*	HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);
		PROCESSENTRY32 pEntry;
		pEntry.dwSize = sizeof(pEntry);
		BOOL hRes = Process32First(hSnapShot, &pEntry);
		while (hRes)
		{
			if (wcscmp(pEntry.szExeFile, filename) == 0)
			{
				HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, 0,
					(DWORD)pEntry.th32ProcessID);
				if (hProcess != NULL)
				{
					TerminateProcess(hProcess, 9);
					CloseHandle(hProcess);
				}
			}
			hRes = Process32Next(hSnapShot, &pEntry);
		}
		CloseHandle(hSnapShot);*/
	#else

	#endif

	}
	//---------------------------------------------------------------------------
	bool dirExists(std::string path)
	{
		struct stat info;
		if(stat( path.c_str(), &info ) != 0)
			return 0;
		else if(info.st_mode & S_IFDIR)
			return 1;
		else
			return 0;
	}
	//---------------------------------------------------------------------------
	//Создать папку
	bool createFolder(std::string directory,int mode)
	{
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND)
		CreateDirectoryA(directory.c_str(), NULL);
		return true;
#else
		mode_t tmp = mode; //На винде тен типа mode_t
		int rez=0;
		if(!dirExists(directory)){
			rez=mkdir(directory.c_str(), mode); //Если папки нет то создать её
		}
		if(rez==0){
			chmod(directory.c_str(), mode); //Бывало что при создании права не назначались
		}
		return rez==0;
#endif
	}
	//---------------------------------------------------------------------------
	std::string intToString(int val)
	{
		std::stringstream ss;
		ss << val;
		return ss.str();
	}
	//---------------------------------------------------------------------------
	std::string uintToString(unsigned int val)
	{
		std::stringstream ss;
		ss << val;
		return ss.str();
	}
	//---------------------------------------------------------------------------
	std::string ullintToString(unsigned long long int val)
	{
		std::stringstream ss;
		ss << val;
		return ss.str();
	}

}
