| [404] | 1 | /*!
 | 
|---|
 | 2 | @file   Classes/System/IO/Path.ab
 | 
|---|
 | 3 | @brief  ファイルパス文字列を操作する
 | 
|---|
 | 4 | @author OverTaker
 | 
|---|
 | 5 | */
 | 
|---|
| [142] | 6 | 
 | 
|---|
 | 7 | #require <Classes/System/Environment.ab>
 | 
|---|
 | 8 | 
 | 
|---|
| [271] | 9 | Namespace System
 | 
|---|
 | 10 | Namespace IO
 | 
|---|
 | 11 | 
 | 
|---|
| [61] | 12 | Class Path
 | 
|---|
 | 13 | Public
 | 
|---|
| [388] | 14 |     Static AltDirectorySeparatorChar = &H2F As StrChar '/
 | 
|---|
| [404] | 15 |     Static DirectorySeparatorChar    = &H5C As StrChar '\
 | 
|---|
 | 16 |     Static PathSeparator             = &H3B As StrChar ';
 | 
|---|
 | 17 |     Static VolumeSeparatorChar       = &H3A As StrChar ':
 | 
|---|
| [61] | 18 | 
 | 
|---|
| [404] | 19 |     /*!
 | 
|---|
 | 20 |     @brief  ファイル名を取得する
 | 
|---|
 | 21 |     @author OverTaker
 | 
|---|
 | 22 |     @date   
 | 
|---|
 | 23 |     @param  ファイルパス
 | 
|---|
 | 24 |     @return ファイル名
 | 
|---|
 | 25 |     */
 | 
|---|
| [61] | 26 |     Static Function GetFileName(path As String) As String
 | 
|---|
| [404] | 27 |         CheckPath(path)
 | 
|---|
 | 28 |         Return path.Remove(0, GetLastSeparatorIndex(path) + 1)
 | 
|---|
| [61] | 29 |     End Function
 | 
|---|
 | 30 | 
 | 
|---|
| [404] | 31 |     /*!
 | 
|---|
 | 32 |     @brief  拡張子を除いたファイル名を取得する
 | 
|---|
 | 33 |     @author OverTaker
 | 
|---|
 | 34 |     @date   
 | 
|---|
 | 35 |     @param  ファイルパス
 | 
|---|
 | 36 |     @return ファイル名
 | 
|---|
 | 37 |     */
 | 
|---|
| [61] | 38 |     Static Function GetFileNameWithoutExtension(path As String) As String
 | 
|---|
| [404] | 39 |         CheckPath(path)
 | 
|---|
| [197] | 40 |         Dim fileName = GetFileName(path) As String
 | 
|---|
| [404] | 41 |         Dim extPos = GetExtensionIndex(fileName) As Long
 | 
|---|
| [61] | 42 |         If extPos = -1 Then Return ""
 | 
|---|
 | 43 | 
 | 
|---|
| [136] | 44 |         Return fileName.Remove(extPos)
 | 
|---|
| [61] | 45 |     End Function
 | 
|---|
 | 46 | 
 | 
|---|
| [404] | 47 |     /*!
 | 
|---|
 | 48 |     @brief  ランダムなファイル名を取得する
 | 
|---|
 | 49 |     @author OverTaker
 | 
|---|
 | 50 |     @date   
 | 
|---|
 | 51 |     @param  ファイルパス
 | 
|---|
 | 52 |     @return ファイル名
 | 
|---|
 | 53 |     */
 | 
|---|
| [61] | 54 |     Static Function GetRandomFileName() As String
 | 
|---|
 | 55 |         Randomize
 | 
|---|
 | 56 |         Dim temp As Long
 | 
|---|
| [296] | 57 |         temp = ((Rnd() * 900000000) As Long) + 10000000
 | 
|---|
| [61] | 58 |         Return Str$(temp)
 | 
|---|
 | 59 |     End Function
 | 
|---|
 | 60 | 
 | 
