他人の空似自作物置場

touhouSE_th145BGMOnly.zip/touhouSE_src/utility.cpp

#include "stdafx.h"

namespace Utility {

namespace {

errno_t wfopen2(FILE ** fp, const wchar_t *fn, const wchar_t *type) {
	if(::_wfopen_s(fp, fn, type) == 0 && *fp != NULL) {
		return 0;
	}

	wchar_t str[256];
	WSTRCPY(str, fn);

	wchar_t *s = str;
	while(*s != '\0'){
		if(*s == '\\' || *s == '/'){
			*s = '\0';
			CreateDirectoryW(str, NULL);
			*s = '/';
		}
		s++;
	}
	errno_t error = ::_wfopen_s(fp, fn, type);
	if(error != 0) {
		return error;
	}
	return 0;
}

void MyFClose(FILE *fp) {
	if(fp == NULL) {
		return;
	}
	::fclose(fp);
}

void MyPClose(FILE *fp) {
	if(fp == NULL) {
		return;
	}
	::_pclose(fp);
}

bool CharToWChar(const char *buffer, unsigned int buffer_size, unsigned int code_page, std::vector<wchar_t> *result) {
	if(buffer == NULL || result == NULL) {
		return false;
	}
	const int size = ::MultiByteToWideChar(code_page, MB_ERR_INVALID_CHARS, buffer, static_cast<int>(buffer_size), NULL, 0);
	if(size <= 0) {
		return false;
	}
	result->resize(static_cast<unsigned int>(size)+1);
	const int convert_size = ::MultiByteToWideChar(code_page, MB_ERR_INVALID_CHARS, buffer, static_cast<int>(buffer_size), &result->front(), static_cast<int>(result->size()));
	if(convert_size <= 0) {
		return false;
	}
	(*result)[static_cast<unsigned int>(size)] = L'\0';
	return true;
}

bool FileReadW(const std::wstring &path, unsigned int code_page, std::vector<wchar_t> *result) {
	if(result == NULL) {
		return false;
	}
	std::vector<char> multi;
	if(!FileRead(path, multi)) {
		return false;
	}
	if(!CharToWChar(&multi.front(), multi.size(), code_page, result)) {
		return false;
	}
	return true;
}

std::vector<unsigned int> crc_table;

void MakeCRCTable(void){
	const unsigned int table_size = 256;
	crc_table.resize(table_size);
	for(unsigned int i = 0; i < table_size; i++) {
		unsigned int c = static_cast<unsigned int>(i);
		for(unsigned int l = 0; l < 8; l++) {
			if (c & 1) {
				c = 0xedb88320L ^ (c >> 1);
			} else {
				c = c >> 1;
			}
		}
		crc_table[i] = c;
	}
}

} // anonymous

#undef GetModuleFileName
bool GetModuleFileName(std::vector<char> &str) {
	::SetLastError(ERROR_SUCCESS);
	unsigned int size = 256;
	while(true) {
		str.resize(size);
		const unsigned int length = ::GetModuleFileNameA(NULL, &str.front(), str.size());
		const DWORD error = ::GetLastError();
		if(error == ERROR_SUCCESS && length <= size) {
			if(length < size) {
				str.resize(length);
			}
			break;
		} else if(error == ERROR_INSUFFICIENT_BUFFER) {
			size *= 2;
			continue;
		} else {
			str.clear();
			return false;
		}
	}
	return true;
}

void GetAppDir(std::vector<char> &str) {
	const bool get_result = GetModuleFileName(str);
	BOOST_ASSERT(get_result);
	BOOST_ASSERT(!str.empty());
	const BOOL path_remove_result = ::PathRemoveFileSpecA(&str.front());
	BOOST_ASSERT(path_remove_result == TRUE);
	str.resize(::strlen(&str.front()) + 1);
}

void SetAppDir(void) {
	std::vector<char> dir_name;
	GetAppDir(dir_name);
	BOOST_ASSERT(!dir_name.empty());
	const BOOL result = ::SetCurrentDirectoryA(&dir_name.front());
	BOOST_ASSERT(result == TRUE);
}

unsigned int Endian32(unsigned int value){
	return reinterpret_cast<unsigned char *>(&value)[3]
		+ reinterpret_cast<unsigned char *>(&value)[2]*0x100
		+ reinterpret_cast<unsigned char *>(&value)[1]*0x10000
		+ static_cast<unsigned int>(reinterpret_cast<unsigned char *>(&value)[0]*0x01000000);
}

unsigned short Endian16(unsigned short value){
	return static_cast<unsigned short>(reinterpret_cast<unsigned char *>(&value)[1] + reinterpret_cast<unsigned char *>(&value)[0] * 0x100);
}

unsigned int Endian(unsigned int value) {
	return Endian32(value);
}

unsigned short Endian(unsigned short value) {
	return Endian16(value);
}

unsigned int Crc(const unsigned char *buf, unsigned int len) {
	if(crc_table.empty()) {
		MakeCRCTable();
	}

	unsigned long c = 0xffffffffL;
	for(unsigned int i = 0; i < len; i++) {
		c = crc_table[(c ^ buf[i]) & 0xff] ^ (c >> 8);
	}
	return c ^ 0xffffffffL;
}

boost::shared_ptr<FILE> MyFOpen(const std::wstring &path, const wchar_t *type) {
	boost::shared_ptr<FILE> result;
	FILE *fp;
	const errno_t error = wfopen2(&fp, path.c_str(), type);
	if(error == 0) {
		BOOST_ASSERT(fp != NULL);
		result.reset(fp, &MyFClose);
	}
	return result;
}

boost::shared_ptr<FILE> MyFOpen(const std::string &path, const char *type) {
	std::vector<wchar_t> wpath;
	std::vector<wchar_t> wtype;
	boost::shared_ptr<FILE> result;
	if(!SJISToWChar(path, &wpath) || wpath.empty()) {
		return result;
	}
	if(!SJISToWChar(type, &wtype) || wtype.empty()) {
		return result;
	}
	result = MyFOpen(&wpath.front(), &wtype.front());
	return result;
}

boost::shared_ptr<FILE> MyPOpen(const std::wstring &command, const wchar_t *type) {
	boost::shared_ptr<FILE> result;
	FILE * const fp = ::_wpopen(command.c_str(), type);
	if(fp != NULL) {
		result.reset(fp, &MyPClose);
	}
	return result;
}

boost::shared_ptr<FILE> MyPOpen(const std::string &command, const char *type) {
	std::vector<wchar_t> wcommand;
	std::vector<wchar_t> wtype;
	boost::shared_ptr<FILE> result;
	if(!SJISToWChar(command, &wcommand) || wcommand.empty()) {
		return result;
	}
	if(!SJISToWChar(type, &wtype) || wtype.empty()) {
		return result;
	}
	result = MyPOpen(&wcommand.front(), &wtype.front());
	return result;
}

bool SJISFileRead(const std::wstring &path, std::vector<wchar_t> *result) {
	return FileReadW(path, CP_ACP, result);
}

bool UTF8FileRead(const std::wstring &path, std::vector<wchar_t> *result) {
	return FileReadW(path, CP_UTF8, result);
}

boost::shared_ptr<const std::string> StrV2Ptr(const std::vector<char> &str) {
	return boost::shared_ptr<const std::string>(new std::string(&str.front(), str.size()));
}

boost::shared_ptr<const std::string> Str2Ptr(const std::string &str) {
	return boost::shared_ptr<const std::string>(new std::string(str));
}

boost::shared_ptr<const std::string> Char2Ptr(const char* str) {
	return boost::shared_ptr<const std::string>(new std::string(str));
}

boost::shared_ptr<const std::wstring> WStrV2Ptr(const std::vector<wchar_t> &str) {
	return boost::shared_ptr<const std::wstring>(new std::wstring(&str.front(), str.size()));
}

boost::shared_ptr<const std::wstring> WStr2Ptr(const std::wstring &str) {
	return boost::shared_ptr<const std::wstring>(new std::wstring(str));
}

boost::shared_ptr<const std::wstring> WChar2Ptr(const wchar_t* str) {
	return boost::shared_ptr<const std::wstring>(new std::wstring(str));
}

#define MULTI_TO_WIDE_PROCS(name, code_page)													\
bool name##ToWChar(const char *str, std::vector<wchar_t> *result) {										\
	return CharToWChar(str, strlen(str), code_page, result);										\
}																			\
bool name##ToWChar(const std::vector<char> &str, std::vector<wchar_t> *result) {								\
	return CharToWChar(&str.front(), str.size(), code_page, result);									\
}																			\
bool name##ToWChar(const std::string &str, std::vector<wchar_t> *result) {									\
	return CharToWChar(str.c_str(), str.size(), code_page, result);									\
}																			\
bool name##ToWChar(const boost::shared_ptr<std::string> str, std::vector<wchar_t> *result) {						\
	return CharToWChar(str->c_str(), str->size(), code_page, result);									\
}

MULTI_TO_WIDE_PROCS(SJIS, CP_ACP)
MULTI_TO_WIDE_PROCS(UTF8, CP_UTF8)

std::wstring strToWStr(const std::string &in) {
  if (in.empty()) {
    return{};
  }
  const unsigned int size = ::MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, &in.front(), in.size(), NULL, 0);
  if (size == 0) {
    return{};
  }
  std::wstring temp;
  temp.resize(size);
  ::MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, &in.front(), in.size(), &temp.front(), temp.size());
  return temp;
}

std::string wStrToStr(const std::wstring &in) {
  if (in.empty()) {
    return{};
  }
  const unsigned int size = ::WideCharToMultiByte(CP_ACP, 0, &in.front(), in.size(), NULL, 0, NULL, NULL);
  if (size == 0) {
    return{};
  }
  std::string temp;
  temp.resize(size);
  ::WideCharToMultiByte(CP_ACP, 0, &in.front(), in.size(), &temp.front(), temp.size(), NULL, NULL);
  return temp;
}

} // Utility