(file) Return to Files.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / utils / mu

File: [Pegasus] / pegasus / src / utils / mu / Files.cpp (download)
Revision: 1.1.1.1 (vendor branch), Sun Jan 14 19:54:07 2001 UTC (23 years, 5 months ago) by mike
Branch: pegasus
CVS Tags: version_0_8, stable, opengroup
Changes since 1.1: +0 -0 lines
Pegasus import

#include "Config.h"
#include <iostream>
#include <fstream>
#include <cstdio>
#include <cstring>
#include "Files.h"

static void _SplitPath(const string& path, vector<string>& components)
{
    char* tmp = new char[path.size() + 1];
    strcpy(tmp, path.c_str());

    if (path[0] == '/')
	components.push_back("/");

    for (char* p = strtok(tmp, "/"); p != NULL; p = strtok(NULL, "/"))
	components.push_back(p);

    // Fixup the drive letter:

    if (components.size() > 1)
    {
	string s = components[0];

	if (s.size() == 2 && isalpha(s[0]) && s[1] == ':')
	{
	    components[0] += "/" + components[1];
	    components.erase(components.begin() + 1, components.begin() + 2);
	}
    }

    delete [] tmp;
}

// string.find_last_of() is broken in GNU C++.

static inline size_t _find_last_of(const string& str, char c)
{
    const char* p = strrchr(str.c_str(), c);

    if (p)
	return size_t(p - str.c_str());
    
    return (size_t)-1;
}

void _SplitPath(
    const string& path, 
    string& dirname, 
    string& basename)
{
    size_t pos = _find_last_of(path, '/');

    if (pos == (size_t)-1)
    {
	dirname = ".";
	basename = path;
    }
    else
    {
	dirname = path.substr(0, pos);
	basename = path.substr(pos + 1);
    }
}

bool RemoveFile(const string& path, bool recurse)
{
    if (!IsDir(path))
	return RemoveFile(path);

    if (!recurse)
	return RemoveDir(path);

    vector<string> filenames;

    if (GetDirEntries(path, filenames))
    {
	string save_cwd;
	GetCwd(save_cwd);

	if (!ChangeDir(path))
	    return false;

	for (size_t i = 0; i < filenames.size(); i++)
	    RemoveFile(filenames[i], true);

	if (!ChangeDir(save_cwd))
	    return false;
    }

    return RemoveDir(path);
}

bool MkDirHier(const string& path)
{
    vector<string> components;

    _SplitPath(path, components);

    for (size_t i = 0; i < components.size(); i++)
    {
	if (!IsDir(components[i]))
	{
	    if (!MakeDir(components[i].c_str()))
		return false;
	}

	if (!ChangeDir(components[i]))
	    return false;
    }

    return true;
}


/*
 *----------------------------------------------------------------------
 *
 * Tcl_StringMatch --
 *
 *	See if a particular string MatchStringes a particular pattern.
 *
 * Results:
 *	The return value is 1 if string MatchStringes pattern, and
 *	0 otherwise.  The MatchStringing operation permits the following
 *	special characters in the pattern: *?\[] (see the manual
 *	entry for details on what these mean).
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int _Tcl_StringMatch(
    char *string,		/* String. */
    char *pattern)		/* Pattern, which may contain special
				 * characters. */
{
    char c2;

    while (1) {
	/* See if we're at the end of both the pattern and the string.
	 * If so, we succeeded.  If we're at the end of the pattern
	 * but not at the end of the string, we failed.
	 */
	
	if (*pattern == 0) {
	    if (*string == 0) {
		return 1;
	    } else {
		return 0;
	    }
	}
	if ((*string == 0) && (*pattern != '*')) {
	    return 0;
	}

	/* Check for a "*" as the next pattern character.  It MatchStringes
	 * any substring.  We handle this by calling ourselves
	 * recursively for each postfix of string, until either we
	 * MatchString or we reach the end of the string.
	 */
	
	if (*pattern == '*') {
	    pattern += 1;
	    if (*pattern == 0) {
		return 1;
	    }
	    while (1) {
		if (_Tcl_StringMatch(string, pattern)) {
		    return 1;
		}
		if (*string == 0) {
		    return 0;
		}
		string += 1;
	    }
	}
    
	/* Check for a "?" as the next pattern character.  It MatchStringes
	 * any single character.
	 */

	if (*pattern == '?') {
	    goto thisCharOK;
	}

	/* Check for a "[" as the next pattern character.  It is followed
	 * by a list of characters that are acceptable, or by a range
	 * (two characters separated by "-").
	 */
	
	if (*pattern == '[') {
	    pattern += 1;
	    while (1) {
		if ((*pattern == ']') || (*pattern == 0)) {
		    return 0;
		}
		if (*pattern == *string) {
		    break;
		}
		if (pattern[1] == '-') {
		    c2 = pattern[2];
		    if (c2 == 0) {
			return 0;
		    }
		    if ((*pattern <= *string) && (c2 >= *string)) {
			break;
		    }
		    if ((*pattern >= *string) && (c2 <= *string)) {
			break;
		    }
		    pattern += 2;
		}
		pattern += 1;
	    }
	    while (*pattern != ']') {
		if (*pattern == 0) {
		    pattern--;
		    break;
		}
		pattern += 1;
	    }
	    goto thisCharOK;
	}
    
	/* If the next pattern character is '/', just strip off the '/'
	 * so we do exact MatchStringing on the character that follows.
	 */
	
	if (*pattern == '\\') {
	    pattern += 1;
	    if (*pattern == 0) {
		return 0;
	    }
	}

	/* There's no special character.  Just make sure that the next
	 * characters of each string MatchString.
	 */
	
	if (*pattern != *string) {
	    return 0;
	}

	thisCharOK: pattern += 1;
	string += 1;
    }
}

