wip II
[sdk] / ecere / src / com / String.ec
index a5efa25..a7314b2 100644 (file)
@@ -1,6 +1,8 @@
 namespace sys;
 
+#define set _set
 #define uint _uint
+#define strlen _strlen
 
 default:
 
@@ -9,13 +11,17 @@ default:
 #if !defined(ECERE_BOOTSTRAP) // quick fix for now
 #if defined(__WIN32__)
 #define WIN32_LEAN_AND_MEAN
+#define String _String
 #include <windows.h>
+#undef String
 #else
 #include <unistd.h>
 #endif
 #endif
 
 #undef uint
+#undef set
+#undef strlen
 private:
 
 import "instance"
@@ -27,7 +33,7 @@ default extern Platform runtimePlatform;
 public define DIR_SEP   = (GetRuntimePlatform() == win32) ? '\\' : '/';
 public define DIR_SEPS  = (GetRuntimePlatform() == win32) ? "\\" : "/";
 
-// Maximum length for a vsprintf string
+// Maximum length for a vsnprintf string
 public define MAX_F_STRING = 1025;
 
 // Maximum length for a directories and filenames strings
@@ -79,7 +85,7 @@ public char * StripLastDirectory(char * string, char * output)
 
       if((runtimePlatform == win32) ? (c >= 0) : (c > 0))
       {
-         strncpy(output, string, c);
+         memmove(output, string, c);
          if(c > 0)
          {
             if(runtimePlatform == win32 && c == 1 && output[0] == '\\' && output[1] == '\\')
@@ -127,7 +133,7 @@ public char * SplitDirectory(const char * string, char * part, char * rest)
    }
 
    for(;(ch = string[c]) && (ch == '/' || ch == '\\'); c++);
-   strcpy(rest, string + c);
+   memmove(rest, string + c, strlen(string + c) + 1);
    for(c = strlen(rest); c >= 0; c--)
       if(ch != '/' && ch != '\\') 
          break;
@@ -148,7 +154,7 @@ public char * GetLastDirectory(char * string, char * output)
 
    c++;
    if(c >= 0)
-      strcpy(output, string+c);
+      memmove(output, string+c, strlen(string+c)+1);
    else
       output[0] = '\0';
 
@@ -187,32 +193,37 @@ public char * PathCatSlash(char * string, char * addedPath)
    bool modified = false;
    if(addedPath)
    {
-      char fileName[MAX_LOCATION] = "", archiveName[MAX_LOCATION] = "", * file;
+      char fileName[MAX_LOCATION] = "", archiveName[MAX_LOCATION] = "", * file = null;
       int c = 0;
       bool isURL = false;
+      bool isArchive = SplitArchivePath(string, archiveName, &file);
       char * urlFileName;
+      char * protocolSymbol;
 
-      if(SplitArchivePath(string, archiveName, &file))
-         strcpy(fileName, file);
-      else
-      {
-         strcpy(fileName, string);
-      }
+      strcpy(fileName, isArchive ? file : string);
 
-      if(strstr(string, "http://") == string)
+      if(!isArchive) // TODO: Support for PathCat'ing .. outside of archive
       {
-         char * slash = strstr(fileName + 7, "/");
-         isURL = true;
-         if(slash)
-            urlFileName = slash;
-         else
-            urlFileName = fileName + strlen(fileName);
+         protocolSymbol = (fileName[0] && fileName[0] != '.' && fileName[0] != '/' && fileName[0] != '\\' && fileName[1] != ':') ? strstr(fileName, "://") : null;
+         if(protocolSymbol)
+         {
+            char * slash = strstr(protocolSymbol + 3, "/");
+            isURL = true;
+            if(slash)
+               urlFileName = slash;
+            else
+               urlFileName = fileName + strlen(fileName);
+         }
       }
-      if(strstr(addedPath, "http://") == addedPath)
+
+      protocolSymbol = (addedPath[0] && addedPath[0] != '.' && addedPath[0] != '/' && addedPath[0] != '\\' && addedPath[1] != ':') ? strstr(addedPath, "://") : null;
+      if(protocolSymbol)
       {
-         strcpy(fileName, "http://");
+         int len = protocolSymbol - addedPath + 3;
+         memcpy(fileName, addedPath, len);
+         fileName[len] = 0;
          isURL = true;
-         c = 7;
+         c = len;
       }
       else if(GetRuntimePlatform() == win32)
       {
@@ -401,32 +412,37 @@ public char * PathCat(char * string, char * addedPath)
    bool modified = false;
    if(addedPath)
    {
-      char fileName[MAX_LOCATION] = "", archiveName[MAX_LOCATION] = "", * file;
+      char fileName[MAX_LOCATION] = "", archiveName[MAX_LOCATION] = "", * file = null;
       int c = 0;
       bool isURL = false;
+      bool isArchive = SplitArchivePath(string, archiveName, &file);
       char * urlFileName;
+      char * protocolSymbol;
 
-      if(SplitArchivePath(string, archiveName, &file))
-         strcpy(fileName, file);
-      else
-      {
-         strcpy(fileName, string);
-      }
+      strcpy(fileName, isArchive ? file : string);
 
-      if(strstr(string, "http://") == string)
+      if(!isArchive) // TODO: Support for PathCat'ing .. outside of archive
       {
-         char * slash = strstr(fileName + 7, "/");
-         isURL = true;
-         if(slash)
-            urlFileName = slash;
-         else
-            urlFileName = fileName + strlen(fileName);
+         protocolSymbol = (fileName[0] && fileName[0] != '.' && fileName[0] != '/' && fileName[0] != '\\' && fileName[1] != ':') ? strstr(fileName, "://") : null;
+         if(protocolSymbol)
+         {
+            char * slash = strstr(protocolSymbol + 3, "/");
+            isURL = true;
+            if(slash)
+               urlFileName = slash;
+            else
+               urlFileName = fileName + strlen(fileName);
+         }
       }
-      if(strstr(addedPath, "http://") == addedPath)
+
+      protocolSymbol = (addedPath[0] && addedPath[0] != '.' && addedPath[0] != '/' && addedPath[0] != '\\' && addedPath[1] != ':') ? strstr(addedPath, "://") : null;
+      if(protocolSymbol)
       {
-         strcpy(fileName, "http://");
+         int len = protocolSymbol - addedPath + 3;
+         memcpy(fileName, addedPath, len);
+         fileName[len] = 0;
          isURL = true;
-         c = 7;
+         c = len;
       }
       else if(runtimePlatform == win32)
       {
@@ -617,9 +633,10 @@ public char * PathCat(char * string, char * addedPath)
 
 public char * MakePathRelative(char * path, char * to, char * destination)
 {
+   int len;
    // Don't process empty paths
    if(!path[0])
-      strcpy(destination, path);
+      memmove(destination, path, strlen(path)+1);
    else
    {
       // TOFIX: DANGER OF OVERFLOW HERE
@@ -653,6 +670,9 @@ public char * MakePathRelative(char * path, char * to, char * destination)
          PathCat(destination, pathPart);
       }
    }
+   len = strlen(destination);
+   if(len>1 && (destination[len-1] == '/' || destination[len-1] == '\\'))
+      destination[--len] = '\0';
    return destination;
 }
 
@@ -672,7 +692,8 @@ public bool StripExtension(char * string)
 
 public char * ChangeExtension(char * string, char * ext, char * output)
 {
-   strcpy(output, string);
+   if(string != output)
+      strcpy(output, string);
    StripExtension(output);
    if(ext[0])
       strcat(output, ".");
@@ -807,65 +828,66 @@ public char * RSearchString(char * buffer, char * subStr, int maxLen, bool match
    return null;
 }
 
-public int Tokenize(char * string, int maxTokens, char* tokens[], bool escapeBackSlashes)
+//public define gnuMakeCharsNeedEscaping = "$%";
+//public define windowsFileNameCharsNotAllowed = "*/:<>?\\\"|";
+//public define linuxFileNameCharsNotAllowed = "/";
+//public define windowsFileNameCharsNeedEscaping = " !%&'()+,;=[]^`{}~"; // "#$-.@_" are ok
+//public define linuxFileNameCharsNeedEscaping = " !\"$&'()*:;<=>?[\\`{|"; // "#%+,-.@]^_}~" are ok
+
+// fix #139 to remove " = 2" and warnings for backward compatible calls to Tokenize using 'true' for the 'esc' argument;
+public enum BackSlashEscaping : bool { forArgsPassing = 2 };
+public int Tokenize(char * string, int maxTokens, char* tokens[], BackSlashEscaping esc)
 {
+#ifdef __WIN32__
+//define windowsFileNameCharsNeedEscaping = " !%&'()+,;=[]^`{}~"; // "#$-.@_" are ok
+   const char * escChars = " !\"%&'()+,;=[]^`{}~"; // windowsFileNameCharsNeedEscaping;
+   const char * escCharsQuoted = "\"";
+#else
+//define linuxFileNameCharsNeedEscaping = " !\"$&'()*:;<=>?[\\`{|"; // "#%+,-.@]^_}~" are ok
+   const char * escChars = " !\"$&'()*:;<=>?[\\`{|"; // linuxFileNameCharsNeedEscaping;
+   const char * escCharsQuoted = "\"()$";
+#endif
    int count = 0;
-   bool quoted = false;
-   byte * start = null;
-   bool escaped = false;
-   char * output = string;
-
-   for(; *string && count < maxTokens; string++, output++)
+   bool quoted = false, escaped = false;
+   char * start = null, * output = string;
+   char ch;
+   for(; (ch = *string) && count<maxTokens; string++, output++)
    {
+      bool wasEscaped = escaped;
       if(output != string)
-         *output = *string;
+         *output = ch;
       if(start)
       {
          if(escaped)
          {
             escaped = false;
             output--;
-
-            // ADDED THIS HERE...
-            if(output != string)
-               *output = *string;
+            *output = ch;
          }
-         else if(escapeBackSlashes && *string == '\\')
-            escaped = true;
-         else if(*string == '\"')
+         else if(ch == '\"')
          {
-            if(quoted)
-            {
-               *output = '\0';
-               quoted = false;
-            }
-            else
-            {
-               memmove(start + 1, start, string - (char *)start);
-               start++;
-            }
+            quoted ^= true;
+            output--;
          }
-         else if(*string == ' ' && !quoted)
+         else if(ch == ' ' && !quoted)
          {
             tokens[count++] = start;
             *output = '\0';
             start = null;
          }
       }
-      else if(*string != ' ')
+      else if(ch != ' ')
       {
-         if(*string == '\"')
+         if(ch == '\"')
          {
             quoted = true;
-            start = output + 1;
+            start = output+1;
          }
          else
-         {
             start = output;
-            if(*string == '\\' && escapeBackSlashes)
-               escaped = true;
-         }
       }
+      if(!wasEscaped && ch == '\\' && ( esc == true || (esc == forArgsPassing && strchr(quoted ? escCharsQuoted : escChars, *(string+1))) ))
+         escaped = true;
    }
    if(start && count < maxTokens)
    {
@@ -949,7 +971,7 @@ public char * TrimLSpaces(char * string, char * output)
 {
    int c;
    for(c = 0; string[c] && string[c] == ' '; c++);
-   strcpy(output, string + c);
+   memmove(output, string + c, strlen(string+c)+1);
    return output;
 }
 
@@ -1053,14 +1075,14 @@ public uint GetHexValue(char ** buffer)
 {
    char string[20];
    GetString(buffer,string,20);
-   return strtoul(string, null, 16);
+   return (uint)strtoul(string, null, 16);
 }
 
 public char * StripQuotes(char * string, char * output)
 {
    int len;
-
-   strcpy(output,(string[0] == '\"') ? (string+1) : string);
+   char * src = (string[0] == '\"') ? (string+1) : string;
+   memmove(output, src, strlen(src)+1);
    len = strlen(output);
    if(len && output[len-1] == '\"')
       output[len-1] = '\0';
@@ -1100,3 +1122,28 @@ public double FloatFromString(char * string)
    }
    return neg * res;
 }
+
+public bool IsPathInsideOf(char * path, char * of)
+{
+   if(!path[0] || !of[0])
+      return false;  // What to do here? Ever used?
+   else
+   {
+      char ofPart[MAX_FILENAME], ofRest[MAX_LOCATION];
+      char pathPart[MAX_FILENAME], pathRest[MAX_LOCATION];
+      strcpy(ofRest, of);
+      strcpy(pathRest, path);
+      for(; ofRest[0] && pathRest[0];)
+      {
+         SplitDirectory(ofRest, ofPart, ofRest);
+         SplitDirectory(pathRest, pathPart, pathRest);
+         if(fstrcmp(pathPart, ofPart))
+            return false;
+      }
+      if(!ofRest[0] && !pathRest[0])  // paths are identical - should return false or true? (changed to false)
+         return false;
+      else if(!pathRest[0])           // not inside of, it's the other way around
+         return false;
+      return true;
+   }
+}