141 lines
4.3 KiB
Plaintext
141 lines
4.3 KiB
Plaintext
/*
|
|
* FileSupport.mm
|
|
*
|
|
* Copyright (c) 2014-2019 The Brenwill Workshop Ltd. (http://www.brenwill.com)
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "FileSupport.h"
|
|
#include "MVKCommonEnvironment.h"
|
|
#include <fstream>
|
|
|
|
#import <Foundation/Foundation.h>
|
|
|
|
using namespace std;
|
|
using namespace mvk;
|
|
|
|
|
|
MVK_PUBLIC_SYMBOL string mvk::absolutePath(const string& path) {
|
|
NSString* nsPath = @(path.data());
|
|
if(nsPath.absolutePath) return path;
|
|
nsPath = [NSFileManager.defaultManager.currentDirectoryPath stringByAppendingPathComponent: nsPath];
|
|
return nsPath.UTF8String;
|
|
}
|
|
|
|
MVK_PUBLIC_SYMBOL string mvk::lastPathComponent(const string& path) {
|
|
NSString* nsPath = @(path.data());
|
|
return nsPath.lastPathComponent.UTF8String;
|
|
}
|
|
|
|
MVK_PUBLIC_SYMBOL string mvk::pathExtension(const string& path) {
|
|
NSString* nsPath = @(path.data());
|
|
return nsPath.pathExtension.UTF8String;
|
|
}
|
|
|
|
MVK_PUBLIC_SYMBOL string mvk::pathWithExtension(const string& path,
|
|
const string pathExtn,
|
|
bool includeOrigPathExtn,
|
|
const string origPathExtnSep) {
|
|
NSString* nsPath = @(path.data());
|
|
NSString* currExtn = nsPath.pathExtension;
|
|
nsPath = nsPath.stringByDeletingPathExtension;
|
|
if (includeOrigPathExtn) {
|
|
nsPath = [nsPath stringByAppendingString: @(origPathExtnSep.data())];
|
|
nsPath = [nsPath stringByAppendingString: currExtn];
|
|
}
|
|
nsPath = [nsPath stringByAppendingPathExtension: @(pathExtn.data())];
|
|
return nsPath.UTF8String;
|
|
}
|
|
|
|
MVK_PUBLIC_SYMBOL bool mvk::canReadFile(const string& path) {
|
|
NSString* nsAbsDirPath = @(absolutePath(path).data());
|
|
NSFileManager* fileMgr = NSFileManager.defaultManager;
|
|
BOOL isDir = false;
|
|
BOOL exists = [fileMgr fileExistsAtPath: nsAbsDirPath isDirectory: &isDir];
|
|
return exists && !isDir && [fileMgr isReadableFileAtPath: nsAbsDirPath];
|
|
}
|
|
|
|
MVK_PUBLIC_SYMBOL bool mvk::canWriteFile(const string& path) {
|
|
NSString* nsAbsDirPath = @(absolutePath(path).data());
|
|
NSFileManager* fileMgr = NSFileManager.defaultManager;
|
|
BOOL isDir = false;
|
|
BOOL exists = [fileMgr fileExistsAtPath: nsAbsDirPath isDirectory: &isDir];
|
|
return !exists || (!isDir && [fileMgr isWritableFileAtPath: nsAbsDirPath]);
|
|
}
|
|
|
|
MVK_PUBLIC_SYMBOL bool mvk::readFile(const string& path, vector<char>& contents, string& errMsg) {
|
|
|
|
contents.clear(); // Ensure contents are empty in case we leave early
|
|
errMsg.clear(); // Assume success, so clear the error message
|
|
|
|
string absPath = absolutePath(path);
|
|
|
|
if ( !canReadFile(absPath) ) {
|
|
errMsg = absPath + " is not a readable file";
|
|
return false;
|
|
}
|
|
|
|
ifstream inFile(absPath, (ifstream::in | ifstream::binary)); // Stream closed when destroyed
|
|
if (inFile.fail()) {
|
|
errMsg = "Could not open file for reading: " + absPath;
|
|
return false;
|
|
}
|
|
|
|
// Get file length
|
|
inFile.seekg (0, inFile.end);
|
|
streampos filePos = inFile.tellg();
|
|
inFile.seekg (0, inFile.beg);
|
|
size_t fileLen = filePos;
|
|
|
|
// Read the contents of file into the vector
|
|
contents.reserve(fileLen);
|
|
char c;
|
|
while (inFile.get(c)) { contents.push_back(c); }
|
|
|
|
// Check if successful
|
|
if (inFile.bad()) {
|
|
errMsg = "Could not read entire contents of file: " + absPath;
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
MVK_PUBLIC_SYMBOL bool mvk::writeFile(const string& path, const vector<char>& contents, string& errMsg) {
|
|
|
|
errMsg.clear(); // Assume success, so clear the error message
|
|
|
|
string absPath = absolutePath(path);
|
|
|
|
if ( !canWriteFile(path) ) {
|
|
errMsg = "Cannot write to file:" + absPath;
|
|
return false;
|
|
}
|
|
|
|
ofstream outFile(absPath); // Stream closed when destroyed
|
|
if (outFile.fail()) {
|
|
errMsg = "Could not open file for writing: " + absPath;
|
|
return false;
|
|
}
|
|
|
|
for (auto iter = contents.begin(), end = contents.end(); iter != end; iter++) {
|
|
outFile.put(*iter);
|
|
if (outFile.bad()) {
|
|
errMsg = "Could not write entire contents of file: " + absPath;
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|