#include <math.h>
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include "mavka/biblioteka.h"
#include "mavka/prystriy.h"
р64 бібліотека_мавки_синус_р64(р64 значення) {
return sin(значення);
}
р64 бібліотека_мавки_косинус_р64(р64 значення) {
return cos(значення);
}
р64 бібліотека_мавки_тангенс_р64(р64 значення) {
return tan(значення);
}
р64 бібліотека_мавки_арксинус_р64(р64 значення) {
return asin(значення);
}
р64 бібліотека_мавки_арккосинус_р64(р64 значення) {
return acos(значення);
}
р64 бібліотека_мавки_арктангенс_р64(р64 значення) {
return atan(значення);
}
р64 бібліотека_мавки_арктангенс2_р64(р64 а, р64 б) {
return atan2(а, б);
}
р64 бібліотека_мавки_абсолютне_р64(р64 значення) {
return fabs(значення);
}
р64 бібліотека_мавки_експонента_р64(р64 значення) {
return exp(значення);
}
р64 бібліотека_мавки_корінь_р64(р64 значення) {
return sqrt(значення);
}
р64 бібліотека_мавки_стеля_р64(р64 значення) {
return ceil(значення);
}
р64 бібліотека_мавки_підлога_р64(р64 значення) {
return floor(значення);
}
р64 бібліотека_мавки_округлити_р64(р64 значення) {
return round(значення);
}
р64 бібліотека_мавки_остача_від_ділення_р64(р64 а, р64 б) {
return fmod(а, б);
}
логічне бібліотека_мавки_видалити(природне розмір_шляху, п8* дані_шляху) {
// Convert UTF-8 path to wide char
int широких_символів =
MultiByteToWideChar(CP_UTF8, 0, (char*)дані_шляху, розмір_шляху, NULL, 0);
if (широких_символів == 0) {
return FALSE;
}
WCHAR* широкий_шлях = (WCHAR*)malloc((широких_символів + 1) * sizeof(WCHAR));
if (!широкий_шлях) {
return FALSE;
}
MultiByteToWideChar(CP_UTF8, 0, (char*)дані_шляху, розмір_шляху, широкий_шлях,
широких_символів);
широкий_шлях[широких_символів] = L'\0';
// Get file attributes
DWORD атрибути = GetFileAttributesW(широкий_шлях);
if (атрибути == INVALID_FILE_ATTRIBUTES) {
free(широкий_шлях);
return FALSE;
}
if (атрибути & FILE_ATTRIBUTE_DIRECTORY) {
// Delete directory recursively
WIN32_FIND_DATAW знайдені_дані;
HANDLE знайти_файл;
size_t довжина_шаблону = wcslen(широкий_шлях) + 3;
WCHAR* шаблон = (WCHAR*)malloc(довжина_шаблону * sizeof(WCHAR));
if (!шаблон) {
free(широкий_шлях);
return FALSE;
}
swprintf(шаблон, довжина_шаблону, L"%s\\*", широкий_шлях);
знайти_файл = FindFirstFileW(шаблон, &знайдені_дані);
if (знайти_файл == INVALID_HANDLE_VALUE) {
free(шаблон);
free(широкий_шлях);
return RemoveDirectoryW(широкий_шлях) ? TRUE : FALSE;
}
логічне успіх = TRUE;
do {
if (wcscmp(знайдені_дані.cFileName, L".") == 0 ||
wcscmp(знайдені_дані.cFileName, L"..") == 0) {
continue;
}
size_t довжина_повного_шляху =
wcslen(широкий_шлях) + wcslen(знайдені_дані.cFileName) + 2;
WCHAR* повний_шлях =
(WCHAR*)malloc(довжина_повного_шляху * sizeof(WCHAR));
if (!повний_шлях) {
успіх = FALSE;
break;
}
swprintf(повний_шлях, довжина_повного_шляху, L"%s\\%s", широкий_шлях,
знайдені_дані.cFileName);
// Convert back to UTF-8
int утф8_довжина =
WideCharToMultiByte(CP_UTF8, 0, повний_шлях, -1, NULL, 0, NULL, NULL);
if (утф8_довжина > 0) {
char* утф8_шлях = (char*)malloc(утф8_довжина);
if (утф8_шлях) {
WideCharToMultiByte(CP_UTF8, 0, повний_шлях, -1, утф8_шлях,
утф8_довжина, NULL, NULL);
if (!бібліотека_мавки_видалити(strlen(утф8_шлях), (п8*)утф8_шлях)) {
успіх = FALSE;
}
free(утф8_шлях);
}
}
free(повний_шлях);
} while (FindNextFileW(знайти_файл, &знайдені_дані));
FindClose(знайти_файл);
free(шаблон);
free(широкий_шлях);
if (!успіх) {
return FALSE;
}
return RemoveDirectoryW(широкий_шлях);
} else {
// Delete file
BOOL результат = DeleteFileW(широкий_шлях);
free(широкий_шлях);
return результат;
}
}
логічне бібліотека_мавки_дописати_файл(природне розмір_шляху,
п8* дані_шляху,
природне розмір_даних,
п8* дані_даних) {
// Convert UTF-8 path to wide char
int широких_символів =
MultiByteToWideChar(CP_UTF8, 0, (char*)дані_шляху, розмір_шляху, NULL, 0);
if (широких_символів == 0) {
return FALSE;
}
WCHAR* широкий_шлях = (WCHAR*)malloc((широких_символів + 1) * sizeof(WCHAR));
if (!широкий_шлях) {
return FALSE;
}
MultiByteToWideChar(CP_UTF8, 0, (char*)дані_шляху, розмір_шляху, широкий_шлях,
широких_символів);
широкий_шлях[широких_символів] = L'\0';
// Open file using Windows API in append mode
HANDLE файл = CreateFileW(широкий_шлях, FILE_APPEND_DATA, 0, NULL,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
free(широкий_шлях);
if (файл == INVALID_HANDLE_VALUE) {
return FALSE;
}
// Write file
DWORD записано;
if (!WriteFile(файл, дані_даних, розмір_даних, &записано, NULL)) {
CloseHandle(файл);
return FALSE;
}
CloseHandle(файл);
return записано == розмір_даних;
}
логічне бібліотека_мавки_записати_файл(природне розмір_шляху,
п8* дані_шляху,
природне розмір_даних,
п8* дані_даних) {
// Convert UTF-8 path to wide char
int широких_символів =
MultiByteToWideChar(CP_UTF8, 0, (char*)дані_шляху, розмір_шляху, NULL, 0);
if (широких_символів == 0) {
return FALSE;
}
WCHAR* широкий_шлях = (WCHAR*)malloc((широких_символів + 1) * sizeof(WCHAR));
if (!широкий_шлях) {
return FALSE;
}
MultiByteToWideChar(CP_UTF8, 0, (char*)дані_шляху, розмір_шляху, широкий_шлях,
широких_символів);
широкий_шлях[широких_символів] = L'\0';
// Create file using Windows API
HANDLE файл = CreateFileW(широкий_шлях, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
free(широкий_шлях);
if (файл == INVALID_HANDLE_VALUE) {
return FALSE;
}
// Write file
DWORD записано;
if (!WriteFile(файл, дані_даних, розмір_даних, &записано, NULL)) {
CloseHandle(файл);
return FALSE;
}
CloseHandle(файл);
return записано == розмір_даних;
}
логічне бібліотека_мавки_прочитати_файл(природне розмір_шляху,
п8* дані_шляху,
Дані* вихід) {
// Convert UTF-8 path to wide char
int широких_символів =
MultiByteToWideChar(CP_UTF8, 0, (char*)дані_шляху, розмір_шляху, NULL, 0);
if (широких_символів == 0) {
return FALSE;
}
WCHAR* широкий_шлях = (WCHAR*)malloc((широких_символів + 1) * sizeof(WCHAR));
if (!широкий_шлях) {
return FALSE;
}
MultiByteToWideChar(CP_UTF8, 0, (char*)дані_шляху, розмір_шляху, широкий_шлях,
широких_символів);
широкий_шлях[широких_символів] = L'\0';
// Open file using Windows API
HANDLE файл = CreateFileW(широкий_шлях, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
free(широкий_шлях);
if (файл == INVALID_HANDLE_VALUE) {
return FALSE;
}
// Get file size
LARGE_INTEGER розмір_файлу;
if (!GetFileSizeEx(файл, &розмір_файлу)) {
CloseHandle(файл);
return FALSE;
}
вихід->розмір = (природне)розмір_файлу.QuadPart;
// Allocate buffer
вихід->дані = (п8*)malloc(вихід->розмір);
if (!вихід->дані) {
CloseHandle(файл);
return FALSE;
}
// Read file
DWORD прочитано;
if (!ReadFile(файл, вихід->дані, вихід->розмір, &прочитано, NULL)) {
free(вихід->дані);
CloseHandle(файл);
return FALSE;
}
CloseHandle(файл);
return прочитано == вихід->розмір;
}
логічне бібліотека_мавки_створити_папку(природне розмір_шляху, п8* дані_шляху) {
// Convert UTF-8 path to wide char
int широких_символів =
MultiByteToWideChar(CP_UTF8, 0, (char*)дані_шляху, розмір_шляху, NULL, 0);
if (широких_символів == 0) {
return FALSE;
}
WCHAR* широкий_шлях = (WCHAR*)malloc((широких_символів + 1) * sizeof(WCHAR));
if (!широкий_шлях) {
return FALSE;
}
MultiByteToWideChar(CP_UTF8, 0, (char*)дані_шляху, розмір_шляху, широкий_шлях,
широких_символів);
широкий_шлях[широких_символів] = L'\0';
// Check if directory already exists
DWORD атрибути = GetFileAttributesW(широкий_шлях);
if (атрибути != INVALID_FILE_ATTRIBUTES &&
атрибути & FILE_ATTRIBUTE_DIRECTORY) {
free(широкий_шлях);
return TRUE;
}
// Create a copy to parse
size_t копія_розмір = (широких_символів + 1) * sizeof(WCHAR);
WCHAR* копія_шляху = (WCHAR*)malloc(копія_розмір);
if (!копія_шляху) {
free(широкий_шлях);
return FALSE;
}
memcpy(копія_шляху, широкий_шлях, копія_розмір);
// Create directories recursively
for (int я = 0; я < широких_символів; я++) {
if (копія_шляху[я] == L'\\' || копія_шляху[я] == L'/') {
копія_шляху[я] = L'\0';
if (я > 0 && я > 2) { // Skip drive letter (C: is 2 chars)
if (!CreateDirectoryW(копія_шляху, NULL)) {
DWORD помилка = GetLastError();
if (помилка != ERROR_ALREADY_EXISTS) {
free(копія_шляху);
free(широкий_шлях);
return FALSE;
}
}
}
копія_шляху[я] = L'\\';
}
}
// Create the final directory
if (!CreateDirectoryW(широкий_шлях, NULL)) {
DWORD помилка = GetLastError();
if (помилка != ERROR_ALREADY_EXISTS) {
free(копія_шляху);
free(широкий_шлях);
return FALSE;
}
// ERROR_ALREADY_EXISTS occurred - verify it's actually a directory, not a file
DWORD атрибути_фіналь = GetFileAttributesW(широкий_шлях);
if (атрибути_фіналь == INVALID_FILE_ATTRIBUTES ||
!(атрибути_фіналь & FILE_ATTRIBUTE_DIRECTORY)) {
free(копія_шляху);
free(широкий_шлях);
return FALSE;
}
}
free(копія_шляху);
free(широкий_шлях);
return TRUE;
}
static WCHAR* utf8_to_wide(const п8* utf8) {
if (!utf8) {
return NULL;
}
int count = MultiByteToWideChar(CP_UTF8, 0, (const char*)utf8, -1, NULL, 0);
if (count == 0) {
return NULL;
}
WCHAR* wide = (WCHAR*)malloc(count * sizeof(WCHAR));
if (!wide) {
return NULL;
}
if (MultiByteToWideChar(CP_UTF8, 0, (const char*)utf8, -1, wide, count) ==
0) {
free(wide);
return NULL;
}
return wide;
}
static WCHAR* utf8_to_wide_sized(const п8* utf8, природне size) {
if (!utf8 || size == 0) {
return NULL;
}
int count =
MultiByteToWideChar(CP_UTF8, 0, (const char*)utf8, (int)size, NULL, 0);
if (count == 0) {
return NULL;
}
WCHAR* wide = (WCHAR*)malloc((count + 1) * sizeof(WCHAR));
if (!wide) {
return NULL;
}
if (MultiByteToWideChar(CP_UTF8, 0, (const char*)utf8, (int)size, wide,
count + 1) == 0) {
free(wide);
return NULL;
}
wide[count] = L'\0';
return wide;
}
static логічне append_to_data(Дані* output, const void* data, size_t size) {
if (size == 0) {
return TRUE;
}
п8* next = (п8*)realloc(output->дані, output->розмір + size);
if (!next) {
return FALSE;
}
memcpy(next + output->розмір, data, size);
output->дані = next;
output->розмір += size;
return TRUE;
}
static BOOL read_pipe(HANDLE handle, Дані* output) {
BYTE buffer[4096];
while (TRUE) {
DWORD bytes_read = 0;
if (!ReadFile(handle, buffer, sizeof(buffer), &bytes_read, NULL)) {
DWORD error = GetLastError();
if (error == ERROR_BROKEN_PIPE) {
return TRUE;
}
return FALSE;
}
if (bytes_read == 0) {
return TRUE;
}
if (!append_to_data(output, buffer, (size_t)bytes_read)) {
return FALSE;
}
}
}
static size_t quote_cmd_argument_length(const WCHAR* arg) {
const WCHAR* p = arg;
size_t length = 0;
логічне needs_quotes = FALSE;
while (*p) {
if (*p == L' ' || *p == L'\t' || *p == L'"') {
needs_quotes = TRUE;
}
if (*p == L'"') {
length += 2;
} else {
length += 1;
}
p++;
}
if (needs_quotes) {
length += 2;
}
return length;
}
static void append_quoted_cmd_argument(WCHAR** dest, const WCHAR* arg) {
const WCHAR* p = arg;
логічне needs_quotes = FALSE;
while (*p) {
if (*p == L' ' || *p == L'\t' || *p == L'"') {
needs_quotes = TRUE;
break;
}
p++;
}
if (needs_quotes) {
**dest = L'"';
*dest += 1;
}
p = arg;
while (*p) {
if (*p == L'"') {
**dest = L'\\';
*dest += 1;
**dest = L'"';
*dest += 1;
} else {
**dest = *p;
*dest += 1;
}
p++;
}
if (needs_quotes) {
**dest = L'"';
*dest += 1;
}
}
void бібліотека_мавки_виконати(природне розмір,
п8* дані,
РезультатВиконання* результат_виконання) {
if (!результат_виконання) {
return;
}
результат_виконання->стдвив.розмір = 0;
результат_виконання->стдвив.дані = NULL;
результат_виконання->стдпом.розмір = 0;
результат_виконання->стдпом.дані = NULL;
результат_виконання->код = -1;
if (розмір == 0 || !дані) {
return;
}
WCHAR* wide_command = utf8_to_wide_sized(дані, розмір);
if (!wide_command) {
return;
}
size_t prefix_len = wcslen(L"cmd.exe /c ");
size_t command_len = wcslen(wide_command);
WCHAR* command_line =
(WCHAR*)malloc((prefix_len + command_len + 1) * sizeof(WCHAR));
if (!command_line) {
free(wide_command);
return;
}
wcscpy_s(command_line, prefix_len + command_len + 1, L"cmd.exe /c ");
wcscat_s(command_line, prefix_len + command_len + 1, wide_command);
SECURITY_ATTRIBUTES sa = {sizeof(sa), NULL, TRUE};
HANDLE stdout_read = NULL;
HANDLE stdout_write = NULL;
HANDLE stderr_read = NULL;
HANDLE stderr_write = NULL;
if (!CreatePipe(&stdout_read, &stdout_write, &sa, 0) ||
!CreatePipe(&stderr_read, &stderr_write, &sa, 0)) {
free(command_line);
free(wide_command);
return;
}
SetHandleInformation(stdout_read, HANDLE_FLAG_INHERIT, 0);
SetHandleInformation(stderr_read, HANDLE_FLAG_INHERIT, 0);
STARTUPINFOW si = {0};
si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdOutput = stdout_write;
si.hStdError = stderr_write;
si.hStdInput = CreateFileW(L"NUL", GENERIC_READ, FILE_SHARE_READ, &sa,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
PROCESS_INFORMATION pi = {0};
if (!CreateProcessW(NULL, command_line, NULL, NULL, TRUE, CREATE_NO_WINDOW,
NULL, NULL, &si, &pi)) {
if (si.hStdInput != INVALID_HANDLE_VALUE) {
CloseHandle(si.hStdInput);
}
if (stdout_read) {
CloseHandle(stdout_read);
}
if (stdout_write) {
CloseHandle(stdout_write);
}
if (stderr_read) {
CloseHandle(stderr_read);
}
if (stderr_write) {
CloseHandle(stderr_write);
}
free(command_line);
free(wide_command);
return;
}
CloseHandle(stdout_write);
stdout_write = NULL;
CloseHandle(stderr_write);
stderr_write = NULL;
if (si.hStdInput != INVALID_HANDLE_VALUE) {
CloseHandle(si.hStdInput);
}
read_pipe(stdout_read, &результат_виконання->стдвив);
read_pipe(stderr_read, &результат_виконання->стдпом);
WaitForSingleObject(pi.hProcess, INFINITE);
DWORD exit_code = 0;
if (GetExitCodeProcess(pi.hProcess, &exit_code)) {
результат_виконання->код = (ц32)exit_code;
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
if (stdout_read) {
CloseHandle(stdout_read);
}
if (stderr_read) {
CloseHandle(stderr_read);
}
free(command_line);
free(wide_command);
}
void бібліотека_мавки_виконати_аргументи(
природне кількість_аргументів,
ю8* аргументи,
РезультатВиконання* результат_виконання) {
if (!результат_виконання) {
return;
}
результат_виконання->стдвив.розмір = 0;
результат_виконання->стдвив.дані = NULL;
результат_виконання->стдпом.розмір = 0;
результат_виконання->стдпом.дані = NULL;
результат_виконання->код = -1;
if (кількість_аргументів == 0 || !аргументи) {
return;
}
// Convert all args to wide
WCHAR** wide_args = (WCHAR**)malloc(кількість_аргументів * sizeof(WCHAR*));
if (!wide_args) {
return;
}
for (природне i = 0; i < кількість_аргументів; ++i) {
wide_args[i] = utf8_to_wide_sized(аргументи[i].дані, аргументи[i].розмір);
if (!wide_args[i]) {
for (природне j = 0; j < i; ++j) {
free(wide_args[j]);
}
free(wide_args);
return;
}
}
// Always use cmd.exe /c for maximum compatibility
size_t cmd_prefix_len = wcslen(L"cmd.exe /c ");
size_t total_len = cmd_prefix_len;
for (природне i = 0; i < кількість_аргументів; ++i) {
total_len += quote_cmd_argument_length(wide_args[i]);
if (i + 1 < кількість_аргументів) {
total_len += 1; // space
}
}
total_len += 1; // null terminator
WCHAR* command_line = (WCHAR*)malloc(total_len * sizeof(WCHAR));
if (!command_line) {
for (природне i = 0; i < кількість_аргументів; ++i) {
free(wide_args[i]);
}
free(wide_args);
return;
}
wcscpy_s(command_line, total_len, L"cmd.exe /c ");
WCHAR* dest = command_line + cmd_prefix_len;
for (природне i = 0; i < кількість_аргументів; ++i) {
append_quoted_cmd_argument(&dest, wide_args[i]);
if (i + 1 < кількість_аргументів) {
*dest++ = L' ';
}
}
*dest = L'\0';
// Create pipes with security attributes for inheritance
SECURITY_ATTRIBUTES sa = {sizeof(sa), NULL, TRUE};
HANDLE stdout_read = NULL;
HANDLE stdout_write = NULL;
HANDLE stderr_read = NULL;
HANDLE stderr_write = NULL;
if (!CreatePipe(&stdout_read, &stdout_write, &sa, 0) ||
!CreatePipe(&stderr_read, &stderr_write, &sa, 0)) {
goto cleanup_command;
}
// Make read ends non-inheritable
SetHandleInformation(stdout_read, HANDLE_FLAG_INHERIT, 0);
SetHandleInformation(stderr_read, HANDLE_FLAG_INHERIT, 0);
// Setup process
STARTUPINFOW si = {0};
si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdOutput = stdout_write;
si.hStdError = stderr_write;
si.hStdInput = CreateFileW(L"NUL", GENERIC_READ, FILE_SHARE_READ, &sa,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
PROCESS_INFORMATION pi = {0};
if (!CreateProcessW(NULL, command_line, NULL, NULL, TRUE, CREATE_NO_WINDOW,
NULL, NULL, &si, &pi)) {
if (si.hStdInput != INVALID_HANDLE_VALUE) {
CloseHandle(si.hStdInput);
}
goto cleanup_pipes;
}
// Close write ends in parent
CloseHandle(stdout_write);
stdout_write = NULL;
CloseHandle(stderr_write);
stderr_write = NULL;
if (si.hStdInput != INVALID_HANDLE_VALUE) {
CloseHandle(si.hStdInput);
}
// Read from child's output
read_pipe(stdout_read, &результат_виконання->стдвив);
read_pipe(stderr_read, &результат_виконання->стдпом);
// Wait and get exit code
WaitForSingleObject(pi.hProcess, INFINITE);
DWORD exit_code = 0;
if (GetExitCodeProcess(pi.hProcess, &exit_code)) {
результат_виконання->код = (ц32)exit_code;
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
cleanup_pipes:
if (stdout_read) {
CloseHandle(stdout_read);
}
if (stdout_write) {
CloseHandle(stdout_write);
}
if (stderr_read) {
CloseHandle(stderr_read);
}
if (stderr_write) {
CloseHandle(stderr_write);
}
cleanup_command:
free(command_line);
for (природне i = 0; i < кількість_аргументів; ++i) {
free(wide_args[i]);
}
free(wide_args);
}