8 #if !defined(ECERE_BOOTSTRAP) // quick fix for now
10 #define WIN32_LEAN_AND_MEAN
22 default extern Platform runtimePlatform;
24 #define IS_ALUNDER(ch) ((ch) == '_' || isalnum((ch)))
26 public define DIR_SEP = (GetRuntimePlatform() == win32) ? '\\' : '/';
27 public define DIR_SEPS = (GetRuntimePlatform() == win32) ? "\\" : "/";
29 // Maximum length for a vsprintf string
30 public define MAX_F_STRING = 1025;
32 // Maximum length for a directories and filenames strings
33 public define MAX_EXTENSION = 17; // 16 + \0
34 public define MAX_FILENAME = 274; // 256 chars + extension + dot + \0
35 public define MAX_DIRECTORY = 534; // 8 levels + 8 separators + \0
36 public define MAX_LOCATION = 797; // directory + filename + separator + \0
38 // --- File related String functions ---
39 public char * GetExtension(char * string, char * output)
42 int len = strlen(string);
43 int limit = Max(0, len-MAX_EXTENSION);
45 for(c = len; c>=limit; c--)
50 strcpy(output, string+c+1);
53 else if(ch == '/' || ch == '\\')
59 public char * StripLastDirectory(char * string, char * output)
62 if(runtimePlatform == win32 && !strcmp(string, "\\\\"))
69 int len = strlen(string);
70 for(c = len-2; c>=0; c--)
71 if(string[c] == '/' || string[c] == '\\')
73 else if(string[c] == '>' || (string[c] == ':' && c == 0))
79 if((runtimePlatform == win32) ? (c >= 0) : (c > 0))
81 strncpy(output, string, c);
84 if(runtimePlatform == win32 && c == 1 && output[0] == '\\' && output[1] == '\\')
90 strcpy(output, DIR_SEPS);
95 // Return root on UNIX instead of null...
98 strcpy(output, DIR_SEPS);
110 public char * SplitDirectory(const char * string, char * part, char * rest)
115 for(;(ch = string[c]) && (ch == '/' || ch == '\\'); c++);
118 part[len++] = DIR_SEP;
121 for(;(ch = string[c]) && (ch != '/' && ch != '\\'); c++)
123 if(len < MAX_FILENAME)
128 for(;(ch = string[c]) && (ch == '/' || ch == '\\'); c++);
129 strcpy(rest, string + c);
130 for(c = strlen(rest); c >= 0; c--)
131 if(ch != '/' && ch != '\\')
140 public char * GetLastDirectory(char * string, char * output)
143 int len = string ? strlen(string) : 0;
144 for(c = len-2; c>=0; c--)
145 if(string[c] == '/' || string[c] == '\\' || string[c] == ':' || string[c] == '>')
150 strcpy(output, string+c);
154 len = strlen(output);
155 if(len > 1 && (output[len-1] == '\\' || output[len-1] == '/'))
156 output[len-1] = '\0';
160 public bool SplitArchivePath(char * fileName, char * archiveName, char ** archiveFile)
163 if(fileName[0] == '<')
165 int c = strlen(fileName);
166 for(;c>0 && fileName[c] != '>'; c--);
169 strncpy(archiveName, fileName + 1, c - 1);
170 archiveName[c - 1] = '\0';
171 *archiveFile = fileName + c + 1;
175 else if(fileName[0] == ':')
177 strcpy(archiveName, ":");
178 *archiveFile = fileName + 1;
184 public char * PathCat(char * string, char * addedPath)
186 bool modified = false;
189 char fileName[MAX_LOCATION] = "", archiveName[MAX_LOCATION] = "", * file;
194 if(SplitArchivePath(string, archiveName, &file))
195 strcpy(fileName, file);
198 strcpy(fileName, string);
201 if(strstr(string, "http://") == string)
203 char * slash = strstr(fileName + 7, "/");
208 urlFileName = fileName + strlen(fileName);
210 if(strstr(addedPath, "http://") == addedPath)
212 strcpy(fileName, "http://");
216 else if(runtimePlatform == win32)
218 if(addedPath[0] && addedPath[1] == ':' && addedPath[0] != '<')
220 fileName[0] = (char)toupper(addedPath[0]);
226 else if(addedPath[0] == '\\' && addedPath[1] == '\\')
228 fileName[0] = fileName[1] = '\\';
233 // A drive needs to be selected
234 else if(fileName[0] == '/' && !archiveName[0] && strcmp(addedPath, "/"))
238 if(!modified && isURL && (addedPath[0] == '\\' || addedPath[0] == '/'))
240 urlFileName[0] = '/';
241 urlFileName[1] = '\0';
243 else if(!modified && (addedPath[0] == '\\' || addedPath[0] == '/'))
245 if(runtimePlatform == win32)
248 if(addedPath[0] == '/' && !addedPath[1])
250 fileName[0] = addedPath[0];
255 else if(fileName[0] && fileName[1] == ':')
260 // Relative path root of drive
277 for(; addedPath[c]; )
279 // DANGER OF OVERFLOW HERE
280 // char directory[MAX_FILENAME];
281 char directory[MAX_FILENAME * 16];
286 for(;(ch = addedPath[c]) && (ch == '/' || ch == '\\'); c++);
287 for(;(ch = addedPath[c]) && (ch != '/' && ch != '\\'); c++)
289 if(isURL && ch == '?')
293 if(len < MAX_FILENAME)
294 directory[len++] = ch;
296 directory[len] = '\0';
298 // Trim rightmost spaces
299 for(count = len-1; count >= 0 && (directory[count] == ' ' || directory[count] == '\t'); count--)
301 directory[count] = '\0';
308 if(strstr(directory, "..") == directory && (!directory[2] || directory[2] == DIR_SEP))
310 int strLen = strlen(fileName) - 1;
313 bool separator = false;
315 // Go back one directory
316 for(;(ch = fileName[strLen]) && strLen > -1 && (ch == '/' || ch == '\\'); strLen--);
317 for(;(ch = fileName[strLen]) && strLen > -1 && (ch != '/' && ch != '\\' && ch != ':'); strLen--);
318 for(;(ch = fileName[strLen]) && strLen > -1 && (ch == '/' || ch == '\\'); strLen--) separator = true;
322 strLen = Max(strLen, urlFileName - fileName);
324 if(!strcmp(fileName + strLen + (separator ? 2 : 1), ".."))
326 strcat(fileName, DIR_SEPS);
327 strcat(fileName, "..");
331 if(runtimePlatform == win32)
333 if(!strLen && fileName[0] == '\\' && fileName[1] == '\\')
345 fileName[strLen+1] = '\0';
349 fileName[strLen+1] = '\0';
361 strcpy(fileName, "..");
364 else if(strcmp(directory, "."))
366 int strLen = strlen(fileName);
367 bool notZeroLen = strLen > 0;
368 // if(strLen > 1 && (fileName[strLen-1] == '/' || fileName[strLen-1] == '\\'))
369 if(strLen > 0 && (fileName[strLen-1] == '/' || fileName[strLen-1] == '\\'))
371 if(notZeroLen /*&& fileName[strLen-1] != ':' && fileName[strLen-1] != '>'*/)
374 fileName[strLen++] = '/';
376 fileName[strLen++] = DIR_SEP;
379 fileName[strLen] = '\0';
381 if(strLen + strlen(directory) > MAX_LOCATION - 3)
382 return null; // AN ERROR OCCURED!
384 strcat(fileName, directory);
387 if(isURL && ch == '/')
388 strcat(fileName, "/");
389 if(isURL && ch == '?')
391 strcat(fileName, addedPath+c);
396 sprintf(string, "<%s>%s", archiveName, fileName);
398 strcpy(string, fileName);
400 return modified ? string : null;
403 public char * MakePathRelative(char * path, char * to, char * destination)
405 // Don't process empty paths
407 strcpy(destination, path);
410 // TOFIX: DANGER OF OVERFLOW HERE
411 char pathPart[MAX_FILENAME * 16], pathRest[MAX_LOCATION];
412 char toPart[MAX_FILENAME * 16], toRest[MAX_LOCATION];
413 bool different = false;
415 strcpy(pathRest, path);
418 destination[0] = '\0';
421 SplitDirectory(toRest, toPart, toRest);
423 SplitDirectory(pathRest, pathPart, pathRest);
425 if(different || fstrcmp(toPart, pathPart))
428 strcat(destination, "..");
429 strcat(destination, DIR_SEPS);
434 PathCat(destination, pathPart);
437 SplitDirectory(pathRest, pathPart, pathRest);
438 PathCat(destination, pathPart);
444 public bool StripExtension(char * string)
447 for(c = strlen(string); c>=0; c--)
453 else if(string[c] == '\\' || string[c] == '/')
458 public char * ChangeExtension(char * string, char * ext, char * output)
460 strcpy(output, string);
461 StripExtension(output);
468 // --- String Stuff (Temporarily outside String class) ---
469 public void PrintSize(char * string, uint size, int prec)
474 sprintf(format, "%%.0%df", prec);
475 if(size > 1024 * 1024 * 1024)
477 sprintf(string, format, size / (float)(1024 * 1024 * 1024));
478 strcat(string, " GB");
480 else if(size > 1024 * 1024)
482 sprintf(string, format, size / (float)(1024 * 1024));
483 strcat(string, " MB");
487 sprintf(string, format, size / (float)1024);
488 strcat(string, " KB");
492 sprintf(string, "%d B", size);
495 public void PrintBigSize(char * string, double size, int prec)
500 sprintf(format, "%%.0%df", prec);
501 if(size > 1024.0 * 1024.0 * 1024.0 * 1024.0)
503 sprintf(string, format, size / (1024 * 1024 * 1024.0 * 1024.0));
504 strcat(string, " TB");
506 else if(size > 1024.0 * 1024.0 * 1024.0)
508 sprintf(string, format, size / (1024.0 * 1024.0 * 1024.0));
509 strcat(string, " GB");
511 else if(size > 1024.0 * 1024.0)
513 sprintf(string, format, size / (1024.0 * 1024.0));
514 strcat(string, " MB");
518 sprintf(string, format, size / 1024.0);
519 strcat(string, " KB");
523 sprintf(string, "%.0f B", size);
526 public char * SearchString(char * buffer, int start, char * subStr, bool matchCase, bool matchWord)
531 char * strBuffer = buffer + start;
532 int subLen = strlen(subStr);
533 char beforeChar = start ? *(strBuffer-1) : 0;
534 int (*strcompare)(const char *, const char *, unsigned int) = matchCase ? strncmp : strnicmp;
536 for(ptr = strBuffer; *ptr; ptr++)
538 if(matchCase ? (*subStr == *ptr) : (tolower(*subStr) == tolower(*ptr)))
542 if(!strcompare(ptr,subStr,subLen) &&
544 !IS_ALUNDER(ptr[subLen]) &&
545 !IS_ALUNDER(beforeChar))
547 (!IS_ALUNDER(subStr[subLen-1]) || !IS_ALUNDER(ptr[subLen])) &&
548 (!IS_ALUNDER(subStr[0]) || !IS_ALUNDER(beforeChar)))
553 if(!strcompare(ptr,subStr,subLen))
563 public char * RSearchString(char * buffer, char * subStr, int maxLen, bool matchCase, bool matchWord)
567 int subLen = strlen(subStr);
568 char * ptr1 = buffer + maxLen - subLen;
569 char * ptr2 = buffer + maxLen - subLen - 1;
570 int (*strcompare)(const char *, const char *, unsigned int) = matchCase ? strncmp : strnicmp;
571 for(; ptr1 >=buffer; ptr1--, ptr2--)
573 if(tolower(*subStr) == tolower(*ptr1))
577 if(!strcompare(ptr1,subStr,subLen) &&
578 //!IS_ALUNDER(ptr1[subLen]) && !IS_ALUNDER(*ptr2))
579 (!IS_ALUNDER(subStr[subLen-1]) || !IS_ALUNDER(ptr1[subLen])) &&
580 (!IS_ALUNDER(subStr[0]) || !IS_ALUNDER(*ptr2)))
586 if(!strcompare(ptr1,subStr,subLen))
595 public int Tokenize(char * string, int maxTokens, char* tokens[], bool escapeBackSlashes)
600 bool escaped = false;
601 char * output = string;
603 for(; *string && count < maxTokens; string++, output++)
614 // ADDED THIS HERE...
618 else if(escapeBackSlashes && *string == '\\')
620 else if(*string == '\"')
629 memmove(start + 1, start, string - (char *)start);
633 else if(*string == ' ' && !quoted)
635 tokens[count++] = start;
640 else if(*string != ' ')
650 if(*string == '\\' && escapeBackSlashes)
655 if(start && count < maxTokens)
657 tokens[count++] = start;
663 public int TokenizeWith(char * string, int maxTokens, char* tokens[], char * tokenizers, bool escapeBackSlashes)
668 bool escaped = false;
669 char * output = string;
670 bool quotedFromStart = false;
672 for(; *string && count < maxTokens; string++, output++)
685 else if(escapeBackSlashes && *string == '\\')
687 else if(*string == '\"')
693 quotedFromStart = false;
699 else if(strchr(tokenizers, *string) && !quoted)
701 tokens[count++] = start;
705 // MOVED THIS INSIDE IF ABOVE...
706 //if(output != string)
707 // *output = *string;
709 else if(!strchr(tokenizers, *string))
713 quotedFromStart = true;
720 if(*string == '\\' && escapeBackSlashes)
725 if(start && count < maxTokens)
727 tokens[count++] = start;
733 public char * TrimLSpaces(char * string, char * output)
736 for(c = 0; string[c] && string[c] == ' '; c++);
737 strcpy(output, string + c);
741 public char * TrimRSpaces(char * string, char * output)
744 for(c = strlen(string)-1; c >= 0 && string[c] == ' '; c--);
747 memmove(output, string, c+1);
755 public void ChangeCh(char * string, char ch1, char ch2)
758 for(c=0; string[c]; c++)
759 if(string[c] == ch1) string[c] = ch2;
762 public void RepeatCh(char * string, int count, char ch)
765 for(c=0; c<count; c++)
770 public char * CopyString(char * string)
774 int len = strlen(string);
775 char * destination = new char[len+1];
777 memcpy(destination, string, len + 1);
784 public bool GetString(char ** buffer, char * string, int max)
790 if(!**buffer) { string[0]=0; return false; }
794 if(!(ch = *((*buffer)++)))
796 if( (ch!='\n') && (ch!='\r') && (ch!=' ') && (ch!=',') && (ch!='\t'))
798 if(!*(*buffer)) break;
802 for(c=0; c<max-1; c++)
804 if(!quoted && ((ch=='\n')||(ch=='\r')||(ch==' ')||(ch==',')||(ch=='\t')))
817 if(!(ch = *(*buffer)))
830 public int GetValue(char ** buffer)
833 GetString(buffer,string,20);
837 public uint GetHexValue(char ** buffer)
840 GetString(buffer,string,20);
841 return strtoul(string, null, 16);
844 public char * StripQuotes(char * string, char * output)
848 strcpy(output,(string[0] == '\"') ? (string+1) : string);
849 len = strlen(output);
850 if(len && output[len-1] == '\"')
851 output[len-1] = '\0';
855 public double FloatFromString(char * string)
858 float dec = 0,res = 0;
861 for(c = 0; string[c]; c++)
864 if(ch == ' ') continue;
870 else if((ch == '.') && !dec)
881 res = res * 10 + dig;
889 public bool GetAlNum(char ** buffer, char * string, int max)
894 if(!**buffer) { string[0]=0; return false; }
898 if(!(ch = *((*buffer)++)))
902 if(!*(*buffer)) break;
906 for(c=0; c<max-1; c++)
914 if(!(ch = *(*buffer)))