示例#1
0
bool vfeParsePathString (const UCS2String& path, UCS2String& volume, vector<UCS2String>& components, UCS2String& filename)
{
    UCS2String q;

    if(path.empty() == true)
        return true;

    if(path[0] == '/')
        volume = '/';

    for(size_t i = 0; i < path.length(); ++i)
    {
        if(path[i] == '/')
        {
            if(q.empty() == false)
                components.push_back(q);
            q.clear();
        }
        else
            q += path[i];
    }

    filename = q;

    return true;
}
示例#2
0
UCS2String TemporaryFile::SuggestName()
{
    POV_ASSERT(!gTempPath.empty());

    // TODO FIXME - This allows only one temporary file per process!
    // TODO FIXME - Avoid converting back and forth between UCS-2 and system-specific encoding.
    char str [POV_FILENAME_BUFFER_CHARS + 1] = "";
    std::snprintf(str, POV_FILENAME_BUFFER_CHARS + 1, "%spov%d", UCS2toSysString(gTempPath).c_str(), int(getpid()));
    return SysToUCS2String(str);
}
示例#3
0
  bool vfeParsePathString (const UCS2String& path, UCS2String& volume, vector<UCS2String>& components, UCS2String& filename)
  {
    char str [MAX_PATH * 4] ;

    volume.clear() ;
    filename.clear() ;
    components.clear() ;

    if (path.empty() == true)
      return (true);
    if (path.size () >= sizeof (str))
      return (false) ;
    strcpy (str, UCS2toASCIIString (path).c_str ()) ;
    char lastch = str[strlen(str) - 1];

    // now determine if it's a network or drive path.
    // (we could use the shlwapi functions here but I'd rather avoid the shlwapi.dll dependency).
    char *p2 = str ;
    char *p3 ;
    if ((strlen (str) > 1) && ((str [1] == ':') || (str[0] == '\\' && str[1] == '\\') || (str[0] == '/' && str[1] == '/')))
    {
      if (str [1] == ':')
      {
        // if it's a drive reference the first character must be in range 'a' - 'z'
        if (!isalpha (str[0]))
          return (false) ;

        // currently we don't support relative paths if a volume is specified
        if ((str [2] != '\\') && (str [2] != '/'))
          return (false) ;
        volume = ASCIItoUCS2String (string (str).substr (0, 3).c_str()) ;
        p2 += 3 ;
      }
      else
      {
        // it's a UNC path ... look for the next separator
        p2 = strchr (str + 2, '\\');
        p3 = strchr (str + 2, '/');
        if ((p3 != NULL) && ((p2 == NULL) || (p2-str) > (p3-str)))
            p2 = p3;
        if (p2 == NULL)
        {
          // no separator; technically this is valid, but it's a relative reference
          // and as above we don't currently support this.
          return (false) ;
        }
        volume = ASCIItoUCS2String (string (str).substr (0, (size_t) (++p2 - str)).c_str()) ;
      }
    }
    else if ((str [0] == '\\') || (str [0] == '/'))
    {
      // it's a path relative to the root of the current drive.
      // we will use '\' as the volume name.
      // for volume-relative paths we also accept '/' as a path separator
      volume = ASCIItoUCS2String("\\");
      p2++;
    }

    // p2 now points at the start of any path or file components
    // the first call to strtok will skip over any extra separators
    // at the start of the path
    for (char *p1 = strtok (p2, "\\/"); p1 != NULL; p1 = strtok (NULL, "/\\"))
    {
      if (*p1 == '\0')
        continue;
      if (p1[0] == '.' && p1[1] == '\0')
        continue;
      if (p1[0] == '.' && p1[1] == '.' && p1[2] == '\0')
      {
        // it's a relative directory reference ... see if we can pop a
        // path from components; if not we leave it in there since it
        // is permitted to refer to a directory above the CWD
        if ((components.empty() == false) && (components.back() != ASCIItoUCS2String("..")))
        {
          components.pop_back();
          continue;
        }
      }
      components.push_back (ASCIItoUCS2String (p1)) ;
    }

    // the filename, if present, will be the last entry in components.
    // we first check the last character of the supplied path to see
    // if it's a path separator char; if it is there's no filename.
    if (lastch == '\\' || lastch == '/')
      return true;

    if (components.empty() == false)
    {
      filename = components.back();
      components.pop_back();
    }

    return true ;
  }
