/*
 * MoltenVKShaderConverterTool.cpp
 *
 * 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 "MoltenVKShaderConverterTool.h"
#include "FileSupport.h"
#include "OSSupport.h"
#include "GLSLToSPIRVConverter.h"
#include "SPIRVToMSLConverter.h"
#include "SPIRVSupport.h"
#include "MVKOSExtensions.h"

using namespace std;
using namespace mvk;


// The default list of vertex file extensions.
static const char* _defaultVertexShaderExtns = "vs vsh vert vertex";

// The default list of fragment file extensions.
static const char* _defaultFragShaderExtns = "fs fsh frag fragment";

// The default list of compute file extensions.
static const char* _defaultCompShaderExtns = "cs csh cp cmp comp compute kn kl krn kern kernel";

// The default list of SPIR-V file extensions.
static const char* _defaultSPIRVShaderExtns = "spv spirv";


uint64_t MVKPerformanceTracker::getTimestamp() { return mvkGetTimestamp(); }

void MVKPerformanceTracker::accumulate(uint64_t startTime, uint64_t endTime) {
	double currInterval = mvkGetElapsedMilliseconds(startTime, endTime);
	minimumDuration = (minimumDuration == 0.0) ? currInterval : min(currInterval, minimumDuration);
	maximumDuration = max(currInterval, maximumDuration);
	double totalInterval = (averageDuration * count++) + currInterval;
	averageDuration = totalInterval / count;
}


#pragma mark -
#pragma mark MoltenVKShaderConverterTool


int MoltenVKShaderConverterTool::run() {
	if ( !_isActive ) { return EXIT_FAILURE; }

	bool success = false;
	if ( !_directoryPath.empty() ) {
		string errMsg;
		success = iterateDirectory(_directoryPath, *this, _shouldUseDirectoryRecursion, errMsg);
		if ( !success ) { log(errMsg.data()); }
	} else {
		if (_shouldReadGLSL) {
			success = convertGLSL(_glslInFilePath, _spvOutFilePath, _mslOutFilePath, _shaderStage);
		} else if (_shouldReadSPIRV) {
			success = convertSPIRV(_spvInFilePath, _mslOutFilePath);
		} else {
			showUsage();
		}
	}
	reportPerformance();

	return success ? EXIT_SUCCESS : EXIT_FAILURE;
}

bool MoltenVKShaderConverterTool::processFile(string filePath) {
	string absPath = absolutePath(filePath);
	string emptyPath;

	string pathExtn = pathExtension(absPath);
	if (_shouldReadGLSL && isGLSLFileExtension(pathExtn)) {
		return convertGLSL(absPath, emptyPath, emptyPath, kMVKGLSLConversionShaderStageAuto);
	} else if (_shouldReadSPIRV && isSPIRVFileExtension(pathExtn)) {
		return convertSPIRV(absPath, emptyPath);
	}

	return true;
}

// Read GLSL code from a GLSL file, convert to SPIR-V, and optionally MSL,
// and write the SPIR-V and/or MSL code to files.
bool MoltenVKShaderConverterTool::convertGLSL(string& glslInFile,
											string& spvOutFile,
											string& mslOutFile,
											MVKGLSLConversionShaderStage shaderStage) {
	string path;
	vector<char> fileContents;
	string glslCode;
	string errMsg;

	// Read the GLSL
	if (glslInFile.empty()) {
		log("The GLSL file to read from was not specified");
		return false;
	}

	path = glslInFile;
	if (readFile(path, fileContents, errMsg)) {
		string logMsg = "Read GLSL from file: " + lastPathComponent(path);
		log(logMsg.data());
	} else {
		errMsg = "Could not read GLSL file. " + errMsg;
		log(errMsg.data());
		return false;
	}
	glslCode.append(fileContents.begin(), fileContents.end());

	if (shaderStage == kMVKGLSLConversionShaderStageAuto) {
		string pathExtn = pathExtension(glslInFile);
		shaderStage = shaderStageFromFileExtension(pathExtn);
	}
	if (shaderStage == kMVKGLSLConversionShaderStageAuto) {
		errMsg = "Could not determine shader type from GLSL file: " + absolutePath(path);
		log(errMsg.data());
		return false;
	}

	// Convert GLSL to SPIR-V
	GLSLToSPIRVConverter glslConverter;
	glslConverter.setGLSL(glslCode);

	uint64_t startTime = _glslConversionPerformance.getTimestamp();
	bool wasConverted = glslConverter.convert(shaderStage, _shouldLogConversions, _shouldLogConversions);
	_glslConversionPerformance.accumulate(startTime);

	if (wasConverted) {
		if (_shouldLogConversions) { log(glslConverter.getResultLog().data()); }
	} else {
		string logMsg = "Could not convert GLSL in file: " + absolutePath(path);
		log(logMsg.data());
		log(glslConverter.getResultLog().data());
		return false;
	}

	const vector<uint32_t>& spv = glslConverter.getSPIRV();

	// Write the SPIR-V code to a file.
	// If no file has been supplied, create one from the GLSL file name.
	if (_shouldWriteSPIRV) {
		path = spvOutFile;
		if (path.empty()) { path = pathWithExtension(glslInFile, "spv", _shouldIncludeOrigPathExtn, _origPathExtnSep); }

		spirvToBytes(spv, fileContents);
		if (writeFile(path, fileContents, errMsg)) {
			string logMsg = "Saved SPIR-V to file: " + lastPathComponent(path);
			log(logMsg.data());
		} else {
			errMsg = "Could not write SPIR-V file. " + errMsg;
			log(errMsg.data());
			return false;
		}
	}

	return convertSPIRV(spv, glslInFile, mslOutFile, false);
}

// Read SPIR-V code from a SPIR-V file, convert to MSL, and write the MSL code to files.
bool MoltenVKShaderConverterTool::convertSPIRV(string& spvInFile, string& mslOutFile) {
	string path;
	vector<char> fileContents;
	vector<uint32_t> spv;
	string errMsg;

	// Read the SPIRV
	if (spvInFile.empty()) {
		log("The SPIR-V file to read from was not specified");
		return false;
	}

	path = spvInFile;
	if (readFile(path, fileContents, errMsg)) {
		string logMsg = "Read SPIR-V from file: " + lastPathComponent(path);
		log(logMsg.data());
	} else {
		errMsg = "Could not read SPIR-V file. " + errMsg;
		log(errMsg.data());
		return false;
	}
	bytesToSPIRV(fileContents, spv);

	return convertSPIRV(spv, spvInFile, mslOutFile, _shouldLogConversions);
}

// Read SPIR-V code from an array, convert to MSL, and write the MSL code to files.
bool MoltenVKShaderConverterTool::convertSPIRV(const vector<uint32_t>& spv,
											   string& inFile,
											   string& mslOutFile,
											   bool shouldLogSPV) {
	if ( !_shouldWriteMSL ) { return true; }

	// Derive the context under which conversion will occur
	SPIRVToMSLConverterContext mslContext;
	mslContext.options.mslOptions.platform = _mslPlatform;
	mslContext.options.mslOptions.set_msl_version(_mslVersionMajor, _mslVersionMinor, _mslVersionPatch);
	mslContext.options.shouldFlipVertexY = _shouldFlipVertexY;

	SPIRVToMSLConverter spvConverter;
	spvConverter.setSPIRV(spv);

	uint64_t startTime = _spvConversionPerformance.getTimestamp();
	bool wasConverted = spvConverter.convert(mslContext, shouldLogSPV, _shouldLogConversions, (_shouldLogConversions && shouldLogSPV));
	_spvConversionPerformance.accumulate(startTime);

	if (wasConverted) {
		if (_shouldLogConversions) { log(spvConverter.getResultLog().data()); }
	} else {
		string errMsg = "Could not convert SPIR-V in file: " + absolutePath(inFile);
		log(errMsg.data());
		log(spvConverter.getResultLog().data());
		return false;
	}

	// Write the MSL to file
	string path = mslOutFile;
	if (mslOutFile.empty()) { path = pathWithExtension(inFile, "metal", _shouldIncludeOrigPathExtn, _origPathExtnSep); }
	const string& msl = spvConverter.getMSL();

	string compileErrMsg;
	bool wasCompiled = compile(msl, compileErrMsg, _mslVersionMajor, _mslVersionMinor, _mslVersionPatch);
	if (compileErrMsg.size() > 0) {
		string preamble = wasCompiled ? "is valid but the validation compilation produced warnings: " : "failed a validation compilation: ";
		compileErrMsg = "Generated MSL " + preamble + compileErrMsg;
		log(compileErrMsg.c_str());
	} else {
		log("Generated MSL was validated by a successful compilation with no warnings.");
	}

	vector<char> fileContents;
	fileContents.insert(fileContents.end(), msl.begin(), msl.end());
	string writeErrMsg;
	if (writeFile(path, fileContents, writeErrMsg)) {
		string logMsg = "Saved MSL to file: " + lastPathComponent(path);
		log(logMsg.c_str());
		return true;
	} else {
		writeErrMsg = "Could not write MSL file. " + writeErrMsg;
		log(writeErrMsg.c_str());
		return false;
	}
}

MVKGLSLConversionShaderStage MoltenVKShaderConverterTool::shaderStageFromFileExtension(string& pathExtension) {
    for (auto& fx : _glslVtxFileExtns) { if (fx == pathExtension) { return kMVKGLSLConversionShaderStageVertex; } }
    for (auto& fx : _glslFragFileExtns) { if (fx == pathExtension) { return kMVKGLSLConversionShaderStageFragment; } }
    for (auto& fx : _glslCompFileExtns) { if (fx == pathExtension) { return kMVKGLSLConversionShaderStageCompute; } }
	return kMVKGLSLConversionShaderStageAuto;
}

bool MoltenVKShaderConverterTool::isGLSLFileExtension(string& pathExtension) {
    for (auto& fx : _glslVtxFileExtns) { if (fx == pathExtension) { return true; } }
    for (auto& fx : _glslFragFileExtns) { if (fx == pathExtension) { return true; } }
    for (auto& fx : _glslCompFileExtns) { if (fx == pathExtension) { return true; } }
	return false;
}

bool MoltenVKShaderConverterTool::isSPIRVFileExtension(string& pathExtension) {
    for (auto& fx : _spvFileExtns) { if (fx == pathExtension) { return true; } }
	return false;
}

// Log the specified message to the console.
void MoltenVKShaderConverterTool::log(const char* logMsg) { printf("%s\n", logMsg); }

// Display usage information about this application on the console.
void MoltenVKShaderConverterTool::showUsage() {
	string line = "\n\e[1m" + _processName + "\e[0m converts OpenGL Shading Language (GLSL) source code to";
	log((const char*)line.c_str());
	log("SPIR-V code, and/or to Metal Shading Language (MSL) source code, or converts");
	log("SPIR-V code to Metal Shading Language source code.");
	log("\nTo convert a single GLSL or SPIR-V file, include a file reference with the -gi");
	log("or -si option, respectively. To convert an entire directory of shader files,");
	log("use the -d option, along with the -gi or -si option. When using the -d option,");
	log("any file name supplied with the -gi or -si option will be ignored.");
    log("\nUse the -so or -mo option to indicate the desired type of output");
    log("(SPIR-V or MSL, respectively).");
	log("\nUsage:");
	log("  -d [\"dirPath\"]     - Path to a directory containing GLSL or SPIR-V shader");
	log("                       source code files. The dirPath may be omitted to use");
	log("                       the current working directory.");
	log("  -r                 - (when using -d) Process directories recursively.");
	log("  -gi [\"glslInFile\"] - Indicates that GLSL shader code should be input.");
	log("                       The optional path parameter specifies the path to a");
	log("                       single file containing GLSL source code to be converted.");
	log("                       When using the -d option, the path parameter is ignored.");
	log("  -si [\"spvInFile\"]  - Indicates that SPIR-V shader code should be input.");
	log("                       The optional path parameter specifies the path to a");
	log("                       single file containing SPIR-V code to be converted.");
	log("                       When using the -d option, the path parameter is ignored.");
	log("  -so [\"spvOutFile\"] - Indicates that SPIR-V shader code should be output.");
	log("                       The optional path parameter specifies the path to a single");
	log("                       file to contain the SPIR-V code. When using the -d option,");
	log("                       the path parameter is ignored.");
	log("  -mo [\"mslOutFile\"] - Indicates that MSL shader source code should be output.");
	log("                       The optional path parameter specifies the path to a single");
	log("                       file to contain the MSL code. When using the -d option,");
	log("                       the path parameter is ignored.");
	log("  -mv mslVersion     - MSL version to output.");
	log("                       Must be in form n[.n][.n] (eg. 2, 2.1, or 2.1.0).");
	log("                       Defaults to the most recent MSL version for the platform");
	log("                       on which this tool is executed.");
	log("  -mp mslPlatform    - MSL platform. Must be one of macos or ios.");
	log("                       Defaults to the platform on which this tool is executed (macos).");
	log("  -t shaderType      - Shader type: vertex or fragment. Must be one of v, f, or c.");
	log("                       May be omitted to auto-detect.");
	log("  -c                 - Combine the GLSL and converted Metal Shader source code");
	log("                       into a single ouput file.");
	log("  -Iv                - Disable inversion of the vertex coordinate Y-axis");
    log("                       (default is to invert vertex coordinates).");
	log("  -xs \"xtnSep\"       - Separator to use when including file extension of original");
	log("                       code file name in derived converted code file name.");
	log("                       Default is \"_\" (myshdr.vsh -> myshdr_vsh.metal).");
	log("  -XS                - Disable including file extension of original code");
	log("                       file name in derived converted code file name");
	log("                       (myshdr.vsh -> myshdr.metal).");
	log("  -vx \"fileExtns\"    - List of GLSL vertex shader file extensions.");
	log("                       May be omitted for defaults (\"vs vsh vert vertex\").");
	log("  -fx \"fileExtns\"    - List of GLSL fragment shader file extensions.");
	log("                       May be omitted for defaults (\"fs fsh frag fragment\").");
    log("  -cx \"fileExtns\"    - List of GLSL compute shader file extensions.");
    log("                       May be omitted for defaults (\"cp cmp comp compute kn kl krn kern kernel\").");
	log("  -sx \"fileExtns\"    - List of SPIR-V shader file extensions.");
	log("                       May be omitted for defaults (\"spv spirv\").");
	log("  -l                 - Log the conversion results to the console (to aid debugging).");
	log("  -p                 - Log the performance of the shader conversions.");
	log("");
}

void MoltenVKShaderConverterTool::reportPerformance() {
	if ( !_shouldReportPerformance ) { return; }

	if (_shouldReadGLSL) { reportPerformance(_glslConversionPerformance, "GLSL to SPIR-V"); }
	reportPerformance(_spvConversionPerformance, "SPIR-V to MSL");
}

void MoltenVKShaderConverterTool::reportPerformance(MVKPerformanceTracker& shaderCompilationEvent, string eventDescription) {
	string logMsg;
	logMsg += "Performance to convert ";
	logMsg += eventDescription;
	logMsg += " count: ";
	logMsg += to_string(shaderCompilationEvent.count);
	logMsg += ", min: ";
	logMsg += to_string(shaderCompilationEvent.minimumDuration);
	logMsg += " ms, max: ";
	logMsg += to_string(shaderCompilationEvent.maximumDuration);
	logMsg += " ms, avg: ";
	logMsg += to_string(shaderCompilationEvent.averageDuration);
	logMsg += " ms.\n";
	log(logMsg.c_str());
}


#pragma mark Construction

MoltenVKShaderConverterTool::MoltenVKShaderConverterTool(int argc, const char* argv[]) {
	extractTokens(_defaultVertexShaderExtns, _glslVtxFileExtns);
	extractTokens(_defaultFragShaderExtns, _glslFragFileExtns);
    extractTokens(_defaultCompShaderExtns, _glslCompFileExtns);
	extractTokens(_defaultSPIRVShaderExtns, _spvFileExtns);
	_origPathExtnSep = "_";
	_shaderStage = kMVKGLSLConversionShaderStageAuto;
	_shouldUseDirectoryRecursion = false;
	_shouldReadGLSL = false;
	_shouldReadSPIRV = false;
	_shouldWriteSPIRV = false;
	_shouldWriteMSL = false;
	_shouldCombineGLSLAndMSL = false;
    _shouldFlipVertexY = true;
	_shouldIncludeOrigPathExtn = true;
	_shouldLogConversions = false;
	_shouldReportPerformance = false;

	_mslVersionMajor = 2;
	_mslVersionMinor = 1;
	_mslVersionPatch = 0;
	_mslPlatform = SPIRVToMSLConverterOptions().mslOptions.platform;

	_isActive = parseArgs(argc, argv);
	if ( !_isActive ) { showUsage(); }
}

bool MoltenVKShaderConverterTool::parseArgs(int argc, const char* argv[]) {
	if (argc == 0) { return false; }

	string execPath(argv[0]);
	_processName = lastPathComponent(execPath);

	for (int argIdx = 1; argIdx < argc; argIdx++) {
		string arg = argv[argIdx];

		if ( !isOptionArg(arg) ) { return false; }

		if (equal(arg, "-d", false)) {
			int optIdx = argIdx;
			argIdx = optionalParam(_directoryPath, argIdx, argc, argv);
			if (argIdx == optIdx) { return false; }
			_directoryPath = absolutePath(_directoryPath);
			continue;
		}

		if(equal(arg, "-r", true)) {
			_shouldUseDirectoryRecursion = true;
			continue;
		}

		if (equal(arg, "-gi", true)) {
			_shouldReadGLSL = true;
			argIdx = optionalParam(_glslInFilePath, argIdx, argc, argv);
			continue;
		}

		if (equal(arg, "-si", true)) {
			_shouldReadSPIRV = true;
			argIdx = optionalParam(_spvInFilePath, argIdx, argc, argv);
			continue;
		}

		if (equal(arg, "-so", true)) {
			_shouldWriteSPIRV = true;
			argIdx = optionalParam(_spvOutFilePath, argIdx, argc, argv);
			continue;
		}

		if (equal(arg, "-mo", true)) {
			_shouldWriteMSL = true;
			argIdx = optionalParam(_mslOutFilePath, argIdx, argc, argv);
			continue;
		}

		if (equal(arg, "-mv", true)) {
			int optIdx = argIdx;
			string mslVerStr;
			argIdx = optionalParam(mslVerStr, argIdx, argc, argv);
			if (argIdx == optIdx || mslVerStr.length() == 0) { return false; }
			vector<uint32_t> mslVerTokens;
			extractTokens(mslVerStr, mslVerTokens);
			auto tknCnt = mslVerTokens.size();
			_mslVersionMajor = (tknCnt > 0) ? mslVerTokens[0] : 0;
			_mslVersionMinor = (tknCnt > 1) ? mslVerTokens[1] : 0;
			_mslVersionPatch = (tknCnt > 2) ? mslVerTokens[2] : 0;
			continue;
		}

		if (equal(arg, "-mp", true)) {
			int optIdx = argIdx;
			string shdrTypeStr;
			argIdx = optionalParam(shdrTypeStr, argIdx, argc, argv);
			if (argIdx == optIdx || shdrTypeStr.length() == 0) { return false; }

			switch (shdrTypeStr.front()) {
				case 'm':
					_mslPlatform = SPIRV_CROSS_NAMESPACE::CompilerMSL::Options::macOS;
					break;
				case 'i':
					_mslPlatform = SPIRV_CROSS_NAMESPACE::CompilerMSL::Options::iOS;
					break;
				default:
					return false;
			}
			continue;
		}

		if (equal(arg, "-t", true)) {
			int optIdx = argIdx;
			string shdrTypeStr;
			argIdx = optionalParam(shdrTypeStr, argIdx, argc, argv);
			if (argIdx == optIdx || shdrTypeStr.length() == 0) { return false; }

			switch (shdrTypeStr.front()) {
				case 'v':
					_shaderStage = kMVKGLSLConversionShaderStageVertex;
					break;
				case 'f':
					_shaderStage = kMVKGLSLConversionShaderStageFragment;
					break;
				case 'c':
					_shaderStage = kMVKGLSLConversionShaderStageCompute;
					break;
				default:
					return false;
			}
			continue;
		}

		if(equal(arg, "-c", true)) {
			_shouldCombineGLSLAndMSL = true;
			continue;
		}

        if(equal(arg, "-Iv", true)) {
            _shouldFlipVertexY = false;
            continue;
        }

		if (equal(arg, "-xs", true)) {
			_shouldIncludeOrigPathExtn = true;
			argIdx++;
			if (argIdx < argc) { _origPathExtnSep = argv[argIdx]; }
			continue;
		}

		if(equal(arg, "-XS", true)) {
			_shouldIncludeOrigPathExtn = false;
			continue;
		}

		if (equal(arg, "-vx", true)) {
			int optIdx = argIdx;
			string shdrExtnStr;
			argIdx = optionalParam(shdrExtnStr, argIdx, argc, argv);
			if (argIdx == optIdx || shdrExtnStr.length() == 0) { return false; }
			extractTokens(shdrExtnStr, _glslVtxFileExtns);
			continue;
		}

		if (equal(arg, "-fx", true)) {
			int optIdx = argIdx;
			string shdrExtnStr;
			argIdx = optionalParam(shdrExtnStr, argIdx, argc, argv);
			if (argIdx == optIdx || shdrExtnStr.length() == 0) { return false; }
			extractTokens(shdrExtnStr, _glslFragFileExtns);
			continue;
		}

        if (equal(arg, "-cx", true)) {
            int optIdx = argIdx;
            string shdrExtnStr;
            argIdx = optionalParam(shdrExtnStr, argIdx, argc, argv);
            if (argIdx == optIdx || shdrExtnStr.length() == 0) { return false; }
            extractTokens(shdrExtnStr, _glslCompFileExtns);
            continue;
        }

		if (equal(arg, "-sx", true)) {
			int optIdx = argIdx;
			string shdrExtnStr;
			argIdx = optionalParam(shdrExtnStr, argIdx, argc, argv);
			if (argIdx == optIdx || shdrExtnStr.length() == 0) { return false; }
			extractTokens(shdrExtnStr, _spvFileExtns);
			continue;
		}

		if(equal(arg, "-l", true)) {
			_shouldLogConversions = true;
			continue;
		}

		if(equal(arg, "-p", true)) {
			_shouldReportPerformance = true;
			continue;
		}

	}

	return true;
}

// Returns whether the specified command line arg is an option arg.
bool MoltenVKShaderConverterTool::isOptionArg(string& arg) {
	return (arg.length() > 1 && arg.front() == '-');
}

// Sets the contents of the specified string to the parameter part of the option at the
// specified arg index, and increments and returns the option index. If no parameter was
// provided for the option, the string will be set to an empty string, and the returned
// index will be the same as the specified index.
int MoltenVKShaderConverterTool::optionalParam(string& optionParamResult,
											   int optionArgIndex,
											   int argc,
											   const char* argv[]) {
	int optParamIdx = optionArgIndex + 1;
	if (optParamIdx < argc) {
		string arg(argv[optParamIdx]);
		if ( !isOptionArg(arg) ) {
			optionParamResult = arg;
			return optParamIdx;
		}
	}
	optionParamResult.clear();
	return optionArgIndex;
}


#pragma mark -
#pragma mark Support functions

// Template function for tokenizing the components of a string into a vector.
template <typename Container>
Container& split(Container& result,
				 const typename Container::value_type& s,
				 const typename Container::value_type& delimiters,
				 bool includeEmptyElements) {
	result.clear();
	size_t current;
	size_t next = -1;
	do {
		if (includeEmptyElements) {
			next = s.find_first_not_of( delimiters, next + 1 );
			if (next == Container::value_type::npos) break;
			next -= 1;
		}
		current = next + 1;
		next = s.find_first_of( delimiters, current );
		result.push_back( s.substr( current, next - current ) );
	} while (next != Container::value_type::npos);
	return result;
}

void mvk::extractTokens(string str, vector<string>& tokens) {
	split(tokens, str, " \t\n\f", false);
}

void mvk::extractTokens(string str, vector<uint32_t>& tokens) {
	vector<string> stringTokens;
	split(stringTokens, str, ".", false);
	for (auto& st : stringTokens) {
		tokens.push_back((uint32_t)strtol(st.c_str(), nullptr, 0));
	}
}

// Compares the specified characters ignoring case.
static bool compareIgnoringCase(unsigned char a, unsigned char b) {
	return tolower(a) == tolower(b);
}

bool mvk::equal(string const& a, string const& b, bool checkCase) {
	if (a.length() != b.length()) { return false; }
	return checkCase ? (a == b) : (equal(b.begin(), b.end(), a.begin(), compareIgnoringCase));
}