|---|
| [404] | 61 |     /*!
 | 
|---|
 | 62 |     @brief  ファイルの拡張子を取得する
 | 
|---|
 | 63 |     @author OverTaker
 | 
|---|
 | 64 |     @date   
 | 
|---|
 | 65 |     @param  ファイルパス
 | 
|---|
 | 66 |     @return 拡張子(.を含む)
 | 
|---|
 | 67 |     */
 | 
|---|
| [61] | 68 |     Static Function GetExtension(path As String) As String
 | 
|---|
| [404] | 69 |         CheckPath(path)
 | 
|---|
 | 70 |         Dim extPos = GetExtensionIndex(path) As Long
 | 
|---|
| [61] | 71 |         If extPos = -1 Then Return ""
 | 
|---|
 | 72 | 
 | 
|---|
| [136] | 73 |         Return path.Remove(0, extPos)
 | 
|---|
| [61] | 74 |     End Function
 | 
|---|
| [142] | 75 | 
 | 
|---|
| [404] | 76 |     /*!
 | 
|---|
 | 77 |     @brief  ファイル拡張子を変更する
 | 
|---|
 | 78 |     @author OverTaker
 | 
|---|
 | 79 |     @date   
 | 
|---|
 | 80 |     @param  拡張子(.を含む)
 | 
|---|
 | 81 |     @return 拡張子を変更したファイルパス
 | 
|---|
 | 82 |     */
 | 
|---|
| [61] | 83 |     Static Function ChangeExtension(path As String, extension As String) As String
 | 
|---|
| [404] | 84 |         Dim extPos = GetExtensionIndex(path) As Long
 | 
|---|
| [61] | 85 |         If extPos => 0 Then
 | 
|---|
| [136] | 86 |             path = path.Remove(extPos)
 | 
|---|
| [61] | 87 |         End If
 | 
|---|
 | 88 | 
 | 
|---|
| [404] | 89 |         CheckPath(path)
 | 
|---|
| [61] | 90 |         Return path + extension
 | 
|---|
 | 91 |     End Function
 | 
|---|
 | 92 | 
 | 
|---|
| [404] | 93 |     /*!
 | 
|---|
 | 94 |     @brief  ファイルパスの拡張子が含まれるかどうか
 | 
|---|
 | 95 |     @author OverTaker
 | 
|---|
 | 96 |     @date   
 | 
|---|
 | 97 |     @param  ファイルパス
 | 
|---|
 | 98 |     @return 拡張子があればTure,なければFalse
 | 
|---|
 | 99 |     */
 | 
|---|
 | 100 |     Static Function HasExtension(path As String) As Boolean
 | 
|---|
 | 101 |         CheckPath(path)
 | 
|---|
| [61] | 102 |         If GetExtension(path) <> "" Then
 | 
|---|
| [142] | 103 |             Return True
 | 
|---|
| [61] | 104 |         Else
 | 
|---|
| [142] | 105 |             Return False
 | 
|---|
| [61] | 106 |         End If
 | 
|---|
 | 107 |     End Function
 | 
|---|
 | 108 | 
 | 
|---|
| [404] | 109 |     /*!
 | 
|---|
 | 110 |     @brief  一時ファイルを作成し、ファイルパスを取得する
 | 
|---|
 | 111 |     @author OverTaker
 | 
|---|
 | 112 |     @date   
 | 
|---|
 | 113 |     @return 一時ファイルを示すファイルパス
 | 
|---|
 | 114 |     */
 | 
|---|
| [61] | 115 |     Static Function GetTempFileName() As String
 | 
|---|
| [125] | 116 |         Dim tempPathSize = __GetTempPath(0, 0)
 | 
|---|
 | 117 |         Dim tempPath = _System_malloc(SizeOf (TCHAR) * tempPathSize) As PTSTR
 | 
|---|
 | 118 |         If tempPath = 0 Then
 | 
|---|
 | 119 |             ' Throw OutOfMemoryException
 | 
