ctr_Repair/trunk/CardSaveData/common/savefile/savefile.cpp

302 lines
8.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//共通関数
#include "savefile.h"
//終端から前方検索で見つかった境界("/"=0x2f)位置を返す
//top :検索範囲の先頭指定
int GetPosDelmLast(wchar_t *s,int top)
{
size_t i = wcslen(s);
if (i <= top)return 0;
i--;
while(i > top-1){
if (s[i]==L'/')return i;
i--;
}
return 0;
}
//パス結合
void ChainPath(wchar_t *p1,wchar_t *p2)
{
int n=wcslen(p1);
if ((p1[n-1] == L'/') && (p2[0] == L'/')) p1[n-1] = 0;
if ((p1[wcslen(p1)-1] != L'/') && (p2[0] != L'/')) wcscat(p1,L"/");
wcscat(p1,p2);
}
//パス名チェック for SD
//fs関数で引数エラー(INVALID_ARGUMENT)にならないものをチェック
bool CheckPath(wchar_t *s)
{
int i;
size_t n = wcslen(s);
if ((n > 253) || (n==0))return false;
if (n>251)
{//ディレクトリオープン時は251まで
if ((s[251]==L'/') || (s[252]==L'/'))return false;
}
for (i =0;i< n-1;i++)
{
if ((s[i-1] == ' ')||(s[i+1] == ' '))return false;//厳密にはスラッシュ前後と最後尾
if ((s[i-1] == 0x5c) ||(s[i+1] == 0x5c))return false;//0x5c = 円マーク
}
return true;
}
//-------------- Class SaveFileWrite
//ディレクトリ作成ありのオープン
bool SaveFileWrite::OpenC(wchar_t *path,s64 size,bool *mkdir)
{
int pos,pos2;
wcscpy(pathw_w,root_w);
ChainPath(pathw_w,path);
*mkdir = false;
LastNnResult = nn::fs::TryCreateFile(pathw_w,size);
if(LastNnResult.IsSuccess())
{
LastNnResult = writer.TryInitialize(pathw_w,false);
return LastNnResult.IsSuccess();
}
//ディレクトリがなければディレクトリを作成
pos = GetPosDelmLast(pathw_w,RootLength);//ファイルが存在するディレクトリ
if (pos <= 0)return false;//rootかパスが不正
wcscpy(pathw_w2,pathw_w);//ワークにコピー
while (LastNnResult.IsFailure()){//ディレクトリ作成できるまで遡る
if(nn::fs::ResultNotFound::Includes(LastNnResult)==false)return false;
pos2 = GetPosDelmLast(pathw_w2,RootLength);//境界位置を探す
if (pos2 == 0)return false;//root到達
pathw_w2[pos2] = 0;//境界まで削除 (例) dir1/dir2/file -> dir1/dir2 -> dir1
LastNnResult = nn::fs::TryCreateDirectory(pathw_w2);
}
//作成ディレクトリ多いと画面止まるので、作成ごとに抜ける
*mkdir = true; // 帰値false で mkdir=true ならディレクトリ作成のみ
return false;
}
//ディレクトリ作成なしオープン、存在する場合は追記
bool SaveFileWrite::OpenAdd(wchar_t *path)
{
wcscpy(pathw_w,root_w);
ChainPath(pathw_w,path);
LastNnResult = writer.TryInitialize(pathw_w,false);
if (LastNnResult.IsSuccess()){
LastNnResult = writer.TrySeek(0,nn::fs::POSITION_BASE_END);//追記
}else LastNnResult = writer.TryInitialize(pathw_w,true);//新規
if (LastNnResult.IsFailure())
{
writer.Finalize();
return false;
}
return true;
}
//ディレクトリ作成なしオープン
bool SaveFileWrite::OpenW(const wchar_t *path)
{
wcscpy(pathw_w,root_w);
ChainPath(pathw_w,(wchar_t*)path);
LastNnResult = writer.TryInitialize(pathw_w,true);
return LastNnResult.IsSuccess();
}
//クローズ
void SaveFileWrite::CloseW()
{
writer.Finalize();
}
s32 SaveFileWrite::Write(char *buffer,size_t size)
{
s32 ct;
LastNnResult = writer.TryWrite(&ct,(void*)buffer,size);
if(LastNnResult.IsFailure()){NN_LOG("write fail\n");ct=0;}
return ct;
}
//ディレクトリ作成
bool SaveFileWrite::CreateDir(const wchar_t *dir)
{
LastNnResult = nn::fs::TryCreateDirectory(dir);
if(LastNnResult.IsSuccess())return true;
return nn::fs::ResultAlreadyExists::Includes(LastNnResult);
}
//削除
bool SaveFileWrite::DeleteDir(const wchar_t *dir)
{
LastNnResult = nn::fs::TryDeleteDirectoryRecursively(dir);
return LastNnResult.IsSuccess();
}
//------------------------------------------------------ Class SaveFileRead
bool SaveFileRead::Open(const wchar_t *path)
{
wcscpy(pathw_w,root_w);
ChainPath(pathw_w,(wchar_t*)path);
LastNnResult = reader.TryInitialize(pathw_w);
if (LastNnResult.IsSuccess())
{
LastNnResult = reader.TryGetSize(&FileSize);
if (LastNnResult.IsSuccess())return true;
else Close();
}
return false;
}
void SaveFileRead::Close()
{
reader.Finalize();
}
//ファイルリード
s32 SaveFileRead::Read(char *buffer,size_t size)
{
s32 ct;
LastNnResult = reader.TryRead(&ct,(void*)buffer,size);
if(LastNnResult.IsFailure())ct=0;
return ct;
}
//存在チェック
myResult SaveFileRead::IsExist(){
myResult res;
res = Mount();
Unmount();
return res;
}
void SaveFileRead::ResetPath()
{
s_lv=0;
s_serch = false;
wcscpy(path_w,root_w);
wcscat(path_w,L"/");
for (int n = 0;n<MAX_LEVEL;n++)dc_readed[n] = 0;
}
myResult SaveFileRead::GetPath(wchar_t *path)
{
static nn::fs::DirectoryEntry dcEntryl;
static nn::fs::Directory dcl;
int n,ct;
while(1){
LastNnResult = dcl.TryInitialize(path_w);//Open
if (LastNnResult.IsFailure())return RESULT_FAIL;
if (dc_readed[s_lv] != 0)for(n=0;n<dc_readed[s_lv];n++)dcl.Read(&dcEntryl,1);
n = (dcl.Read(&dcEntryl,1));
dc_readed[s_lv]++;
dcl.Finalize();
if ( n==0 )//終端
{
if (s_lv == 0){path[0]=0;return RESULT_OK;}// ---- rootなら終了
dc_readed[s_lv]=0;
s_lv--;//上の層に戻る
wcscpy(path_w,pathu_w[s_lv]);//パス戻す
}else{
if(dcEntryl.attributes.isDirectory){//ディレクトリ
wcscpy(pathu_w[s_lv],path_w);//パス保存
wcscat(path_w,dcEntryl.entryName);//次のディレクトリパス
wcscat(path_w,L"/");
if (++s_lv == MAX_LEVEL)return RESULT_DIR_LEVEL_OVER;
}else{//ファイル
wcscpy(path,pPathTop);
ct =wcslen(path) + wcslen(dcEntryl.entryName);
if (ct>MAX_PATH_LENGTH - 1)return RESULT_PATH_LENGTH_OVER;
wcscat(path,dcEntryl.entryName);
return RESULT_OK;
}
}
}
}
//アーカイブ情報の取得
bool SaveFileRead::GetInfo(tArcInfo *pinfo,size_t clsz)
{
static nn::fs::DirectoryEntry dcEntryl;
static nn::fs::Directory dcl;
if(IsMounted==false){NN_LOG("GetInfo: Not Mounted\n");return false;};
s_lv=0;
m_info.DirCount = 0;
m_info.FileCount = 0;
m_info.DirEntry = 0;
m_info.FileEntry = 0;
m_info.total = 0;
m_info.Dup = false;
wcscpy(pathw_w,root_w);
wcscat(pathw_w,L"/");
int n;
int lv = 0;
for (n = 0;n<MAX_LEVEL;n++)dc_readed[n] = 0;
bool cont = true;
size_t sn;
while(cont){
LastNnResult = dcl.TryInitialize(pathw_w);//Open
if (LastNnResult.IsFailure())return false;
if (dc_readed[lv] != 0)for(n=0;n<dc_readed[lv];n++)dcl.Read(&dcEntryl,1);
while(1){
n = (dcl.Read(&dcEntryl,1));
dc_readed[lv]++;
if ( n==0 )//終端
{
if (lv == 0){cont=false;break;}// ---- 終了
dc_readed[lv]=0;
lv--;//上の層に戻る
wcscpy(pathw_w,pathu_w[lv]);//パス戻す
break;
}else{
if(dcEntryl.attributes.isDirectory){//ディレクトリ
m_info.DirCount++;
if (clsz>0)m_info.total +=clsz;//SD..ディレクトリでクラスタ分取る
wcscpy(pathu_w[lv],pathw_w);//パス保存
wcscat(pathw_w,dcEntryl.entryName);//次のディレクトリパス
wcscat(pathw_w,L"/");
if (++lv == MAX_LEVEL)return false;
break;
}else{//ファイル
m_info.FileCount++;
if (clsz==0){
m_info.total += dcEntryl.entrySize;
}else{//クラスタサイズで調整 .. SD占有容量
sn = dcEntryl.entrySize / clsz;
if ((dcEntryl.entrySize % clsz) > 0 )sn++;
m_info.total += sn*clsz;
}
}
}
}
dcl.Finalize();
}
for (n = 0;n<MAX_LEVEL;n++)dc_readed[n] = 0;
Unmount();//GetCtrCardSaveDataFormatInfo内でマウントするので一旦アンマウント(SDK2.13のみエラー)
GetFormatInfoCore(&m_info);
Mount();
*pinfo = m_info;
return true;
}