// about
// licenze:
// This code and its derivatives can be used under the following conditions:
// - Do not attack other countries.
// - Jerk off on public at least 1 time per day.
// - Observe hygiene.
// - check my other projects https://chiselapp.com/user/sergey6661313
// about:
// ScalpiEditor - ansi-only text editor for terminals.
// killer features: no. its just editor.
// Compile:
// this file is just part of zig version (for now)
// current version used zig compiller for compile zig file. (unstructions inside zig file)
// in future you can use tcc for compile
// tcc se_windows.c
// to support me
// with boosty:
// https://boosty.to/cutloosedev
// with monero:
// 87T7 qGbA TrM3 a6Br
// DyeC jQQf NWtU u3iZ
// bHVB MC6W mEbN NE13
// Qrrt KhBb e4vF 58NR
// 8PTF dYk2 Sozc HexX
// 4Q69 jbdQ Asrs P7B
// imports
// libC
#include "stdarg.h"
#include "stdbool.h"
#include "stddef.h"
#include "stdint.h"
#include "stdio.h"
#include "stdlib.h"
#include "assert.h"
#include "ctype.h"
#include "errno.h"
#include "fenv.h"
#include "float.h"
#include "inttypes.h"
#include "iso646.h"
#include "limits.h"
#include "locale.h"
#include "math.h"
#include "setjmp.h"
#include "signal.h"
#include "string.h"
#include "tgmath.h"
#include "time.h"
#include "uchar.h"
#include "wchar.h"
#include "wctype.h"
#ifdef _WIN32
// posix
#include "fcntl.h"
// Windows
#include "windef.h"
#include "windows.h"
#include "winuser.h"
#include "commctrl.h"
#include "io.h"
#include "conio.h"
// network
// #include "ws2tcpip.h"
// #include "winsock2.h"
#elif defined(__linux__)
#include "sys/ioctl.h"
#include "termios.h"
#include "unistd.h"
// network
// #include "arpa/inet.h"
// #include "netinet/in.h"
// #include "netinet/ip.h"
// #include "sys/socket.h"
#endif
// enums and constants
// core
#define Endians_Little 1
#define Endians_Big 2
// time
#define Scalpi_time_ms_per_s 1000
// Scalpi_Logger_writers
#define Scalpi_Logger_writers_c_out_writer 0
#define Scalpi_Logger_writers_file_writer 1
#define Scalpi_Logger_writers_console_writer 2
#define Scalpi_Logger_writers_terminal_writer 3
// Scalpi_Console_ansi
#define Scalpi_Console_ansi_esc "\x1B"
#define Scalpi_Console_ansi_control Scalpi_Console_ansi_esc "["
#define Scalpi_Console_ansi_output_clear_to_end_line Scalpi_Console_ansi_control "0K"
#define Scalpi_Console_ansi_output_clear_to_start_line Scalpi_Console_ansi_control "1K"
#define Scalpi_Console_ansi_output_clear_line Scalpi_Console_ansi_control "2K"
// cursor
#define Scalpi_Console_ansi_output_cursor_hide Scalpi_Console_ansi_control "?25l"
#define Scalpi_Console_ansi_output_cursor_show Scalpi_Console_ansi_control "?25h"
#define Scalpi_Console_ansi_output_cursor_style_reset Scalpi_Console_ansi_control "0 q"
#define Scalpi_Console_ansi_output_cursor_style_blinking_block Scalpi_Console_ansi_control "1 q"
#define Scalpi_Console_ansi_output_cursor_style_steady_block Scalpi_Console_ansi_control "2 q"
#define Scalpi_Console_ansi_output_cursor_style_blinking_underline Scalpi_Console_ansi_control "3 q"
#define Scalpi_Console_ansi_output_cursor_style_steady_underline Scalpi_Console_ansi_control "4 q"
#define Scalpi_Console_ansi_output_cursor_style_blinking_I_beam Scalpi_Console_ansi_control "5 q"
#define Scalpi_Console_ansi_output_cursor_style_steady_I_beam Scalpi_Console_ansi_control "6 q"
// color
#define Scalpi_Console_ansi_output_FontStyle_color_zero "39"
#define Scalpi_Console_ansi_output_FontStyle_color_black "30"
#define Scalpi_Console_ansi_output_FontStyle_color_red "31"
#define Scalpi_Console_ansi_output_FontStyle_color_green "32"
#define Scalpi_Console_ansi_output_FontStyle_color_gold "33"
#define Scalpi_Console_ansi_output_FontStyle_color_blue "34"
#define Scalpi_Console_ansi_output_FontStyle_color_magenta "35"
#define Scalpi_Console_ansi_output_FontStyle_color_cyan "36"
#define Scalpi_Console_ansi_output_FontStyle_color_light_gray "37"
#define Scalpi_Console_ansi_output_FontStyle_color_gray "90"
#define Scalpi_Console_ansi_output_FontStyle_color_pink "91"
#define Scalpi_Console_ansi_output_FontStyle_color_light_green "92"
#define Scalpi_Console_ansi_output_FontStyle_color_yellow "93"
#define Scalpi_Console_ansi_output_FontStyle_color_light_blue "94"
#define Scalpi_Console_ansi_output_FontStyle_color_light_magenta "95"
#define Scalpi_Console_ansi_output_FontStyle_color_light_cyan "96"
#define Scalpi_Console_ansi_output_FontStyle_color_white "97"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_zero "49"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_black "40"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_red "41"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_green "42"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_gold "43"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_blue "44"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_magenta "45"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_cyan "46"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_light_gray "47"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_gray "100"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_pink "101"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_light_green "102"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_yellow "103"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_light_blue "104"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_light_magenta "105"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_light_cyan "106"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_white "107"
#define Scalpi_Console_ansi_output_FontStyle_sep ";"
#define Scalpi_Console_ansi_output_FontStyle_end "m"
#define Scalpi_Console_ansi_output_FontStyle_reset "0"
#define Scalpi_Console_ansi_output_FontStyle_bold "1"
#define Scalpi_Console_ansi_output_FontStyle_dim "2"
#define Scalpi_Console_ansi_output_FontStyle_italic "3"
#define Scalpi_Console_ansi_output_FontStyle_underline "4"
#define Scalpi_Console_ansi_output_FontStyle_conceal "8"
#define Scalpi_Console_ansi_output_FontStyle_fraktur "20"
#define Scalpi_Console_ansi_output_FontStyle_unbold "21;24"
#define Scalpi_Console_ansi_output_FontStyle_set_color "38"
#define Scalpi_Console_ansi_output_FontStyle_set_bg_color "48"
#define Scalpi_Console_ansi_output_FontStyle_start Scalpi_Console_ansi_control
#define Scalpi_Console_ansi_output_FontStyle_RESET Scalpi_Console_ansi_output_FontStyle_start Scalpi_Console_ansi_output_FontStyle_reset Scalpi_Console_ansi_output_FontStyle_end
// mouse
#define Scalpi_ansi_input_mouse_release Scalpi_Console_ansi_control "?1000l"
#define Scalpi_ansi_input_mouse_grab Scalpi_Console_ansi_control "?1000h"
#define Scalpi_Console_ansi_output_settings_enable_line_wrap "\x1b[?7h"
#define Scalpi_Console_ansi_output_settings_disable_line_wrap "\x1b[?7l"
// const Scalpi_Console_ansi_input_Key
// ascii
#define __Scalpi_Console_ansi_input_Key_ctrl_a__ 1 /* start_of_heading */
#define __Scalpi_Console_ansi_input_Key_ctrl_b__ 2
#define __Scalpi_Console_ansi_input_Key_ctrl_c__ 3
#define __Scalpi_Console_ansi_input_Key_ctrl_d__ 4
#define __Scalpi_Console_ansi_input_Key_ctrl_e__ 5
#define __Scalpi_Console_ansi_input_Key_ctrl_f__ 6
#define __Scalpi_Console_ansi_input_Key_ctrl_g__ 7
#define __Scalpi_Console_ansi_input_Key_ctrl_bs__ 8 /* ctrl_h */
#define __Scalpi_Console_ansi_input_Key_tab__ 9 /* ctrl_i */
#define __Scalpi_Console_ansi_input_Key_ctrl_j__ 10
#define __Scalpi_Console_ansi_input_Key_ctrl_k__ 11 /* vertical_tab */
#define __Scalpi_Console_ansi_input_Key_ctrl_l__ 12 /* formFeed */
#define __Scalpi_Console_ansi_input_Key_enter__ 13 /* ctrl_m */
#define __Scalpi_Console_ansi_input_Key_ctrl_n__ 14
#define __Scalpi_Console_ansi_input_Key_ctrl_o__ 15
#define __Scalpi_Console_ansi_input_Key_ctrl_p__ 16
#define __Scalpi_Console_ansi_input_Key_ctrl_q__ 17
#define __Scalpi_Console_ansi_input_Key_ctrl_r__ 18
#define __Scalpi_Console_ansi_input_Key_ctrl_s__ 19
#define __Scalpi_Console_ansi_input_Key_ctrl_t__ 20
#define __Scalpi_Console_ansi_input_Key_ctrl_u__ 21
#define __Scalpi_Console_ansi_input_Key_ctrl_v__ 22
#define __Scalpi_Console_ansi_input_Key_ctrl_w__ 23
#define __Scalpi_Console_ansi_input_Key_ctrl_x__ 24
#define __Scalpi_Console_ansi_input_Key_ctrl_y__ 25
#define __Scalpi_Console_ansi_input_Key_ctrl_z__ 26
#define __Scalpi_Console_ansi_input_Key_escape__ 27
#define __Scalpi_Console_ansi_input_Key_back_space__ 127 /* sometime delete */
#define __Scalpi_Console_ansi_input_Key_non_ascii__ 256
#define __Scalpi_Console_ansi_input_Key_mouse__ 257
// FN
#define __Scalpi_Console_ansi_input_Key_f1__ 301
#define __Scalpi_Console_ansi_input_Key_f2__ 302
#define __Scalpi_Console_ansi_input_Key_f3__ 303
#define __Scalpi_Console_ansi_input_Key_f4__ 304
#define __Scalpi_Console_ansi_input_Key_f5__ 305
#define __Scalpi_Console_ansi_input_Key_f6__ 306
#define __Scalpi_Console_ansi_input_Key_f7__ 307
#define __Scalpi_Console_ansi_input_Key_f8__ 308
#define __Scalpi_Console_ansi_input_Key_f9__ 309
#define __Scalpi_Console_ansi_input_Key_f10__ 310
#define __Scalpi_Console_ansi_input_Key_f11__ 311
#define __Scalpi_Console_ansi_input_Key_f12__ 312
#define __Scalpi_Console_ansi_input_Key_f1_rxvt__ 401
#define __Scalpi_Console_ansi_input_Key_f2_rxvt__ 402
#define __Scalpi_Console_ansi_input_Key_f1_tty__ 501
#define __Scalpi_Console_ansi_input_Key_f2_tty__ 502
#define __Scalpi_Console_ansi_input_Key_f3_tty__ 503
#define __Scalpi_Console_ansi_input_Key_f4_tty__ 504
// arrows
// left
#define __Scalpi_Console_ansi_input_Key_left__ 1000
#define __Scalpi_Console_ansi_input_Key_ctrl_left__ 1001
#define __Scalpi_Console_ansi_input_Key_ctrl_left_rxvt__ 1002
#define __Scalpi_Console_ansi_input_Key_ctrl_shift_left__ 1003
#define __Scalpi_Console_ansi_input_Key_shift_left__ 1004
#define __Scalpi_Console_ansi_input_Key_alt_left__ 1005
// right
#define __Scalpi_Console_ansi_input_Key_right__ 1100
#define __Scalpi_Console_ansi_input_Key_ctrl_right__ 1101
#define __Scalpi_Console_ansi_input_Key_ctrl_right_rxvt__ 1102
#define __Scalpi_Console_ansi_input_Key_ctrl_shift_right__ 1103
#define __Scalpi_Console_ansi_input_Key_shift_right__ 1104
#define __Scalpi_Console_ansi_input_Key_alt_right__ 1105
// up
#define __Scalpi_Console_ansi_input_Key_up__ 1200
#define __Scalpi_Console_ansi_input_Key_ctrl_up__ 1201
#define __Scalpi_Console_ansi_input_Key_shift_up__ 1202
#define __Scalpi_Console_ansi_input_Key_alt_up__ 1203
// down
#define __Scalpi_Console_ansi_input_Key_down__ 1300
#define __Scalpi_Console_ansi_input_Key_ctrl_down__ 1301
#define __Scalpi_Console_ansi_input_Key_shift_down__ 1302
#define __Scalpi_Console_ansi_input_Key_alt_down__ 1303
// spec keys
#define __Scalpi_Console_ansi_input_Key_delete__ 1400
#define __Scalpi_Console_ansi_input_Key_shift_delete__ 1401
#define __Scalpi_Console_ansi_input_Key_page_up__ 1402
#define __Scalpi_Console_ansi_input_Key_page_down__ 1403
#define __Scalpi_Console_ansi_input_Key_end__ 1404
#define __Scalpi_Console_ansi_input_Key_home__ 1405
#define __Scalpi_Console_ansi_input_Key_ctrl_enter__ 1501
#define __Scalpi_Console_ansi_input_Key_ctrl_triangular_open_quotation_mark__ 1502
#define __Scalpi_Console_ansi_input_Key_ctrl_triangular_close_quotation_mark__ 1503
#define __Scalpi_Console_ansi_input_Key_ctrl_alt_v__ 2000
// altX
#define __Scalpi_Console_ansi_input_Key_alt_a__ 3000
#define __Scalpi_Console_ansi_input_Key_alt_b__ 3001
#define __Scalpi_Console_ansi_input_Key_alt_c__ 3002
#define __Scalpi_Console_ansi_input_Key_alt_d__ 3003
#define __Scalpi_Console_ansi_input_Key_alt_e__ 3004
#define __Scalpi_Console_ansi_input_Key_alt_f__ 3005
#define __Scalpi_Console_ansi_input_Key_alt_g__ 3006
#define __Scalpi_Console_ansi_input_Key_alt_h__ 3007
#define __Scalpi_Console_ansi_input_Key_alt_i__ 3008
#define __Scalpi_Console_ansi_input_Key_alt_j__ 3009
#define __Scalpi_Console_ansi_input_Key_alt_k__ 3010
#define __Scalpi_Console_ansi_input_Key_alt_l__ 3011
#define __Scalpi_Console_ansi_input_Key_alt_m__ 3012
#define __Scalpi_Console_ansi_input_Key_alt_n__ 3013
#define __Scalpi_Console_ansi_input_Key_alt_o__ 3014
#define __Scalpi_Console_ansi_input_Key_alt_p__ 3015
#define __Scalpi_Console_ansi_input_Key_alt_q__ 3016
#define __Scalpi_Console_ansi_input_Key_alt_r__ 3017
#define __Scalpi_Console_ansi_input_Key_alt_s__ 3018
#define __Scalpi_Console_ansi_input_Key_alt_t__ 3019
#define __Scalpi_Console_ansi_input_Key_alt_u__ 3020
#define __Scalpi_Console_ansi_input_Key_alt_v__ 3021
#define __Scalpi_Console_ansi_input_Key_alt_w__ 3022
#define __Scalpi_Console_ansi_input_Key_alt_x__ 3023
#define __Scalpi_Console_ansi_input_Key_alt_y__ 3024
#define __Scalpi_Console_ansi_input_Key_alt_z__ 3025
// alt_shiftX,
#define __Scalpi_Console_ansi_input_Key_alt_M__ 3100
#define __Scalpi_Console_ansi_input_Key_alt_N__ 3101
// altN
#define __Scalpi_Console_ansi_input_Key_alt_0__ 3200
#define __Scalpi_Console_ansi_input_Key_alt_1__ 3201
#define __Scalpi_Console_ansi_input_Key_alt_2__ 3202
#define __Scalpi_Console_ansi_input_Key_alt_3__ 3203
#define __Scalpi_Console_ansi_input_Key_alt_4__ 3204
#define __Scalpi_Console_ansi_input_Key_alt_5__ 3205
#define __Scalpi_Console_ansi_input_Key_alt_6__ 3206
#define __Scalpi_Console_ansi_input_Key_alt_7__ 3207
#define __Scalpi_Console_ansi_input_Key_alt_8__ 3208
#define __Scalpi_Console_ansi_input_Key_alt_9__ 3209
// alt_spec
#define __Scalpi_Console_ansi_input_Key_alt_comma__ 3301
#define __Scalpi_Console_ansi_input_Key_alt_comma_1__ 3302
#define __Scalpi_Console_ansi_input_Key_alt_open_bracket__ 3303
#define __Scalpi_Console_ansi_input_Key_alt_close_bracket__ 3304
#define __Scalpi_Console_ansi_input_Key_alt_semicolon__ 3305
#define __Scalpi_Console_ansi_input_Key_alt_apostrophe__ 3306
// settings
#define MEMORY_TYPE_ENDIANS Endians_Little
#define __Scalpi_Terminal_Input_size__ 32
// App
#define App_expected_fps 30
// macroses
// c
#define or ||
#define and &&
#define OFFSETOF(type, field) ((size_t) &(((type *)0)->field))
#define FIELD_PARENT_PTR(type, field, instance) ((type *)((char *)(instance) - OFFSETOF(type, field)))
#define ARRAY_LEN(array) (sizeof(array) / sizeof(array[0]))
#define TEXT_LEN(str) (ARRAY_LEN(str) - 1)
// text
#define SLICE_TEXT(text) {.ptr=text, .len=TEXT_LEN(text)}
#define TEXT_PTR(text) (char(*)[TEXT_LEN(text)]) text
#define DEF_TEXT_PTR(name, text) char(*name)[TEXT_LEN(text)] = TEXT_PTR(text)
#define DEF_SLICE_TEXT(name, text) struct Slice name = SLICE_TEXT(text)
// App
#define App_delay_to_start_frame_target (Scalpi_time_ms_per_s / App_expected_fps)
// basic types
typedef uint64_t Scalpi_Console_ansi_input_Key_t;
// structs
// core
// memory
typedef size_t (*WriteFnPtr) (void* context, const char bytes[], size_t bytes_len);
struct Slice {
char* ptr;
size_t len;
};
struct Finder {
struct Slice text;
struct Slice desired;
size_t pos;
};
// Os
struct Os_Console_Flags {
bool inited;
#ifdef _WIN32
DWORD input_mode;
DWORD output_mode;
#elif defined(__linux__)
struct termios termios;
#endif
};
// Os_Console_Input_Handle
#ifdef _WIN32
typedef void* Os_Console_Input_Handle;
#elif defined(__linux__)
typedef FILE* Os_Console_Input_Handle;
#endif
struct Os_Console_Input {
Os_Console_Input_Handle handle;
#ifdef _WIN32
#elif defined(__linux__)
int fileno;
#endif
};
// Os_Console_Output_Handle
#ifdef _WIN32
typedef void* Os_Console_Output_Handle;
#elif defined(__linux__)
typedef FILE* Os_Console_Output_Handle;
#endif
struct Os_Console_Output {
Os_Console_Output_Handle handle;
#ifdef _WIN32
#elif defined(__linux__)
int fileno;
#endif
};
// Scalpi
// text
struct Scalpi_Text_Splitter {
struct Finder finder;
bool stop;
size_t last_pos;
};
struct __Scalpi_Writer__ {
void* context;
WriteFnPtr write;
};
struct Scalpi_Logger {
// write to terminal, console, file or to all together, but no real check "bytes is writen"
struct __Scalpi_Writer__ writers[4] // Scalpi_Logger_writers
};
// Console
// __Scalpi_Console_ansi_input_Key_SequenceParser__
struct __Scalpi_Console_ansi_input_Key_SequenceParser__ {
Scalpi_Console_ansi_input_Key_t sequence;
size_t used;
};
struct Scalpi_Console_ansi_input_Key_SequenceParser_fromBytes_SequenceInfo {
const char* text;
size_t len;
Scalpi_Console_ansi_input_Key_t key;
};
struct __Scalpi_Console__ {
struct Os_Console_Input input;
struct Os_Console_Output output;
};
// Terminal
struct __Scalpi_Terminal_Input__ {
// usage:
// call __Scalpi_Terminal_Input_update_buffer__ for update unreaded
// use __Scalpi_Terminal_Input_grab__ in loop for get keys
size_t ungrabed;
char buffer[__Scalpi_Terminal_Input_size__];
};
// App
struct App_Os_Helper {
#ifdef _WIN32
// WinApi
HINSTANCE instance;
void* console_input_handle;
void* console_output_handle;
WSADATA wsdata;
#endif
};
struct App {
struct App_Os_Helper os_helper;
struct Scalpi_Logger logger;
uint64_t tick;
};
// function prototypes
// globals
struct App global_app;
// functions
// core
// mem
// bits operations
uint8_t bits_rotl8(uint8_t value, unsigned int shift) {
shift %= 8;
return (value << shift) | (value >> (8 - shift));
}
uint16_t bits_rotl16(uint16_t value, unsigned int shift) {
shift %= 16;
return (value << shift) | (value >> (16 - shift));
}
uint32_t bits_rotl32(uint32_t value, unsigned int shift) {
shift %= 32;
return (value << shift) | (value >> (32 - shift));
}
uint64_t bits_rotl64(uint64_t value, unsigned int shift) {
shift %= 64;
return (value << shift) | (value >> (64 - shift));
}
// bytes operations
size_t Scalpi_mem_fill(char* dest, char symbol, size_t len) {
for (size_t pos = 0; pos < len; pos++) {
dest[pos] = symbol;
}
}
size_t Scalpi_mem_write(char* dest, char* src, size_t size) {
// i use this instead memcpy becouse clang-in-zig just replace memcpy to crash-zig-bloated-version code
size_t pos;
for(pos = 0; pos < size; pos++) {
dest[pos] = src[pos];
}
return pos;
}
bool Scalpi_mem_isEql(const char a[], const char b[], size_t len) {
for(size_t pos = 0; pos < len; pos ++) {
char ac = a[pos];
char bc = b[pos];
if (ac != bc) return false;
}
return true;
}
void writeWithOffset(char* dest, size_t* writed, char* data, size_t data_len) {
*writed += Scalpi_mem_write(&dest[*writed], data, data_len);
}
// format_number
// copy non aligned data
void memcpy2(char* dest, char* src) {
dest[0] = src[0];
dest[1] = src[1];
}
void memcpy4(char* dest, char* src) {
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
dest[3] = src[3];
}
void memcpy8(char* dest, char* src) {
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
dest[3] = src[3];
dest[4] = src[4];
dest[5] = src[5];
dest[6] = src[6];
dest[7] = src[7];
}
// swap bytes for converting endians
void swapBytes16(char* a, char* b) {
// b is output
b[0] = a[1];
b[1] = a[0];
}
void swapBytes32(char* a, char* b) {
// b is output
b[0] = a[3];
b[1] = a[2];
b[2] = a[1];
b[3] = a[0];
}
void swapBytes64(char* a, char* b) {
// b is output
b[0] = a[7];
b[1] = a[6];
b[2] = a[5];
b[3] = a[4];
b[4] = a[3];
b[5] = a[2];
b[6] = a[1];
b[7] = a[0];
}
bool cpu_checkNumberFormat() {
char current_endians = 0;
int n = 1;
if (* (char *) &n == 1) {
current_endians = Endians_Little;
} else {
current_endians = Endians_Big;
}
if (MEMORY_TYPE_ENDIANS == current_endians) {
return true;
} else {
printf("%d wrong MEMORY_TYPE !\r\n", __LINE__);
}
return false;
}
#if MEMORY_TYPE_ENDIANS == Endians_Big
#define nativeToBig16(src, dest) memcpy2(dest, src)
#define nativeToBig32(src, dest) memcpy4(dest, src)
#define nativeToBig64(src, dest) memcpy8(dest, src)
#define nativeToLittle16(src, dest) swapBytes16(src, dest)
#define nativeToLittle32(src, dest) swapBytes32(src, dest)
#define nativeToLittle64(src, dest) swapBytes64(src, dest)
#elif MEMORY_TYPE_ENDIANS == Endians_Little
#define nativeToBig16(src, dest) swapBytes16(src, dest)
#define nativeToBig32(src, dest) swapBytes32(src, dest)
#define nativeToBig64(src, dest) swapBytes64(src, dest)
#define nativeToLittle16(src, dest) memcpy2(dest, src)
#define nativeToLittle32(src, dest) memcpy4(dest, src)
#define nativeToLittle64(src, dest) memcpy8(dest, src)
#else
#error "please define MEMORY_TYPE_ENDIANS with Endians_Big or Endians_Little. (you can test endings with cpu_checkNumberFormat function)"
#endif
// read unaligned memory
// big
uint16_t readBig16(char* src) {
uint16_t ret;
nativeToBig16(src, (char*) &ret);
return ret;
}
uint32_t readBig32(char* src) {
uint32_t ret;
nativeToBig32(src, (char*) &ret);
return ret;
}
uint64_t readBig64(char* src) {
uint64_t ret;
nativeToBig64(src, (char*) &ret);
return ret;
}
// little
uint16_t readLittle16(char* src) {
uint16_t ret;
nativeToLittle16(src, (char*) &ret);
return ret;
}
uint32_t readLittle32(char* src) {
uint32_t ret;
nativeToLittle32(src, (char*) &ret);
return ret;
}
uint64_t readLittle64(char* src) {
uint64_t ret;
nativeToLittle64(src, (char*) &ret);
return ret;
}
// write unaligned memory
// big
void writeBig16(uint16_t value, char* dest) {
nativeToBig16((char*)&value, dest);
}
void writeBig32(uint32_t value, char* dest) {
nativeToBig32((char*)&value, dest);
}
void writeBig64(uint64_t value, char* dest) {
nativeToBig64((char*)&value, dest);
}
// little
void writeLittle16(uint16_t value, char* dest) {
nativeToLittle16((char*)&value, dest);
}
void writeLittle32(uint32_t value, char* dest) {
nativeToLittle32((char*)&value, dest);
}
void writeLittle64(uint64_t value, char* dest) {
nativeToLittle64((char*)&value, dest);
}
// Slice
void Slice_debug(struct Slice* slice, char* name, size_t line) {
if (slice->len == 0) {
printf("%zu: %s is NULL. \r\n", line, name);
} else {
printf("%zu: %s (%zu): \"%.*s", line, name, slice->len, (int)slice->len, slice->ptr);
}
}
bool Scalpi_mem_find(struct Slice* slice, struct Slice* desired, uintptr_t* out_pos) {
// not fast
if (slice->len >= desired->len) {
uintptr_t last_pos = slice->len - desired->len;
for (uintptr_t pos = 0; pos <= last_pos; pos++) {
size_t slice_len = slice->len - pos;
if (slice_len >= desired->len) {
if (Scalpi_mem_isEql(&slice->ptr[pos], desired->ptr, desired->len)) {
*out_pos = pos;
return true;
}
} else {
break;
}
}
} else {
// printf("%d desired is too long\r\n", __LINE__);
}
return false;
}
bool isStartWith(struct Slice* a, struct Slice* b) {
return (a->len >= b->len) && Scalpi_mem_isEql(a->ptr, b->ptr, b->len);
}
// Finder
void Finder_init(struct Finder* t, char* text, size_t text_len, char* desired, size_t desired_len) {
t->pos = 0;
t->text.ptr = text;
t->text.len = text_len;
t->desired.ptr = desired;
t->desired.len = desired_len;
}
bool Finder_next(struct Finder* t, size_t* out_pos) {
if (t->pos != t->text.len) {
struct Slice slice; // = t->text[->.pos..];
slice.ptr = &t->text.ptr[t->pos];
slice.len = t->text.len - t->pos;
size_t finded;
if (Scalpi_mem_find(&slice, &t->desired, &finded)) {
size_t new_pos = t->pos + finded;
t->pos = new_pos + t->desired.len;
*out_pos = new_pos;
return true;
}
}
return false;
}
// text Splitter
void Scalpi_Text_Splitter_init(struct Scalpi_Text_Splitter* t, char* text, size_t text_len, char* delim, size_t delim_len) {
t->stop = false;
t->last_pos = 0;
Finder_init(&t->finder, text, text_len, delim, delim_len);
}
bool Scalpi_Text_Splitter_next(struct Scalpi_Text_Splitter* t, struct Slice* out_slice) {
if (t->stop == false) {
size_t finded;
if (Finder_next(&t->finder, &finded)) {
out_slice->ptr = &t->finder.text.ptr[t->last_pos]; // slice = t->finder.text[t->last_pos..finded];
out_slice->len = finded - t->last_pos;
t->last_pos = t->finder.pos;
return true;
} else {
t->stop = true;
out_slice->ptr = &t->finder.text.ptr[t->last_pos]; // slice = t->finder.text[t->last_pos..];
out_slice->len = t->finder.text.len - t->last_pos;
t->last_pos = t->finder.pos;
return true;
}
}
return false;
}
// math
uint32_t ceilDiv32(uint32_t a, uint32_t b) {
return (a + b - 1) / b;
}
// Os
// time
uint64_t os_getTick() {
#ifdef _WIN32
FILETIME ft;
GetSystemTimeAsFileTime(&ft);
uint64_t ft64;
memcpy8((char*) &ft64, (void*)&ft);
return ft64 / 10000; // in ft is intervals * 100 ns. to ms need * 100 / 1000000
#endif
// TODO ME FOR LINUX
}
void Os_sleep(uint64_t ms) {
#ifdef _WIN32
Sleep(ms);
#endif
// TODO ME FOR LINUX
}
void Os_Console_Output_init(struct Os_Console_Output* output, Os_Console_Output_Handle handle) {
output->handle = handle;
#ifdef _WIN32
// output->handle = GetStdHandle(c.STD_OUTPUT_HANDLE);
#elif defined(__linux__)
// output->handle = stdout
output->fileno = fileno(output->handle);
#endif
}
void Os_Console_Input_init(struct Os_Console_Input* input, Os_Console_Input_Handle handle) {
input->handle = handle;
#ifdef _WIN32
// output->handle = GetStdHandle(c.STD_INPUT_HANDLE);
#elif defined(__linux__)
// output->handle = stdout
input->fileno = fileno(input->handle);
#endif
}
size_t Os_Console_Output_write(struct Os_Console_Output* output, const char* text, size_t len) {
#ifdef _WIN32
size_t writed = 0;
WriteConsoleA(output->handle, text, len, &writed, 0);
#elif defined(__linux__)
//write(output->fileno, text, len);
fwrite(text, sizeof(char), len, output->handle);
#endif
return len;
}
// Scalpi lib
// C_Text
size_t C_Text_getLen(const char text[]) {
size_t len = 0;
while(text[len] != 0) len++;
return len;
}
size_t C_Text_writeToBuffer(char buffer[], char data[]) {
const size_t len = C_Text_getLen(data);
return Scalpi_mem_write(buffer, data, len);
}
size_t C_Text_writeToWriteFn(WriteFnPtr write, void* context, const char text[]) {
const size_t len = C_Text_getLen(text);
return write(context, text, len);
}
// Scalpi_Text_writeU64AsText
#define Scalpi_Text_CharsDecFromU64_MAX_LEN TEXT_LEN("18446744073709551615")
size_t Scalpi_Text_writeU64AsTextToBuffer(char buffer[], uint64_t number, size_t min_width) { // utoa
size_t writed = 0;
// write number to tmp
char buffer_tmp[Scalpi_Text_CharsDecFromU64_MAX_LEN];
uintptr_t tmp_ptr = (uintptr_t) &buffer_tmp[0] + Scalpi_Text_CharsDecFromU64_MAX_LEN;
for (uint64_t num = number; num > 0; num = num / 10) {
uint8_t remainder = num % 10;
tmp_ptr--;
*(char*)tmp_ptr = '0' + (char) remainder;
}
const uintptr_t writed_tmp = (uintptr_t) &buffer_tmp[0] + Scalpi_Text_CharsDecFromU64_MAX_LEN - (uintptr_t) tmp_ptr;
// fill zeroes to min_width
size_t extra_fill = 0;
if (min_width > writed_tmp) {
extra_fill = min_width - writed_tmp;
writed += Scalpi_mem_fill(&buffer[0], '0', extra_fill);
}
if (writed_tmp > 0) writed += Scalpi_mem_write(&buffer[writed], (char*)tmp_ptr, writed_tmp);
return writed;
}
size_t Scalpi_Text_writeU64AsTextToWriteFn(WriteFnPtr write, void* context, uint64_t number, size_t min_width) {
char buffer_tmp[Scalpi_Text_CharsDecFromU64_MAX_LEN];
const size_t writed = Scalpi_Text_writeU64AsTextToBuffer(buffer_tmp, number, min_width);
return write(context, buffer_tmp, writed);
}
// Scalpi_Logger
void Scalpi_Logger_init (struct Scalpi_Logger* t) {
for (int i = 0; i < ARRAY_LEN(t->writers); i++) {
struct __Scalpi_Writer__* w = &t->writers[i];
w->context = 0;
w->write = 0;
}
}
size_t Scalpi_Logger_writeToSelf(struct Scalpi_Logger* t, const char bytes[], size_t len) {
for (size_t i = 0; i < ARRAY_LEN(t->writers); i++) {
struct __Scalpi_Writer__* w = &t->writers[i];
if (w->write) {
size_t writed = w->write(w->context, bytes, len);
}
}
}
// App
// struct App_Os_Helper
bool App_Os_Helper_init(struct App_Os_Helper* os_helper) {
#ifdef _WIN32
os_helper->instance = GetModuleHandleA(0);
if (os_helper->instance) { // enable network
return true;
}
FreeLibrary(os_helper->instance);
return false;
#endif
// TODO ME FOR LINUX
}
void App_Os_Helper_deinit(struct App_Os_Helper* os_helper) {
#ifdef _WIN32
FreeLibrary(os_helper->instance);
#endif
// TODO ME FOR LINUX
}
void App_Os_Helper_process(struct App_Os_Helper* os_helper) {
#ifdef _WIN32
MSG msg;
size_t message_count = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE);
if (message_count == 0) return;
TranslateMessage(&msg);
DispatchMessageA(&msg);
#endif
// TODO ME FOR LINUX
}
// struct App
bool App_init(struct App* t) {
Scalpi_Logger_init(&t->logger); // preinit console output for debug
if (App_Os_Helper_init(&t->os_helper)) {
t->tick = os_getTick();
return true;
// fallback
// App_Os_Helper_deinit(&t->os_helper);
} else {
printf("%d app.os_helper not inited\r\n", __LINE__);
}
return false;
}
void App_deinit(struct App* app) {
App_Os_Helper_deinit(&app->os_helper);
}
bool App_process(struct App* t) {
App_Os_Helper_process(&t->os_helper);
return true;
}
void App_waitToNextFrame(struct App* t) {
uint64_t expected_frame_end_time = t->tick + App_delay_to_start_frame_target;
uint64_t resulting_frame_end_time = os_getTick();
if (resulting_frame_end_time > expected_frame_end_time + 120) {
uint64_t delta = resulting_frame_end_time - expected_frame_end_time;
printf("%d \t hitch detection: %zu delta: %zu ms \r\n", __LINE__, t->tick, delta);
}
uint64_t delay_sleep = 1;
if (resulting_frame_end_time < expected_frame_end_time) {
delay_sleep = expected_frame_end_time - resulting_frame_end_time;
}
Os_sleep(delay_sleep);
t->tick = resulting_frame_end_time + delay_sleep;
}
// main
bool tests() {
if ( true
and cpu_checkNumberFormat()
// and etc...
// and etc...
) {
return true;
} else {
printf("%d fail tests \r\n", __LINE__);
return false;
}
return true;
}
bool real_main(int args_len, char** args_ptr) {
if (tests()) {
if (App_init(&global_app)) {
while(true) {
if (!App_process(&global_app)) break;
App_waitToNextFrame(&global_app);
}
App_deinit(&global_app);
return true;
} else {
printf("%d fail: App_init\r\n", __LINE__);
}
} else {
printf("%d fail tests \r\n", __LINE__);
}
return false;
}
int main2(int args_len, char** args_ptr) {
printf("ScalpiEditor ver: " __TIMESTAMP__ " \r\n");
if (real_main(args_len, args_ptr)) return 0;
return 1;
}