示例#4
0
bool Path::ParsePathString (UCS2String& volume, vector<UCS2String>& dirnames, UCS2String& filename, const UCS2String& path)
{
    UCS2String stash;

    // Unless noted otherwise, all components are considered empty.
    volume.clear();
    dirnames.clear();
    filename.clear();

    // Empty strings are considered valid path names, too.
    if (path.empty() == true)
        return true;

    UCS2String::const_iterator i = path.begin();

    // Check for a volume identifier:
    // - If the second character is a colon, we presume the first two characters to identify the drive. In that case
    //   we'll also check whether the following character is a path separator, indicating an absolute path on that
    //   drive, in which case we'll also include a trailing separator to the drive letter.
    // - If the path starts with two identical path separator characters, we presume the string to be a UNC path, in
    //   which case we set the volume identifier to the network share, including two leading and a trailing separator
    //   characters.
    // - Otherwise, if the first character is a path separator, this indicates an absolute path on the current drive,
    //   in which case we set the volume identifier to a single path separator character.
    // - In any other case, we presume the string to be a relative path, and set the volume identifier to an empty
    //   string.

    if ((*i == POV_PATH_SEPARATOR) || (*i == POV_PATH_SEPARATOR_2))
    {
        // String starts with a path separator; may be an absolute path on the current drive or a UNC path.

        // Stash the separator (use the canonical one, not the one actually used).
        stash += POV_PATH_SEPARATOR;
        ++i;

        if ((i != path.end()) && (*i == stash[0]))
        {
            // The second character is also an (identical) separator character, indicating a UNC path.

            // Stash another path separators (use the canonical one, not the one actually used).
            stash += POV_PATH_SEPARATOR;
            ++i;

            // Stash everything that follows, up to the next path separator.
            for (; (i != path.end()) && (*i != POV_PATH_SEPARATOR) && (*i != POV_PATH_SEPARATOR_2); ++i)
                stash += *i;

            // Currently, we don't support bare UNC share names without trailing separator character,
            // even though allegedly they are technically valid.
            if (i == path.end())
                return false;

            // Stash another path separator (use the canonical one, not the one actually used)
            // to indicate an absolute path.
            stash += POV_PATH_SEPARATOR;
            ++i;
        }
        // If it's not a UNC path, at this point our stash contains a single path separator,
        // which is exactly what we intend to emit as the volume identifier in that case.

        // Emit whatever string we have stashed as the volume identifier.
        volume = stash;
        stash.clear();
    }
    else if (isalpha (*i))
    {
        // String starts with an ASCII letter; may be a relative path or a drive letter.

        // Stash the character, then go on to test what's next.
        stash += *i;
        ++i;

        if ((i != path.end()) && (*i == ':'))
        {
            // Yup, that's a drive letter. Add the colon to the stashed letter.
            stash += ':';
            ++i;

            // Currently, we don't support relative paths if a volume is specified.
            if ((i == path.end()) || ((*i != POV_PATH_SEPARATOR) && (*i != POV_PATH_SEPARATOR_2)))
                return false;

            // Stash another path separator (use the canonical one, not the one actually used)
            // to indicate an absolute path.
            stash += POV_PATH_SEPARATOR;
            ++i;

            // Emit the stashed string as the volume identifier.
            volume = stash;
            stash.clear();
        }
        // If it's not a drive letter, at this point we have only stashed the first letter, but
        // our index still points to the second one so the following algorithm will take care of it.
    }

    // Walk through the path string, stashing any non-separator characters. Whenever we hit a separator
    // character, emit the stashed characters (if any) as a directory name and clear the stash.
    // Also, as we go along, resolve the special directory names `.` and `..` if possible.

    // NB since we do not emit "empty" directory names, any sequence of consecutive separator
    // characters is effectively treated as a single separator character.

    for(; i != path.end(); ++i)
    {
        if ((*i == POV_PATH_SEPARATOR) || (*i == POV_PATH_SEPARATOR_2))
        {
            if (!stash.empty() && !IsCurrentDir(stash))
            {
                if (!dirnames.empty() && IsParentDir(stash))
                    dirnames.pop_back();
                else
                    dirnames.push_back (stash);
                stash.clear();
            }
        }
        else
            stash += *i;
    }

    // Whatever is left in the stash is presumably the actual file name.

    // NB as a consequence of the algorithm chosen, any path name ending in a path separator
    // character will be emitted as a list of directories only, with the file name left empty.

    filename = stash;

    return true;
}