|---|
 | 120 |             Debug
 | 
|---|
 | 121 |         End If
 | 
|---|
 | 122 |         If __GetTempPath(tempPathSize, tempPath) > tempPathSize Then
 | 
|---|
 | 123 |             ' Throw IOException?
 | 
|---|
 | 124 |             Debug
 | 
|---|
 | 125 |         End If
 | 
|---|
 | 126 | 
 | 
|---|
 | 127 |         Dim tempFileName[ELM(MAX_PATH)] As TCHAR
 | 
|---|
| [285] | 128 |         Dim len = __GetTempFileName(tempPath, "ABT", 0, tempFileName)
 | 
|---|
 | 129 |         _System_free(tempPath)
 | 
|---|
 | 130 |         Return New String(tempFileName, len As Long)
 | 
|---|
| [61] | 131 |     End Function
 | 
|---|
| [404] | 132 |     
 | 
|---|
 | 133 |     /*!
 | 
|---|
 | 134 |     @brief  システムの一時フォルダを取得する
 | 
|---|
 | 135 |     @author OverTaker
 | 
|---|
 | 136 |     @date   
 | 
|---|
 | 137 |     @return ファイルパス
 | 
|---|
 | 138 |     */
 | 
|---|
| [61] | 139 |     Static Function GetTempPath() As String
 | 
|---|
| [292] | 140 |         Dim size = __GetTempPath(0, 0)
 | 
|---|
 | 141 |         Dim tempPath = _System_malloc(size) As PTSTR
 | 
|---|
| [142] | 142 |         __GetTempPath(size, tempPath)
 | 
|---|
| [281] | 143 |         GetTempPath = New String(tempPath)
 | 
|---|
| [142] | 144 |         _System_free(tempPath)
 | 
|---|
| [61] | 145 |     End Function
 | 
|---|
 | 146 | 
 | 
|---|
| [404] | 147 |     /*!
 | 
|---|
 | 148 |     @brief  フルパスを取得する
 | 
|---|
 | 149 |     @author OverTaker
 | 
|---|
 | 150 |     @date   
 | 
|---|
 | 151 |     @param  ファイルパス
 | 
|---|
 | 152 |     @return ファイルパス
 | 
|---|
 | 153 |     */
 | 
|---|
| [61] | 154 |     Static Function GetFullPath(path As String) As String
 | 
|---|
| [404] | 155 |         CheckPath(path)
 | 
|---|
| [142] | 156 |         If IsPathRooted(path) Then
 | 
|---|
 | 157 |             Return path
 | 
|---|
 | 158 |         Else
 | 
|---|
 | 159 |             Return Environment.CurrentDirectory + Chr$(DirectorySeparatorChar) + path
 | 
|---|
 | 160 |         End If
 | 
|---|
| [61] | 161 |     End Function
 | 
|---|
 | 162 | 
 | 
|---|
| [404] | 163 |     /*!
 | 
|---|
 | 164 |     @brief  ひとつ上のディレクトリを取得する
 | 
|---|
 | 165 |     @author OverTaker
 | 
|---|
 | 166 |     @date   
 | 
|---|
 | 167 |     @param  ファイルパス
 | 
|---|
 | 168 |     @return ひとつ上のディレクトリを示すファイルパス
 | 
|---|
 | 169 |     */
 | 
|---|
| [61] | 170 |     Static Function GetDirectoryName(path As String) As String
 | 
|---|
| [404] | 171 |         CheckPath(path)
 | 
|---|
 | 172 |         Dim lastSepPos = GetLastSeparatorIndex(path) As Long
 | 
|---|
| [61] | 173 |         If lastSepPos = -1 Then Return ""
 | 
|---|
 | 174 | 
 | 
|---|
| [136] | 175 |         path = path.Remove(lastSepPos)
 | 
|---|
| [61] | 176 |         If path.Length <= 3 Then
 | 
|---|
 | 177 |             If IsPathRooted(path) Then Return ""
 | 
