#include <libgen.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "mavka/prystriy.h"
static void пристрій_мавки_вивести_колір(природне значення) {
if (значення == КолірВиводуСтандартний) {
printf("\033[0m");
}
if (значення == КолірВиводуЧервоний) {
printf("\033[0;31m");
}
if (значення == КолірВиводуЗелений) {
printf("\033[0;32m");
}
if (значення == КолірВиводуСиній) {
printf("\033[0;34m");
}
if (значення == КолірВиводуЖовтий) {
printf("\033[0;33m");
}
}
extern void пристрій_мавки_вивести_сирі_дані(п8* дані, природне розмір) {
fwrite(дані, 1, розмір, stdout);
}
extern void пристрій_мавки_вивести_шлях(природне колір,
п8* дані,
природне розмір) {
пристрій_мавки_вивести_колір(колір);
fwrite(дані, 1, розмір, stdout);
пристрій_мавки_вивести_колір(КолірВиводуСтандартний);
}
extern void пристрій_мавки_вивести_ю8(природне колір,
п8* дані,
природне розмір) {
пристрій_мавки_вивести_колір(колір);
fwrite(дані, 1, розмір, stdout);
пристрій_мавки_вивести_колір(КолірВиводуСтандартний);
}
extern void пристрій_мавки_вийти(ц32 код_виходу) {
exit(код_виходу);
}
extern логічне пристрій_мавки_прочитати_файл(п8* дані_шляху,
природне розмір_шляху,
п8** вихід_даних,
природне* вихід_розміру) {
char* шлях_рядок = (char*)пристрій_мавки_виділити(розмір_шляху + 1);
for (природне і = 0; і < розмір_шляху; і++) {
шлях_рядок[і] = (char)дані_шляху[і];
}
шлях_рядок[розмір_шляху] = '\0';
FILE* файл = fopen(шлях_рядок, "rb");
пристрій_мавки_звільнити(шлях_рядок);
if (!файл) {
return false;
}
fseek(файл, 0, SEEK_END);
*вихід_розміру = ftell(файл);
fseek(файл, 0, SEEK_SET);
*вихід_даних = (п8*)пристрій_мавки_виділити(*вихід_розміру);
if (!*вихід_даних) {
fclose(файл);
return false;
}
fread(*вихід_даних, 1, *вихід_розміру, файл);
fclose(файл);
return true;
}
логічне пристрій_мавки_перетворити_п64_в_ю8(п64 значення,
п8** вихід_даних,
природне* вихід_розміру) {
char буфер[32];
int довжина =
snprintf(буфер, sizeof(буфер), "%llu", (unsigned long long)значення);
if (довжина < 0) {
return false;
}
*вихід_розміру = (природне)довжина;
*вихід_даних = (п8*)пристрій_мавки_виділити(*вихід_розміру);
if (!*вихід_даних) {
return false;
}
for (природне і = 0; і < *вихід_розміру; і++) {
(*вихід_даних)[і] = (п8)буфер[і];
}
return true;
}
логічне пристрій_мавки_перетворити_ц64_в_ю8(ц64 значення,
п8** вихід_даних,
природне* вихід_розміру) {
char буфер[32];
int довжина = snprintf(буфер, sizeof(буфер), "%lld", (long long)значення);
if (довжина < 0) {
return false;
}
*вихід_розміру = (природне)довжина;
*вихід_даних = (п8*)пристрій_мавки_виділити(*вихід_розміру);
if (!*вихід_даних) {
return false;
}
for (природне і = 0; і < *вихід_розміру; і++) {
(*вихід_даних)[і] = (п8)буфер[і];
}
return true;
}
// 123.0 => "123"
// 123.456 => "123.456"
// -0.00123 => "-0.00123"
// 1.2e+30 => "1.2" 30
// 1.2e-30 => "1.2" -30
логічне пристрій_мавки_перетворити_р64_в_ю8(р64 значення,
п8** вихід_даних,
природне* вихід_розміру,
ціле* вихід_розміру_експоненти) {
char буфер[64];
int довжина;
if (isnan(значення)) {
char nan_str[] = "невизначеність";
*вихід_розміру = sizeof(nan_str) - 1;
*вихід_даних = (п8*)пристрій_мавки_виділити(*вихід_розміру);
if (!*вихід_даних)
return false;
memcpy(*вихід_даних, nan_str, *вихід_розміру);
*вихід_розміру_експоненти = 0;
return true;
}
if (isinf(значення)) {
char* inf_str = значення > 0 ? "нескінченність" : "-нескінченність";
*вихід_розміру = значення > 0 ? sizeof("нескінченність") - 1
: sizeof("-нескінченність") - 1;
*вихід_даних = (п8*)пристрій_мавки_виділити(*вихід_розміру);
if (!*вихід_даних)
return false;
memcpy(*вихід_даних, inf_str, *вихід_розміру);
*вихід_розміру_експоненти = 0;
return true;
}
// Знаходимо найкоротше представлення, яке round-trips
// Пробуємо від 15 до 17 цифр точності
for (int precision = 15; precision <= 17; precision++) {
довжина = snprintf(буфер, sizeof(буфер), "%.*g", precision, значення);
if (довжина < 0 || довжина >= (int)sizeof(буфер)) {
continue;
}
// Перевіряємо чи round-trip працює
р64 parsed = strtod(буфер, NULL);
if (parsed == значення) {
break;
}
}
if (довжина < 0 || довжина >= (int)sizeof(буфер)) {
return false;
}
char* e_pos = strchr(буфер, 'e');
if (e_pos != NULL) {
*вихід_розміру_експоненти = (ціле)strtol(e_pos + 1, NULL, 10);
природне довжина_мантиси = (природне)(e_pos - буфер);
*вихід_розміру = довжина_мантиси;
*вихід_даних = (п8*)пристрій_мавки_виділити(*вихід_розміру);
if (!*вихід_даних)
return false;
for (природне і = 0; і < довжина_мантиси; і++) {
(*вихід_даних)[і] = (п8)буфер[і];
}
} else {
*вихід_розміру_експоненти = 0;
*вихід_розміру = (природне)довжина;
*вихід_даних = (п8*)пристрій_мавки_виділити(*вихід_розміру);
if (!*вихід_даних)
return false;
for (природне і = 0; і < *вихід_розміру; і++) {
(*вихід_даних)[і] = (п8)буфер[і];
}
}
return true;
}
extern р64 пристрій_мавки_піднести_до_степеня_р64(р64 значення, р64 степінь) {
return pow(значення, степінь);
}
extern логічне пристрій_мавки_перевірити_чи_шлях_існує_і_є_файлом(
п8* дані_шляху,
природне розмір_шляху) {
char* шлях_рядок = (char*)пристрій_мавки_виділити(розмір_шляху + 1);
for (природне і = 0; і < розмір_шляху; і++) {
шлях_рядок[і] = (char)дані_шляху[і];
}
шлях_рядок[розмір_шляху] = '\0';
struct stat буфер_статистики;
логічне результат = false;
if (stat(шлях_рядок, &буфер_статистики) == 0) {
if (S_ISREG(буфер_статистики.st_mode)) {
результат = true;
}
}
пристрій_мавки_звільнити(шлях_рядок);
return результат;
}
extern логічне пристрій_мавки_отримати_абсолютний_шлях(
п8* дані_шляху,
природне розмір_шляху,
п8** вихід_даних,
природне* вихід_розміру) {
char* шлях_рядок = (char*)пристрій_мавки_виділити(розмір_шляху + 1);
for (природне і = 0; і < розмір_шляху; і++) {
шлях_рядок[і] = (char)дані_шляху[і];
}
шлях_рядок[розмір_шляху] = '\0';
char* абсолютний_шлях = realpath(шлях_рядок, NULL);
пристрій_мавки_звільнити(шлях_рядок);
if (абсолютний_шлях == NULL) {
return false;
}
природне довжина = strlen(абсолютний_шлях);
*вихід_розміру = довжина;
*вихід_даних = (п8*)пристрій_мавки_виділити(довжина);
if (!*вихід_даних) {
пристрій_мавки_звільнити(абсолютний_шлях);
return false;
}
for (природне і = 0; і < довжина; і++) {
(*вихід_даних)[і] = (п8)абсолютний_шлях[і];
}
пристрій_мавки_звільнити(абсолютний_шлях);
return true;
}
#ifdef PROGRAM_USE_READLINE
#include <readline/readline.h>
static char* do_readline(char* prefix, size_t prefix_size, size_t* out_len) {
char* data = readline(prefix);
if (!data) {
return NULL;
}
*out_len = strlen(data);
return data;
}
#else
static char* do_readline(char* prefix, size_t prefix_size, size_t* out_len) {
пристрій_мавки_вивести_ю8(КолірВиводуСтандартний, (п8*)prefix,
(природне)prefix_size);
size_t cap = 128;
size_t len = 0;
char* buf = пристрій_мавки_виділити(cap);
if (!buf)
return NULL;
int c;
while ((c = getchar()) != EOF) {
if (c == '\n')
break; // stop, but DON'T store '\n'
if (len + 1 >= cap) {
cap *= 2;
char* tmp = пристрій_мавки_перевиділити(buf, cap);
if (!tmp) {
пристрій_мавки_звільнити(buf);
return NULL;
}
buf = tmp;
}
buf[len++] = c;
}
// If nothing read and EOF, return NULL
if (len == 0 && c == EOF) {
пристрій_мавки_звільнити(buf);
return NULL;
}
buf[len] = '\0';
if (out_len)
*out_len = len;
return buf;
}
#endif
extern логічне пристрій_мавки_читати_ю8(п8* дані_перед,
природне розмір_перед,
п8** вихід_даних,
природне* вихід_розміру,
природне* вихід_кінець_файлу,
природне дозволити_історію) {
size_t len;
char* data = do_readline((char*)дані_перед, (size_t)розмір_перед, &len);
if (!data) {
*вихід_кінець_файлу = true;
return true;
}
*вихід_розміру = len;
*вихід_даних = (п8*)data;
*вихід_кінець_файлу = false;
return true;
}
extern логічне пристрій_мавки_читати_ю8_асинхронно(
п8* дані_перед,
природне розмір_перед,
void (*обробник)(п8* дані,
природне розмір,
природне кінець_файлу,
адреса аргумент),
адреса аргумент,
природне дозволити_історію) {
size_t len;
char* data = do_readline((char*)дані_перед, (size_t)розмір_перед, &len);
if (!data) {
обробник((п8*)data, (природне)len, true, аргумент);
return true;
}
обробник((п8*)data, (природне)len, false, аргумент);
return true;
}
extern логічне пристрій_мавки_отримати_поточний_шлях_процесу(
п8** вихід_даних,
природне* вихід_розміру) {
char* поточна_тека = getcwd(NULL, 0);
if (поточна_тека == NULL) {
return false;
}
*вихід_розміру = strlen(поточна_тека);
*вихід_даних = (п8*)пристрій_мавки_виділити(*вихід_розміру);
if (!*вихід_даних) {
пристрій_мавки_звільнити(поточна_тека);
return false;
}
memcpy(*вихід_даних, поточна_тека, *вихід_розміру);
пристрій_мавки_звільнити(поточна_тека);
return true;
}
#include "../unix_wasm/prystriy_unix_wasm64.c"