// 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 any C compiller, but not now.
nevest C compillers is DUMB!
they insert thousands of checks of what I did not ask them to insert. Here is how you can avoid it:
-fno-stack-protector -fno-sanitize=undefined
also for debug use:
-Og -g
todo. alse try next keys for optimize size
-ffunction-sections -fdata-sections -Wl,--gc-sections
-nostdlib -Oz -Qn -m32 -static -s -N -Wl,--build-id=none -fno-asynchronous-unwind-tables
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
why i cancel use zig:
gabarages in output code.
zig perfecly crash without printing stack trace in non standart situations.
Zig does not try fix console flags before print stack trace.
zig can crash to segfault like c.
tagged enum does not sense.
c: tagged_enum.tag = ANOTHER_TAG;
zig: tagged_enum = .{.ANOTHER_TAG = tagged_enum.LAST_USED_TAG.data};
operator ".?" does not sense:
c: while(link) { i++; link = link->next; }
zig: while(link) |_| { i += 1; link = link.?.next; }
zig idiomatic: while(link) |unwrapped_link|{ i += 1; link = unwrapped_link.next; }
nullable types are inconvenient.
c: if (link) i++;
zig idiomatic: if (link) |_| i += 1;
zig but C pointer: if (@intFromPtr(link) != @intFromPtr(c.NULL)) i += 1;
*/
// TODO
/*
remove name buffer_len. use buffer_max_size and buffer_used instead.
fix bold in folding mode. why one upper line is skipped?
update OsConsoleInput_Handle // remove C variant.
*/
// enums and constants
// compilation target
// os
#define __TargetOs_windows__ 1
#define __TargetOs_linux__ 2
// memory type
#define __TargetMemoryType_endiansLittle__ 1
#define __TargetMemoryType_endiansBig__ 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_input_Key
// ascii
#define __Scalpi_Console_ansi_input_Key_ascii_ctrl__ (-'a' + 1) /* do not use externally */
#define __Scalpi_Console_ansi_input_Key_ctrl_bs__ 8 /* also ctrl_h */
#define __Scalpi_Console_ansi_input_Key_tab__ 9 /* also ctrl_i */
#define __Scalpi_Console_ansi_input_Key_enter__ 13 /* also ctrl_m */
#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_ctrl_a__ ('a' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 1 start_of_heading */
#define __Scalpi_Console_ansi_input_Key_ctrl_b__ ('b' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 2 */
#define __Scalpi_Console_ansi_input_Key_ctrl_c__ ('c' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 3 */
#define __Scalpi_Console_ansi_input_Key_ctrl_d__ ('d' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 4 */
#define __Scalpi_Console_ansi_input_Key_ctrl_e__ ('e' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 5 */
#define __Scalpi_Console_ansi_input_Key_ctrl_f__ ('f' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 6 */
#define __Scalpi_Console_ansi_input_Key_ctrl_g__ ('g' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 7 */
#define __Scalpi_Console_ansi_input_Key_ctrl_h__ ('h' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 8 also */ ctrl_bs */
#define __Scalpi_Console_ansi_input_Key_ctrl_i__ ('i' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 9 also */ tab */
#define __Scalpi_Console_ansi_input_Key_ctrl_j__ ('j' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 10 */
#define __Scalpi_Console_ansi_input_Key_ctrl_k__ ('k' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 11 vertical_tab */ */
#define __Scalpi_Console_ansi_input_Key_ctrl_l__ ('l' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 12 formFeed */ */
#define __Scalpi_Console_ansi_input_Key_ctrl_m__ ('m' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 13 also */ enter */
#define __Scalpi_Console_ansi_input_Key_ctrl_n__ ('n' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 14 */
#define __Scalpi_Console_ansi_input_Key_ctrl_o__ ('o' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 15 */
#define __Scalpi_Console_ansi_input_Key_ctrl_p__ ('p' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 16 */
#define __Scalpi_Console_ansi_input_Key_ctrl_q__ ('q' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 17 */
#define __Scalpi_Console_ansi_input_Key_ctrl_r__ ('r' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 18 */
#define __Scalpi_Console_ansi_input_Key_ctrl_s__ ('s' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 19 */
#define __Scalpi_Console_ansi_input_Key_ctrl_t__ ('t' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 20 */
#define __Scalpi_Console_ansi_input_Key_ctrl_u__ ('u' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 21 */
#define __Scalpi_Console_ansi_input_Key_ctrl_v__ ('v' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 22 */
#define __Scalpi_Console_ansi_input_Key_ctrl_w__ ('w' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 23 */
#define __Scalpi_Console_ansi_input_Key_ctrl_x__ ('x' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 24 */
#define __Scalpi_Console_ansi_input_Key_ctrl_y__ ('y' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 25 */
#define __Scalpi_Console_ansi_input_Key_ctrl_z__ ('z' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 26 */
// __Scalpi_Console_ansi_input_Key_non_ascii__
#define __Scalpi_Console_ansi_input_Key_special__ (1 << 8)
#define __Scalpi_Console_ansi_input_Key_functional__ (1 << 9)
#define __Scalpi_Console_ansi_input_Key_ctrl__ (1 << 10)
#define __Scalpi_Console_ansi_input_Key_alt__ (1 << 11)
#define __Scalpi_Console_ansi_input_Key_shift__ (1 << 12)
#define __Scalpi_Console_ansi_input_Key_mouse__ (1 << 13)
// FN
#define __Scalpi_Console_ansi_input_Key_f1__ (1 + __Scalpi_Console_ansi_input_Key_functional__)
#define __Scalpi_Console_ansi_input_Key_f2__ (2 + __Scalpi_Console_ansi_input_Key_functional__)
#define __Scalpi_Console_ansi_input_Key_f3__ (3 + __Scalpi_Console_ansi_input_Key_functional__)
#define __Scalpi_Console_ansi_input_Key_f4__ (4 + __Scalpi_Console_ansi_input_Key_functional__)
#define __Scalpi_Console_ansi_input_Key_f5__ (5 + __Scalpi_Console_ansi_input_Key_functional__)
#define __Scalpi_Console_ansi_input_Key_f6__ (6 + __Scalpi_Console_ansi_input_Key_functional__)
#define __Scalpi_Console_ansi_input_Key_f7__ (7 + __Scalpi_Console_ansi_input_Key_functional__)
#define __Scalpi_Console_ansi_input_Key_f8__ (8 + __Scalpi_Console_ansi_input_Key_functional__)
#define __Scalpi_Console_ansi_input_Key_f9__ (9 + __Scalpi_Console_ansi_input_Key_functional__)
#define __Scalpi_Console_ansi_input_Key_f10__ (10 + __Scalpi_Console_ansi_input_Key_functional__)
#define __Scalpi_Console_ansi_input_Key_f11__ (11 + __Scalpi_Console_ansi_input_Key_functional__)
#define __Scalpi_Console_ansi_input_Key_f12__ (12 + __Scalpi_Console_ansi_input_Key_functional__)
// arrows
// left
#define __Scalpi_Console_ansi_input_Key_left__ (1 + __Scalpi_Console_ansi_input_Key_special__)
#define __Scalpi_Console_ansi_input_Key_ctrl_left__ (__Scalpi_Console_ansi_input_Key_left__ + __Scalpi_Console_ansi_input_Key_ctrl__)
#define __Scalpi_Console_ansi_input_Key_alt_left__ (__Scalpi_Console_ansi_input_Key_left__ + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_shift_left__ (__Scalpi_Console_ansi_input_Key_left__ + __Scalpi_Console_ansi_input_Key_shift__)
#define __Scalpi_Console_ansi_input_Key_ctrl_shift_left__ (__Scalpi_Console_ansi_input_Key_left__ + __Scalpi_Console_ansi_input_Key_ctrl__ + __Scalpi_Console_ansi_input_Key_shift__)
// right
#define __Scalpi_Console_ansi_input_Key_right__ (2 + __Scalpi_Console_ansi_input_Key_special__)
#define __Scalpi_Console_ansi_input_Key_ctrl_right__ (__Scalpi_Console_ansi_input_Key_right__ + __Scalpi_Console_ansi_input_Key_ctrl__)
#define __Scalpi_Console_ansi_input_Key_alt_right__ (__Scalpi_Console_ansi_input_Key_right__ + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_shift_right__ (__Scalpi_Console_ansi_input_Key_right__ + __Scalpi_Console_ansi_input_Key_shift__)
#define __Scalpi_Console_ansi_input_Key_ctrl_shift_right__ (__Scalpi_Console_ansi_input_Key_right__ + __Scalpi_Console_ansi_input_Key_ctrl__ + __Scalpi_Console_ansi_input_Key_shift__)
// up
#define __Scalpi_Console_ansi_input_Key_up__ (3 + __Scalpi_Console_ansi_input_Key_special__)
#define __Scalpi_Console_ansi_input_Key_ctrl_up__ (__Scalpi_Console_ansi_input_Key_up__ + __Scalpi_Console_ansi_input_Key_ctrl__)
#define __Scalpi_Console_ansi_input_Key_alt_up__ (__Scalpi_Console_ansi_input_Key_up__ + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_shift_up__ (__Scalpi_Console_ansi_input_Key_up__ + __Scalpi_Console_ansi_input_Key_shift__)
// down
#define __Scalpi_Console_ansi_input_Key_down__ (4 + __Scalpi_Console_ansi_input_Key_special__)
#define __Scalpi_Console_ansi_input_Key_ctrl_down__ (__Scalpi_Console_ansi_input_Key_down__ + __Scalpi_Console_ansi_input_Key_ctrl__)
#define __Scalpi_Console_ansi_input_Key_alt_down__ (__Scalpi_Console_ansi_input_Key_down__ + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_shift_down__ (__Scalpi_Console_ansi_input_Key_down__ + __Scalpi_Console_ansi_input_Key_shift__)
// spec keys
#define __Scalpi_Console_ansi_input_Key_delete__ (5 + __Scalpi_Console_ansi_input_Key_special__)
#define __Scalpi_Console_ansi_input_Key_shift_delete__ (__Scalpi_Console_ansi_input_Key_delete__ + __Scalpi_Console_ansi_input_Key_shift__)
#define __Scalpi_Console_ansi_input_Key_page_up__ (6 + __Scalpi_Console_ansi_input_Key_special__)
#define __Scalpi_Console_ansi_input_Key_page_down__ (7 + __Scalpi_Console_ansi_input_Key_special__)
#define __Scalpi_Console_ansi_input_Key_end__ (8 + __Scalpi_Console_ansi_input_Key_special__)
#define __Scalpi_Console_ansi_input_Key_home__ (9 + __Scalpi_Console_ansi_input_Key_special__)
#define __Scalpi_Console_ansi_input_Key_ctrl_enter__ (__Scalpi_Console_ansi_input_Key_enter__ + __Scalpi_Console_ansi_input_Key_special__ + __Scalpi_Console_ansi_input_Key_ctrl__)
#define __Scalpi_Console_ansi_input_Key_ctrl_triangular_open_quotation_mark__ ('<' + __Scalpi_Console_ansi_input_Key_special__ + __Scalpi_Console_ansi_input_Key_ctrl__)
#define __Scalpi_Console_ansi_input_Key_ctrl_triangular_close_quotation_mark__ ('>' + __Scalpi_Console_ansi_input_Key_special__ + __Scalpi_Console_ansi_input_Key_ctrl__)
#define __Scalpi_Console_ansi_input_Key_ctrl_alt_v__ ('v' + __Scalpi_Console_ansi_input_Key_alt__ + __Scalpi_Console_ansi_input_Key_ctrl__)
// altX
#define __Scalpi_Console_ansi_input_Key_alt_a__ ('a' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_b__ ('b' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_c__ ('c' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_d__ ('d' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_e__ ('e' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_f__ ('f' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_g__ ('g' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_h__ ('h' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_i__ ('i' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_j__ ('j' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_k__ ('k' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_l__ ('l' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_m__ ('m' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_n__ ('n' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_o__ ('o' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_p__ ('p' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_q__ ('q' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_r__ ('r' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_s__ ('s' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_t__ ('t' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_u__ ('u' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_v__ ('v' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_w__ ('w' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_x__ ('x' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_y__ ('y' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_z__ ('z' + __Scalpi_Console_ansi_input_Key_alt__)
// alt_shiftX,
#define __Scalpi_Console_ansi_input_Key_alt_M__ ('M' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_N__ ('N' + __Scalpi_Console_ansi_input_Key_alt__)
// altN
#define __Scalpi_Console_ansi_input_Key_alt_0__ ('0' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_1__ ('1' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_2__ ('2' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_3__ ('3' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_4__ ('4' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_5__ ('5' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_6__ ('6' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_7__ ('7' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_8__ ('8' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_9__ ('9' + __Scalpi_Console_ansi_input_Key_alt__)
// alt_spec
#define __Scalpi_Console_ansi_input_Key_alt_comma__ (',' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_dot__ ('.' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_open_bracket__ ('[' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_close_bracket__ (']' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_semicolon__ (';' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_apostrophe__ ('`' + __Scalpi_Console_ansi_input_Key_alt__)
// websocket
#define __ScalpiNetworkTcpHttpWebSocketHandShake_encoded_text_len__ 28
// settings
// platform
// #define __target_os__ __TargetOs_
#ifndef __target_os__
#ifdef _WIN32
#define __target_os__ __TargetOs_windows__
#elif defined(__linux__)
#define __target_os__ __TargetOs_linux__
#endif
#endif
#if __target_os__ == __TargetOs_windows__
#elif __target_os__ == __TargetOs_linux__
#else
#error "__target_os__ not implemented"
#endif
#define __target_memory_type__ __TargetMemoryType_endiansLittle__
#define __with_network__ 0
#define __OsFilePathLen_max__ 1024
#define __ScalpiTerminalInput_size__ 32
// App
#define __AppEditorLineLen_max__ (1024 * 8)
#define App_expected_fps 30
// 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>
#if __target_os__ == __TargetOs_windows__
// posix
#include <fcntl.h>
// Windows
#include <windef.h>
#include <windows.h>
#include <winuser.h>
#include <commctrl.h>
#include <io.h>
#include <conio.h>
// HACK for zig 0.14
#define INVALID_HANDLE_VALUE (HANDLE)0xFFFFFFFF
#if __with_network__
#include <ws2tcpip.h>
#include <winsock2.h>
#endif
#elif __target_os__ == __TargetOs_linux__
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <termios.h>
#include <unistd.h>
#include <time.h>
#if __with_network__
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#endif
#endif
// strings
#define Scalpi_Text_CharsDecFromU64_MAX_LEN __CTextLen__("18446744073709551615")
// Scalpi_Console_ansi
#define Scalpi_Console_ansi_esc "\x1B"
#define __ScalpiConsoleAnsi_control__ Scalpi_Console_ansi_esc "["
// clear_output
#define Scalpi_Console_ansi_output_clear_to_end_line __ScalpiConsoleAnsi_control__ "0K"
#define Scalpi_Console_ansi_output_clear_to_start_line __ScalpiConsoleAnsi_control__ "1K"
#define Scalpi_Console_ansi_output_clear_line __ScalpiConsoleAnsi_control__ "2K"
// cursor
#define Scalpi_Console_ansi_output_cursor_hide __ScalpiConsoleAnsi_control__ "?25l"
#define Scalpi_Console_ansi_output_cursor_show __ScalpiConsoleAnsi_control__ "?25h"
#define __ScalpiConsoleAnsiOutputCursorStyle_reset__ __ScalpiConsoleAnsi_control__ "0 q"
#define Scalpi_Console_ansi_output_cursor_style_blinking_block __ScalpiConsoleAnsi_control__ "1 q"
#define Scalpi_Console_ansi_output_cursor_style_steady_block __ScalpiConsoleAnsi_control__ "2 q"
#define Scalpi_Console_ansi_output_cursor_style_blinking_underline __ScalpiConsoleAnsi_control__ "3 q"
#define Scalpi_Console_ansi_output_cursor_style_steady_underline __ScalpiConsoleAnsi_control__ "4 q"
#define Scalpi_Console_ansi_output_cursor_style_blinking_I_beam __ScalpiConsoleAnsi_control__ "5 q"
#define Scalpi_Console_ansi_output_cursor_style_steady_I_beam __ScalpiConsoleAnsi_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 __ScalpiConsoleAnsi_control__
#define __ScalpiConsoleAnsiOutputFontStyle_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 __ScalpiConsoleAnsi_control__ "?1000l"
#define Scalpi_ansi_input_mouse_grab __ScalpiConsoleAnsi_control__ "?1000h"
// settings
#define __ScalpiConsoleAnsiOutputSettings_enableLineWrap__ __ScalpiConsoleAnsi_control__ "?7h"
#define __ScalpiConsoleAnsiOutputSettings_disableLineWrap__ __ScalpiConsoleAnsi_control__ "?7l"
// __OsFilePath_separator__
#if __target_os__ == __TargetOs_windows__
#define __OsFilePath_separator__ "\\"
#elif __target_os__ == __TargetOs_linux__
#define __OsFilePath_separator__ "/"
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
// basic types
// scalpi
typedef uint8_t* __AlignedPtr__;
typedef uint64_t __ScalpiConsoleAnsiInputKey__;
typedef size_t (*__WriteFnPtr__) (void* context, const char* bytes, size_t bytes_len);
typedef void (*__WriteFnPtrVoid__) (void* context, const char* bytes, size_t bytes_len);
// OS
// var __OsFile__
#if __target_os__ == __TargetOs_windows__
typedef HANDLE __OsFile__;
#elif __target_os__ == __TargetOs_linux__
typedef int __OsFile__;
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
// var __OsConsoleInputHandle__
#if __target_os__ == __TargetOs_windows__
typedef void* __OsConsoleInputHandle__;
#elif __target_os__ == __TargetOs_linux__
typedef FILE* __OsConsoleInputHandle__;
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
// var __OsConsoleOutputHandle__
#if __target_os__ == __TargetOs_windows__
typedef HANDLE __OsConsoleOutputHandle__;
#elif __target_os__ == __TargetOs_linux__
typedef int __OsConsoleOutputHandle__;
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
// var __OsNetworkTcpHandle__
#if __target_os__ == __TargetOs_windows__
typedef SOCKET __OsNetworkTcpHandle__;
#elif __target_os__ == __TargetOs_linux__
typedef int __OsNetworkTcpHandle__;
#else
#error "__target_os__ not implemented"
#endif
// macroses
// c
#define or ||
#define and &&
#define __addrFromPtr__(ptr) ((uintptr_t)(ptr))
#define __ptrFromInt__(type, number) ((type*)number)
#define __getFieldPtr__(obj, field) (&((obj)->field))
#define __getField__(ptr, offset, type) (* (*type) ( __addrFromPtr__(ptr) + offset ) )
#define __alignOf__(type) (offsetof(struct { char c; type member; }, member))
#define __fieldParentPtr__(type, field, instance) ((type *)(__addrFromPtr__(instance) - offsetof(type, field)))
#define __arrayLen__(array) (sizeof(array) / sizeof(array[0]))
// text
#define __CTextLen__(str) (__arrayLen__(str) - 1)
#define __Slice_fromCText__(text) {.ptr=text, .len=__CTextLen__(text)}
#define __CTextPtr_fromCText__(text) ((char(*)[__CTextLen__(text)]) text)
#define __CTextPtr_lvalue__(name, text) (char(*name)[__CTextLen__(text)])
#define __CTextPtr_declare__(name, text) __CTextPtr_lvalue__(name, text) = __CTextPtr_fromCText__(text)
// crypto
#define Sha1_block_size 64
#define Sha1_digest_length 20
// Network
#define max_allowed_listen_port 49151
#define PRISOCK "%llx"
#if __target_os__ == __TargetOs_windows__
#define WSA_SUCCESS 0
#elif __target_os__ == __TargetOs_linux__
#else
#error "__target_os__ not implemented"
#endif
// Scalpi_network_tcp_http_WebSocket_Header
#define Scalpi_network_tcp_http_WebSocket_Header_Mask_size 4
// Scalpi_network_tcp_http_WebSocket_Header_Opcode
#define Scalpi_network_tcp_http_WebSocket_Header_Opcode_continuation 0
#define Scalpi_network_tcp_http_WebSocket_Header_Opcode_text 1
#define Scalpi_network_tcp_http_WebSocket_Header_Opcode_binary 2
#define Scalpi_network_tcp_http_WebSocket_Header_Opcode_close 8
#define Scalpi_network_tcp_http_WebSocket_Header_Opcode_ping 9
#define Scalpi_network_tcp_http_WebSocket_Header_Opcode_pong 10
// 2 bytes header for sizes 1 ... 125
#define Scalpi_network_tcp_http_WebSocket_Header_Size_small 0
#define Scalpi_network_tcp_http_WebSocket_Header_Size_small_header 2
#define Scalpi_network_tcp_http_WebSocket_Header_Size_small_extended_payload_len_size 0
// 4 bytes header for sizes 126 ... 65535
#define Scalpi_network_tcp_http_WebSocket_Header_Size_medium 1
#define Scalpi_network_tcp_http_WebSocket_Header_Size_medium_flag 126
#define Scalpi_network_tcp_http_WebSocket_Header_Size_medium_extended_payload_len_size 2
#define Scalpi_network_tcp_http_WebSocket_Header_Size_medium_header (Scalpi_network_tcp_http_WebSocket_Header_Size_small_header + Scalpi_network_tcp_http_WebSocket_Header_Size_medium_extended_payload_len_size)
// 10 bytes header for sizes more than 65535
#define Scalpi_network_tcp_http_WebSocket_Header_Size_long 2
#define Scalpi_network_tcp_http_WebSocket_Header_Size_long_flag 127
#define Scalpi_network_tcp_http_WebSocket_Header_Size_long_extended_payload_len_size 8
#define Scalpi_network_tcp_http_WebSocket_Header_Size_long_header (Scalpi_network_tcp_http_WebSocket_Header_Size_small_header + Scalpi_network_tcp_http_WebSocket_Header_Size_long_extended_payload_len_size)
// structs
// core
// memory
// __AlignedPtr__
// is pointer to data. but after data placed offset to origingal allocated pointer
// | data_size | u8 |
// original | data | offsetToOriginal |
//
struct __ScalpiMemListLink__ {
struct __ScalpiMemListLink__* prev;
struct __ScalpiMemListLink__* next;
struct __ScalpiMemList__* list;
};
struct __ScalpiMemList__ {
struct __ScalpiMemListLink__* first;
struct __ScalpiMemListLink__* last;
size_t count;
};
struct Slice {
char* ptr;
size_t len;
};
struct Finder {
struct Slice text;
struct Slice desired;
size_t pos;
};
// Os
// system specifics
#if __target_os__ == __TargetOs_windows__
#elif __target_os__ == __TargetOs_linux__
struct __OsLinux_timespec__ {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
#else
#error "__target_os__ not implemented"
#endif
// OsConsole
struct __OsConsoleFlags__ {
bool inited;
#if __target_os__ == __TargetOs_windows__
DWORD input_mode;
DWORD output_mode;
#elif __target_os__ == __TargetOs_linux__
struct termios termios;
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
};
struct __OsConsoleInput__ {
__OsConsoleInputHandle__ handle;
#if __target_os__ == __TargetOs_windows__
#elif __target_os__ == __TargetOs_linux__
int fileno;
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
};
struct __OsConsoleOutput__ {
#if __target_os__ == __TargetOs_windows__
__OsConsoleOutputHandle__ __OsConsoleOutput_handle__;
#elif __target_os__ == __TargetOs_linux__
__OsConsoleOutputHandle__ __OsConsoleOutput_handle__;
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
};
struct __OsHelper__ {
#if __target_os__ == __TargetOs_windows__
HINSTANCE instance;
void* console_input_handle;
__OsConsoleOutputHandle__ console_output_handle;
#if __with_network__
bool network_inited;
WSADATA wsdata;
#endif
#elif __target_os__ == __TargetOs_linux__
FILE* console_input_handle;
__OsConsoleOutputHandle__ console_output_handle;
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
};
// Scalpi
// mem
struct __Scalpi_Writer__ {
void* context;
__WriteFnPtr__ write;
};
struct __ScalpiMemTree__ {
struct __ScalpiMemTree__* parent; // todo remove me. use link.list or __ ...
struct __ScalpiMemList__ childs;
struct __ScalpiMemListLink__ link;
size_t count; // recurse. for get non recurse use childs.count
size_t nested;
};
// math
struct __Scalpi_math_d2_U_Pos__ {
size_t x;
size_t y;
};
// text
struct Scalpi_Text_Splitter {
struct Finder finder;
bool stop;
size_t last_pos;
};
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__ {
__ScalpiConsoleAnsiInputKey__ sequence;
size_t used;
};
struct Scalpi_Console_ansi_input_Key_SequenceParser_fromBytes_SequenceInfo {
const char* text;
size_t len;
__ScalpiConsoleAnsiInputKey__ key;
};
struct __ScalpiConsole__ {
struct __OsConsoleInput__ input;
struct __OsConsoleOutput__ output;
};
// Terminal
typedef struct __Scalpi_math_d2_U_Pos__ __ScalpiTerminalOutput_CursorPos__;
struct __ScalpiTerminalOutput__ {
__ScalpiTerminalOutput_CursorPos__ cursor_pos;
const char* font_style;
struct __Scalpi_math_d2_U_Pos__ size;
bool convert_n_to_rn;
bool apply_r;
bool apply_n;
};
struct __ScalpiTerminalInput__ {
// usage:
// call __ScalpiTerminalInput_updateBuffer__ for update unreaded
// use __ScalpiTerminalInput_grab__ in loop for get keys
size_t ungrabed;
char buffer[__ScalpiTerminalInput_size__];
};
struct __ScalpiTerminal__ {
struct __ScalpiConsole__* console;
struct __OsConsoleFlags__ system_flags;
struct __ScalpiTerminalInput__ input;
struct __ScalpiTerminalOutput__ output;
};
// crypto
// Sha1_Streaming
struct Sha1_Streaming {
uint32_t state[5];
char block[Sha1_block_size];
size_t buf_len; // current? filling level of block
uint64_t total_len;
};
struct RoundParam {uint32_t a; uint32_t b; uint32_t c; uint32_t d; uint32_t e; uint32_t i;};
// network
// Scalpi_network_tcp_Ip
// ip
struct Scalpi_network_tcp_Ip {
uint8_t address[4];
uint16_t port;
};
struct Scalpi_network_tcp_Ip_ToText {
/// 255.255.255.255:65535
/// 127. 0. 0. 1:27015
/// 0. 0. 0. 1: 0
char buffer[25];
size_t len;
};
#if __with_network__
struct Scalpi_network_tcp_Visitor {
__OsNetworkTcpHandle__ socket_handle;
struct Scalpi_network_tcp_Ip ip;
struct sockaddr_in addr;
};
#endif
struct Scalpi_network_tcp_Server {
bool ready;
__OsNetworkTcpHandle__ socket_handle;
size_t max_waiting_clients;
uint16_t port;
};
// Scalpi_network_tcp_http_WebSocket
// real struct of web socket header:
// fin_flag: u1 = 1,
// rsv: [3]u1 = .{0,0,0},
// opcode: Opcode = .binary, // may be text
// mask_flag: u1 = 0,
// payload_len: u7 = 0,
// extended_payload_len: u16 or u64 or void (optional)
// masking_key: u64 or void (optional)
struct Scalpi_network_tcp_http_WebSocket_Parser {
size_t frame_len;
size_t header_len;
char* message; // no null
size_t message_len;
};
// App
struct __AppEditorLine__ {
struct __ScalpiMemListLink__ link; // used in Views.Flat.lines for iterating
struct __ScalpiMemTree__ tree; // used in Views.Fold.lines
char text[__AppEditorLineLen_max__]; // todo use ptr to allocated data
size_t text_len;
};
struct __AppEditorHistoryNote__ {
__ScalpiConsoleAnsiInputKey__ key;
struct __ScalpiMemListLink__ link;
};
struct App {
struct __OsHelper__ __App_osHelper__;
struct Scalpi_Logger logger;
uint64_t tick;
};
// function prototypes
bool __OsFile_exist__(const char* file_name, size_t file_name_len);
bool __Os_allocBytes__(char**ret, size_t size);
void __Os_freeBytes__(char* ptr);
size_t __OsFallbackConsole_write__(void* unused_ctx, char* data, size_t len);
// 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
void __ScalpiMem_fill__(char* dest, char symbol, size_t len) {
for (size_t pos = 0; pos < len; pos++) {
dest[pos] = symbol;
}
}
void __ScalpiMem_copyBackward__(char* dest, const char* src, size_t size) {
size_t pos = size;
while(pos > 0) {
pos--;
dest[pos] = src[pos];
}
}
void __ScalpiMem_copy__(char* dest, const 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 = 0;
while(pos < size) {
dest[pos] = src[pos];
pos++;
}
}
bool __ScalpiMem_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) {
__ScalpiMem_copy__(&dest[*writed], data, data_len);
*writed += data_len;
}
// AlignedPtr
// var __AlignedPtr_alloc__
bool __AlignedPtr_alloc__(
__AlignedPtr__ *ret,
uint8_t mem_align, // expected >= 1
size_t size // expected >= 1
) {
bool ok = true;
size_t len = size + (mem_align - 1) + 1;
uintptr_t origin;
if (__Os_allocBytes__((void*) &origin, len)) {
uint8_t offset = 0;
uint8_t nodled = origin % mem_align;
if (nodled) {
offset = mem_align - nodled;
}
uintptr_t data_ptr = origin + offset;
uint8_t* offset_ptr = (uint8_t*) (data_ptr + size);
*offset_ptr = offset;
*ret = (void*)data_ptr;
if (!ok) __Os_freeBytes__((void*)origin);
} else {
ok = false;
}
return ok;
}
// var __AlignedPtr_free__
void __AlignedPtr_free__(
__AlignedPtr__ ptr,
size_t size
) {
uint8_t offset = ptr[size];
char* origin = (char*)((uintptr_t) ptr - offset);
free(origin);
}
void __ScalpiMem_reverse__(char dest[], const char src[], size_t len) {
const char* source = &src[len - 1];
size_t iter = 0;
for(; iter < len; iter++, dest++, source--) {
*dest = *source;
}
}
// format_number
bool cpu_checkNumberFormat() {
char current_endians = 0;
int n = 1;
if (* (char *) &n == 1) {
current_endians = __TargetMemoryType_endiansLittle__;
} else {
current_endians = __TargetMemoryType_endiansBig__;
}
if (__target_memory_type__ == current_endians) {
return true;
} else {
printf("%d wrong MEMORY_TYPE !\r\n", __LINE__);
}
return false;
}
#if __target_memory_type__ == __TargetMemoryType_endiansBig__
#define nativeToBig16(dest, src) __ScalpiMem_copy__(dest, src, 2)
#define nativeToBig32(dest, src) __ScalpiMem_copy__(dest, src, 4)
#define nativeToBig64(dest, src) __ScalpiMem_copy__(dest, src, 8)
#define nativeToLittle16(dest, src) __ScalpiMem_reverse__(dest, src, 2)
#define nativeToLittle32(dest, src) __ScalpiMem_reverse__(dest, src, 4)
#define nativeToLittle64(dest, src) __ScalpiMem_reverse__(dest, src, 8)
#elif __target_memory_type__ == __TargetMemoryType_endiansLittle__
#define nativeToBig16(dest, src) __ScalpiMem_reverse__(dest, src, 2)
#define nativeToBig32(dest, src) __ScalpiMem_reverse__(dest, src, 4)
#define nativeToBig64(dest, src) __ScalpiMem_reverse__(dest, src, 8)
#define nativeToLittle16(dest, src) __ScalpiMem_copy__(dest, src, 2)
#define nativeToLittle32(dest, src) __ScalpiMem_copy__(dest, src, 4)
#define nativeToLittle64(dest, src) __ScalpiMem_copy__(dest, src, 8)
#else
#error "please define __target_memory_type__ with __TargetMemoryType_ (you can test endings with cpu_checkNumberFormat function)"
#endif
// read unaligned memory
// big
uint16_t readBig16(char* src) {
uint16_t ret;
nativeToBig16( (char*) &ret, src );
return ret;
}
uint32_t readBig32(char* src) {
uint32_t ret;
nativeToBig32( (char*) &ret, src );
return ret;
}
uint64_t readBig64(char* src) {
uint64_t ret;
nativeToBig64( (char*) &ret, src );
return ret;
}
// little
uint16_t readLittle16(char* src) {
uint16_t ret;
nativeToLittle16( (char*) &ret, src );
return ret;
}
uint32_t readLittle32(char* src) {
uint32_t ret;
nativeToLittle32( (char*) &ret, src );
return ret;
}
uint64_t readLittle64(char* src) {
uint64_t ret;
nativeToLittle64( (char*) &ret, src );
return ret;
}
// write unaligned memory
// big
// var writeBig16
void writeBig16(
char *dest,
uint16_t value
) {
nativeToBig16( dest, (char*)&value );
}
// var writeBig32
void writeBig32(
char* dest,
uint32_t value
) {
nativeToBig32(dest, (char*)&value);
}
// var writeBig64
void writeBig64(
char* dest,
uint64_t value
) {
nativeToBig64(dest, (char*)&value);
}
// little
// var writeLittle16
void writeLittle16(
char* dest,
uint16_t value
) {
nativeToLittle16(dest, (char*)&value);
}
// var writeLittle32
void writeLittle32(
char* dest,
uint32_t value
) {
nativeToLittle32(dest, (char*)&value);
}
// var writeLittle64
void writeLittle64(
char* dest,
uint64_t value
) {
nativeToLittle64(dest, (char*)&value);
}
// 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 (__ScalpiMem_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) && __ScalpiMem_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;
}
// Scalpi_Text_writeU64AsText
size_t Scalpi_Text_writeU64AsTextToBuffer(char buffer[], uint64_t number, size_t min_width) { // utoa utos
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;
__ScalpiMem_fill__(&buffer[0], '0', extra_fill);
writed += extra_fill;
}
if (writed_tmp > 0) {
__ScalpiMem_copy__(&buffer[writed], (char*)tmp_ptr, writed_tmp);
writed += writed_tmp;
}
return writed;
}
size_t __ScalpiText_writeU64AsTextToWriteFnVoid__(__WriteFnPtrVoid__ fn_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[0], number, min_width);
fn_write(context, buffer_tmp, writed);
return writed;
}
// ZText - zero ended text
// TODO rename all functions to __ZText_...__
void __ZText_fromBytes__(char* buffer, const char bytes[], size_t bytes_len) {
// expected buffer_len >= bytes_len + 1
__ScalpiMem_copy__(buffer, bytes, bytes_len);
buffer[bytes_len] = 0;
}
size_t __ZText_countLen__(const char text[]) {
size_t len = 0;
while(text[len] != 0) len++;
return len;
}
size_t C_Text_writeToBuffer(char buffer[], const char data[]) {
const size_t len = __ZText_countLen__(data);
__ScalpiMem_copy__(buffer, data, len);
return len;
}
size_t C_Text_writeToWriteFn(__WriteFnPtr__ fn_write, void* context, const char text[]) {
const size_t len = __ZText_countLen__(text);
return fn_write(context, text, len);
}
// Os
// mem
// var __Os_allocBytes__
bool __Os_allocBytes__(
char* *ret,
size_t size
) {
bool ok = true;
char* ptr = malloc(size);
if (ptr) {
*ret = ptr;
} else {
ok = false;
// TODO print debug
}
return ok;
}
// var __Os_freeBytes__
void __Os_freeBytes__(char* ptr) {
free(ptr);
}
// enviroment
size_t __OsEnvHome_getLen__() {
size_t len = 0;
#if __target_os__ == __TargetOs_windows__
char* home_drive = getenv("HOMEDRIVE");
len += __ZText_countLen__(home_drive);
char* home_path = getenv("HOMEPATH");
len += __ZText_countLen__(home_path);
#elif __target_os__ == __TargetOs_linux__
char* home = getenv("HOME");
len += __ZText_countLen__(home);
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
return len;
}
// var __OsEnvHome_write__ TODO rename me to __OsEnvHome_write__
void __Os_writeHome__(
char* buffer // expected len >= __OsEnvHome_getLen__()
) {
#if __target_os__ == __TargetOs_windows__
size_t writed = 0;
// write HOMEDRIVE
char* home_drive = getenv("HOMEDRIVE");
size_t home_drive_len = __ZText_countLen__(home_drive);
__ScalpiMem_copy__(&buffer[writed], home_drive, home_drive_len);
writed += home_drive_len;
// write HOMEPATH
char* home_path = getenv("HOMEPATH");
size_t home_path_len = __ZText_countLen__(home_path);
__ScalpiMem_copy__(&buffer[writed], home_path, home_path_len);
writed += home_path_len;
#elif __target_os__ == __TargetOs_linux__
char* home = getenv("HOME");
size_t len = __ZText_countLen__(home);
__ScalpiMem_copy__(buffer, home, len);
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
}
// file
// var __OsFile_exist__
bool __OsFile_exist__(
const char* file_name,
size_t file_name_len // expected < __OsFilePathLen_max__
) {
bool ok = true;
#if __target_os__ == __TargetOs_windows__
char file_name_z[__OsFilePathLen_max__ + 1]; // create null terminated string
__ScalpiMem_copy__(file_name_z, file_name, file_name_len);
file_name_z[file_name_len] = 0;
DWORD attrs = GetFileAttributesA(file_name_z);
if (true
and (attrs != INVALID_FILE_ATTRIBUTES)
and (!(attrs & FILE_ATTRIBUTE_DIRECTORY))
) {
} else {
ok = false;
}
#elif __target_os__ == __TargetOs_linux__
char file_name_z[__OsFilePathLen_max__ + 1]; // create null terminated string
__ScalpiMem_copy__(file_name_z, file_name, file_name_len);
file_name_z[file_name_len] = 0;
struct stat buffer;
if (stat(file_name_z, &buffer) == 0) {
} else {
ok = false;
}
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
return ok;
}
// var __OsFile_create__
bool __OsFile_create__(
__OsFile__ *ret,
const char file_name[],
size_t file_name_len // expected < __OsFilePathLen_max__
) {
bool ok = true;
#if __target_os__ == __TargetOs_windows__
char file_name_z[__OsFilePathLen_max__ + 1]; // null terminated string
__ScalpiMem_copy__(file_name_z, file_name, file_name_len);
file_name_z[file_name_len] = 0;
HANDLE file = CreateFile( // open
file_name_z, // [in] LPCSTR lpFileName,
GENERIC_WRITE | GENERIC_READ, // [in] DWORD dwDesiredAccess,
0, // [in] DWORD dwShareMode, // TODO also try FILE_SHARE_WRITE
NULL, // [in, optional] LPSECURITY_ATTRIBUTES lpSecurityAttributes,
OPEN_ALWAYS, // [in] DWORD dwCreationDisposition,
FILE_ATTRIBUTE_NORMAL, // [in] DWORD dwFlagsAndAttributes,
NULL // [in, optional] HANDLE hTemplateFile
);
if (file != INVALID_HANDLE_VALUE) {
*ret = file;
} else {
ok = false;
}
#elif __target_os__ == __TargetOs_linux__
char file_name_z[__OsFilePathLen_max__ + 1]; // create null terminated string
__ScalpiMem_copy__(file_name_z, file_name, file_name_len);
file_name_z[file_name_len] = 0;
int file = creat(file_name_z, 0777);
if (file != -1) {
*ret = file;
} else {
ok = false;
}
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
return ok;
}
// var __OsFile_open__
bool __OsFile_open__(
__OsFile__ *ret,
const char file_name[],
size_t file_name_len // expected < __OsFilePathLen_max__
) {
bool ok = true;
#if __target_os__ == __TargetOs_windows__
char file_name_z[__OsFilePathLen_max__ + 1]; // null terminated string
__ScalpiMem_copy__(file_name_z, file_name, file_name_len);
file_name_z[file_name_len] = 0;
HANDLE file = CreateFile( // open
file_name_z, // [in] LPCSTR lpFileName,
GENERIC_WRITE | GENERIC_READ, // [in] DWORD dwDesiredAccess,
0, // [in] DWORD dwShareMode, // TODO also try FILE_SHARE_WRITE
NULL, // [in, optional] LPSECURITY_ATTRIBUTES lpSecurityAttributes,
OPEN_EXISTING, // [in] DWORD dwCreationDisposition,
FILE_ATTRIBUTE_NORMAL, // [in] DWORD dwFlagsAndAttributes,
NULL // [in, optional] HANDLE hTemplateFile
);
if (file != INVALID_HANDLE_VALUE) {
*ret = file;
} else {
ok = false;
}
#elif __target_os__ == __TargetOs_linux__
char file_name_z[__OsFilePathLen_max__ + 1]; // null terminated string
__ScalpiMem_copy__(file_name_z, file_name, file_name_len);
file_name_z[file_name_len] = 0;
// open
int file = open(file_name_z, O_RDWR);
if (file != -1) {
*ret = file;
} else {
ok = false;
}
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
return ok;
}
// var __OsFile_close__
void __OsFile_close__(
__OsFile__ file
) {
#if __target_os__ == __TargetOs_windows__
CloseHandle(file);
#elif __target_os__ == __TargetOs_linux__
close(file);
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
}
// var __OsFile_getPos__
size_t __OsFile_getPos__(
__OsFile__ file
) {
#if __target_os__ == __TargetOs_windows__
LARGE_INTEGER liPosition = {0};
LARGE_INTEGER liNewPosition = {0};
BOOL sfp_result = SetFilePointerEx (
file,
liPosition,
&liNewPosition,
FILE_CURRENT
);
if (sfp_result == FALSE) {
// unexpected
int err = GetLastError();
printf("%d SetFilePointerEx error: %d", __LINE__, err);
}
return liNewPosition.QuadPart;
#elif __target_os__ == __TargetOs_linux__
return lseek(file, 0, SEEK_CUR);
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
}
// var __OsFile_setPos__
void __OsFile_setPos__(
__OsFile__ file,
size_t pos
) {
#if __target_os__ == __TargetOs_windows__
LARGE_INTEGER liPosition = {0};
liPosition.QuadPart = pos;
BOOL sfp_result = SetFilePointerEx(file, liPosition, NULL, FILE_BEGIN);
if (sfp_result == FALSE) {
// unexpeced
printf("%d, unexpected SetFilePointer result", __LINE__);
}
#elif __target_os__ == __TargetOs_linux__
lseek(file, pos, SEEK_SET);
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
}
// var __OsFile_write__
bool __OsFile_write__(
__OsFile__ file,
const char* data,
size_t data_len,
size_t offset
) {
bool ok = true;
size_t writed = 0;
while (ok and (writed < data_len)) {
__OsFile_setPos__(file, writed);
#if __target_os__ == __TargetOs_windows__
DWORD atom_writed = 0;
if ( WriteFile(file, &data[offset + writed], data_len - writed, &atom_writed, NULL) ) {
writed += atom_writed;
ok = FlushFileBuffers(file);
} else {
ok = false;
}
#elif __target_os__ == __TargetOs_linux__
ssize_t atom_write = write(file, &data[offset + writed], data_len - writed);
if (atom_write != -1) {
writed += atom_write;
} else {
ok = false;
}
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
}
return ok;
}
// var __OsFile_getSize__
size_t __OsFile_getSize__(
__OsFile__ file
) {
#if __target_os__ == __TargetOs_windows__
LARGE_INTEGER size;
if (GetFileSizeEx(file, &size)) {
return size.QuadPart;
} else {
// unexpected
return 0;
}
#elif __target_os__ == __TargetOs_linux__
struct stat st;
fstat(file, &st);
return st.st_size;
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
}
// var __OsFile_truncate__
void __OsFile_truncate__(
__OsFile__ file
) {
#if __target_os__ == __TargetOs_windows__
bool ok = true;
if (FlushFileBuffers(file)) {
if (SetEndOfFile(file)) {
if (FlushFileBuffers(file)) {
} else { // unexpected
ok = false;
printf("%d unexpected retusult of FlushFileBuffers", __LINE__);
}
} else { // unexpected
ok = false;
printf("%d unexpected retusult of SetEndOfFile", __LINE__);
}
} else { // unexpected
ok = false;
printf("%d unexpected retusult of FlushFileBuffers", __LINE__);
}
if (!ok) printf("%d failue", __LINE__);
// return ok; not needed to real return ok state becouse expected posibly truncate any file without errors.
#elif __target_os__ == __TargetOs_linux__
size_t current_pos = __OsFile_getPos__(file);
ftruncate(file, current_pos);
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
}
// time
uint64_t __os_getTick__() {
#if __target_os__ == __TargetOs_windows__
FILETIME ft;
GetSystemTimeAsFileTime(&ft);
uint64_t ft64;
__ScalpiMem_copy__((char*) &ft64, (char*) &ft, 8);
return ft64 / 10000; // in ft is intervals * 100 ns. to ms need * 100 / 1000000
#elif __target_os__ == __TargetOs_linux__
// NOT TESTED
struct timespec ts;
clock_gettime(CLOCK_REALTIME, (void*)&ts);
uint64_t ms = ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
return ms;
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
}
void Os_sleep(uint64_t ms) {
#if __target_os__ == __TargetOs_windows__
Sleep(ms);
#elif __target_os__ == __TargetOs_linux__
// NOT TESTED
struct timespec delay;
delay.tv_sec = ms / 1000;
delay.tv_nsec = (ms % 1000) * 1000000;
nanosleep(&delay, NULL);
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
}
// Console
// ConsoleOutput
// var __OsConsoleOutput_getSize__
void __OsConsoleOutput_getSize__ (
struct __OsConsoleOutput__ *t,
struct __Scalpi_math_d2_U_Pos__ *ret_pos
) {
#if __target_os__ == __TargetOs_windows__
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(t->__OsConsoleOutput_handle__, &csbi);
int x = csbi.srWindow.Right - csbi.srWindow.Left + 1;
int y = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
ret_pos->x = x;
ret_pos->y = y;
// printf("%d, %d x %d\n", __LINE__, x, y);
#elif __target_os__ == __TargetOs_linux__
struct winsize w;
ioctl(t->__OsConsoleOutput_handle__, TIOCGWINSZ, &w);
ret_pos->x = w.ws_col;
ret_pos->y = w.ws_row;
#else
#error "__target_os__ not implemented"
#endif
}
// var __OsConsoleOutput_init__
void __OsConsoleOutput_init__(struct __OsConsoleOutput__* output, __OsConsoleOutputHandle__ handle) {
#if __target_os__ == __TargetOs_windows__
output->__OsConsoleOutput_handle__ = handle;
#elif __target_os__ == __TargetOs_linux__
output->__OsConsoleOutput_handle__ = handle;
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
}
// var __OsConsoleOutput_write__
bool __OsConsoleOutput_write__(struct __OsConsoleOutput__* os_console_output, const char* data, size_t _len) {
bool ok = true;
// support null-string // todo remove me
size_t len = _len;
if (len == 0) {
while(data[len] != 0) len += 1;
}
#if __target_os__ == __TargetOs_windows__
unsigned long writed = 0;
WriteConsoleA(os_console_output->__OsConsoleOutput_handle__, data, len, &writed, NULL);
len = writed;
#elif __target_os__ == __TargetOs_linux__
// stdin = 0
// stdout = 1
// stderr = 2
if (write(1, data, len) == len) {
} else {
ok = false;
}
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
return ok;
}
// ConsoleIntput
// var __OsConsoleInput_readByte__
bool __OsConsoleInput_readByte__(struct __OsConsoleInput__* t, char* byte) {
bool ok = true;
#if __target_os__ == __TargetOs_windows__
INPUT_RECORD key;
DWORD picked = 0;
if ( ReadConsoleInputA(t->handle, &key, 1, &picked) ) {
if (picked != 0) {
if (key.EventType == KEY_EVENT) {
KEY_EVENT_RECORD *event = &key.Event.KeyEvent;
if (event->bKeyDown != 0) {
if (event->uChar.AsciiChar != 0) {
*byte = event->uChar.AsciiChar;
} else {ok = false;}
} else {ok = false;}
} else {ok = false;}
} else {ok = false;}
} else {ok = false;}
#elif __target_os__ == __TargetOs_linux__
ssize_t result = read(t->fileno, byte, 1);
if (result != 1) {ok = false;}
#else
#error "__target_os__ not implemented"
#endif
return ok;
}
// var __OsConsoleInput_getCountOfUnreaded__
bool __OsConsoleInput_getCountOfUnreaded__(struct __OsConsoleInput__* t, size_t *ret_unreaded) {
bool ok = true;
#if __target_os__ == __TargetOs_windows__
DWORD unreaded = 0;
if ( GetNumberOfConsoleInputEvents(t->handle, &unreaded) ) {
*ret_unreaded += unreaded;
} else {
ok = false;
}
#elif __target_os__ == __TargetOs_linux__
int unreaded = 0;
int result = ioctl(t->fileno, FIONREAD, &unreaded);
*ret_unreaded += unreaded;
#else
#error "__target_os__ not implemented"
#endif
return ok;
}
// var __OsConsoleInput_init__
void __OsConsoleInput_init__(
struct __OsConsoleInput__* t,
__OsConsoleInputHandle__ input_hanle
) {
#if __target_os__ == __TargetOs_windows__
t->handle = input_hanle;
#elif __target_os__ == __TargetOs_linux__
t->handle = input_hanle;
t->fileno = fileno(t->handle);
#else
#error "__target_os__ not implemented"
#endif
}
// Flags
uint32_t __ScalpiBitsU32_enable__(uint32_t value, uint32_t mask) {
return value | mask;
}
uint32_t __ScalpiBitsU32_disable__(uint32_t value, uint32_t mask) {
return value & (~mask);
}
uint32_t __ScalpiBitsU32_toggle__(uint32_t value, uint32_t mask, bool new_state) {
if (new_state) {
return __ScalpiBitsU32_enable__(value, mask);
} else {
return __ScalpiBitsU32_disable__(value, mask);
}
}
bool __OsConsoleFlags_setNonCanonicalMode__(struct __OsConsoleFlags__ *t) {
bool ok = true;
#if __target_os__ == __TargetOs_windows__
uint32_t input = t->input_mode;
input = __ScalpiBitsU32_toggle__(input, ENABLE_EXTENDED_FLAGS, true);
input = __ScalpiBitsU32_toggle__(input, ENABLE_ECHO_INPUT, false); // print pressed keys
input = __ScalpiBitsU32_toggle__(input, ENABLE_LINE_INPUT, false); // wait '\n' (buffering on enter)
input = __ScalpiBitsU32_toggle__(input, ENABLE_VIRTUAL_TERMINAL_INPUT, true);
input = __ScalpiBitsU32_toggle__(input, ENABLE_PROCESSED_INPUT, false); // CTRL+C
input = __ScalpiBitsU32_toggle__(input, ENABLE_MOUSE_INPUT, false);
input = __ScalpiBitsU32_toggle__(input, ENABLE_QUICK_EDIT_MODE, true); // enable mouse select and copy
input = __ScalpiBitsU32_toggle__(input, ENABLE_WINDOW_INPUT, false); // reported of change size of the console screen buffer
input = __ScalpiBitsU32_toggle__(input, ENABLE_INSERT_MODE, true); // When enabled, text entered in a console window will be inserted at the current cursor location and all text following that location will not be overwritten. When disabled, all following text will be overwritten.
t->input_mode = input;
uint32_t output = t->output_mode;
output = __ScalpiBitsU32_toggle__(output, ENABLE_LVB_GRID_WORLDWIDE, true); // enable colors
output = __ScalpiBitsU32_toggle__(output, ENABLE_VIRTUAL_TERMINAL_PROCESSING, true); // emulate VT100
output = __ScalpiBitsU32_toggle__(output, ENABLE_PROCESSED_OUTPUT, true); // Backspace, tab, bell, carriage return, and line feed characters are processed
output = __ScalpiBitsU32_toggle__(output, ENABLE_WRAP_AT_EOL_OUTPUT, false); // disable line wrap
output = __ScalpiBitsU32_toggle__(output, DISABLE_NEWLINE_AUTO_RETURN, true);
t->output_mode = output;
#elif __target_os__ == __TargetOs_linux__
// clear c_cc
cc_t* cc = &t->termios.c_cc[0]; // cc_t c_cc[NCCS]
for (int i = 0; i < NCCS ; i++) {
cc[i] = 0;
}
// timers off
cc = &t->termios.c_cc[0];
cc[VTIME] = 0;
cc[VMIN] = 1;
uint32_t cflag = t->termios.c_cflag;
cflag = __ScalpiBitsU32_toggle__(cflag, CS8, true); // use 8 bit
cflag = __ScalpiBitsU32_toggle__(cflag, CSTOPB, false); // two stops bits
cflag = __ScalpiBitsU32_toggle__(cflag, PARENB, false); // parity check
cflag = __ScalpiBitsU32_toggle__(cflag, PARODD, false); // parity check
t->termios.c_cflag = cflag;
uint32_t lflag = t->termios.c_lflag;
lflag = __ScalpiBitsU32_toggle__(lflag, ISIG, false); // disable react to Ctrl+C
lflag = __ScalpiBitsU32_toggle__(lflag, ICANON, false); // no wait '\n'
lflag = __ScalpiBitsU32_toggle__(lflag, ECHO, false); // print pressed keys
lflag = __ScalpiBitsU32_toggle__(lflag, ECHOE, false); // mashing
lflag = __ScalpiBitsU32_toggle__(lflag, ECHONL, false); // print NL
lflag = __ScalpiBitsU32_toggle__(lflag, ECHOK, false); // nl after clear line
lflag = __ScalpiBitsU32_toggle__(lflag, ECHOKE, false); // print NL after BS
lflag = __ScalpiBitsU32_toggle__(lflag, ECHOPRT, false); // print BS (BS SP BS)
lflag = __ScalpiBitsU32_toggle__(lflag, IEXTEN, false); // special funcs
t->termios.c_lflag = lflag;
uint32_t iflag = t->termios.c_iflag;
iflag = __ScalpiBitsU32_toggle__(iflag, IGNBRK, true); // ignore break control
iflag = __ScalpiBitsU32_toggle__(iflag, BRKINT, true); // do not delete all data after break control
iflag = __ScalpiBitsU32_toggle__(iflag, IXON, false); // disable react to Ctrl+S Ctlr+Q
iflag = __ScalpiBitsU32_toggle__(iflag, ISTRIP, false); // strip
iflag = __ScalpiBitsU32_toggle__(iflag, INLCR, false); // convert NL to CR
iflag = __ScalpiBitsU32_toggle__(iflag, ICRNL, false); // convert CR to NL
iflag = __ScalpiBitsU32_toggle__(iflag, XCASE, false); // convert register to UP
iflag = __ScalpiBitsU32_toggle__(iflag, IUCLC, false); // convert register to down
iflag = __ScalpiBitsU32_toggle__(iflag, IGNPAR, true); // ignore framing or parity errors
iflag = __ScalpiBitsU32_toggle__(iflag, IMAXBEL, false); // no bell
t->termios.c_iflag = iflag;
uint32_t oflag = t->termios.c_oflag;
oflag = __ScalpiBitsU32_toggle__(oflag, ONOCR, false); // on start line // Auto CR
oflag = __ScalpiBitsU32_toggle__(oflag, ONLRET, false); // on end line // Auto CR
oflag = __ScalpiBitsU32_toggle__(oflag, OPOST, true); // \_(O_o)_/
oflag = __ScalpiBitsU32_toggle__(oflag, ONLCR, true); // NL to CR
oflag = __ScalpiBitsU32_toggle__(oflag, OCRNL, false); // CR to NL
oflag = __ScalpiBitsU32_toggle__(oflag, OLCUC, false); // convert to CAPS
oflag = __ScalpiBitsU32_toggle__(oflag, XTABS, false); // convert tab
oflag = __ScalpiBitsU32_toggle__(oflag, TAB3, false); // convert tab
oflag = __ScalpiBitsU32_toggle__(oflag, OFDEL, false); // use null for deleted symbol
t->termios.c_oflag = oflag;
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
return ok;
}
bool __OsConsoleFlags_apply__(
struct __OsConsoleFlags__ *t,
struct __OsConsoleInput__ *input,
struct __OsConsoleOutput__ *output
) {
// expected inited
bool ok = true;
#if __target_os__ == __TargetOs_windows__
int result1 = SetConsoleMode(input->handle, t->input_mode);
if (result1 == 0) {
ok = false;
// todo GetLastError();
}
int result2 = SetConsoleMode(output->__OsConsoleOutput_handle__, t->output_mode);
if (result2 == 0) {
ok = false;
// todo GetLastError();
}
#elif __target_os__ == __TargetOs_linux__
tcsetattr(input->fileno, TCSANOW, &t->termios);
tcsetattr(output->__OsConsoleOutput_handle__, TCSANOW, &t->termios);
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
return ok;
}
bool __OsConsoleFlags_init__(struct __OsConsoleFlags__ *t, struct __OsConsoleInput__* input, struct __OsConsoleOutput__ *output) {
bool ok = true;
#if __target_os__ == __TargetOs_windows__
bool result1 = GetConsoleMode(input->handle, &t->input_mode);
if (result1 != 0) {
bool result2 = GetConsoleMode(output->__OsConsoleOutput_handle__, &t->output_mode);
if (result2 != 0) {
t->inited = true;
} else {
ok = false;
}
} else {
ok = false;
}
#elif __target_os__ == __TargetOs_linux__
int result = tcgetattr(input->fileno, &t->termios);
if (result == 0) {
t->inited = true;
} else {
ok = false;
}
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
return ok;
}
// var __OsFallbackConsole_write__
size_t
__OsFallbackConsole_write__ (
void* unused_ctx,
char* data,
size_t len
) {
#if __target_os__ == __TargetOs_windows__
struct __OsConsoleOutput__ console_output;
__OsConsoleOutput_init__(&console_output, GetStdHandle(STD_OUTPUT_HANDLE));
__OsConsoleOutput_write__(&console_output, data, len);
#elif __target_os__ == __TargetOs_linux__
__OsConsoleOutput_write__ (NULL, data, len);
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
return len;
}
// Helper
bool __OsHelper_init__(struct __OsHelper__* t) {
bool ok = true;
#if __target_os__ == __TargetOs_windows__
HMODULE instance = GetModuleHandleA(NULL);
if (instance != NULL) {
t->instance = instance;
HANDLE console_input_handle = GetStdHandle(STD_INPUT_HANDLE);
if (console_input_handle != INVALID_HANDLE_VALUE) {
t->console_input_handle = console_input_handle;
HANDLE console_output_handle = GetStdHandle(STD_OUTPUT_HANDLE);
if (console_output_handle != INVALID_HANDLE_VALUE) {
t->console_output_handle = console_output_handle;
#if __with_network__
if (
WSAStartup(
514, // wVersionRequested ver 2.2
&t->wsdata
) == 0
) { } else {
ok = false;
}
#endif
} else {
ok = false;
}
} else {
ok = false;
}
} else {
ok = false;
}
#elif __target_os__ == __TargetOs_linux__
t->console_input_handle = stdin;
t->console_output_handle = 1; // standart output
#else
#error "__target_os__ not implemented"
#endif
return ok;
}
void __OsHelper_deinit__(struct __OsHelper__*t) {
#if __target_os__ == __TargetOs_windows__
#if __with_network__
WSACleanup();
#endif
FreeLibrary(t->instance);
#elif __target_os__ == __TargetOs_linux__
// nothing to do
#else
#error "__target_os__ not implemented"
#endif
}
void __OsHelper_process__(struct __OsHelper__* t) {
#if __target_os__ == __TargetOs_windows__
MSG msg;
if (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
#elif __target_os__ == __TargetOs_linux__
// nothing to do
#else
#error "__target_os__ not implemented"
#endif
}
// Scalpi
// text
// var __Text_countIndent__
size_t
__Text_countIndent__(
char* text,
size_t text_len, // can be 0
size_t tab_size
) {
size_t counted = 0;
size_t pos = 0;
while (pos < text_len) {
char symbol = text[pos];
if (symbol == ' ') {
counted = counted + 1;
} else if (symbol == '\t') {
counted = counted + tab_size;
} else {
break;
}
pos = pos + 1;
}
return counted;
}
// Buffer
// var __Buffer_push__
void __Buffer_push__(
char *buffer,
size_t *buffer_used, // expected < allocated
size_t pos, // expected < allocated
char item
) {
if (pos < *buffer_used) { // shiftSymbolsToRight
__ScalpiMem_copyBackward__(&buffer[pos + 1], &buffer[pos], *buffer_used - pos);
}
buffer[pos] = item;
(*buffer_used)++;
}
// var __Buffer_pop_check__
bool __Buffer_pop_check__(
size_t buffer_used,
size_t pos
) {
return ((buffer_used > 0) and (pos <= buffer_used));
}
// var __Buffer_pop__
char __Buffer_pop__(
char *buffer,
size_t *buffer_used, // expected (*) > 0
size_t pos // expected <= buffer_used
) {
char ret = buffer[pos];
(*buffer_used)--;
if (pos < *buffer_used) {
__ScalpiMem_copy__(&buffer[pos], &buffer[pos + 1], *buffer_used - pos);
}
return ret;
}
// var __Buffer_addIndent_check__
bool
__Buffer_addIndent_check__(
char *buffer,
size_t *buffer_used,
size_t buffer_max,
size_t count
) {
size_t space = buffer_max - *buffer_used;
return space > count;
}
// var __Buffer_addIndent__
void __Buffer_addIndent__(
char *buffer,
size_t *buffer_used,
size_t count // expected < (buffer_max - *buffer_used)
) {
size_t pos = 0;
while (pos < count) {
__Buffer_push__(buffer, buffer_used, 0, ' ');
pos = pos + 1;
}
}
// var __Buffer_removeIndent__
// does not check which characters it removes.
bool // not safed.
__Buffer_removeIndent__(
char *buffer,
size_t *buffer_used, // expected >= count
size_t count // expected < buffer_used
) {
bool ok = true;
if (*buffer_used < count) {
ok = false;
} else if (*buffer_used == count) {
*buffer_used = count;
} else { // *buffer_used > count
size_t pos = 0;
while (pos < count) {
if (
__Buffer_pop_check__(
*buffer_used,
pos
)
) {
__Buffer_pop__(
buffer,
buffer_used, // (*) > 0 becouse *buffer_used > loop count checked in upper if
0
);
} else {
ok = false;
}
if (!ok) break;
pos += 1;
}
}
return ok;
}
// var __Buffer_setIndent__
bool
__Buffer_setIndent__(
char *buffer,
size_t *buffer_used,
size_t buffer_max,
size_t new_indent // expected < buffer_max
) {
bool ok = true;
size_t indent = __Text_countIndent__(buffer, *buffer_used, 1);
if (new_indent != indent) {
if (new_indent > indent) {
size_t delta = new_indent - indent;
if (__Buffer_addIndent_check__(buffer, buffer_used, buffer_max, delta)) {
__Buffer_addIndent__(buffer, buffer_used, delta);
} else {
ok = false;
}
} else { // new_indent < indent
size_t delta = indent - new_indent;
if(__Buffer_removeIndent__(buffer, buffer_used, delta)) {
} else {
ok = false;
}
}
}
return ok;
}
// File
// var __File_clear__
void __ScalpiFile_clear__(
__OsFile__ file
) {
__OsFile_setPos__(file, 0);
__OsFile_truncate__(file);
}
// FileComplete
// __ScalpiFileComplete_clear__
bool __ScalpiFileComplete_clear__(
const char* file_name,
size_t file_name_len
) {
bool ok = true;
__OsFile__ file;
if (__OsFile_open__(&file, file_name, file_name_len)) {
__ScalpiFile_clear__(file);
__OsFile_close__(file);
} else {
ok = false;
}
return ok;
}
// __ScalpiFileComplete_write__
bool __ScalpiFileComplete_write__(
const char* file_name,
size_t file_name_len,
const char* bytes,
size_t bytes_len
) {
bool ok = true;
__OsFile__ file;
if(__OsFile_exist__(file_name, file_name_len)) {
ok = __OsFile_open__(&file, file_name, file_name_len);
} else {
ok = __OsFile_create__(&file, file_name, file_name_len);
}
if (ok) {
if (__OsFile_write__(file, bytes, bytes_len, 0)) {
__OsFile_truncate__(file);
} else {
ok = false;
}
__OsFile_close__(file);
}
return ok;
}
// List
// VAR __ScalpiMemList_pushBefore__
void __ScalpiMemList_pushBefore__(
struct __ScalpiMemList__* list,
struct __ScalpiMemListLink__* before,
struct __ScalpiMemListLink__* item
) {
if (before->prev) { // non firts
struct __ScalpiMemListLink__* prev = before->prev;
prev->next = item;
item->prev = prev;
} else { // is first. TODO use pushFirst
list->first = item;
item->prev = 0;
}
before->prev = item;
item->next = before;
item->list = list;
list->count += 1;
}
char Scalpi_crypto_sumBytes(char* data, size_t data_len) {
char ret = 0;
for (size_t pos = 0; pos < data_len; pos++) {
ret += data[pos];
}
return ret;
}
char Scalpi_crypto_xorBytes(char* data, size_t data_len) {
char ret = 0;
for (size_t pos = 0; pos < data_len; pos++) {
ret ^= data[pos];
}
return ret;
}
void Scalpi_crypto_xorCyclic(char* dest, char* a, size_t dest_len, char* b, size_t b_len) {
// expected dest_len == a.len
size_t ci = 0; // cyclical iterator
for (size_t pos = 0; pos < dest_len; pos++) {
dest[pos] = a[pos] ^ b[ci];
ci += 1;
if (ci == b_len) ci = 0;
}
}
// Scalpi_Logger
void Scalpi_Logger_init (struct Scalpi_Logger* t) {
for (int i = 0; i < __arrayLen__(t->writers); i++) {
struct __Scalpi_Writer__* w = &t->writers[i];
w->context = 0;
w->write = 0;
}
}
void __ScalpiLogger_writeToSelf__(struct Scalpi_Logger* t, const char bytes[], size_t len) {
for (size_t i = 0; i < __arrayLen__(t->writers); i++) {
struct __Scalpi_Writer__* w = &t->writers[i];
if (w->write) {
size_t writed = w->write(w->context, bytes, len);
}
}
}
// __ScalpiTerminalOutput_CursorPos__
void __ScalpiTerminalOutputCursorPos_init__(__ScalpiTerminalOutput_CursorPos__ *cursor_pos) {
cursor_pos->x = 0;
cursor_pos->y = 0;
}
// App
bool __AppEditorHistoryNote_alloc__(
struct __AppEditorHistoryNote__* *ptr
) {
return __AlignedPtr_alloc__(
ptr,
__alignOf__(struct __AppEditorHistoryNote__),
sizeof(struct __AppEditorHistoryNote__)
);
}
// struct App
bool App_init(struct App* t) {
bool ok = true;
Scalpi_Logger_init(&t->logger); // preinit console output for debug
if (__OsHelper_init__(&t->__App_osHelper__)) {
t->tick = __os_getTick__();
if (!ok) __OsHelper_deinit__(&t->__App_osHelper__);
} else {
ok = false;
printf("%d app.os_helper not inited\r\n", __LINE__);
}
return ok;
}
void App_deinit(struct App* app) {
__OsHelper_deinit__(&app->__App_osHelper__);
}
bool App_process(struct App* t) {
bool ok = true;
__OsHelper_process__(&t->__App_osHelper__);
return ok;
}
void App_waitToNextFrame(struct App* t) {
uint64_t expected_frame_end_time = t->tick + Scalpi_time_ms_per_s / App_expected_fps;
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() {
// const char* test_file_name = "scalpi_testing_file.txt";
// size_t test_file_name_len = __ZText_countLen__(test_file_name);
if ( true
and cpu_checkNumberFormat()
// and __ScalpiFileComplete_write__(test_file_name, test_file_name_len, "abcd", 4)
// and __ScalpiFileComplete_write__(test_file_name, test_file_name_len, "efgh", 4)
// and __ScalpiFileComplete_write__(test_file_name, test_file_name_len, "ijkm", 4)
// 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;
}
#ifndef __COMPILED_FROM_ZIG_FILE__
int main(int args_len, char** args_ptr) {
if (real_main(args_len, args_ptr)) return 0;
return 1;
}
#endif