inline bool MatchString(const string& pattern, const string& str)
{
    return _Tcl_StringMatch((char*)str.c_str(), (char*)pattern.c_str()) != 0;
}

static bool _contains_special_chars(const string& str)
{
    const char* p = str.c_str();

    return 
	strchr(p, '[') || strchr(p, ']') || strchr(p, '*') || strchr(p, '?');
}

bool Glob(const string& pattern_, vector<string>& filenames_out)
{
    // Remove trailing slashes:

    string pattern = pattern_;

    while (pattern.size() > 0 && pattern[pattern.size()-1] == '/')
	pattern.erase(pattern.begin() + pattern.size() - 1);

    // Split the pattern into directory name and base name:

    string dirname;
    string basename;
    _SplitPath(pattern, dirname, basename);

    if (!_contains_special_chars(basename))
	filenames_out.push_back(pattern_);
    else
    {
	// Find all files in the given directory MatchStringing the pattern:

	bool found = false;
	vector<string> filenames;

	if (!GetDirEntries(dirname, filenames))
	    return false;

	for (size_t i = 0; i < filenames.size(); i++)
	{
	    if (MatchString(basename, filenames[i]))
	    {
		found = true;

		if (dirname == ".")
		    filenames_out.push_back(filenames[i]);
		else
		    filenames_out.push_back(dirname + "/" + filenames[i]);
	    }
	}

	if (!found)
	    return false;
    }

    return true;
}

bool CopyFile(const string& from_file, const string& to_file)
{
    // Open input file:

#ifdef OS_TYPE_WINDOWS
    ifstream is(from_file.c_str(), ios::binary);
#else
    ifstream is(from_file.c_str());
#endif

    if (!is)
	return false;

    // Open output file:

#ifdef OS_TYPE_WINDOWS
    ofstream os(to_file.c_str(), ios::binary);
#else
    ofstream os(to_file.c_str());
#endif

    if (!os)
	return false;

    // ATTN: optimize this for speed! Use block-oriented copy approach.
    // Copy the blocks:

    char c;

    while (is.get(c))
	os.put(c);

    return true;
}

bool CopyFiles(const vector<string>& from, const string& to)
{
    // There are two cases. If there is more than one from file, then the
    // to argument must designate a directory. If there is exactly one from
    // file then the to may designate either the destination directory or
    // the new file name.

    if (from.size() > 1)
    {
	if (!IsDir(to))
	    return false;

	bool success = true;

	for (size_t i = 0; i < from.size(); i++)
	{
	    string dirname;
	    string basename;
	    _SplitPath(from[i], dirname, basename);

	    if (!CopyFile(from[i], to + "/" + basename))
		success = false;
	}

	return success;
    }
    else if (from.size() == 1)
    {
	if (IsDir(to))
	{
	    string dirname;
	    string basename;
	    _SplitPath(from[0], dirname, basename);

	    return CopyFile(from[0], to + "/" + basename);
	}
	else
	    return CopyFile(from[0], to);
    }
    else
	return false;
}

bool CompareFiles(
    const string& filename1, 
    const string& filename2, 
    size_t& offset)
{
#ifdef OS_TYPE_WINDOWS
    ifstream is1(filename1.c_str(), ios::binary);
#else
    ifstream is1(filename1.c_str());
#endif

    if (!is1)
	return false;

#ifdef OS_TYPE_WINDOWS
    ifstream is2(filename2.c_str(), ios::binary);
#else
    ifstream is2(filename2.c_str());
#endif

    if (!is2)
	return false;

    char c1;
    char c2;
    offset = 0;

    for (;;)
    {
	bool more1 = is1.get(c1) ? true : false;
	bool more2 = is2.get(c2) ? true : false;

	if (!more1 || !more2)
	    return more1 == more2;

	offset++;

	if (c1 != c2)
	    return false;
    }

    return true;
}

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2