Program Listing for File FileUtility.h

Program Listing for File FileUtility.h#

Return to documentation for file (src/util/StringUtility/FileUtility.h)

#ifndef ROSE_FileUtility_H
#define ROSE_FileUtility_H

#include "commandline_processing.h"

namespace Rose {

// [Robb P Matzke 2016-06-16]: These file utilities were all originally part of StringUtility. I'm leaving them here for now
// just so I don't need to make so many changes to projects that use these, but you should expect these to be moved sometime in
// the future.
namespace StringUtility {


// This part of the StringUtility API deals with file names and should be moved to some other name space. In particular, it
// provides no definitions for "path", "filename", "extension", etc. and many of these functions won't work properly on a
// non-POSIX system. Therefore, consider using Rose::FileSystem, which is mostly a thin wrapper around std::filesystem. The
// std::filesystem documentation has good definitions for what the various terms should mean and works on non-POSIX file
// systems.


enum OSType {
    OS_TYPE_UNKNOWN,
    OS_TYPE_LINUX,
    OS_TYPE_OSX,
    OS_TYPE_WINDOWS,
    OS_TPYE_WINDOWSXP
};

struct StringWithLineNumber {
    std::string str;                                    // DQ (1/23/2010): this name is difficult to trace within the code.
    std::string filename;                               // Empty string means generated code
    unsigned int line;

    StringWithLineNumber(const std::string& str, const std::string& filename, unsigned int line)
        : str(str), filename(filename), line(line) {}

    ROSE_UTIL_API std::string toString() const;
};

typedef std::vector<StringWithLineNumber> FileWithLineNumbers;

ROSE_UTIL_API OSType getOSType();

ROSE_UTIL_API void writeFile(const std::string& outputString, const std::string& fileNameString,
                             const std::string& directoryName);

ROSE_UTIL_API std::string readFile(const std::string& fileName);

ROSE_UTIL_API FileWithLineNumbers readFileWithPos(const std::string& fileName);

ROSE_UTIL_API void homeDir(std::string& dir);

ROSE_UTIL_API std::string stripPathFromFileName(const std::string &fileNameWithPath);

ROSE_UTIL_API std::string getPathFromFileName(const std::string &fileNameWithPath);

ROSE_UTIL_API std::string stripFileSuffixFromFileName(const std::string & fileNameWithSuffix);

ROSE_UTIL_API std::string getAbsolutePathFromRelativePath(const std::string &relativePath, bool printErrorIfAny = false);

ROSE_UTIL_API std::string fileNameSuffix(const std::string &fileName);


// [Robb Matzke 2016-05-06]: I am deprecating "findfile" because:
//   1. It appears to not be used anywhere in ROSE, projects, tests, or documentation.
//   2. The name is spelled wrong (should be "findFile")
//   3. File operations should not be in StringUtility since they have nothing to do with string manipulation
//   4. Rose::FileSystem::findNames does something similar.

//ROSE_UTIL_API std::list<std::string> findfile(std::string patternString, std::string pathString)
    //SAWYER_DEPRECATED("use Rose::FileSystem functions instead"); // ROSE_DEPRECATED is not defined here

/* File name location.
 *
 * Files can be classified as being in one of three locations: We don't know if it's user or system It is a user (application)
 * file It is a system library This file does not exist */
enum FileNameLocation {
    FILENAME_LOCATION_UNKNOWN,
    FILENAME_LOCATION_USER,
    FILENAME_LOCATION_LIBRARY,
    FILENAME_LOCATION_NOT_EXIST
};

static const std::string FILENAME_LIBRARY_UNKNOWN = "Unknown";
static const std::string FILENAME_LIBRARY_USER = "User";
static const std::string FILENAME_LIBRARY_C = "C";
static const std::string FILENAME_LIBRARY_STDCXX = "C++";
static const std::string FILENAME_LIBRARY_STL = "STL";
static const std::string FILENAME_LIBRARY_LINUX = "Linux";
static const std::string FILENAME_LIBRARY_GCC = "GCC";
static const std::string FILENAME_LIBRARY_BOOST = "Boost";
static const std::string FILENAME_LIBRARY_ROSE = "Rose";

// CH (2/16/2010): Use this typedef to avoid following changes
typedef std::string FileNameLibrary;

/* This is the return type of classifyFileName, which provides all the details it infers */
class FileNameClassification {
private:
    FileNameLocation location;