|---|
 | 178 |         End If
 | 
|---|
 | 179 |         Return path
 | 
|---|
 | 180 |     End Function
 | 
|---|
 | 181 | 
 | 
|---|
| [404] | 182 |     /*!
 | 
|---|
 | 183 |     @brief  ルートディレクトリを取得する
 | 
|---|
 | 184 |     @author OverTaker
 | 
|---|
 | 185 |     @date   
 | 
|---|
 | 186 |     @param  ファイルパス
 | 
|---|
 | 187 |     @return ルートディレクトリを示すパス
 | 
|---|
 | 188 |     */
 | 
|---|
| [61] | 189 |     Static Function GetPathRoot(path As String) As String
 | 
|---|
| [404] | 190 |         CheckPath(path)
 | 
|---|
| [61] | 191 |         If IsPathRooted(path) Then
 | 
|---|
| [136] | 192 |             Return path.Remove(3)
 | 
|---|
| [61] | 193 |         Else
 | 
|---|
 | 194 |             Return ""
 | 
|---|
 | 195 |         End If
 | 
|---|
 | 196 |     End Function
 | 
|---|
 | 197 | 
 | 
|---|
| [404] | 198 |     /*!
 | 
|---|
 | 199 |     @brief  パスにルートディレクトリが含まれるかどうか
 | 
|---|
 | 200 |     @author OverTaker
 | 
|---|
 | 201 |     @date   
 | 
|---|
 | 202 |     @param  ファイルパス
 | 
|---|
 | 203 |     @return 含まれる場合True,そうでない場合False
 | 
|---|
 | 204 |     */
 | 
|---|
| [142] | 205 |     Static Function IsPathRooted(path As String) As Boolean
 | 
|---|
| [404] | 206 |         CheckPath(path)
 | 
|---|
| [197] | 207 |         If path.IndexOf(Chr$(VolumeSeparatorChar), 1, 1) = 1 Then
 | 
|---|
| [142] | 208 |             Return True
 | 
|---|
| [61] | 209 |         Else
 | 
|---|
| [142] | 210 |             Return False
 | 
|---|
| [61] | 211 |         End If
 | 
|---|
 | 212 |     End Function
 | 
|---|
 | 213 | 
 | 
|---|
| [404] | 214 |     /*!
 | 
|---|
 | 215 |     @brief  二つのパスを結合します
 | 
|---|
 | 216 |     @author OverTaker
 | 
|---|
 | 217 |     @date   
 | 
|---|
 | 218 |     @param  結合されるファイルパス
 | 
|---|
 | 219 |     @param  結合するファイルパス
 | 
|---|
 | 220 |     @return 結合されたファイルパス
 | 
|---|
 | 221 |     */
 | 
|---|
| [61] | 222 |     Static Function Combine(path1 As String, path2 As String) As String
 | 
|---|
| [404] | 223 |         CheckPath(path1)
 | 
|---|
 | 224 |         CheckPath(path2)
 | 
|---|
| [388] | 225 |         If path1.LastIndexOf(VolumeSeparatorChar) And path1.Length = 2 Then
 | 
|---|
| [61] | 226 |             Return path1 + path2
 | 
|---|
 | 227 |         End If
 | 
|---|
 | 228 | 
 | 
|---|
| [388] | 229 |         If path1.LastIndexOf(DirectorySeparatorChar, ELM(path1.Length), 1) = -1 Then
 | 
|---|
| [197] | 230 |             Return path1 + Chr$(DirectorySeparatorChar) + path2
 | 
|---|
| [61] | 231 |         Else
 | 
|---|
 | 232 |             Return path1 + path2
 | 
|---|
 | 233 |         End If
 | 
|---|
 | 234 |     End Function
 | 
|---|
 | 235 | 
 | 
|---|
 | 236 | Private
 | 
|---|
| [404] | 237 |     Static Const InvalidPathChars = Ex"\q<>|\0\t" As String
 | 
