コード例 #1
0
ファイル: file.cpp プロジェクト: MAPJe71/libyuni
	File::File(const AnyString& filePath):
		pFormat(nullptr)
	{
		if (filePath.empty())
			return;

		# if LIBAVFORMAT_VERSION_MAJOR < 53
		if (::av_open_input_file(&pFormat, filePath.c_str(), nullptr, 0, nullptr))
		# else
		if (::avformat_open_input(&pFormat, filePath.c_str(), nullptr, nullptr))
		# endif // LIBAVFORMAT_VERSION_MAJOR < 53
		{
			pFormat = nullptr;
			return;
		}

		// After opening, we must search for the stream information because not
		// all formats will have it in stream headers (eg. system MPEG streams)
		# if LIBAVFORMAT_VERSION_MAJOR < 53
		if (::av_find_stream_info(pFormat) < 0)
		# else
		if (::avformat_find_stream_info(pFormat, nullptr) < 0)
		# endif // LIBAVFORMAT_VERSION_MAJOR < 53
		{
			# if LIBAVFORMAT_VERSION_MAJOR < 53
			::av_close_input_file(pFormat);
			# else
			::avformat_close_input(&pFormat);
			# endif // LIBAVFORMAT_VERSION_MAJOR < 53
			pFormat = nullptr;
			return;
		}
	}
コード例 #2
0
ファイル: transaction.cpp プロジェクト: ollie314/libyuni
DBI::Error Transaction::truncate(const AnyString& tablename)
{
    if (YUNI_UNLIKELY(not IsValidIdentifier(tablename)))
        return errInvalidIdentifier;

    assert(!(!pChannel));

    // the adapter
    ::yn_dbi_adapter& adapter = pChannel->adapter;

    // The DBI interface should provide the most appropriate way for
    // truncating a table (autoincrement / cascade...)
    if (YUNI_LIKELY(adapter.truncate))
    {
        return (DBI::Error) adapter.truncate(adapter.dbh, tablename.c_str(), tablename.size());
    }
    else
    {
        // Fallback to a failsafe method
        // -- stmt << "TRUNCATE " << tablename << ';';
        // The SQL command Truncate is not supported by all databases. `DELETE FROM`
        // is not  the most efficient way for truncating a table
        // but it should work almost everywhere
        String stmt;
        stmt << "DELETE FROM " << tablename << ';';
        return perform(stmt);
    }
}
コード例 #3
0
ファイル: transaction.cpp プロジェクト: ollie314/libyuni
Cursor Transaction::prepare(const AnyString& stmt)
{
    assert(!(!pChannel));

    // the adapter
    ::yn_dbi_adapter& adapter = pChannel->adapter;

    if (YUNI_UNLIKELY(nullHandle == pTxHandle))
    {
        if (errNone != pChannel->begin(pTxHandle))
            return Cursor(adapter, nullptr);
    }

    // query handle
    void* handle = nullptr;

    if (YUNI_LIKELY(not stmt.empty() and adapter.dbh))
    {
        assert(adapter.query_new != NULL  and "invalid adapter query_new");
        assert(adapter.query_ref_acquire != NULL and "invalid adapter query_ref_acquire");
        assert(adapter.query_ref_release != NULL and "invalid adapter query_ref_release");

        adapter.query_new(&handle, adapter.dbh, stmt.c_str(), stmt.size());
    }

    return Cursor(adapter, handle);
}
コード例 #4
0
ファイル: luhn.cpp プロジェクト: UNIVERSAL-IT-SYSTEMS/libyuni
	int Luhn::Mod10(const AnyString& s)
	{
		// The string must have at least one char
		if (s.size() > 1)
		{
			// The algorithm :
			// 1 - Counting from the check digit, which is the rightmost, and moving
			//     left, double the value of every second digit.
			// 2 - Sum the digits of the products together with the undoubled digits
			//     from the original number.
			// 3 - If the total ends in 0 (put another way, if the total modulo 10 is
			//     congruent to 0), then the number is valid according to the Luhn formula
			//
			static const int prefetch[] = {0, 2, 4, 6, 8, 1, 3, 5, 7, 9};

			int sum = 0;
			bool alternate = true;

			const AnyString::iterator end = s.end();
			// For each char
			for (AnyString::iterator i = s.begin(); end != i; ++i)
			{
				// Each char in the string must be a digit
				if (!String::IsDigit(i.value()))
					return false;
				// The `real` digit
				int n = i.value() - '0';
				// Computing the sum
				sum += (alternate = !alternate) ? prefetch[n] : n;
			}
			return sum % 10;
		}
		return -1;
	}