    // CH (2/12/2010): Change 'library' type from enum to string to let user set it
    FileNameLibrary library;
    int distance;

public:
    FileNameClassification(FileNameLocation loc, const FileNameLibrary& lib, int dist)
        : location(loc), library(lib), distance(dist) {}

    FileNameClassification()
        : location(FILENAME_LOCATION_UNKNOWN), library("Unknown"), distance(0) {}

    /* Return the FileNameLocation which is described above with the definition of the enum */
    FileNameLocation getLocation() const {
        return location;
    }

    /* Return the FileNameLibrary which is described above with the definition of the enum */
    FileNameLibrary getLibrary() const {
        return library;
    }

    /* Return the "distance" of the filename from the appPath that was supplied during the call.  The distance is defined as
     * the number of cd's that only move up or down one directory that it would take to move from the directory of the filename
     * to the directory that was given by appPath.  This is intended as a heuristic to gage whether or not one believes that
     * the filename is related to the source (appPath) directory.  Examples:
     *
     * Between /a/b/c/file.h and /a/b/d/e/ the distance is 3 because one must cd ..; cd d; cd e; to get to appPath
     *
     * *EXCEPTION*: if the appPath is an ancestor of filename then the distance will be 0.  The idea being that this filename
     * is "in" the appPath somewhere and thus part of the application. */
    int getDistanceFromSourceDirectory() const {
        return distance;
    }

    bool isUserCode() const {
        return location == FILENAME_LOCATION_USER;
    }

    bool isLibraryCode() const {
        return location == FILENAME_LOCATION_LIBRARY;
    }

    /* Return a string name for the library indicated by getLibrary() */
    std::string getLibraryName() const {
        return library;
    }
};

ROSE_UTIL_API FileNameClassification classifyFileName(const std::string& fileName, const std::string& appPath);

ROSE_UTIL_API FileNameClassification classifyFileName(const std::string& fileName, const std::string& appPath, OSType os);

ROSE_UTIL_API FileNameClassification classifyFileName(const std::string& fileName, const std::string& appPath,
                                                      const std::map<std::string, std::string>& libPathCollection);

ROSE_UTIL_API FileNameClassification classifyFileName(const std::string& fileName, const std::string& appPath,
                                                      const std::map<std::string, std::string>& libPathCollection,
                                                      OSType os);

ROSE_UTIL_API const std::string stripDotsFromHeaderFileName(const std::string& name);

ROSE_UTIL_API int directoryDistance(const std::string& left, const std::string& right);

ROSE_UTIL_API std::vector<std::string> readWordsInFile(std::string filename);

// popen_wrapper is defined in sage_support.cpp

bool popen_wrapper(const std::string &command, std::vector<std::string> &result);

inline std::ostream& operator<<(std::ostream& os, const StringWithLineNumber& s) {
    os << s.toString();
    return os;
}

ROSE_UTIL_API std::string toString(const FileWithLineNumbers& strings, const std::string& filename = "<unknown>", int line = 1);

inline FileWithLineNumbers& operator+=(FileWithLineNumbers& a, const FileWithLineNumbers& b) {
    a.insert(a.end(), b.begin(), b.end());
    return a;
}

inline FileWithLineNumbers operator+(const FileWithLineNumbers& a, const FileWithLineNumbers& b) {
    FileWithLineNumbers f = a;
    f += b;
    return f;
}

inline FileWithLineNumbers& operator<<(FileWithLineNumbers& f, const std::string& str) {
    if (!f.empty() && f.back().filename == "") {
        f.back().str += str;
    } else {
        f.push_back(StringWithLineNumber(str, "", 1));
    }
    return f;
}

inline FileWithLineNumbers& operator<<(FileWithLineNumbers& f, const char* str) {
    f << std::string(str);
    return f;
}
ROSE_UTIL_API std::string copyEdit(const std::string& inputString, const std::string & oldToken, const std::string & newToken);
ROSE_UTIL_API FileWithLineNumbers copyEdit(const FileWithLineNumbers& inputString, const std::string& oldToken,
                                           const std::string& newToken);
ROSE_UTIL_API FileWithLineNumbers copyEdit(const FileWithLineNumbers& inputString, const std::string& oldToken,
                                           const FileWithLineNumbers& newToken);
} // namespace
} // namespace

#endif