|---|
| [61] | 238 | 
 | 
|---|
| [404] | 239 |     /*!
 | 
|---|
 | 240 |     @brief  無効なパス文字列がないか調べる
 | 
|---|
 | 241 |     @author OverTaker
 | 
|---|
 | 242 |     @date   
 | 
|---|
 | 243 |     @param  ファイルパス
 | 
|---|
 | 244 |     */
 | 
|---|
 | 245 |     Static Sub CheckPath(path As String)
 | 
|---|
 | 246 |         Dim i As Long
 | 
|---|
 | 247 |         For i = 0 To ELM(InvalidPathChars.Length)
 | 
|---|
 | 248 |             If path.Contains(InvalidPathChars.Substring(i, 1)) Then
 | 
|---|
 | 249 |                 Throw
 | 
|---|
 | 250 |             End If
 | 
|---|
 | 251 |         Next
 | 
|---|
 | 252 |     End Sub
 | 
|---|
| [61] | 253 | 
 | 
|---|
| [404] | 254 |     /*!
 | 
|---|
 | 255 |     @brief  ファイルの拡張子の位置を取得する
 | 
|---|
 | 256 |     @author OverTaker
 | 
|---|
 | 257 |     @date   
 | 
|---|
 | 258 |     @param  ファイルパス
 | 
|---|
 | 259 |     @return 0から始まるインデックス値。みつからない場合-1
 | 
|---|
 | 260 |     */
 | 
|---|
 | 261 |     Static Function GetExtensionIndex(path As String) As Long
 | 
|---|
 | 262 |         Dim lastSepIndex = GetLastSeparatorIndex(path) As Long
 | 
|---|
 | 263 |         If lastSepIndex = -1 Then lastSepIndex = 0
 | 
|---|
 | 264 |         Return path.LastIndexOf(Asc("."), ELM(path.Length), path.Length - lastSepIndex)
 | 
|---|
| [61] | 265 |     End Function
 | 
|---|
| [404] | 266 | 
 | 
|---|
 | 267 |     /*!
 | 
|---|
 | 268 |     @brief  最も後ろにあるディレクトリ区切り文字の位置を取得する
 | 
|---|
 | 269 |     @author OverTaker
 | 
|---|
 | 270 |     @date   
 | 
|---|
 | 271 |     @param  ファイルパス
 | 
|---|
 | 272 |     @return 0から始まるインデックス値。みつからない場合-1
 | 
|---|
 | 273 |     */
 | 
|---|
 | 274 |     Static Function GetLastSeparatorIndex(path As String) As Long
 | 
|---|
 | 275 |         Return System.Math.Max( path.LastIndexOf(DirectorySeparatorChar),
 | 
|---|
 | 276 |                                 path.LastIndexOf(VolumeSeparatorChar) )
 | 
|---|
 | 277 |     End Function
 | 
|---|
| [61] | 278 | End Class
 | 
|---|
 | 279 | 
 | 
|---|
 | 280 | '今はメソッド内で使えないので、実装されるまで回避
 | 
|---|
 | 281 | Function __GetTempPath(nBufferLength As DWord, lpBuffer As LPSTR) As DWord
 | 
|---|
 | 282 |     Return GetTempPath(nBufferLength, lpBuffer)
 | 
|---|
| [125] | 283 | End Function
 | 
|---|
 | 284 | 
 | 
|---|
 | 285 | Function __GetTempFileName(pPathName As PCSTR, pPrefixString As PCSTR, uUnique As DWord, pTempFileName As PSTR) As DWord
 | 
|---|
 | 286 |     Return GetTempFileName(pPathName, pPrefixString, uUnique, pTempFileName)
 | 
|---|
| [271] | 287 | End Function
 | 
|---|
 | 288 | 
 | 
|---|
 | 289 | 
 | 
|---|
 | 290 | End Namespace
 | 
|---|
 | 291 | End Namespace
 | 
|---|