11 #if !defined(ECERE_BOOTSTRAP) // quick fix for now
12 #if defined(__WIN32__)
13 #define WIN32_LEAN_AND_MEAN
14 #define String _String
29 default extern Platform runtimePlatform;
31 #define IS_ALUNDER(ch) ((ch) == '_' || isalnum((ch)))
33 public define DIR_SEP = (GetRuntimePlatform() == win32) ? '\\' : '/';
34 public define DIR_SEPS = (GetRuntimePlatform() == win32) ? "\\" : "/";
36 // Maximum length for a vsnprintf string
37 public define MAX_F_STRING = 1025;
39 // Maximum length for a directories and filenames strings
40 public define MAX_EXTENSION = 17; // 16 + \0
41 public define MAX_FILENAME = 274; // 256 chars + extension + dot + \0
42 public define MAX_DIRECTORY = 534; // 8 levels + 8 separators + \0
43 public define MAX_LOCATION = 797; // directory + filename + separator + \0
45 // --- File related String functions ---
46 public char * GetExtension(char * string, char * output)
49 int len = strlen(string);
50 int limit = Max(0, len-MAX_EXTENSION);
52 for(c = len; c>=limit; c--)
57 strcpy(output, string+c+1);
60 else if(ch == '/' || ch == '\\')
66 public char * StripLastDirectory(char * string, char * output)
69 if(runtimePlatform == win32 && !strcmp(string, "\\\\"))
76 int len = strlen(string);
77 for(c = len-2; c>=0; c--)
78 if(string[c] == '/' || string[c] == '\\')
80 else if(string[c] == '>' || (string[c] == ':' && c == 0))
86 if((runtimePlatform == win32) ? (c >= 0) : (c > 0))
88 memmove(output, string, c);
91 if(runtimePlatform == win32 && c == 1 && output[0] == '\\' && output[1] == '\\')
97 strcpy(output, DIR_SEPS);
102 // Return root on UNIX instead of null...
105 strcpy(output, DIR_SEPS);
117 public char * SplitDirectory(const char * string, char * part, char * rest)
122 for(;(ch = string[c]) && (ch == '/' || ch == '\\'); c++);
125 part[len++] = DIR_SEP;
128 for(;(ch = string[c]) && (ch != '/' && ch != '\\'); c++)
130 if(len < MAX_FILENAME)
135 for(;(ch = string[c]) && (ch == '/' || ch == '\\'); c++);
136 memmove(rest, string + c, strlen(string + c) + 1);
137 for(c = strlen(rest); c >= 0; c--)
138 if(ch != '/' && ch != '\\')
147 public char * GetLastDirectory(char * string, char * output)
150 int len = string ? strlen(string) : 0;
151 for(c = len-2; c>=0; c--)
152 if(string[c] == '/' || string[c] == '\\' || string[c] == ':' || string[c] == '>')
157 memmove(output, string+c, strlen(string+c)+1);
161 len = strlen(output);
162 if(len > 1 && (output[len-1] == '\\' || output[len-1] == '/'))
163 output[len-1] = '\0';
167 public bool SplitArchivePath(char * fileName, char * archiveName, char ** archiveFile)
170 if(fileName[0] == '<')
172 int c = strlen(fileName);
173 for(;c>0 && fileName[c] != '>'; c--);
176 strncpy(archiveName, fileName + 1, c - 1);
177 archiveName[c - 1] = '\0';
178 *archiveFile = fileName + c + 1;
182 else if(fileName[0] == ':')
184 strcpy(archiveName, ":");
185 *archiveFile = fileName + 1;
191 public char * PathCatSlash(char * string, char * addedPath)
193 bool modified = false;
196 char fileName[MAX_LOCATION] = "", archiveName[MAX_LOCATION] = "", * file;
201 if(SplitArchivePath(string, archiveName, &file))
202 strcpy(fileName, file);
205 strcpy(fileName, string);
208 if(strstr(string, "http://") == string)
210 char * slash = strstr(fileName + 7, "/");
215 urlFileName = fileName + strlen(fileName);
217 if(strstr(addedPath, "http://") == addedPath)
219 strcpy(fileName, "http://");
223 else if(GetRuntimePlatform() == win32)
225 if(addedPath[0] && addedPath[1] == ':' && addedPath[0] != '<')
227 fileName[0] = (char)toupper(addedPath[0]);
233 else if(addedPath[0] == '\\' && addedPath[1] == '\\')
235 fileName[0] = fileName[1] = '\\';
240 // A drive needs to be selected
241 /* TOCHECK: Cutting this out, can't handle relative path
242 else if(fileName[0] == '/' && !archiveName[0] && strcmp(addedPath, "/"))
247 if(!modified && isURL && (addedPath[0] == '\\' || addedPath[0] == '/'))
249 urlFileName[0] = '/';
250 urlFileName[1] = '\0';
252 else if(!modified && (addedPath[0] == '\\' || addedPath[0] == '/'))
254 if(GetRuntimePlatform() == win32)
257 if(addedPath[0] == '/' && !addedPath[1])
259 fileName[0] = addedPath[0];
264 else if(fileName[0] && fileName[1] == ':')
269 // Relative path root of drive
286 for(; addedPath[c]; )
288 // DANGER OF OVERFLOW HERE
289 // char directory[MAX_FILENAME];
290 char directory[MAX_FILENAME * 16];
295 for(;(ch = addedPath[c]) && (ch == '/' || ch == '\\'); c++);
296 for(;(ch = addedPath[c]) && (ch != '/' && ch != '\\'); c++)
298 if(isURL && ch == '?')
302 if(len < MAX_FILENAME)
303 directory[len++] = ch;
305 directory[len] = '\0';
307 // Trim rightmost spaces
308 for(count = len-1; count >= 0 && (directory[count] == ' ' || directory[count] == '\t'); count--)
310 directory[count] = '\0';
317 if(strstr(directory, "..") == directory && (!directory[2] || directory[2] == DIR_SEP || directory[2] == '/'))
319 int strLen = strlen(fileName) - 1;
322 // Go back one directory
323 for(;(ch = fileName[strLen]) && strLen > -1 && (ch == '/' || ch == '\\'); strLen--);
324 for(;(ch = fileName[strLen]) && strLen > -1 && (ch != '/' && ch != '\\' && ch != ':'); strLen--);
325 for(;(ch = fileName[strLen]) && strLen > -1 && (ch == '/' || ch == '\\'); strLen--);
329 strLen = Max(strLen, urlFileName - fileName);
331 if(!strcmp(fileName + strLen + 1, ".."))
333 strcat(fileName, "/" /*DIR_SEPS*/);
334 strcat(fileName, "..");
338 if(GetRuntimePlatform() == win32)
340 if(!strLen && fileName[0] == '\\' && fileName[1] == '\\')
352 fileName[strLen+1] = '\0';
356 fileName[strLen+1] = '\0';
368 strcpy(fileName, "..");
371 else if(strcmp(directory, "."))
373 int strLen = strlen(fileName);
374 bool notZeroLen = strLen > 0;
375 // if(strLen > 1 && (fileName[strLen-1] == '/' || fileName[strLen-1] == '\\'))
376 if(strLen > 0 && (fileName[strLen-1] == '/' || fileName[strLen-1] == '\\'))
378 if(notZeroLen /*&& fileName[strLen-1] != ':' && fileName[strLen-1] != '>'*/)
379 fileName[strLen++] = '/';
381 fileName[strLen] = '\0';
383 if(strLen + strlen(directory) > MAX_LOCATION - 3)
384 return null; // AN ERROR OCCURED!
386 strcat(fileName, directory);
389 if(isURL && ch == '/')
390 strcat(fileName, "/");
391 if(isURL && ch == '?')
393 strcat(fileName, addedPath+c);
398 sprintf(string, "<%s>%s", archiveName, fileName);
400 strcpy(string, fileName);
402 return modified ? string : null;
405 public char * PathCat(char * string, char * addedPath)
407 bool modified = false;
410 char fileName[MAX_LOCATION] = "", archiveName[MAX_LOCATION] = "", * file;
415 if(SplitArchivePath(string, archiveName, &file))
416 strcpy(fileName, file);
419 strcpy(fileName, string);
422 if(strstr(string, "http://") == string)
424 char * slash = strstr(fileName + 7, "/");
429 urlFileName = fileName + strlen(fileName);
431 if(strstr(addedPath, "http://") == addedPath)
433 strcpy(fileName, "http://");
437 else if(runtimePlatform == win32)
439 if(addedPath[0] && addedPath[1] == ':' && addedPath[0] != '<')
441 fileName[0] = (char)toupper(addedPath[0]);
447 else if(addedPath[0] == '\\' && addedPath[1] == '\\')
449 fileName[0] = fileName[1] = '\\';
454 // A drive needs to be selected
455 else if(fileName[0] == '/' && !archiveName[0] && strcmp(addedPath, "/"))
459 if(!modified && isURL && (addedPath[0] == '\\' || addedPath[0] == '/'))
461 urlFileName[0] = '/';
462 urlFileName[1] = '\0';
464 else if(!modified && (addedPath[0] == '\\' || addedPath[0] == '/'))
466 if(runtimePlatform == win32)
469 if(addedPath[0] == '/' && !addedPath[1])
471 fileName[0] = addedPath[0];
476 else if(fileName[0] && fileName[1] == ':')
481 // Relative path root of drive
498 for(; addedPath[c]; )
500 // DANGER OF OVERFLOW HERE
501 // char directory[MAX_FILENAME];
502 char directory[MAX_FILENAME * 16];
507 for(;(ch = addedPath[c]) && (ch == '/' || ch == '\\'); c++);
508 for(;(ch = addedPath[c]) && (ch != '/' && ch != '\\'); c++)
510 if(isURL && ch == '?')
514 if(len < MAX_FILENAME)
515 directory[len++] = ch;
517 directory[len] = '\0';
519 // Trim rightmost spaces
520 for(count = len-1; count >= 0 && (directory[count] == ' ' || directory[count] == '\t'); count--)
522 directory[count] = '\0';
529 if(strstr(directory, "..") == directory && (!directory[2] || directory[2] == DIR_SEP))
531 int strLen = strlen(fileName) - 1;
534 bool separator = false;
536 // Go back one directory
537 for(;(ch = fileName[strLen]) && strLen > -1 && (ch == '/' || ch == '\\'); strLen--);
538 for(;(ch = fileName[strLen]) && strLen > -1 && (ch != '/' && ch != '\\' && ch != ':'); strLen--);
539 for(;(ch = fileName[strLen]) && strLen > -1 && (ch == '/' || ch == '\\'); strLen--) separator = true;
543 strLen = Max(strLen, urlFileName - fileName);
545 if(!strcmp(fileName + strLen + (separator ? 2 : 1), ".."))
547 strcat(fileName, DIR_SEPS);
548 strcat(fileName, "..");
552 if(runtimePlatform == win32)
554 if(!strLen && fileName[0] == '\\' && fileName[1] == '\\')
566 fileName[strLen+1] = '\0';
570 fileName[strLen+1] = '\0';
582 strcpy(fileName, "..");
585 else if(strcmp(directory, "."))
587 int strLen = strlen(fileName);
588 bool notZeroLen = strLen > 0;
589 // if(strLen > 1 && (fileName[strLen-1] == '/' || fileName[strLen-1] == '\\'))
590 if(strLen > 0 && (fileName[strLen-1] == '/' || fileName[strLen-1] == '\\'))
592 if(notZeroLen /*&& fileName[strLen-1] != ':' && fileName[strLen-1] != '>'*/)
595 fileName[strLen++] = '/';
597 fileName[strLen++] = DIR_SEP;
600 fileName[strLen] = '\0';
602 if(strLen + strlen(directory) > MAX_LOCATION - 3)
603 return null; // AN ERROR OCCURED!
605 strcat(fileName, directory);
608 if(isURL && ch == '/')
609 strcat(fileName, "/");
610 if(isURL && ch == '?')
612 strcat(fileName, addedPath+c);
617 sprintf(string, "<%s>%s", archiveName, fileName);
619 strcpy(string, fileName);
621 return modified ? string : null;
624 public char * MakePathRelative(char * path, char * to, char * destination)
626 // Don't process empty paths
628 memmove(destination, path, strlen(path)+1);
631 // TOFIX: DANGER OF OVERFLOW HERE
632 char pathPart[MAX_FILENAME * 16], pathRest[MAX_LOCATION];
633 char toPart[MAX_FILENAME * 16], toRest[MAX_LOCATION];
634 bool different = false;
636 strcpy(pathRest, path);
639 destination[0] = '\0';
642 SplitDirectory(toRest, toPart, toRest);
644 SplitDirectory(pathRest, pathPart, pathRest);
646 if(different || fstrcmp(toPart, pathPart))
649 strcat(destination, "..");
650 strcat(destination, DIR_SEPS);
655 PathCat(destination, pathPart);
658 SplitDirectory(pathRest, pathPart, pathRest);
659 PathCat(destination, pathPart);
665 public bool StripExtension(char * string)
668 for(c = strlen(string); c>=0; c--)
674 else if(string[c] == '\\' || string[c] == '/')
679 public char * ChangeExtension(char * string, char * ext, char * output)
682 strcpy(output, string);
683 StripExtension(output);
690 // --- String Stuff (Temporarily outside String class) ---
691 public void PrintSize(char * string, uint size, int prec)
696 sprintf(format, "%%.0%df", prec);
697 if(size > 1024 * 1024 * 1024)
699 sprintf(string, format, size / (float)(1024 * 1024 * 1024));
700 strcat(string, " GB");
702 else if(size > 1024 * 1024)
704 sprintf(string, format, size / (float)(1024 * 1024));
705 strcat(string, " MB");
709 sprintf(string, format, size / (float)1024);
710 strcat(string, " KB");
714 sprintf(string, "%d B", size);
717 public void PrintBigSize(char * string, double size, int prec)
722 sprintf(format, "%%.0%df", prec);
723 if(size > 1024.0 * 1024.0 * 1024.0 * 1024.0)
725 sprintf(string, format, size / (1024 * 1024 * 1024.0 * 1024.0));
726 strcat(string, " TB");
728 else if(size > 1024.0 * 1024.0 * 1024.0)
730 sprintf(string, format, size / (1024.0 * 1024.0 * 1024.0));
731 strcat(string, " GB");
733 else if(size > 1024.0 * 1024.0)
735 sprintf(string, format, size / (1024.0 * 1024.0));
736 strcat(string, " MB");
740 sprintf(string, format, size / 1024.0);
741 strcat(string, " KB");
745 sprintf(string, "%.0f B", size);
748 public char * SearchString(char * buffer, int start, char * subStr, bool matchCase, bool matchWord)
753 char * strBuffer = buffer + start;
754 int subLen = strlen(subStr);
755 char beforeChar = start ? *(strBuffer-1) : 0;
756 int (*strcompare)(const char *, const char *, unsigned int) = matchCase ? strncmp : strnicmp;
758 for(ptr = strBuffer; *ptr; ptr++)
760 if(matchCase ? (*subStr == *ptr) : (tolower(*subStr) == tolower(*ptr)))
764 if(!strcompare(ptr,subStr,subLen) &&
766 !IS_ALUNDER(ptr[subLen]) &&
767 !IS_ALUNDER(beforeChar))
769 (!IS_ALUNDER(subStr[subLen-1]) || !IS_ALUNDER(ptr[subLen])) &&
770 (!IS_ALUNDER(subStr[0]) || !IS_ALUNDER(beforeChar)))
775 if(!strcompare(ptr,subStr,subLen))
785 public char * RSearchString(char * buffer, char * subStr, int maxLen, bool matchCase, bool matchWord)
789 int subLen = strlen(subStr);
790 char * ptr1 = buffer + maxLen - subLen;
791 char * ptr2 = buffer + maxLen - subLen - 1;
792 int (*strcompare)(const char *, const char *, unsigned int) = matchCase ? strncmp : strnicmp;
793 for(; ptr1 >=buffer; ptr1--, ptr2--)
795 if(tolower(*subStr) == tolower(*ptr1))
799 if(!strcompare(ptr1,subStr,subLen) &&
800 //!IS_ALUNDER(ptr1[subLen]) && !IS_ALUNDER(*ptr2))
801 (!IS_ALUNDER(subStr[subLen-1]) || !IS_ALUNDER(ptr1[subLen])) &&
802 (!IS_ALUNDER(subStr[0]) || !IS_ALUNDER(*ptr2)))
808 if(!strcompare(ptr1,subStr,subLen))
817 public int Tokenize(char * string, int maxTokens, char* tokens[], bool escapeBackSlashes)
822 bool escaped = false;
823 char * output = string;
825 for(; *string && count < maxTokens; string++, output++)
836 // ADDED THIS HERE...
840 else if(escapeBackSlashes && *string == '\\')
842 else if(*string == '\"')
851 memmove(start + 1, start, string - (char *)start);
855 else if(*string == ' ' && !quoted)
857 tokens[count++] = start;
862 else if(*string != ' ')
872 if(*string == '\\' && escapeBackSlashes)
877 if(start && count < maxTokens)
879 tokens[count++] = start;
885 public int TokenizeWith(char * string, int maxTokens, char* tokens[], char * tokenizers, bool escapeBackSlashes)
890 bool escaped = false;
891 char * output = string;
892 bool quotedFromStart = false;
894 for(; *string && count < maxTokens; string++, output++)
907 else if(escapeBackSlashes && *string == '\\')
909 else if(*string == '\"')
915 quotedFromStart = false;
921 else if(strchr(tokenizers, *string) && !quoted)
923 tokens[count++] = start;
927 // MOVED THIS INSIDE IF ABOVE...
928 //if(output != string)
929 // *output = *string;
931 else if(!strchr(tokenizers, *string))
935 quotedFromStart = true;
942 if(*string == '\\' && escapeBackSlashes)
947 if(start && count < maxTokens)
949 tokens[count++] = start;
955 public char * TrimLSpaces(char * string, char * output)
958 for(c = 0; string[c] && string[c] == ' '; c++);
959 memmove(output, string + c, strlen(string+c)+1);
963 public char * TrimRSpaces(char * string, char * output)
966 for(c = strlen(string)-1; c >= 0 && string[c] == ' '; c--);
969 memmove(output, string, c+1);
977 public void ChangeCh(char * string, char ch1, char ch2)
980 for(c=0; string[c]; c++)
981 if(string[c] == ch1) string[c] = ch2;
984 public void RepeatCh(char * string, int count, char ch)
987 for(c=0; c<count; c++)
992 public char * CopyString(char * string)
996 int len = strlen(string);
997 char * destination = new char[len+1];
999 memcpy(destination, string, len + 1);
1006 public bool GetString(char ** buffer, char * string, int max)
1010 bool quoted = false;
1012 if(!**buffer) { string[0]=0; return false; }
1016 if(!(ch = *((*buffer)++)))
1018 if( (ch!='\n') && (ch!='\r') && (ch!=' ') && (ch!=',') && (ch!='\t'))
1020 if(!*(*buffer)) break;
1024 for(c=0; c<max-1; c++)
1026 if(!quoted && ((ch=='\n')||(ch=='\r')||(ch==' ')||(ch==',')||(ch=='\t')))
1039 if(!(ch = *(*buffer)))
1052 public int GetValue(char ** buffer)
1055 GetString(buffer,string,20);
1056 return atoi(string);
1059 public uint GetHexValue(char ** buffer)
1062 GetString(buffer,string,20);
1063 return (uint)strtoul(string, null, 16);
1066 public char * StripQuotes(char * string, char * output)
1069 char * src = (string[0] == '\"') ? (string+1) : string;
1070 memmove(output, src, strlen(src)+1);
1071 len = strlen(output);
1072 if(len && output[len-1] == '\"')
1073 output[len-1] = '\0';
1077 public double FloatFromString(char * string)
1080 float dec = 0,res = 0;
1083 for(c = 0; string[c]; c++)
1086 if(ch == ' ') continue;
1089 if(neg == -1) break;
1092 else if((ch == '.') && !dec)
1094 else if(isdigit(ch))
1103 res = res * 10 + dig;
1111 public bool IsPathInsideOf(char * path, char * of)
1113 if(!path[0] || !of[0])
1114 return false; // What to do here? Ever used?
1117 char ofPart[MAX_FILENAME], ofRest[MAX_LOCATION];
1118 char pathPart[MAX_FILENAME], pathRest[MAX_LOCATION];
1120 strcpy(pathRest, path);
1121 for(; ofRest[0] && pathRest[0];)
1123 SplitDirectory(ofRest, ofPart, ofRest);
1124 SplitDirectory(pathRest, pathPart, pathRest);
1125 if(fstrcmp(pathPart, ofPart))
1128 if(!ofRest[0] && !pathRest[0]) // paths are identical - should return false or true? (changed to false)
1130 else if(!pathRest[0]) // not inside of, it's the other way around