コード例 #5
0
ファイル: file.cpp プロジェクト: srpgilles/pict_stock
	bool Size(const AnyString& filename, uint64& value)
	{
		struct stat results;
		if (not filename.empty() && stat(filename.c_str(), &results) == 0)
		{
			value = (uint64) results.st_size;
			return true;
		}
		value = 0u;
		return false;
	}
コード例 #6
0
ファイル: exists.cpp プロジェクト: MAPJe71/libyuni
	Yuni::IO::NodeType TypeOf(const AnyString& filename)
	{
		if (filename.empty())
			return Yuni::IO::typeUnknown;

		# ifdef YUNI_OS_WINDOWS
		const char* p = filename.c_str();
		unsigned int len = filename.size();
		if (p[len - 1] == '\\' or p[len - 1] == '/')
		{
			if (!--len)
			{
				# ifdef YUNI_OS_WINDOWS
				return Yuni::IO::typeUnknown;
				# else
				// On Unixes, `/` is a valid folder
				return Yuni::IO::typeFolder;
				# endif
			}
		}

		// Driver letters
		if (len == 2 and p[1] == ':')
			return Yuni::IO::typeFolder;

		String  norm;
		Yuni::IO::Normalize(norm, AnyString(p, len));
		// Conversion into wchar_t
		Private::WString<true> wstr(norm);
		if (wstr.empty())
			return Yuni::IO::typeUnknown;

		WIN32_FILE_ATTRIBUTE_DATA infoFile;
		if (!GetFileAttributesExW(wstr.c_str(), GetFileExInfoStandard, &infoFile))
			return Yuni::IO::typeUnknown;

		return ((infoFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
			? Yuni::IO::typeFolder
			: Yuni::IO::typeFile;

		# else // WINDOWS

		struct stat s;
		if (stat(filename.c_str(), &s) != 0)
			return Yuni::IO::typeUnknown;

		return (S_ISDIR(s.st_mode))
			? Yuni::IO::typeFolder
			: Yuni::IO::typeFile;
		# endif
	}
コード例 #7
0
ファイル: file.cpp プロジェクト: srpgilles/pict_stock
	bool Size(const AnyString& filename, uint64& value)
	{
		unsigned int len = filename.size();
		if (!len)
		{
			value = 0u;
			return false;
		}

		const char* const p = filename.c_str();

		if (p[len - 1] == '\\' || p[len - 1] == '/')
			--len;

		// Driver letters
		if (len == 2 && p[1] == ':')
		{
			value = 0u;
			return true;
		}

		String  norm;
		Yuni::IO::Normalize(norm, p, len);
		// Conversion into wchar_t
		Private::WString<true> wstr(norm);
		if (wstr.empty())
		{
			value = 0u;
			return false;
		}

		HANDLE hndl = CreateFileW(wstr.c_str(), 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
		if (hndl == INVALID_HANDLE_VALUE)
		{
			value = 0u;
			return false;
		}
		LARGE_INTEGER v;
		if (!GetFileSizeEx(hndl, &v))
		{
			CloseHandle(hndl);
			value = 0u;
			return false;
		}
		value = (uint64) v.QuadPart;

		CloseHandle(hndl);
		return true;
	}
コード例 #8
0
ファイル: path_format.cpp プロジェクト: srpgilles/pict_stock
	PathFormat::PathFormat(LoggingFacility& logs, const AnyString& format)
		: logs(logs),
		  pFolderPart(nullptr),
		  pFilePart(nullptr)
	{
		if (format.contains('('))
			throw GenericTools::Exception("Format shouldn't include any parenthesis");

		{
			String folderName, fileName;

			// Split the path and the filename
			IO::ExtractFilePath(folderName, format, false);

			if (folderName.empty())
				fileName = format;
			else
			{
				IO::ExtractFileName(fileName, format, false);
				if (IO::Separator != '/')
				{
					if (IO::Separator == '\\')
						folderName.replace("/", "\\\\");
					else
						folderName.replace('/', IO::Separator);
				}
				logs.notice("Folder = ") << folderName;
				pFolderPart = new Private::PathFormatHelper(logs, folderName);
			}

			logs.notice("File = ") << fileName;
			pFilePart = new Private::PathFormatHelper(logs, fileName);
		}
	}
コード例 #9
0
	NodeType TypeOf(const AnyString& filename, bool followSymLink)
	{
		yuint64 size; // useless
		yint64 lastModified;
		return (YUNI_LIKELY(not filename.empty()))
			? Stat(filename, size, lastModified, followSymLink) : IO::typeUnknown;
	}
コード例 #10
0
	NodeType FetchFileStatus(const AnyString& filename, yuint64& size, yint64& lastModified, bool followSymLink)
	{
		size = 0u;
		lastModified = 0;
		return (YUNI_LIKELY(not filename.empty()))
			? Stat(filename, size, lastModified, followSymLink) : IO::typeUnknown;
	}
コード例 #11
0
ファイル: shader.cpp プロジェクト: MAPJe71/libyuni
	bool VertexShader::loadFromMemory(const AnyString& source)
	{
		if (pID == invalidID)
			pID = ::glCreateShader(GL_VERTEX_SHADER);
		const char* data = source.data();
		::glShaderSource(pID, 1, &data, nullptr);
		::glCompileShader(pID);
		return GLTestError("VertexShader::loadFromMemory");
	}
コード例 #12
0
ファイル: file.cpp プロジェクト: libyuni/libyuni
	Yuni::IO::Error Delete(const AnyString& filename)
	{
		// DeleteFile is actually a macro and will be replaced by DeleteFileW
		// with Visual Studio. Consequently we can not use the word DeleteFile.....

		if (filename.empty())
			return Yuni::IO::errUnknown;

		# ifndef YUNI_OS_WINDOWS

		return (unlink(filename.c_str()))
			? Yuni::IO::errUnknown
			: Yuni::IO::errNone;

		# else

		const char* const p = filename.c_str();
		uint len = filename.size();

		if (p[len - 1] == '\\' or p[len - 1] == '/')
			--len;

		// Driver letters
		if (len == 2 and p[1] == ':')
			return Yuni::IO::errBadFilename;

		String norm;
		Yuni::IO::Normalize(norm, AnyString(p, len));

		// Conversion into wchar_t
		WString wstr(norm, true);
		if (wstr.empty())
			return Yuni::IO::errUnknown;
		wstr.replace('/', '\\');

		return (DeleteFileW(wstr.c_str()))
			? Yuni::IO::errNone
			: Yuni::IO::errUnknown;
		# endif
	}
コード例 #13
0
ファイル: create.cpp プロジェクト: MAPJe71/libyuni
	bool Create(const AnyString& path, uint mode)
	{
		if (not path.empty() and not Yuni::IO::Exists(path))
		{
			# ifdef YUNI_OS_WINDOWS
			// `mode` is not used on Windows
			(void) mode;
			return WindowsMake(path);
			# else
			return UnixMake(path, mode);
			# endif
		}
		return true;
	}
コード例 #14
0
ファイル: transaction.cpp プロジェクト: ollie314/libyuni
DBI::Error Transaction::perform(const AnyString& script)
{
    assert(!(!pChannel));

    // the adapter
    ::yn_dbi_adapter& adapter = pChannel->adapter;
    assert(adapter.query_exec != NULL);

    if (YUNI_LIKELY(nullHandle != pTxHandle))
    {
        return (DBI::Error) adapter.query_exec(adapter.dbh, script.c_str(), script.size());
    }
    else
    {
        // start a new transaction
        DBI::Error error = pChannel->begin(pTxHandle);

        if (YUNI_LIKELY(error == errNone))
            error = (DBI::Error) adapter.query_exec(adapter.dbh, script.c_str(), script.size());

        return error;
    }
}
コード例 #15
0
ファイル: create.cpp プロジェクト: MAPJe71/libyuni
	static bool UnixMake(const AnyString& path, uint mode)
	{
		const uint len = path.size();
		char* buffer = new char[len + 1];
		YUNI_MEMCPY(buffer, len, path.c_str(), len);
		buffer[len] = '\0';
		char* pt = buffer;
		char tmp;

		do
		{
			if ('\\' == *pt or '/' == *pt or '\0' == *pt)
			{
				tmp = *pt;
				*pt = '\0';
				if ('\0' != buffer[0] and '\0' != buffer[1] and '\0' != buffer[2])
				{
					if (mkdir(buffer, static_cast<mode_t>(mode)) < 0)
					{
						if (errno != EEXIST and errno != EISDIR and errno != ENOSYS)
						{
							delete[] buffer;
							return false;
						}
					}
				}
				if ('\0' == tmp)
					break;
				*pt = tmp;
			}
			++pt;
		}
		while (true);

		delete[] buffer;
		return true;
	}
コード例 #16
0
ファイル: file.cpp プロジェクト: srpgilles/pict_stock
	sint64 LastModificationTime(const AnyString& filename)
	{
		# ifdef YUNI_OS_WINDOWS

		Private::WString<> wfilenm(filename);
		if (wfilenm.empty())
			return 0;
		HANDLE hFile = CreateFileW(wfilenm.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL,
			OPEN_EXISTING, 0, NULL);
		if (hFile == INVALID_HANDLE_VALUE)
			return 0;

		FILETIME ftCreate, ftAccess, ftWrite;
		// Retrieve the file times for the file.
		if (GetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite))
		{
			CloseHandle(hFile);

			LARGE_INTEGER date, adjust;
			date.HighPart = ftWrite.dwHighDateTime;
			date.LowPart = ftWrite.dwLowDateTime;

			// 100-nanoseconds = milliseconds * 10000
			adjust.QuadPart = 11644473600000 * 10000;

			// removes the diff between 1970 and 1601
			date.QuadPart -= adjust.QuadPart;

			// converts back from 100-nanoseconds to seconds
			return date.QuadPart / 10000000;
		}

		CloseHandle(hFile);
		return 0;

		# else // UNIX

		struct stat st;
		if (!stat(filename.c_str(), &st))
			return st.st_mtime;
		return 0;

		# endif
	}
コード例 #17
0
	bool Stream::open(const AnyString& filename, int mode)
	{
		// Close the file if already opened
		if (pFd)
			(void)::fclose(pFd);

		# ifdef YUNI_OS_WINDOWS
		pFd = OpenFileOnWindows(filename, mode);
		# else
		// It is mandatory to open file with the flag O_CLOEXEC to avoid race
		// conditions with fork
		// fopen should used O_CLOEXEC as one of the option. However, at the current
		// state, not all operating systems do that.
		// So we have to do it by ourselves with open and fdopen.
		/*int flag = O_CLOEXEC;
		if (0 != (mode & OpenMode::read) and 0 != (mode & OpenMode::write))
			flag |= O_RDWR;
		else if (0 != (mode & OpenMode::read))
			flag |= O_RDONLY;
		else if (0 != (mode & OpenMode::write))
			flag |= O_WRONLY;

		if (0 != (mode & OpenMode::truncate))
			flag |= O_TRUNC;
		else if (0 != (mode & OpenMode::append))
			flag |= O_APPEND;

		if (0 != (mode & ~OpenMode::read))
			flag |= O_CREAT;

		int fd = ::open(filename.c_str(), flag);
		if (fd < 0) // error
			pFd = nullptr;
		else
			pFd = ::fdopen(fd, OpenMode::ToCString(mode));*/
		pFd = ::fopen(filename.c_str(), OpenMode::ToCString(mode));
		# endif

		return (NULL != pFd);
	}
コード例 #18
0
	void WString::prepareWString(const AnyString& string, bool uncprefix)
	{
		if (string.empty())
		{
			if (uncprefix)
			{
				pSize = 4;
				pWString = (wchar_t*)::realloc(pWString, sizeof(wchar_t) * 5);
				pWString[0] = L'\\';
				pWString[1] = L'\\';
				pWString[2] = L'?';
				pWString[3] = L'\\';
				pWString[4] = L'\0';
			}
			else
				clear();
			return;
		}

		if (string.size() > INT_MAX)
		{
			clear();
			return;
		}

		// Offset according to the presence of the UNC prefix
		const uint offset = (not uncprefix) ? 0 : 4;

		#ifdef YUNI_OS_WINDOWS
		{
			// Allocate and convert the C-String. Several iterations may be required
			// for allocating enough room for the conversion.
			const int sizeRequired = MultiByteToWideChar(CP_UTF8, 0, string.c_str(), string.size(), nullptr, 0);
			if (sizeRequired <= 0)
			{
				clear();
				return;
			}

			pSize = sizeRequired + offset;

			pWString = (wchar_t*) realloc(pWString, sizeof(wchar_t) * (pSize + 1));
			if (nullptr == pWString) // Impossible to allocate the buffer. Aborting.
			{
				clear();
				return;
			}

			// Converting into Wide String
			const int n = MultiByteToWideChar(CP_UTF8, 0, string.c_str(), static_cast<int>(string.size()), pWString + offset, static_cast<int>(pSize - offset));
			if (n != sizeRequired)
			{
				assert(false and "most likely an error");
				clear();
				return;
			}
		}
		#else
		{
			const char* wcstr = string.c_str();

			mbstate_t state;
			memset (&state, '\0', sizeof (state));

			size_t sizeRequired = mbsnrtowcs(nullptr, &wcstr, string.size(), 0, &state);
			if (0 == sizeRequired or (size_t) -1 == sizeRequired)
			{
				clear();
				return;
			}

			pSize = sizeRequired + offset;

			pWString = (wchar_t*) realloc(pWString, sizeof(wchar_t) * (pSize + 1));
			if (nullptr == pWString) // Impossible to allocate the buffer. Aborting.
			{
				clear();
				return;
			}

			memset (&state, '\0', sizeof (state));
			size_t written = mbsnrtowcs(pWString + offset, &wcstr, string.size(), pSize - offset, &state);
			if (0 == written or (size_t) -1 == written)
			{
				clear();
				return;
			}
		}
		#endif


		// prepend the Windows UNC prefix
		if (uncprefix)
		{
			pWString[0] = L'\\';
			pWString[1] = L'\\';
			pWString[2] = L'?';
			pWString[3] = L'\\';
		}

		// always ensure that the string is zero terminated
		pWString[pSize] = L'\0';
	}
コード例 #19
0
ファイル: program.cpp プロジェクト: libyuni/libyuni
	void Program::commandLine(AnyString cmd)
	{
		// remove all whitespaces
		cmd.trim();

		auto envptr = pEnv; // keeping a reference to the current env
		if (!envptr)
		{
			envptr = std::make_shared<ProcessSharedInfo>();
			pEnv = envptr;
		}
		ProcessSharedInfo& env = *envptr;

		MutexLocker locker(env.mutex);
		env.executable.clear();
		env.arguments.clear();

		if (cmd.empty())
			return;


		String* str = &env.executable;
		char instring = '\0';
		const AnyString::null_iterator end = cmd.utf8end();
		for (AnyString::const_utf8iterator i = cmd.utf8begin(); i != end; ++i)
		{
			char c = *i;
			switch (c)
			{
				default:
				{
					*str += i.value();
					break;
				}
				case '"':
					[[fallthrough]];
				case '\'':
				{
					if (instring == '\0')
					{
						instring = c;
					}
					else
					{
						if (instring == c)
							instring = '\0';
						else
							*str += c;
					}
					break;
				}
				case '\\':
				{
					++i;
					if (YUNI_UNLIKELY(i == end))
						return;
					c = *i;
					switch (c)
					{
						case 'n':  (*str) += '\n'; break;
						case 't':  (*str) += '\t'; break;
						case 'r':  (*str) += '\r'; break;
						case 'b':  (*str) += '\b'; break;
						case 'f':  (*str) += '\f'; break;
						case 'v':  (*str) += '\v'; break;
						case '0':  (*str) += '\0'; break;
						case 'e': [[fallthrough]];
						case 'a': [[fallthrough]];
						case 'E':  break;
						default:   (*str) << '\\' << c; break;
					}
					break;
				}
				case ' ':
					[[fallthrough]];
				case '\t':
				{
					if (instring == '\0')
					{
						if (not str->empty())
						{
							env.arguments.push_back(nullptr);
							str = &(env.arguments.back());
						}
					}
					else
						*str += c;
					break;
				}
			}
		}
	}
コード例 #20
0
	static bool DecodeURLQuery(KeyValueStore& params, const AnyString& query)
	{
		// note: mongoose does not provide the fragment here, so we don't have
		// to check it

		// Some tests are already done before calling this method
		assert(not query.empty());

		String key; // temporary string for parameters handling
		uint offset = 0;
		uint start = 0;
		AnyString value;
		do
		{
			offset = query.find_first_of("=&", offset);
			if (offset >= query.size())
			{
				// ignoring fields with empty value (using default)
				break;
			}
			if (query[offset] == '=')
			{
				key.assign(query, offset - start, start);
				if (key.empty()) // malformed url. aborting
					return false;

				++offset;

				// FIXME !!!! &amp; are not properly handled !!!!!!!!!!!!
				uint ampersand = offset;
				ampersand = query.find('&', ampersand);
				if (ampersand >= query.size())
				{
					value.adapt(query, query.size() - offset, offset);
					ampersand = query.size();
				}
				else
					value.adapt(query, ampersand - offset, offset);

				if (not value.empty())
				{
					KeyValueStore::iterator i = params.find(key);
					if (i != params.end())
					{
						// the item has been found !
						params[key] = value;
					}
				}

				offset = ampersand;
			}
			else
			{
				// ignoring fields with empty value (using default)
			}

			// updating offsets
			start = ++offset;
		}
		while (true);
		return true;
	}
コード例 #21
0
ファイル: texteditor.cpp プロジェクト: libyuni/libyuni
	EventPropagation TextEditor::charInput(const AnyString& str)
	{
		switch (str[0])
		{
			// Backspace
			case 0x08:
				for (uint i = 0; i < str.size(); ++i)
				{
					// Cannot use backspace when at beginning of file
					if (0 == pCursorPos.y && 1 == pCursorPos.x)
						return epStop;
					// When at beginning of line but not on first line, move up
					if (0 == pCursorPos.y && pCursorPos.x > 1)
						cursorPos(pCursorPos.x - 1, columnCount(pCursorPos.x - 1));
					else
						cursorPos(pCursorPos.x, pCursorPos.y - 1);
					// Erase
					pText.erase(cursorToByte(pCursorPos), 1);
				}
				invalidate();
				break;
			// Space
			case ' ':
				pText.insert(cursorToByte(pCursorPos), str);
				pCursorPos.x += str.size();
				invalidate();
				break;
			// Tab
			case '\t':
				pText.insert(cursorToByte(pCursorPos), str);
				cursorPos(pCursorPos.x, pCursorPos.y + str.size() * pTabWidth);
				invalidate();
				break;
			// Carriage Return
			case '\r':
			// New Line / Line Feed
			case '\n':
				for (uint i = 0; i < str.size(); ++i)
					pText.insert(cursorToByte(pCursorPos), '\n');
				pCursorPos.y += str.size();
				invalidate();
				break;
			// Normal displayable characters
			default:
				// Normal ASCII
				if ((uint8)str[0] < 0x80)
				{
					// Non-displayable characters are ignored
					std::locale loc;
					if (!std::isgraph(str[0], loc))
						break;
				}
				pText.insert(cursorToByte(pCursorPos), str);

				// Advance the cursor
				pCursorPos.x += str.utf8size();
				invalidate();
				break;
		}
		return epStop;
	}
コード例 #22
-1
ファイル: file.cpp プロジェクト: libyuni/libyuni
	bool Resize(const AnyString& filename, uint64_t size)
	{
		if (not filename.empty())
		{
			if (size < std::numeric_limits<off_t>::max())
			{
				#ifndef YUNI_OS_WINDOWS
				{
					assert((filename.c_str())[filename.size()] == '\0');
					#ifdef YUNI_OS_MAC
					int fd = open(filename.c_str(), O_WRONLY|O_CREAT, 0644);
					#else
					int fd = open(filename.c_str(), O_WRONLY|O_CREAT|O_LARGEFILE, 0644);
					#endif
					if (fd != -1)
					{
						bool success = (0 == ftruncate(fd, static_cast<off_t>(size)));
						close(fd);
						return success;
					}
				}
				#else
				{
					WString wstr(filename, true);
					if (not wstr.empty())
					{
						HANDLE hndl = CreateFileW(wstr.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
						if (hndl)
						{
							LARGE_INTEGER li;
							li.QuadPart = size;
							DWORD dwPtr = SetFilePointer(hndl, li.LowPart, &li.HighPart, FILE_BEGIN);
							if (dwPtr != INVALID_SET_FILE_POINTER)
								SetEndOfFile(hndl);
							CloseHandle(hndl);
							return true;
						}
					}
				}
				#endif
			}
		}
		return false;
	}