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