Frost Moon Project

Src/sslib/Path.cpp -MagicPNG Ver.1.00- - Frost Moon Project   アクセスランキング  

Home > ソフトウェア > MagicPNG > MagicPNG100.zip > Src > sslib > Path.cpp

 
//Path.cpp
//パス操作関数

#include"../StdAfx.h"
#include"sslib.h"
#include<mbstring.h>
#include<vector>
#include<algorithm>

namespace sslib{
namespace path{

namespace{
    int isNumbersOrSymbols(int c){
        return str::isSymbol(c)||isdigit(c);
    }

    int isSpacesOrDots(int c){
        return c==' '||c=='.';
    }

    static const TCHAR long_path_prefix[]=_T("\\\\?\\");
    bool hasLongPathPrefix(const tstring& file_path){
        return file_path.substr(0,ARRAY_SIZEOF(long_path_prefix)-1)==long_path_prefix;
    }
}

//スペースが含まれていれば'"'で囲む
tstring quote(const tstring& file_path){
    return (str::containsWhiteSpace(file_path))?
        _T("\"")+file_path+_T("\""):
        file_path;
}

//MAX_PATHを超えるパスの為の接頭辞'\\?\'を追加
tstring addLongPathPrefix(const tstring& file_path){
    if(file_path.size()>MAX_PATH&&
       !hasLongPathPrefix(file_path)){
        return long_path_prefix+file_path;
    }else{
        return file_path;
    }
}

//MAX_PATHを超えるパスの為の接頭辞'\\?\'を削除
tstring removeLongPathPrefix(const tstring& file_path){
    if(hasLongPathPrefix(file_path)){
        return file_path.substr(ARRAY_SIZEOF(long_path_prefix)-1);
    }else{
        return file_path;
    }
}

#ifndef DISABLE_FILE_SEARCH
//ディレクトリを再帰的に検索してlistに追加
void recursiveSearch(std::list<tstring>* path_list,const TCHAR* search_dir,const TCHAR* wildcard,bool include_dir){
    if(path_list==NULL)return;

    FileSearch fs;

    for(fs.first(addLongPathPrefix(search_dir).c_str(),wildcard);!IS_TERMINATED&&fs.next();){
        if(!fs.hasAttribute(FILE_ATTRIBUTE_DIRECTORY)){
            //ファイル
            path_list->push_back(removeLongPathPrefix(fs.filepath()));
        }else{
            if(include_dir)path_list->push_back(removeLongPathPrefix(fs.filepath()));
            //サブディレクトリを検索
            recursiveSearch(path_list,fs.filepath().c_str(),wildcard,include_dir);
        }
    }
    return;
}
#endif

//ファイル名に使えない文字が含まれるかどうか
bool isBadName(const TCHAR* file_name){
    if(str::locateLastCharacter(file_name,'\\')!=-1||
       str::locateLastCharacter(file_name,'/')!=-1||
       str::locateLastCharacter(file_name,':')!=-1||
//      str::locateLastCharacter(file_name,',')!=-1||
//      str::locateLastCharacter(file_name,';')!=-1||
       str::locateLastCharacter(file_name,'*')!=-1||
       str::locateLastCharacter(file_name,'?')!=-1||
       str::locateLastCharacter(file_name,'\"')!=-1||
       str::locateLastCharacter(file_name,'<')!=-1||
       str::locateLastCharacter(file_name,'>')!=-1||
       str::locateLastCharacter(file_name,'|')!=-1)return true;
    else return false;
}

//末尾にスラッシュ/バックスラッシュを追加
tstring addTailSlash(const tstring& file_path){
    int slash_pos=-1;
    bool is_slash=false;

    if(file_path.empty())return file_path;

    slash_pos=str::locateLastCharacter(file_path.c_str(),'\\');
    if(slash_pos==-1){
        if((slash_pos=str::locateLastCharacter(file_path.c_str(),'/'))!=-1){
            is_slash=true;
        }
    }
    if(slash_pos==2&&file_path[2]==':'&&file_path[3]=='\0'){//file_path==ルート
        return file_path;
    }else{
        int last_slash_pos=file_path.size()-1;
        if(slash_pos!=last_slash_pos){
            return file_path+((is_slash)?_T("/"):_T("\\"));
        }
    }
    return file_path;
}

//末尾のスラッシュ/バックスラッシュを削除
tstring removeTailSlash(const tstring& file_path){
    int slash_pos=-1;

    if(file_path.empty())return file_path;

    slash_pos=str::locateLastCharacter(file_path.c_str(),'\\');
    if(slash_pos==-1){
        slash_pos=str::locateLastCharacter(file_path.c_str(),'/');
    }
    if(slash_pos==2&&file_path[2]==':'&&file_path[4]=='\0'){//file_path==ルート
        return file_path;
    }else{
        int last_slash_pos=file_path.size()-1;

        if(slash_pos==last_slash_pos){
            return file_path.substr(0,slash_pos);
        }
    }
    return file_path;
}

//カレントディレクトリを取得
tstring getCurrentDirectory(){
    std::vector<TCHAR> buffer(::GetCurrentDirectory(0,NULL));

    ::GetCurrentDirectory(buffer.size(),&buffer[0]);
    return &buffer[0];
}

//親ディレクトリを取得
//foo\bar\baz->foo\bar
//C:\foo\bar\baz->C:\foo\bar
//foo\->foo
tstring getParentDirectory(const tstring& file_path_orig){
    int slash_pos=-1;

    if(file_path_orig.empty())return file_path_orig;

    tstring file_path(removeTailSlash(file_path_orig));

    slash_pos=str::locateLastCharacter(file_path.c_str(),'\\');
    if(slash_pos==-1)slash_pos=str::locateLastCharacter(file_path.c_str(),'/');
    if(slash_pos==-1||
       (file_path[1]==':'&&slash_pos==2&&file_path[3]=='\0')){//区切り文字が含まれないかルート
        return file_path;
    }else{
        if(file_path[1]==':'&&slash_pos==2&&file_path[3]!='\0'){//C:\foo
            ++slash_pos;
        }
        return file_path.substr(0,slash_pos);
    }
}

//ルートディレクトリを取得
//foo\bar\baz->foo
/*C:\foo\bar->C:\*/
//foo\->foo
tstring getRootDirectory(const tstring& file_path){
    int slash_pos=-1;

    if(file_path.empty())return file_path;

    slash_pos=str::locateLastCharacter(file_path.c_str(),'\\');
    if(slash_pos==-1)slash_pos=str::locateLastCharacter(file_path.c_str(),'/');
    if(slash_pos==-1||
       (file_path[1]==':'&&slash_pos==2&&file_path[3]=='\0')){
        //区切り文字が含まれないかルート
        return file_path;
    }else{
        slash_pos=str::locateFirstCharacter(file_path.c_str(),'\\');
        if(slash_pos==-1)slash_pos=str::locateFirstCharacter(file_path.c_str(),'/');
        if(slash_pos==2&&file_path[2]==':'&&file_path[3]!='\0'){//C:\foo\*
            ++slash_pos;
        }
        return file_path.substr(0,slash_pos);
    }
}

//ルートディレクトリを削除
tstring removeRootDirectory(const tstring& file_path){
    int slash_pos=-1;

    if(file_path.empty())return file_path;

    slash_pos=str::locateLastCharacter(file_path.c_str(),'\\');
    if(slash_pos==-1)slash_pos=str::locateLastCharacter(file_path.c_str(),'/');
    if(slash_pos==-1||
       (file_path[1]==':'&&slash_pos==2&&file_path[3]=='\0')){
        //区切り文字が含まれないかルート
        return _T("");
    }else{
        slash_pos=str::locateFirstCharacter(file_path.c_str(),'\\');
        if(slash_pos==-1)slash_pos=str::locateFirstCharacter(file_path.c_str(),'/');
        if(slash_pos==2&&file_path[2]==':'&&file_path[3]!='\0'){//C:\foo\*
            ++slash_pos;
        }
        return file_path.substr(slash_pos+1);
    }
}

//実行ファイル名を取得
tstring getExeName(){
    std::vector<TCHAR> buffer(MAX_PATH);

    if(::GetModuleFileName(NULL,&buffer[0],buffer.size())){
        return &buffer[0];
    }
    return _T("");
}

//実行ファイルのディレクトリを取得
//C:\foo\bar\baz.exe->C:\foo\bar
tstring getExeDirectory(){
    std::vector<TCHAR> buffer(MAX_PATH);

    if(::GetModuleFileName(NULL,&buffer[0],buffer.size())){
        return getParentDirectory(&buffer[0]);
    }
    return _T("");
}

//ファイル名を取得
tstring getFileName(const tstring& file_path_orig){
    int slash_pos=-1;

    if(file_path_orig.empty())return file_path_orig;

    tstring file_path(removeTailSlash(file_path_orig));

    slash_pos=str::locateLastCharacter(file_path.c_str(),'\\');
    if(slash_pos==-1)slash_pos=str::locateLastCharacter(file_path.c_str(),'/');
    if(slash_pos==-1||
       (file_path[1]==':'&&slash_pos==2&&file_path[3]=='\0')){
        //区切り文字が含まれないかルート
        return file_path;
    }else{
        return file_path.substr(slash_pos+1);
    }
}

//拡張子を削除
tstring removeExtension(const tstring& file_path){
    int dot_pos=-1;

    if(file_path.empty())return file_path;

    dot_pos=str::locateLastCharacter(file_path.c_str(),'.');
    if(dot_pos!=-1){
        return file_path.substr(0,dot_pos);
    }
    return file_path;
}

//拡張子を取得
tstring getExtension(const tstring& file_path){
    int dot_pos=-1;

    if(file_path.empty())return file_path;

    tstring file_name=getFileName(file_path);

    dot_pos=str::locateLastCharacter(file_name.c_str(),'.');
    if(dot_pos!=-1){
        return file_name.substr(dot_pos+1);
    }
    return file_path;
}

//短いファイル名を取得
tstring getShortPathName(const TCHAR* file_path){
    if(!fileExists(file_path))return _T("");

    std::vector<TCHAR> buffer(::GetShortPathName(path::addLongPathPrefix(file_path).c_str(),NULL,0));

    ::GetShortPathName(path::addLongPathPrefix(file_path).c_str(),&buffer[0],buffer.size());
    return path::removeLongPathPrefix(&buffer[0]);
}

//長いファイル名を取得
tstring getLongPathName(const TCHAR* file_path){
    if(!fileExists(file_path))return _T("");

    std::vector<TCHAR> buffer(::GetLongPathName(path::addLongPathPrefix(file_path).c_str(),NULL,0));

    ::GetLongPathName(path::addLongPathPrefix(file_path).c_str(),&buffer[0],buffer.size());
    return path::removeLongPathPrefix(&buffer[0]);
}

//二重引用符を取り除く
tstring removeQuotation(const tstring& file_path){
    if(file_path.empty())return file_path;

    return file_path.substr((file_path.find_first_of('\"')==0)?1:0,
                            (file_path.find_last_of('\"')==file_path.length()-1)?file_path.length()-2:tstring::npos);
}

//末尾の条件に合致する文字を削除
tstring removeLastCharacters(const tstring& file_path,int(*check)(int c)){
    for(int i=file_path.length()-1;i!=-1;--i){
#ifndef UNICODE
        if(::IsDBCSLeadByte(file_path.c_str()[i])){
            --i;
            continue;
        }
#endif

        if(!check(file_path.c_str()[i])){
#ifndef UNICODE
            if(::IsDBCSLeadByte(file_path.c_str()[i])){
                ++i;
            }
#endif
            return file_path.substr(0,++i);
        }
    }
    return file_path;
}

//末尾の記号を削除
tstring removeLastSymbols(const tstring& file_path){
    return removeLastCharacters(file_path,str::isSymbol);
}

//末尾の数字を削除
tstring removeLastNumbers(const tstring& file_path){
    return removeLastCharacters(file_path,isdigit);
}

//末尾の数字と記号を削除
tstring removeLastNumbersAndSymbols(const tstring& file_path){
    return removeLastCharacters(file_path,isNumbersOrSymbols);
}

//末尾のスペースとドットを削除
tstring removeSpacesAndDots(const tstring& file_path){
    return removeLastCharacters(file_path,isSpacesOrDots);
}

//一時ディレクトリのパスを取得(末尾に\有り)
tstring getTempDirPath(){
    std::vector<TCHAR> buffer(::GetTempPath(0,NULL));

    ::GetTempPath(buffer.size(),&buffer[0]);
    return getLongPathName(&buffer[0]);
}

//相対パスを取得する
//注意:ディレクトリの場合末尾に区切り文字が追加される
tstring makeRelativePath(const TCHAR* base_path_orig,DWORD base_path_attr,const TCHAR* file_path_orig,DWORD file_path_attr){
    tstring relative_path;
    tstring base_path;
    tstring file_path;
    tstring::size_type delimiter_pos;

    if(base_path_orig==NULL||file_path_orig==NULL)return _T("");

    tstring base_path_bak(base_path_orig);
    tstring file_path_bak(file_path_orig);

    //ディレクトリのパスの末尾に区切り文字を追加
    if(base_path_attr&FILE_ATTRIBUTE_DIRECTORY){
        base_path_bak=addTailSlash(base_path_bak);
    }

    if(file_path_attr&FILE_ATTRIBUTE_DIRECTORY){
        file_path_bak=addTailSlash(file_path_bak);
    }

    base_path=base_path_bak;
    file_path=file_path_bak;
    if(base_path.length()==0||file_path.length()==0)return file_path;

    int base_path_delimiter=guessDelimiter(base_path.c_str());

    delimiter_pos=base_path.rfind(base_path_delimiter);
    if(delimiter_pos==tstring::npos){
        return _T("");
    }

    if(!(base_path_attr&FILE_ATTRIBUTE_DIRECTORY)){
        base_path=base_path.substr(0,delimiter_pos);
    }

    int file_path_delimiter=guessDelimiter(file_path.c_str());;

    delimiter_pos=file_path.rfind(file_path_delimiter);
    if(delimiter_pos==tstring::npos){
        return _T("");
    }

    if(!(file_path_attr&FILE_ATTRIBUTE_DIRECTORY)){
        file_path=file_path.substr(0,delimiter_pos);
    }

    if(base_path_delimiter!=file_path_delimiter){
        //双方の区切り文字が異なる場合、base_path_delimiterに統一する
        str::replaceCharacter(file_path,file_path_delimiter,base_path_delimiter);
    }

    if(base_path.length()==0||file_path.length()==0)return _T("");

    if(file_path.find(base_path,0)==0){
        return file_path_bak.substr(base_path.length());
    }

    //以下、'..'を用いてディレクトリの移動が必要なパス
    while(1){
        if(base_path.find(file_path)==0){
            relative_path=file_path_bak.substr(file_path.length()+1);

            base_path=base_path_bak.substr(file_path.length()+1);
            int delimiter_count=str::countCharacter(base_path.c_str(),base_path_delimiter);

            for(int i=0;i<delimiter_count;i++){
                relative_path=((base_path_delimiter=='\\')?_T("..\\"):_T("../"))+relative_path;
            }
            return relative_path;
        }

        delimiter_pos=file_path.rfind(base_path_delimiter);
        if(delimiter_pos==tstring::npos)break;
        file_path=file_path.substr(0,delimiter_pos);
    }
    return _T("");
}

//ルートであるか否か
bool isRoot(const TCHAR* file_path){
    switch(lstrlen(file_path)){
        case 1:
            //区切り文字単体
            if((file_path[0]=='\\'||file_path[0]=='/')&&file_path[1]=='\0')return true;
            else return false;
            break;

        case 3:
            //ルート(X:\)
            if(file_path[1]==':'&&(file_path[2]=='\\'||file_path[2]=='/')&&file_path[3]=='\0')return true;
            else return false;
            break;

        default:
            if(str::countCharacter(file_path,'\\')<3){
                if(str::countCharacter(file_path,'/')<3)return false;
            }
            //UNCパス
            if((file_path[0]=='\\'&&file_path[1]=='\\'&&file_path[2]!='\\')||
               (file_path[0]=='/'&&file_path[1]=='/'&&file_path[2]!='/'))return true;
            else return false;
            break;
    }
}

//絶対パスであるか否か
bool isAbsolutePath(const TCHAR* file_path){
    return static_cast<bool>(file_path[0]&&file_path[1]&&file_path[2]&&file_path[1]==':'&&(file_path[2]=='\\'||file_path[2]=='/'));
}

//相対パスであるか否か
bool isRelativePath(const TCHAR* file_path){
    if(file_path[0]=='.'){
        //'.\\'or'..\\'
        if(file_path[1]=='\\'||
           (file_path[1]=='.'&&file_path[2]=='\\'))return true;
    }
    return false;
}

//ディレクトリであるか否か
bool isDirectory(const TCHAR* file_path){
    return file_path&&
        fileExists(file_path)&&
            (::GetFileAttributes(addLongPathPrefix(file_path).c_str())&FILE_ATTRIBUTE_DIRECTORY)!=0;
}

//ファイルが存在するか否か
bool fileExists(const TCHAR* file_path){
    return file_path&&(::GetFileAttributes(addLongPathPrefix(file_path).c_str())!=0xffffffff);
}

#ifndef DISABLE_FILE_SEARCH
//空のディレクトリである
bool isEmptyDirectory(const TCHAR* dir_path){

    if(dir_path==NULL)return false;
    if(!isDirectory(dir_path))return false;

    FileSearch fs;
    fs.first(dir_path);

    return fs.next()==NULL;
}
#endif

//フルパスを取得(存在する保証は無し)
bool getFullPath(TCHAR* full_path,unsigned int buffer_size,const TCHAR*relative_path,const TCHAR*base_dir){
    bool result=false;
    tstring cur_dir;

    if(base_dir){
        cur_dir=getCurrentDirectory();
        //勿論base_dirが存在することが条件
        ::SetCurrentDirectory(base_dir);
    }
    result=::GetFullPathName(relative_path,buffer_size,full_path,NULL)!=0;

    if(base_dir)::SetCurrentDirectory(cur_dir.c_str());
    return result;
}

//ワイルドカードを含むパスである
bool containsWildcard(const TCHAR* file_path){
    return (str::locateLastCharacter(file_path,'*')!=-1||str::locateLastCharacter(file_path,'?')!=-1);
}

//分割ファイル名の拡張子を作成
tstring createPartExtension(long count,int digit){
    tstring ext;

    int max_number=0;
    long max_alphabet=1;

    //'999'や'99999'など数字のみで構成される拡張子のmaxを作成
    for(int i=0;i<digit;i++){
        int temp=9;
        for(int ii=0;ii<i;ii++)temp*=10;
        max_number+=temp;
    }

    //アルファベットのみで構成される拡張子の総数を計算
    for(int i=0;i<digit;i++)max_alphabet*=26;

    if(count<=max_number){
        //'*'を使用すると桁数を変数から指定できる
        ext=format(_T("%0*ld"),digit,count);
    }else if(count<=max_number+max_alphabet){
        long i=count-(max_number+1);

        ext.substr(0,digit);
        for(long ii=digit-1;;ii--){
            ext[ii]=i%26+'a';
            if(ii>0)i/=26;
            else break;
        }
    }
    return ext;
}

//namespace path
}
//namespace sslib
}


Home > ソフトウェア > MagicPNG > MagicPNG100.zip > Src > sslib > Path.cpp