1 #ifndef _Functions4U_Functions4U_h
2 #define _Functions4U_Functions4U_h
3 
4 #include <float.h>
5 #include <Draw/Draw.h>
6 #ifdef flagGUI
7 //#include <Web/Web.h>
8 #include "GatherTpp.h"
9 #endif
10 
11 #include <Functions4U/SvgColors.h>
12 #include "StaticPlugin.h"
13 #include "LocalProcess2.h"
14 #include <random>
15 
16 namespace Upp {
17 
18 
19 enum EXT_FILE_FLAGS {NO_FLAG = 0,
20 					 USE_TRASH_BIN = 1,
21 					 BROWSE_LINKS = 2,
22 					 DELETE_READ_ONLY = 4
23 };
24 
25 String GetDesktopManagerNew();
26 
27 bool LaunchFile(const char *file, const char *params = 0, const char *directory = ".");
28 
29 bool FileCat(const char *file, const char *appendFile);
30 
31 int FileCompare(const char *path1, const char *path2);
32 
33 int64 FindStringInFile(const char *file, const String text, int64 pos0 = 0);
34 
35 bool FileStrAppend(const char *file, const char *str);
36 bool AppendFile(const char *filename, const char *str);
37 
38 template<typename T>
AppendFileNameX(T t)39 String AppendFileNameX(T t) {
40     return t;
41 }
42 
43 template<typename T, typename... Args>
AppendFileNameX(T t,Args...args)44 String AppendFileNameX(T t, Args... args) {
45     return AppendFileName(t, AppendFileNameX(args...));
46 }
47 
Trim(const String & s)48 inline String Trim(const String& s)   {return TrimBoth(s);}
49 //inline WString Trim(const WString& s) {return TrimLeft(TrimRight(s));}
50 
51 String FitFileName(String fileName, int len);
52 
53 Vector<String> Tokenize(const String &str, const String &token, int pos = 0);
54 void Tokenize(const String &str, const String &token, Vector<String> &ret, int pos = 0);
55 String Tokenize2(const String &str, const String &token, int &pos);
56 String Tokenize2(const String &str, const String &token);
57 //String Tokenize(const String &str, const String &token, int &pos);
58 //String Tokenize(const String &str, const String &token);
59 
60 /////////
61 bool DirectoryExistsX(const char *path, EXT_FILE_FLAGS flags = NO_FLAG);
62 void DirectoryCopyX(const char *dir, const char *newPlace, bool replaceOnlyNew, String filesToExclude, String &erroList);
63 bool DirectoryMove(const char *dir, const char *newPlace);
64 bool DeleteDeepWildcardsX(const char *path, bool filefolder, EXT_FILE_FLAGS flags = NO_FLAG, bool deep = true);
65 bool DeleteDeepWildcardsX(const char *pathwc, const char *namewc, bool filefolder, EXT_FILE_FLAGS flags = NO_FLAG, bool deep = true);
66 bool DeleteFolderDeepWildcardsX(const char *path, EXT_FILE_FLAGS flags = NO_FLAG);
67 bool DeleteFolderDeepWildcardsX(const char *path, const char *name, EXT_FILE_FLAGS flags = NO_FLAG);
68 bool DeleteFileDeepWildcardsX(const char *path, EXT_FILE_FLAGS flags = NO_FLAG);
69 bool DeleteFileWildcardsX(const char *path, EXT_FILE_FLAGS flags = NO_FLAG);
70 bool DeleteFolderDeepX(const char *path, EXT_FILE_FLAGS flags = NO_FLAG);
71 bool RenameDeepWildcardsX(const char *path, const char *namewc, const char *newname, bool forfile, bool forfolder, EXT_FILE_FLAGS flags = NO_FLAG);
72 bool FolderIsEmpty(const char *path);
73 
74 bool FileMoveX(const char *oldpath, const char *newpath, EXT_FILE_FLAGS flags = NO_FLAG);
75 bool FileDeleteX(const char *path, EXT_FILE_FLAGS flags = NO_FLAG);
76 
77 bool IsRootFolder(const char *folderName);
78 String GetUpperFolder(const String &folderName);
79 String GetNextFolder(const String &folder, const String &lastFolder);
80 String FileRealName(const char *fileName);
81 bool IsFile(const char *fileName);
82 bool IsFolder(const char *fileName);
83 bool GetRelativePath(String from, String path, String& ret, bool normalize = true);
84 
85 bool IsSymLink(const char *path);
86 
87 bool SetReadOnly(const char *path, bool readOnly);
88 bool SetReadOnly(const char *path, bool usr, bool grp, bool oth);
89 bool IsReadOnly(const char *path, bool &usr, bool &grp, bool &oth);
90 
91 String LoadFile_Safe(const String fileName);
92 String LoadFile(const char *fileName, off_t from, size_t len = 0);
93 
94 int64 GetLength(const char *fileDirName);
95 int64 GetDirectoryLength(const char *directoryName);
96 
97 ///////////////////////////////
98 Vector<String> SearchFile(String dir, const Vector<String> &condFiles, const Vector<String> &condFolders,
99 								 const Vector<String> &extFiles,  const Vector<String> &extFolders,
100 								 const String text, Vector<String> &errorList);
101 Vector<String> SearchFile(String dir, String condFile, String text, Vector<String> &errorList);//, int flags = 0);
102 Vector<String> SearchFile(String dir, String condFile = "*.*", String text = "");//, int flags = 0);
103 ///////////////////////////////
104 
105 bool FileToTrashBin(const char *path);
106 int64 TrashBinGetCount();
107 bool TrashBinClear();
108 
109 String GetPersonalFolder();
110 String GetRootFolder();
111 String GetTempFolder();
112 String GetOsFolder();
113 String GetSystemFolder();
114 #ifdef PLATFORM_WIN32
115 String GetCommonAppDataFolder();
116 #endif
117 bool SetEnv(const char *id, const char *val);
118 
119 struct FileData : Moveable<FileData> {
120 	bool isFolder;
121 	String fileName;
122 	String relFilename;
123 	int64 length;
124 	struct Upp::Time t;
125 	int64 id;
126 
ToStringFileData127 	String ToString() const { return Format("%s %0n", fileName, length); }
128 
FileDataFileData129 	FileData(bool _isFolder, String _fileName, String _relFilename, int64 _length,
130 		struct Upp::Time _t, int64 _id) : isFolder(_isFolder), fileName(_fileName),
131 		relFilename(_relFilename), length(_length), t(_t), id(_id) {}
FileDataFileData132 	FileData() {}
133 };
134 
135 struct FileDiffData {
136 	char action;	// 'n': New, 'u': Update, 'd': Delete, 'p': Problem
137 	bool isFolder;
138 	String relPath;
139 	String fileName;
140 	uint64 idMaster, idSecondary;
141 	struct Upp::Time tMaster, tSecondary;
142 	uint64 lengthMaster, lengthSecondary;
143 };
144 
145 class ErrorHandling {
146 public:
SetLastError(String _lastError)147 	void SetLastError(String _lastError)	{lastError = _lastError;};
GetLastError()148 	String GetLastError()					{return lastError;};
149 
150 private:
151 	String lastError;
152 };
153 
154 class FileDiffArray;
155 
156 class FileDataArray : public ErrorHandling {
157 public:
158 	FileDataArray(bool use = false, int fileFlags = 0);
159 	bool Init(String folder, FileDataArray &orig, FileDiffArray &diff);
160 	void Clear();
161 	bool Search(String dir, String condFile, bool recurse = false, String text = "");
162 	FileData& operator[](long i)	{return fileList[i];}
GetFileCount()163 	long GetFileCount()				{return fileCount;};
GetFolderCount()164 	long GetFolderCount()			{return folderCount;};
GetCount()165 	long GetCount() 				{return fileCount + folderCount;};
GetSize()166 	int64 GetSize()					{return fileSize;};
UseId()167 	inline bool UseId() 			{return useId;};
168 	void SortByName(bool ascending = true);
169 	void SortByDate(bool ascending = true);
170 	void SortBySize(bool ascending = true);
GetLastError()171 	Vector<String> &GetLastError()	{return errorList;};
172 	int Find(String &relFileName, String &fileName, bool isFolder);
173 	int Find(FileDataArray &data, int id);
FullFileName(int i)174 	String FullFileName(int i)		{return AppendFileName(basePath, fileList[i].fileName);};
175 	bool SaveFile(const char *fileName);
176 	bool AppendFile(const char *fileName);
177 	bool LoadFile(const char *fileName);
178 
179 private:
180 	void Search_Each(String dir, String condFile, bool recurse, String text);
181 	int64 GetFileId(String fileName);
182 	String GetRelativePath(const String &fullPath);
183 	String GetFileText();
184 
185 	Upp::Array<FileData> fileList;
186 	Vector<String> errorList;
187 	String basePath;
188 	long fileCount, folderCount;
189 	int64 fileSize;
190 	bool useId;
191 	int fileFlags;
192 };
193 
194 class FileDiffArray : public ErrorHandling {
195 public:
196 	FileDiffArray();
197 	void Clear();
198 	FileDiffData& operator[](long i)	{return diffList[i];}
199 	bool Compare(FileDataArray &master, FileDataArray &secondary, const String folderFrom,
200 		Vector<String> &excepFolders, Vector<String> &excepFiles, int sensSecs = 0);
201 	bool Apply(String toFolder, String fromFolder, EXT_FILE_FLAGS flags = NO_FLAG);
GetCount()202 	long GetCount()				{return diffList.size();};
203 	bool SaveFile(const char *fileName);
204 	bool LoadFile(const char *fileName);
205 	String ToString();
206 
207 private:
208 	Upp::Array<FileDiffData> diffList;
209 };
210 
211 String Replace(String str, String find, String replace);
212 String Replace(String str, char find, char replace);
213 
214 int ReverseFind(const String& s, const String& toFind, int from = 0);
215 
216 String FormatLong(long a);
217 
218 Upp::Time StrToTime(const char *s);
219 Date StrToDate(const char *s);
220 
221 String BytesToString(uint64 bytes, bool units = true);
222 
223 String SecondsToString(double seconds, int dec = 2, bool units = false, bool space = false,
224 						bool tp = false, bool longUnits = false, bool forceSec = false);
225 String HMSToString(int hour, int min, double seconds, int dec = 2, bool units = false, bool space = false,
226 						bool tp = false, bool longUnits = false, bool forceSec = false);
227 double StringToSeconds(String str);
228 void StringToHMS(String durat, int &hour, int &min, double &seconds);
229 
230 String SeasonName(int iseason);
231 int GetSeason(Date &date);
232 
233 String FormatDoubleAdjust(double d, double range);
234 
235 String RemoveAccents(String str);
236 String RemoveAccent(wchar c);
237 bool IsPunctuation(wchar c);
238 String RemovePunctuation(String str);
239 
240 template<class T>
ToRad(T angle)241 inline T ToRad(T angle)	{return angle*M_PI/180.;}
242 template<class T>
ToDeg(T angle)243 inline T ToDeg(T angle)	{return angle*180./M_PI;}
244 template<class T>
atan2_360(T y,T x)245 inline T atan2_360(T y, T x) {
246 	T ret = ToDeg(atan2<T>(y, x));
247 	return ret > 90 ? 450 - ret : 90 - ret;
248 }
249 
Odd(int val)250 inline bool Odd(int val)	  		{return val%2;}
Even(int val)251 inline bool Even(int val) 	  		{return !Odd(val);}
RoundEven(int val)252 inline int RoundEven(int val) 		{return Even(val) ? val : val+1;}
253 template<class T>
Sign(T a)254 inline int Sign(T a) 				{return (a > 0) - (a < 0);}
255 template<class T>
Neg(T a)256 inline T Neg(T a) 					{return a > 0 ? -a : a;}
257 template<class T>
Average(T a,T b)258 inline T Average(T a, T b) 			{return T(a+b)/2;}
259 template<class T>
Avg(T a,T b)260 inline T Avg(T a, T b) 				{return Average(a, b);}
261 template<class T>
Average(T a,T b,T c)262 inline T Average(T a, T b, T c)		{return T(a+b+c)/3;}
263 template<class T>
Avg(T a,T b,T c)264 inline T Avg(T a, T b, T c) 		{return Average(a, b, c);}
265 template<class T>
Average(T a,T b,T c,T d)266 inline T Average(T a, T b, T c, T d){return T(a+b+c+d)/4;}
267 template<class T>
Avg(T a,T b,T c,T d)268 inline T Avg(T a, T b, T c, T d)	{return Average(a, b, c, d);}
269 template<class T>
pow2(T a)270 inline T pow2(T a) {return a*a;}
271 template<class T>
pow3(T a)272 inline T pow3(T a) {return a*a*a;}
273 template<class T>
pow4(T a)274 inline T pow4(T a) {return pow2(pow2(a));}
275 template<class T>
fround(T x,int numdec)276 inline T fround(T x, int numdec) {
277 	int64 mult = 10*numdec;
278 	return T(int64(x*mult + .5))/mult;
279 }
280 template<typename T>
fact(T val)281 T fact(T val) {
282 	if (val <= 0)
283 		throw std::invalid_argument("fact() accepts only nonzero positive numbers");
284 	T ret = 1;
285 	while (val > 1)
286 		ret *= val--;
287 	return ret;
288 }
289 template <class T>
Between(const T & val,const T & min,const T & max)290 inline bool Between(const T& val, const T& min, const T& max) {
291 	return val >= min && val <= max;
292 }
293 template <class T>
BetweenVal(const T & val,const T & _min,const T & _max)294 inline T BetweenVal(const T& val, const T& _min, const T& _max) {
295 	return max(_min, min(_max, val));
296 }
297 template <class T>
IsNAN(T val)298 inline bool IsNAN(T val) {return std::isnan(val);}
299 
300 template <class T>
FixFloat(T val)301 inline T FixFloat(T val) {
302 	if(std::isnan(val) || std::isinf(val) || val == HUGE_VAL || val == -HUGE_VAL)
303 		return Null;
304 	return val;
305 }
306 
307 template <class T>
AngleAdd360(T ang,T val)308 T AngleAdd360(T ang, T val) {
309 	ang += val;
310 	while (ang >= 360)
311 		ang -= 360;
312 	while (ang < 0)
313 		ang += 360;
314 	return ang;
315 }
316 
317 template <class T>
Norm(const T & dx,const T & dy)318 inline const T Norm(const T& dx, const T& dy)  {
319 	return static_cast<T>(sqrt(dx*dx + dy*dy)); }
320 
321 template <class T>
Distance(const T & x1,const T & y1,const T & x2,const T & y2)322 inline const T Distance(const T& x1, const T& y1, const T& x2, const T& y2)  {
323 	return Norm(x1-x2, y1-y2); }
324 
325 template <class T>
Distance(const Point_<T> & p1,const Point_<T> & p2)326 inline const T Distance(const Point_<T>& p1, const Point_<T>& p2)  {
327 	return Distance<T>(p1.x, p1.y, p2.x, p2.y); }
328 
329 template <class T>
Distance(const T & x1,const T & y1,const T & z1,const T & x2,const T & y2,const T & z2)330 inline const T Distance(const T& x1, const T& y1, const T& z1, const T& x2, const T& y2, const T& z2)  {
331 	return static_cast<T>(sqrt(pow2(x1-x2) + pow2(y1-y2) + pow2(z1-z2))); }
332 
333 template <class T>
Angle(const T & x1,const T & y1,const T & x2,const T & y2)334 inline const T Angle(const T& x1, const T& y1, const T& x2, const T& y2)  {
335 	return static_cast<T>(atan2(y2-y1, x2-x1));
336 }
337 
338 template <class T>
Angle(const Point_<T> & p1,const Point_<T> & p2)339 inline const T Angle(const Point_<T>& p1, const Point_<T>& p2)  {
340 	return Angle<T>(p1.x, p1.y, p2.x, p2.y);
341 }
342 
343 
344 Vector<Vector <Value> > ReadCSV(const String strFile, char separator = ',', bool bycols = true, bool removeRepeated = true, char decimalSign = '.', bool onlyStrings = false, int fromRow = 0);
345 Vector<Vector <Value> > ReadCSVFile(const String fileName, char separator = ',', bool bycols = true, bool removeRepeated = true, char decimalSign = '.', bool onlyStrings = false, int fromRow = 0);
346 bool ReadCSVFileByLine(const String fileName, Gate<int, Vector<Value>&, String &> WhenRow, char separator = ',', char decimalSign = '.', bool onlyStrings = false, int fromRow = 0);
347 String WriteCSV(Vector<Vector <Value> > &data, char separator = ',', bool bycols = true, char decimalSign = '.');
348 bool WriteCSVFile(const String fileName, Vector<Vector <Value> > &data, char separator = ',', bool bycols = true, char decimalSign = '.');
349 
350 
351 // A String based class to parse into
352 class StringParse : public String {
353 public:
GoInit()354 	void GoInit()	{pos = 0; lastSeparator='\0';};
StringParse()355 	StringParse():String("") {GoInit();};
StringParse(String _s)356 	StringParse(String _s): String(_s) {GoInit();};
GoBefore(const String text)357 	bool GoBefore(const String text) {
358 		if (pos >= GetLength()) {
359 			pos = GetLength()-1;
360 			return false;
361 		}
362 		int newpos = String::Find(text, pos);
363 		if (newpos < 0)
364 			return false;	// If it does not find it, it does not move
365 		pos = newpos;
366 		return true;
367 	};
GoAfter(const String text)368 	bool GoAfter(const String text) {
369 		if(!GoBefore(text))
370 			return false;
371 		pos += int(strlen(text));
372 		return true;
373 	};
GoAfter(const String text,const String text2)374 	bool GoAfter(const String text, const String text2) {
375 		if(!GoAfter(text))
376 			return false;
377 		if(!GoAfter(text2))
378 			return false;
379 		return true;
380 	};
GoAfter(const String text,const String text2,const String text3)381 	bool GoAfter(const String text, const String text2, const String text3) {
382 		if(!GoAfter(text))
383 			return false;
384 		if(!GoAfter(text2))
385 			return false;
386 		if(!GoAfter(text3))
387 			return false;
388 		return true;
389 	};
GoAfter_Init(const String text)390 	bool GoAfter_Init(const String text) {GoInit();	return GoAfter(text);};
GoAfter_Init(const String text,const String text2)391 	bool GoAfter_Init(const String text, const String text2) {GoInit();	return GoAfter(text, text2);};
GoAfter_Init(const String text,const String text2,const String text3)392 	bool GoAfter_Init(const String text, const String text2, const String text3) {GoInit();	return GoAfter(text, text2, text3);};
393 
GoBeginLine()394 	void GoBeginLine() {
395 		for (; pos >= 0; --pos) {
396 			if ((ToString()[pos-1] == '\r') || (ToString()[pos-1] == '\n'))
397 				return;
398 		}
399 	}
IsBeginLine()400 	bool IsBeginLine() {
401 		if (pos == 0)
402 			return true;
403 		if ((ToString()[pos-1] == '\r') || (ToString()[pos-1] == '\n'))
404 			return true;
405 		return false;
406 	}
IsSpaceRN(int c)407 	bool IsSpaceRN(int c) {
408 		if (IsSpace(c))
409 			return true;
410 		if ((c == '\r') || (c == '\n'))
411 		     return true;
412 		return false;
413 	}
414 	// Gets text between "" or just a word until an space
415 	// It considers special characters with \ if between ""
416 	// If not between "" it gets the word when it finds one of the separator characters
417 	String GetText(String separators = "") {
418 		String ret = "";
419 		if (pos > GetCount() || pos == -1)
420 			return ret;
421 		int newpos = pos;
422 
423 		while ((IsSpaceRN(ToString()[newpos]) && (ToString()[newpos] != '\"') &&
424 			   (ToString()[newpos] != '\0')))
425 			newpos++;
426 		if (ToString()[newpos] == '\0') {
427 			pos = newpos;
428 			return "";
429 		}
430 
431 		if (ToString()[newpos] == '\"') {	// Between ""
432 			newpos++;
433 			while (ToString()[newpos] != '\"' && ToString()[newpos] != '\0') {
434 				if (ToString()[newpos] == '\\') {
435 					newpos++;
436 					if (ToString()[newpos] == '\0')
437 						return "";
438 				}
439 				ret.Cat(ToString()[newpos]);
440 				newpos++;
441 			}
442 			lastSeparator = '"';
443 		} else if (separators == "") {		// Simple word
444 			while (!IsSpaceRN(ToString()[newpos]) && ToString()[newpos] != '\0') {
445 				if (ToString()[newpos] == '\"') {
446 					newpos--;	// This " belongs to the next
447 					break;
448 				}
449 				ret.Cat(ToString()[newpos]);
450 				newpos++;
451 			}
452 			lastSeparator = ToString()[newpos];
453 		} else {							// Simple word, special separator
454 			while (ToString()[newpos] != '\0') {// Only consider included spaces (!IsSpaceRN(ToString()[newpos]) && ToString()[newpos] != '\0') {
455 				if (ToString()[newpos] == '\"') {
456 					newpos--;	// This " belongs to the next
457 					break;
458 				}
459 				if (separators.Find(ToString()[newpos]) >= 0) {
460 					lastSeparator = ToString()[newpos];
461 					break;
462 				}
463 				ret.Cat(ToString()[newpos]);
464 				newpos++;
465 			}
466 			lastSeparator = ToString()[newpos];
467 		}
468 		pos = ++newpos;		// After the separator: ", space or separator
469 		return ret;
470 	}
GetLine()471 	String GetLine() {
472 		String ret;
473 		if (pos > GetCount() || pos == -1)
474 			return String();
475 		while (ToString()[pos] != '\0') {
476 			if (ToString()[pos] == '\n') {
477 				pos++;
478 				return ret;
479 			}
480 			if (ToString()[pos] == '\r' && ToString()[pos+1] == '\n') {
481 				pos += 2;
482 				return ret;
483 			}
484 			ret.Cat(ToString()[pos]);
485 			pos++;
486 		}
487 		return ret;
488 	}
489 	double GetDouble(String separators = "")  	{return FixFloat(atof(GetText(separators)));};
490 	int GetInt(String separators = "")			{return static_cast<int>(FixFloat(atof(GetText(separators))));};
491 	long GetLong(String separators = "")		{return static_cast<long>(FixFloat(atof(GetText(separators))));};
492 	uint64 GetUInt64(String separators = "")	{return static_cast<uint64>(FixFloat(atof(GetText(separators))));};
493 
Right()494 	String Right() 			{return String::Mid(pos+1);}
GetLastSeparator()495 	int GetLastSeparator() 	{return lastSeparator;}
MoveRel(int val)496 	void MoveRel(int val) {
497 		pos += val;
498 		if (pos < 0)
499 			pos = 0;
500 		else if (pos >= GetCount())
501 			pos = GetCount() - 1;
502 	}
GetPos()503 	int GetPos() {return pos;};
SetPos(int i)504 	bool SetPos(int i)
505 	{
506 		if (i < 0 || i >= GetCount())
507 			return false;
508 		else {
509 			pos = i;
510 			return true;
511 		}
512 	}
Eof()513 	bool Eof()
514 	{
515 		return pos >= GetCount();
516 	}
Count(String _s)517 	unsigned Count(String _s)
518 	{
519 		int from = 0;
520 		unsigned count = 0;
521 
522 		while ((from = ToString().Find(_s, from)) >= 0) {
523 			count++;
524 			from++;
525 		}
526 		return count;
527 	}
528 private:
529 	int pos;
530 	int lastSeparator;
531 };
532 
533 #if defined(PLATFORM_WIN32)
534 Value GetVARIANT(VARIANT &result);
535 String WideToString(LPCWSTR wcs, int len = -1);
536 #endif
537 
538 
539 String GetExtExecutable(const String ext);
540 
541 Vector<String> GetDriveList();
542 
543 
544 class Dl {
545 public:
546 	Dl();
547 	virtual ~Dl();
548 	bool Load(const String &fileDll);
549 	void *GetFunction(const String &functionName);
550 
551 private:
552 #if defined(PLATFORM_WIN32)
553 	HINSTANCE hinstLib;
554 #else
555 	void *hinstLib;
556 #endif
557 };
558 
559 typedef Dl Dll;
560 
561 //bool RunFromMemory(const String &progBuffer, const String &name);
562 
563 
564 String BsGetLastError();
565 bool BSPatch(String oldfile, String newfile, String patchfile);
566 bool BSDiff(String oldfile, String newfile, String patchfile);
567 
568 
569 template <class T>
FitInFrame(const Size_<T> & frame,const Size_<T> & object)570 Rect_<T> FitInFrame(const Size_<T> &frame, const Size_<T> &object)
571 {
572 	double frameAspect  = frame.cx/static_cast<double>(frame.cy);
573 	double objectAspect = object.cx/static_cast<double>(object.cy);
574 
575 	if (frameAspect > objectAspect) {
576 		double x = (frame.cx - objectAspect*frame.cy)/2.;
577 		return Rect_<T>(static_cast<T>(x), 0, static_cast<T>(x + objectAspect*frame.cy), frame.cy);
578 	} else {
579 		double y = (frame.cy - frame.cx/objectAspect)/2.;
580 		return Rect_<T>(0, static_cast<T>(y), frame.cx, static_cast<T>(y + frame.cx/objectAspect));
581 	}
582 }
583 
584 Color RandomColor();
585 
586 Image GetRect(const Image& orig, const Rect &r);
587 
588 double tmGetTimeX();
589 
590 int SysX(const char *cmd, String& out, String& err, double timeOut = Null,
591 			Gate3<double, String&, String&> progress = false, bool convertcharset = true);
592 
593 
594 class _NRFuse {
595 public:
_NRFuse(bool * _inside)596 	_NRFuse(bool *_inside) {inside = _inside; failed = true;}
~_NRFuse()597 	virtual ~_NRFuse() 			   {if (!failed) *inside = false;}
598 	bool failed;
599 private:
600 	bool *inside;
601 };
602 
603 #define NON_REENTRANT_V	 	static bool _insideNR; _NRFuse _fuseNR(&_insideNR); \
604 							if(!_insideNR) {									\
605 								_insideNR = true; 								\
606 								_fuseNR.failed = false;							\
607 							} else 												\
608 								return
609 #define NON_REENTRANT(v) 	static bool _insideNR; _NRFuse _fuseNR(&_insideNR); \
610 							if(!_insideNR) {									\
611 								_insideNR = true; 								\
612 								_fuseNR.failed = false;							\
613 							} else 												\
614 								return v
615 
616 template <class T>
617 struct TempAssign {
TempAssignTempAssign618 	TempAssign(T &_val, T set) {
619 		old = _val;
620 		_val = set;
621 		val = &_val;
622 	}
~TempAssignTempAssign623 	virtual ~TempAssign() {
624 		*val = old;
625 	}
626 
627 	T *val, old;
628 };
629 
630 /*						Replaced with std::atomic
631 template <class T>
632 class ThreadSafe {
633 public:
634 	inline ThreadSafe()    {val = Null;}
635 	inline ThreadSafe(T v) {operator=(v);}
636 	inline void operator=(T v) {
637 		mutex.Enter();
638 		val = v;
639 		mutex.Leave();
640 	}
641 	inline void operator+=(T v) {
642 		mutex.Enter();
643 		val += v;
644 		mutex.Leave();
645 	}
646 	inline void operator-=(T v) {
647 		mutex.Enter();
648 		val -= v;
649 		mutex.Leave();
650 	}
651 	inline operator T() {
652 		T ret;
653 		mutex.Enter();
654 		ret = val;
655 		mutex.Leave();
656 		return ret;
657 	}
658 	Value GetData() {
659 		Value ret;
660 		mutex.Enter();
661 		ret = val;
662 		mutex.Leave();
663 		return ret;
664 	}
665 	Value operator~() const 		{return GetData();}
666 	inline ThreadSafe& operator++() {
667 		mutex.Enter();
668 		val++;
669 		mutex.Leave();
670 		return *this;
671 	}
672    	inline ThreadSafe operator++(int) {
673 		ThreadSafe tmp = *this;
674    		++*this;
675    		return tmp;
676 	}
677 
678 private:
679 	Mutex mutex;
680 	T val;
681 };*/
682 
683 template <class C>
ShuffleAscending(C & data,std::default_random_engine & generator)684 static void ShuffleAscending(C &data, std::default_random_engine &generator) {
685 	for (int i = 0; i < data.size() - 2; i++) {
686 	  	std::uniform_int_distribution<int> distribution(i, data.size() - 1);
687         Swap(data[i], data[distribution(generator)]);
688     }
689 }
690 
691 template <class C>
ShuffleDescending(C & data,std::default_random_engine & generator)692 static void ShuffleDescending(C &data, std::default_random_engine &generator) {
693 	for (int i = data.size() - 1; i > 0; i--) {
694 	  	std::uniform_int_distribution<int> distribution(0, i);
695         Swap(data[i], data[distribution(generator)]);
696     }
697 }
698 
699 template <class C>
700 void Shuffle(C &data, int randomSeed = Null) {
701 	if (IsNull(randomSeed))	{
702 		std::random_device rd;
703 		randomSeed = rd();
704 	}
705 	std::default_random_engine re(randomSeed);
706 
707 	std::mt19937 generator(randomSeed);
708 
709 	ShuffleAscending(data, re);
710 	ShuffleDescending(data, re);
711 }
712 
713 template <class T>
714 bool EqualRatio(const T& a, const T& b, const T& ratio, const T& zero = 0) {
715 	if (abs(a) <= zero) {
716 		if (abs(b) <= zero)
717 			return true;
718 		else {
719 			if(abs((zero - b)/b) <= ratio)
720 				return true;
721 			else
722 				return false;
723 		}
724 	} else if (abs(b) <= zero) {
725 		if(abs((a - zero)/a) <= ratio)
726 			return true;
727 		else
728 			return false;
729 	}
730 	if(abs((a - b)/b) <= ratio)
731 		return true;
732 	return false;
733 }
734 
735 template <class Range, class V>
736 int Find(const Range& r, const V& value, int from = 0) {
737 	for(int i = from; i < r.size(); i++)
738 		if(r[i] == value)
739 			return i;
740 	return -1;
741 }
742 
743 template <class Range, class V>
744 int FindAdd(Range& r, const V& value, int from = 0) {
745 	int id = Find(r, value, from);
746 	if (id >= 0)
747 		return id;
748 	r.Add(value);
749 	return r.size()-1;
750 }
751 
752 template <class Range, class V>
753 int FindRatio(const Range& r, const V& value, const V& ratio, int from = 0) {
754 	for(int i = from; i < r.size(); i++) {
755 		if (EqualRatio(r[i], value, ratio))
756 			return i;
757 	}
758 	return -1;
759 }
760 
761 template <class Range, class V>
762 int FindAddRatio(Range& r, const V& value, const V& ratio, int from = 0) {
763 	int id = FindRatio(r, value, ratio, from);
764 	if (id >= 0)
765 		return id;
766 	r.Add(value);
767 	return r.size()-1;
768 }
769 
770 template <class Range, class V>
771 int FindDelta(const Range& r, const V& value, const V& delta, int from = 0) {
772 	for(int i = from; i < r.size(); i++)
773 		if(abs(r[i] - value) <= delta)
774 			return i;
775 	return -1;
776 }
777 
778 template <class Range, class V>
779 int FindAddDelta(Range& r, const V& value, const V& delta, int from = 0) {
780 	int id = FindDelta(r, value, delta, from);
781 	if (id >= 0)
782 		return id;
783 	r.Add(value);
784 	return r.size()-1;
785 }
786 
787 template <class Range, class V>
788 int FindRoundDecimals(const Range& r, const V& value, int numDecimals, int from = 0) {
789 	String svalue = FormatDouble(value, numDecimals);
790 	for(int i = from; i < r.size(); i++)
791 		if(FormatDouble(r[i], numDecimals) == svalue)
792 			return i;
793 	return -1;
794 }
795 
796 template <class Range, class V>
797 int FindClosest(const Range& r, const V& value, int from = 0) {
798 	int minId = -1;
799 	V minDiff = FLT_MAX;
800 	for(int i = from; i < r.size(); i++) {
801 		V diff = abs(value - r[i]);
802 		if (diff < minDiff) {
803 			minDiff = diff;
804 			minId = i;
805 		}
806 	}
807 	return minId;
808 }
809 
810 template <class Range>
Compare(const Range & a,const Range & b)811 bool Compare(const Range& a, const Range& b) {
812 	if (a.size() != b.size())
813 		return false;
814 	for(int i = 0; i < a.size(); i++) {
815 		if(a[i] != b[i])
816 			return false;
817 	}
818 	return true;
819 }
820 
821 template <class Range, class V>
CompareRatio(const Range & a,const Range & b,const V & ratio)822 bool CompareRatio(const Range& a, const Range& b, const V& ratio) {
823 	if (a.size() != b.size())
824 		return false;
825 	for(int i = 0; i < a.size(); i++)
826 		if (!EqualRatio(a[i], b[i], ratio))
827 			return false;
828 	return true;
829 }
830 
831 template <class Range>
ToString(const Range & a)832 String ToString(const Range& a) {
833 	String ret;
834 	for(int i = 0; i < a.size(); i++) {
835 		if (i > 0)
836 			ret << ";";
837 		ret << a[i];
838 	}
839 	return ret;
840 }
841 
842 class RealTimeStop {
843 typedef RealTimeStop CLASSNAME;
844 public:
RealTimeStop()845 	RealTimeStop() {
846 #ifdef CTRLLIB_H
847 		callbackOn = false;
848 		lastTick = -1;
849 #endif
850 		Start();
851 	}
Reset()852 	void Reset() {
853 		timeElapsed = lastTimeElapsed = 0;
854 #ifdef CTRLLIB_H
855 		if (!callbackOn) {
856 			timeCallback.Set(-5*1000, THISBACK(Tick));
857 			callbackOn = true;
858 		}
859 #endif
860 		isPaused = true;
861 		Continue();
862 	}
Start()863 	void Start() {Reset();}
Pause(bool pause)864 	void Pause(bool pause) {
865 		if (pause)
866 			Pause();
867 		else
868 			Continue();
869 	}
Pause()870 	void Pause() {
871 		if (!isPaused) {
872 			timeElapsed += (tmGetTimeX() - time0);
873 			isPaused = true;
874 		}
875 	}
Continue()876 	void Continue() {
877 		if (isPaused) {
878 			time0 = tmGetTimeX();
879 			isPaused = false;
880 		}
881 	}
Seconds()882 	double Seconds() {
883 		if (isPaused)
884 			return timeElapsed;
885 		else
886 			return timeElapsed + (tmGetTimeX() - time0);
887 	}
Elapsed()888 	double Elapsed() {
889 		double t = Seconds();
890 		double elapsed = t - lastTimeElapsed;
891 		lastTimeElapsed = t;
892 		return elapsed;
893 	}
SetBack(double secs)894 	void SetBack(double secs) {
895 		timeElapsed -= secs;
896 	}
IsPaused()897 	bool IsPaused()		{return isPaused;}
898 
899 private:
900 	double timeElapsed;				// Time elapsed
901 	double time0;					// Time of last Continue()
902 	double lastTimeElapsed;
903 	bool isPaused;
904 #ifdef CTRLLIB_H
905 	bool callbackOn;
906 	double lastTick;
907 	TimeCallback timeCallback;
908 
Tick()909 	void Tick() {
910 		double tActual = tmGetTimeX();
911 		if (!isPaused && lastTick > -1) {
912 			double deltaLastTick = tActual - lastTick;
913 			if (deltaLastTick > 5*10) 	// Some external issue has stopped normal running
914 				SetBack(deltaLastTick);	// Timeout timer is fixed accordingly
915 		}
916 		lastTick = tActual;
917 	}
918 #endif
919 };
920 
921 class LocalProcessX
922 #ifdef CTRLLIB_H
923  : public Ctrl
924  #endif
925  {
926 typedef LocalProcessX CLASSNAME;
927 public:
LocalProcessX()928 	LocalProcessX() {}
~LocalProcessX()929 	virtual ~LocalProcessX() 		{Stop();}
930 	enum ProcessStatus {RUNNING = 1, STOP_OK = 0, STOP_TIMEOUT = -1, STOP_USER = -2, STOP_NORESPONSE = -3};
931 	bool Start(const char *cmd, const char *envptr = 0, const char *dir = 0, double _refreshTime = -1,
932 		double _maxTimeWithoutOutput = -1, double _maxRunTime = -1, bool convertcharset = true) {
933 		status = STOP_OK;
934 		p.ConvertCharset(convertcharset);
935 		timeElapsed.Start();
936 		timeWithoutOutput.Start();
937 		if(!p.Start(cmd, envptr, dir))
938 			return false;
939 		status = RUNNING;
940 		maxTimeWithoutOutput = _maxTimeWithoutOutput;
941 		maxRunTime = _maxRunTime;
942 		refreshTime = _refreshTime;
943 
944 #ifdef CTRLLIB_H
945 		if (refreshTime > 0) {
946 			if (!callbackOn) {
947 				timeCallback.Set(-int(refreshTime*1000), THISBACK(Perform));
948 				callbackOn = true;
949 			}
950 		}
951 #endif
952 		return true;
953 	}
Perform()954 	void Perform() {
955 		if (status <= 0)
956 			return;
957 		String out;
958 		p.Read(out);
959 		if(p.IsRunning()) {
960 #ifdef PLATFORM_WIN32
961 			if (!p.IsPaused()) {
962 #endif
963 				if (maxTimeWithoutOutput > 0 && timeWithoutOutput.Seconds() > maxTimeWithoutOutput)
964 					status = STOP_NORESPONSE;
965 				else if (maxRunTime > 0 && timeElapsed.Seconds() > maxRunTime)
966 					status = STOP_TIMEOUT;
967 #ifdef PLATFORM_WIN32
968 			}
969 #endif
970 		} else
971 			status = STOP_OK;
972 
973 		bool resetTimeout = false;
974 		if (!out.IsEmpty())
975 			resetTimeout = true;
976 
977 		if (!WhenTimer(timeElapsed.Seconds(), out, status <= 0, resetTimeout))
978 			status = STOP_USER;
979 
980 		if (resetTimeout)
981 			timeWithoutOutput.Reset();
982 
983 		if (status < 0)
984 			p.Kill();
985 
986 #ifdef CTRLLIB_H
987 		if (callbackOn) {
988 			timeCallback.Kill();
989 			callbackOn = false;
990 		}
991 #endif
992 	}
993 	void Stop(ProcessStatus _status = STOP_USER) {
994 		if (!IsRunning())
995 			return;
996 		status = _status;
997 		p.Kill();
998 #ifdef CTRLLIB_H
999 		if (callbackOn) {
1000 			timeCallback.Kill();
1001 			callbackOn = false;
1002 		}
1003 #endif
1004 	}
1005 #ifdef PLATFORM_WIN32
Pause()1006 	void Pause() {
1007 		p.Pause();
1008 		if (p.IsRunning()) {
1009 			timeElapsed.Pause(p.IsPaused());
1010 			timeWithoutOutput.Pause(p.IsPaused());
1011 		}
1012 	}
IsPaused()1013 	bool IsPaused()			{return p.IsPaused();}
Seconds()1014 	double Seconds()		{return timeElapsed.Seconds();}
1015 #endif
Write(String str)1016 	void Write(String str) 	{p.Write(str);}
GetStatus()1017 	int GetStatus()  		{return status;}
IsRunning()1018 	bool IsRunning() 		{return status > 0;}
1019 	Gate4<double, String&, bool, bool&> WhenTimer;
1020 	#ifdef PLATFORM_WIN32
GetPid()1021 	DWORD GetPid()	{return p.GetPid();}
1022 	#endif
1023 
1024 private:
1025 	LocalProcess2 p;
1026 	RealTimeStop timeElapsed, timeWithoutOutput;
1027 	ProcessStatus status = STOP_OK;
1028 	double maxTimeWithoutOutput, maxRunTime;
1029 	double refreshTime;
1030 #ifdef CTRLLIB_H
1031 	bool callbackOn = false;
1032 	TimeCallback timeCallback;
1033 #endif
1034 };
1035 
1036 int LevenshteinDistance(const char *s, const char *t);
1037 int DamerauLevenshteinDistance(const char *s, const char *t, int alphabetLength = 256);
1038 int SentenceSimilitude(const char *s, const char *t);
1039 
1040 #define S(y)	Upp::String(y)
1041 
1042 
1043 template<class T>
Jsonize(JsonIO & io,std::complex<T> & var)1044 void Jsonize(JsonIO& io, std::complex<T>& var) {
1045 	T re, im;
1046 	if (io.IsStoring()) {
1047 		re = var.real();
1048 		im = var.imag();
1049 	}
1050 	io("re", re)("im", im);
1051 	if (io.IsLoading()) {
1052 		var.real(re);
1053 		var.imag(im);
1054 	}
1055 }
1056 
1057 size_t GetNumLines(Stream &stream);
1058 
1059 class FileInLine : public FileIn {
1060 public:
FileInLine(String _fileName)1061 	FileInLine(String _fileName) : FileIn(_fileName), line(0), fileName(_fileName) {};
GetLine()1062 	String GetLine() {
1063 		line++;
1064 		return FileIn::GetLine();
1065 	}
GetLine(int num)1066 	void GetLine(int num) {
1067 		for (int i = 0; i < num; ++i)
1068 			GetLine();
1069 	}
GetLineNumber()1070 	int GetLineNumber()	const 	{return line;}
Str()1071 	String Str() const 			{return Format(t_("[File: '%s', line: %d]:"), fileName, line);}
1072 
1073 	struct Pos {
PosPos1074 		Pos() : byt(0), line(0) {}
1075 		int64 byt;
1076 		int line;
1077 	};
1078 
GetPos()1079 	Pos GetPos() {
1080 		Pos ret;
1081 		ret.byt = FileIn::GetPos();
1082 		ret.line = line;
1083 		return ret;
1084 	}
1085 
SeekPos(Pos & pos)1086 	void SeekPos(Pos &pos) {
1087 		FileIn::Seek(pos.byt);
1088 		line = pos.line;
1089 	}
1090 
1091 private:
1092 	int line;
1093 	String fileName;
1094 };
1095 
1096 class FileInBinary : public FileIn {
1097 public:
FileInBinary()1098 	FileInBinary()                          	{}
FileInBinary(const char * fn)1099 	FileInBinary(const char *fn) : FileIn(fn)	{}
1100 
ReadB(void * data,size_t sz)1101 	void ReadB(void *data, size_t sz) {
1102 		int64 len = Get64(data, sz);
1103 		if (len != sz)
1104 			throw Exc(Format(t_("Data not loaded in FileInBinary::Read(%ld)"), int64(sz)));
1105 	}
1106 
1107 	template <class T>
ReadB()1108 	T ReadB() {
1109 		T data;
1110 		ReadB(&data, sizeof(T));
1111 		return data;
1112 	}
1113 	template <class T, size_t len>
ReadB()1114 	T ReadB() {
1115 		T data;
1116 		ReadB(&data, min(len, sizeof(T)));
1117 		return data;
1118 	}
1119 };
1120 
1121 class FileOutBinary : public FileOut {
1122 public:
FileOutBinary(const char * fn)1123 	FileOutBinary(const char *fn) : FileOut(fn)	{}
FileOutBinary()1124 	FileOutBinary()                          		{}
1125 
1126 	template <class T>
Write(T data)1127 	void Write(T data) {
1128 		Put64(&data, sizeof(T));
1129 	}
1130 };
1131 
1132 class FieldSplit {
1133 public:
1134 	const int FIRST = 0;
1135 	const int LAST = Null;
1136 
FieldSplit(FileInLine & _in)1137 	FieldSplit(FileInLine &_in) {in = &_in;}
1138 
Load(String _line)1139 	FieldSplit& Load(String _line) {
1140 		line = _line;
1141 		fields = Split(line, IsSeparator, true);
1142 		return *this;
1143 	}
GetText()1144 	String GetText() const {
1145 		return line;
1146 	}
GetText(int i)1147 	String GetText(int i) const {
1148 		if (fields.IsEmpty())
1149 			throw Exc(in->Str() + t_("No data available"));
1150 		if (IsNull(i))
1151 			i = fields.GetCount()-1;
1152 		CheckId(i);
1153 		return fields[i];
1154 	}
GetInt(int i)1155 	int GetInt(int i) const {
1156 		if (fields.IsEmpty())
1157 			throw Exc(in->Str() + t_("No data available"));
1158 		if (IsNull(i))
1159 			i = fields.GetCount()-1;
1160 		CheckId(i);
1161 		int res = ScanInt(fields[i]);
1162 		if (IsNull(res))
1163 			throw Exc(in->Str() + Format(t_("Bad %s '%s' in field #%d, line\n'%s'"), "integer", fields[i], i+1, line));
1164 		return res;
1165 	}
GetDouble(int i)1166 	double GetDouble(int i) const {
1167 		if (fields.IsEmpty())
1168 			throw Exc(in->Str() + t_("No data available"));
1169 		if (IsNull(i))
1170 			i = fields.GetCount()-1;
1171 		CheckId(i);
1172 		double res = ScanDouble(fields[i]);
1173 		if (IsNull(res))
1174 			throw Exc(in->Str() + Format(t_("Bad %s '%s' in field #%d, line\n'%s'"), "double", fields[i], i+1, line));
1175 		return res;
1176 	}
1177 
size()1178 	int size() const 		{return fields.GetCount();}
GetCount()1179 	int GetCount() const 	{return size();}
1180 
1181 	int (*IsSeparator)(int) = defaultIsSeparator;
1182 
1183 protected:
1184 	String line;
1185 	Upp::Vector<String> fields;
1186 	FileInLine *in;
1187 
CheckId(int i)1188 	void CheckId(int i) const {
1189 		if (i >= fields.GetCount() || i < 0)
1190 			throw Exc(in->Str() + Format(t_("Field #%d not found in line\n'%s'"), i+1, line));
1191 	}
defaultIsSeparator(int c)1192 	static int defaultIsSeparator(int c) {
1193 		if (c == '\t' || c == ' ')
1194 			return true;
1195 		return false;
1196 	}
1197 };
1198 
1199 enum CONSOLE_COLOR {
1200 #ifdef PLATFORM_WIN32
1201     BLACK       = 0,
1202     BLUE        = FOREGROUND_BLUE,
1203     GREEN       = FOREGROUND_GREEN,
1204     CYAN        = FOREGROUND_GREEN | FOREGROUND_BLUE,
1205     RED         = FOREGROUND_RED,
1206     MAGENTA     = FOREGROUND_RED | FOREGROUND_BLUE,
1207     YELLOW      = FOREGROUND_RED | FOREGROUND_GREEN,
1208     GRAY        = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
1209     LTBLUE      = FOREGROUND_INTENSITY | FOREGROUND_BLUE,
1210     LTGREEN     = FOREGROUND_INTENSITY | FOREGROUND_GREEN,
1211     LTCYAN      = FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE,
1212     LTRED       = FOREGROUND_INTENSITY | FOREGROUND_RED,
1213     LTMAGENTA	= FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE,
1214     LTYELLOW    = FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN,
1215     WHITE      	= FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
1216     RESET,
1217     PREVIOUS
1218 #else
1219 	BLACK     	= 30,
1220 	RED     	= 31,
1221 	GREEN   	= 32,
1222 	YELLOW  	= 33,
1223 	BLUE    	= 34,
1224 	MAGENTA 	= 35,
1225 	CYAN    	= 36,
1226 	GRAY    	= 37,
1227 	LTRED     	= 131,
1228 	LTGREEN   	= 132,
1229 	LTYELLOW  	= 133,
1230 	LTBLUE    	= 134,
1231 	LTMAGENTA 	= 135,
1232 	LTCYAN    	= 136,
1233 	WHITE    	= 137,
1234 	RESET   	= 0,
1235 	PREVIOUS	= 1000
1236 #endif
1237 };
1238 
1239 bool SetConsoleColor(CONSOLE_COLOR color);
1240 void ConsoleOutputDisable(bool disable);
1241 
1242 }
1243 
1244 #endif
1245