[win32 build/link]

- Build milepost as a dynamic library
- Add import/export directives to public API symbols
- Change example build scripts accordingly
This commit is contained in:
martinfouilleul 2023-02-21 18:43:30 +01:00
parent dc2961f513
commit 665c63c3d0
20 changed files with 2529 additions and 2519 deletions

View File

@ -6,5 +6,6 @@ set glsl_shaders=src\glsl_shaders\common.glsl src\glsl_shaders\blit_vertex.glsl
call python3 scripts\embed_text.py %glsl_shaders% --prefix=glsl_ --output src\glsl_shaders.h
set INCLUDES=/I src /I src/util /I src/platform /I ext /I ext/angle_headers
cl /we4013 /Zi /Zc:preprocessor /std:c11 %INCLUDES% /c /Fo:bin/milepost.obj src/milepost.c
lib bin/milepost.obj /OUT:bin/milepost.lib
set LIBS=user32.lib opengl32.lib gdi32.lib shcore.lib /LIBPATH:./bin libEGL.dll.lib libGLESv2.dll.lib
cl /we4013 /Zi /Zc:preprocessor /DMP_BUILD_DLL /std:c11 %INCLUDES% src/milepost.c /Fo:bin/milepost.o /LD /link %LIBS% /OUT:bin/milepost.dll /IMPLIB:bin/milepost.dll.lib

View File

@ -1,4 +1,4 @@
set INCLUDES=/I ..\..\src /I ..\..\src\util /I ..\..\src\platform /I ../../ext /I ../../ext/angle_headers
cl /we4013 /Zi /Zc:preprocessor /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.lib user32.lib opengl32.lib gdi32.lib shcore.lib /out:../../bin/example_canvas.exe
cl /we4013 /Zi /Zc:preprocessor /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.dll.lib /out:../../bin/example_canvas.exe

View File

@ -1,4 +1,4 @@
set INCLUDES=/I ..\..\src /I ..\..\src\util /I ..\..\src\platform /I ../../ext
cl /we4013 /Zi /Zc:preprocessor /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.lib user32.lib opengl32.lib gdi32.lib shcore.lib /out:../../bin/perf_text.exe
cl /we4013 /Zi /Zc:preprocessor /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.dll.lib /out:../../bin/perf_text.exe

View File

@ -1,3 +1,3 @@
set INCLUDES=/I ..\..\src /I ..\..\src\util /I ..\..\src\platform /I ../../ext
cl /we4013 /Zi /Zc:preprocessor /DMG_IMPLEMENTS_BACKEND_GL /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.lib user32.lib opengl32.lib gdi32.lib shcore.lib /LIBPATH:../../bin libEGL.dll.lib libGLESv2.dll.lib /out:../../bin/example_gl_triangle.exe
cl /we4013 /Zi /Zc:preprocessor /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.dll.lib /out:../../bin/example_gl_triangle.exe

View File

@ -1,3 +1,3 @@
set INCLUDES=/I ..\..\src /I ..\..\src\util /I ..\..\src\platform /I ../../ext /I ../../ext/angle_headers
cl /we4013 /Zi /Zc:preprocessor /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.lib /LIBPATH:../../bin libEGL.dll.lib libGLESv2.dll.lib user32.lib opengl32.lib gdi32.lib shcore.lib /out:../../bin/example_gles_triangle.exe
cl /we4013 /Zi /Zc:preprocessor /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.dll.lib /out:../../bin/example_gles_triangle.exe

View File

@ -96,12 +96,13 @@ for func in glall:
f.write('\t' + 'PFN' + func.upper() + 'PROC ' + remove_prefix(func, 'gl') + ';\n')
f.write('} mg_gl_api;\n\n')
f.write('extern mp_thread_local mg_gl_api* __mgGLAPI;\n\n');
# generate interface macros
# TODO guard for different api/versions and only #define functions present in desired version
f.write("MP_API mg_gl_api* mg_gl_get_api(void);\n\n")
for func in glall:
f.write('#define ' + func + ' __mgGLAPI->' + remove_prefix(func, 'gl') + '\n')
f.write('#define ' + func + ' mg_gl_get_api()->' + remove_prefix(func, 'gl') + '\n')
emit_end_guard(f, apiName)
f.close()
@ -124,8 +125,8 @@ f.write("void mg_gl_load_gl43(mg_gl_api* api, mg_gl_load_proc loadProc);\n")
f.write("void mg_gl_load_gles31(mg_gl_api* api, mg_gl_load_proc loadProc);\n")
f.write("void mg_gl_load_gles32(mg_gl_api* api, mg_gl_load_proc loadProc);\n\n")
f.write("void mg_gl_select_api(mg_gl_api* api);\n")
f.write("mg_gl_api* mg_gl_get_api(void);\n\n")
f.write("void mg_gl_select_api(mg_gl_api* api);\n\n")
emit_end_guard(f, loaderName)
f.close()

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
*
* @file: gl_loader.c
* @note: auto-generated by glapi.py from gl.xml
* @date: 20/022023
* @date: 21/022023
*
*********************************************************/
#include"gl_loader.h"

View File

@ -2,7 +2,7 @@
*
* @file: gl_loader.h
* @note: auto-generated by glapi.py from gl.xml
* @date: 20/022023
* @date: 21/022023
*
*********************************************************/
#ifndef __GL_LOADER_H__
@ -18,6 +18,5 @@ void mg_gl_load_gles31(mg_gl_api* api, mg_gl_load_proc loadProc);
void mg_gl_load_gles32(mg_gl_api* api, mg_gl_load_proc loadProc);
void mg_gl_select_api(mg_gl_api* api);
mg_gl_api* mg_gl_get_api(void);
#endif // __GL_LOADER_H__

View File

@ -79,27 +79,27 @@ typedef enum {
//TODO: add MG_INCLUDE_OPENGL/GLES/etc, once we know how we make different gl versions co-exist
bool mg_is_surface_backend_available(mg_backend_id id);
bool mg_is_canvas_backend_available(mg_backend_id id);
MP_API bool mg_is_surface_backend_available(mg_backend_id id);
MP_API bool mg_is_canvas_backend_available(mg_backend_id id);
//------------------------------------------------------------------------------------------
//NOTE(martin): graphics surface
//------------------------------------------------------------------------------------------
typedef struct mg_surface { u64 h; } mg_surface;
mg_surface mg_surface_nil();
bool mg_surface_is_nil(mg_surface surface);
MP_API mg_surface mg_surface_nil();
MP_API bool mg_surface_is_nil(mg_surface surface);
mg_surface mg_surface_create_for_window(mp_window window, mg_backend_id backend);
void mg_surface_destroy(mg_surface surface);
void mg_surface_prepare(mg_surface surface);
void mg_surface_present(mg_surface surface);
void mg_surface_swap_interval(mg_surface surface, int swap);
vec2 mg_surface_contents_scaling(mg_surface surface);
mp_rect mg_surface_get_frame(mg_surface surface);
void mg_surface_set_frame(mg_surface surface, mp_rect frame);
bool mg_surface_get_hidden(mg_surface surface);
void mg_surface_set_hidden(mg_surface surface, bool hidden);
MP_API mg_surface mg_surface_create_for_window(mp_window window, mg_backend_id backend);
MP_API void mg_surface_destroy(mg_surface surface);
MP_API void mg_surface_prepare(mg_surface surface);
MP_API void mg_surface_present(mg_surface surface);
MP_API void mg_surface_swap_interval(mg_surface surface, int swap);
MP_API vec2 mg_surface_contents_scaling(mg_surface surface);
MP_API mp_rect mg_surface_get_frame(mg_surface surface);
MP_API void mg_surface_set_frame(mg_surface surface, mp_rect frame);
MP_API bool mg_surface_get_hidden(mg_surface surface);
MP_API void mg_surface_set_hidden(mg_surface surface, bool hidden);
//------------------------------------------------------------------------------------------
@ -161,128 +161,128 @@ typedef struct mg_text_extents
//------------------------------------------------------------------------------------------
//NOTE(martin): graphics canvas
//------------------------------------------------------------------------------------------
mg_canvas mg_canvas_nil();
bool mg_canvas_is_nil(mg_canvas canvas);
MP_API mg_canvas mg_canvas_nil();
MP_API bool mg_canvas_is_nil(mg_canvas canvas);
mg_canvas mg_canvas_create(mg_surface surface);
void mg_canvas_destroy(mg_canvas canvas);
mg_canvas mg_canvas_set_current(mg_canvas canvas);
MP_API mg_canvas mg_canvas_create(mg_surface surface);
MP_API void mg_canvas_destroy(mg_canvas canvas);
MP_API mg_canvas mg_canvas_set_current(mg_canvas canvas);
void mg_flush();
MP_API void mg_flush();
//------------------------------------------------------------------------------------------
//NOTE(martin): transform, viewport and clipping
//------------------------------------------------------------------------------------------
void mg_viewport(mp_rect viewPort);
MP_API void mg_viewport(mp_rect viewPort);
void mg_matrix_push(mg_mat2x3 matrix);
void mg_matrix_pop();
MP_API void mg_matrix_push(mg_mat2x3 matrix);
MP_API void mg_matrix_pop();
void mg_clip_push(f32 x, f32 y, f32 w, f32 h);
void mg_clip_pop();
MP_API void mg_clip_push(f32 x, f32 y, f32 w, f32 h);
MP_API void mg_clip_pop();
//------------------------------------------------------------------------------------------
//NOTE(martin): graphics attributes setting/getting
//------------------------------------------------------------------------------------------
void mg_set_color(mg_color color);
void mg_set_color_rgba(f32 r, f32 g, f32 b, f32 a);
void mg_set_width(f32 width);
void mg_set_tolerance(f32 tolerance);
void mg_set_joint(mg_joint_type joint);
void mg_set_max_joint_excursion(f32 maxJointExcursion);
void mg_set_cap(mg_cap_type cap);
void mg_set_font(mg_font font);
void mg_set_font_size(f32 size);
void mg_set_text_flip(bool flip);
MP_API void mg_set_color(mg_color color);
MP_API void mg_set_color_rgba(f32 r, f32 g, f32 b, f32 a);
MP_API void mg_set_width(f32 width);
MP_API void mg_set_tolerance(f32 tolerance);
MP_API void mg_set_joint(mg_joint_type joint);
MP_API void mg_set_max_joint_excursion(f32 maxJointExcursion);
MP_API void mg_set_cap(mg_cap_type cap);
MP_API void mg_set_font(mg_font font);
MP_API void mg_set_font_size(f32 size);
MP_API void mg_set_text_flip(bool flip);
mg_color mg_get_color();
f32 mg_get_width();
f32 mg_get_tolerance();
mg_joint_type mg_get_joint();
f32 mg_get_max_joint_excursion();
mg_cap_type mg_get_cap();
mg_font mg_get_font();
f32 mg_get_font_size();
bool mg_get_text_flip();
MP_API mg_color mg_get_color();
MP_API f32 mg_get_width();
MP_API f32 mg_get_tolerance();
MP_API mg_joint_type mg_get_joint();
MP_API f32 mg_get_max_joint_excursion();
MP_API mg_cap_type mg_get_cap();
MP_API mg_font mg_get_font();
MP_API f32 mg_get_font_size();
MP_API bool mg_get_text_flip();
//------------------------------------------------------------------------------------------
//NOTE(martin): path construction
//------------------------------------------------------------------------------------------
vec2 mg_get_position();
void mg_move_to(f32 x, f32 y);
void mg_line_to(f32 x, f32 y);
void mg_quadratic_to(f32 x1, f32 y1, f32 x2, f32 y2);
void mg_cubic_to(f32 x1, f32 y1, f32 x2, f32 y2, f32 x3, f32 y3);
void mg_close_path();
MP_API vec2 mg_get_position();
MP_API void mg_move_to(f32 x, f32 y);
MP_API void mg_line_to(f32 x, f32 y);
MP_API void mg_quadratic_to(f32 x1, f32 y1, f32 x2, f32 y2);
MP_API void mg_cubic_to(f32 x1, f32 y1, f32 x2, f32 y2, f32 x3, f32 y3);
MP_API void mg_close_path();
mp_rect mg_glyph_outlines(str32 glyphIndices);
void mg_codepoints_outlines(str32 string);
void mg_text_outlines(str8 string);
MP_API mp_rect mg_glyph_outlines(str32 glyphIndices);
MP_API void mg_codepoints_outlines(str32 string);
MP_API void mg_text_outlines(str8 string);
//------------------------------------------------------------------------------------------
//NOTE(martin): clear/fill/stroke
//------------------------------------------------------------------------------------------
void mg_clear();
void mg_fill();
void mg_stroke();
MP_API void mg_clear();
MP_API void mg_fill();
MP_API void mg_stroke();
//------------------------------------------------------------------------------------------
//NOTE(martin): 'fast' shapes primitives
//------------------------------------------------------------------------------------------
void mg_rectangle_fill(f32 x, f32 y, f32 w, f32 h);
void mg_rectangle_stroke(f32 x, f32 y, f32 w, f32 h);
void mg_rounded_rectangle_fill(f32 x, f32 y, f32 w, f32 h, f32 r);
void mg_rounded_rectangle_stroke(f32 x, f32 y, f32 w, f32 h, f32 r);
void mg_ellipse_fill(f32 x, f32 y, f32 rx, f32 ry);
void mg_ellipse_stroke(f32 x, f32 y, f32 rx, f32 ry);
void mg_circle_fill(f32 x, f32 y, f32 r);
void mg_circle_stroke(f32 x, f32 y, f32 r);
void mg_arc(f32 x, f32 y, f32 r, f32 arcAngle, f32 startAngle);
MP_API void mg_rectangle_fill(f32 x, f32 y, f32 w, f32 h);
MP_API void mg_rectangle_stroke(f32 x, f32 y, f32 w, f32 h);
MP_API void mg_rounded_rectangle_fill(f32 x, f32 y, f32 w, f32 h, f32 r);
MP_API void mg_rounded_rectangle_stroke(f32 x, f32 y, f32 w, f32 h, f32 r);
MP_API void mg_ellipse_fill(f32 x, f32 y, f32 rx, f32 ry);
MP_API void mg_ellipse_stroke(f32 x, f32 y, f32 rx, f32 ry);
MP_API void mg_circle_fill(f32 x, f32 y, f32 r);
MP_API void mg_circle_stroke(f32 x, f32 y, f32 r);
MP_API void mg_arc(f32 x, f32 y, f32 r, f32 arcAngle, f32 startAngle);
//------------------------------------------------------------------------------------------
//NOTE(martin): fonts
//------------------------------------------------------------------------------------------
mg_font mg_font_nil();
mg_font mg_font_create_from_memory(u32 size, byte* buffer, u32 rangeCount, unicode_range* ranges);
void mg_font_destroy(mg_font font);
MP_API mg_font mg_font_nil();
MP_API mg_font mg_font_create_from_memory(u32 size, byte* buffer, u32 rangeCount, unicode_range* ranges);
MP_API void mg_font_destroy(mg_font font);
//NOTE(martin): the following int valued functions return -1 if font is invalid or codepoint is not present in font//
//TODO(martin): add enum error codes
mg_font_extents mg_font_get_extents(mg_font font);
mg_font_extents mg_font_get_scaled_extents(mg_font font, f32 emSize);
f32 mg_font_get_scale_for_em_pixels(mg_font font, f32 emSize);
MP_API mg_font_extents mg_font_get_extents(mg_font font);
MP_API mg_font_extents mg_font_get_scaled_extents(mg_font font, f32 emSize);
MP_API f32 mg_font_get_scale_for_em_pixels(mg_font font, f32 emSize);
//NOTE(martin): if you need to process more than one codepoint, first convert your codepoints to glyph indices, then use the
// glyph index versions of the functions, which can take an array of glyph indices.
str32 mg_font_get_glyph_indices(mg_font font, str32 codePoints, str32 backing);
str32 mg_font_push_glyph_indices(mg_font font, mem_arena* arena, str32 codePoints);
u32 mg_font_get_glyph_index(mg_font font, utf32 codePoint);
MP_API str32 mg_font_get_glyph_indices(mg_font font, str32 codePoints, str32 backing);
MP_API str32 mg_font_push_glyph_indices(mg_font font, mem_arena* arena, str32 codePoints);
MP_API u32 mg_font_get_glyph_index(mg_font font, utf32 codePoint);
int mg_font_get_codepoint_extents(mg_font font, utf32 codePoint, mg_text_extents* outExtents);
MP_API int mg_font_get_codepoint_extents(mg_font font, utf32 codePoint, mg_text_extents* outExtents);
int mg_font_get_glyph_extents(mg_font font, str32 glyphIndices, mg_text_extents* outExtents);
MP_API int mg_font_get_glyph_extents(mg_font font, str32 glyphIndices, mg_text_extents* outExtents);
mp_rect mg_text_bounding_box_utf32(mg_font font, f32 fontSize, str32 text);
mp_rect mg_text_bounding_box(mg_font font, f32 fontSize, str8 text);
MP_API mp_rect mg_text_bounding_box_utf32(mg_font font, f32 fontSize, str32 text);
MP_API mp_rect mg_text_bounding_box(mg_font font, f32 fontSize, str8 text);
//------------------------------------------------------------------------------------------
//NOTE(martin): images
//------------------------------------------------------------------------------------------
typedef struct mg_image { u64 h; } mg_image;
mg_image mg_image_nil();
bool mg_image_equal(mg_image a, mg_image b);
MP_API mg_image mg_image_nil();
MP_API bool mg_image_equal(mg_image a, mg_image b);
mg_image mg_image_create_from_rgba8(u32 width, u32 height, u8* pixels);
mg_image mg_image_create_from_data(str8 data, bool flip);
mg_image mg_image_create_from_file(str8 path, bool flip);
MP_API mg_image mg_image_create_from_rgba8(u32 width, u32 height, u8* pixels);
MP_API mg_image mg_image_create_from_data(str8 data, bool flip);
MP_API mg_image mg_image_create_from_file(str8 path, bool flip);
void mg_image_drestroy(mg_image image);
MP_API void mg_image_drestroy(mg_image image);
vec2 mg_image_size(mg_image image);
void mg_image_draw(mg_image image, mp_rect rect);
void mg_rounded_image_draw(mg_image image, mp_rect rect, f32 roundness);
MP_API vec2 mg_image_size(mg_image image);
MP_API void mg_image_draw(mg_image image, mp_rect rect);
MP_API void mg_rounded_image_draw(mg_image image, mp_rect rect, f32 roundness);
#endif //__GRAPHICS_H_

View File

@ -1,398 +1,398 @@
/************************************************************//**
*
* @file: platform_app.h
* @author: Martin Fouilleul
* @date: 16/05/2020
* @revision:
*
*****************************************************************/
#ifndef __PLATFORM_APP_H_
#define __PLATFORM_APP_H_
#include"typedefs.h"
#include"utf8.h"
#include"lists.h"
#ifdef __cplusplus
extern "C" {
#endif
//--------------------------------------------------------------------
// Typedefs, enums and constants
//--------------------------------------------------------------------
typedef struct mp_window { u64 h; } mp_window;
typedef enum { MP_MOUSE_CURSOR_ARROW,
MP_MOUSE_CURSOR_RESIZE_0,
MP_MOUSE_CURSOR_RESIZE_90,
MP_MOUSE_CURSOR_RESIZE_45,
MP_MOUSE_CURSOR_RESIZE_135,
MP_MOUSE_CURSOR_TEXT } mp_mouse_cursor;
typedef i32 mp_window_style;
static const mp_window_style MP_WINDOW_STYLE_NO_TITLE = 0x01<<0,
MP_WINDOW_STYLE_FIXED_SIZE = 0x01<<1,
MP_WINDOW_STYLE_NO_CLOSE = 0x01<<2,
MP_WINDOW_STYLE_NO_MINIFY = 0x01<<3,
MP_WINDOW_STYLE_NO_FOCUS = 0x01<<4,
MP_WINDOW_STYLE_FLOAT = 0x01<<5,
MP_WINDOW_STYLE_POPUPMENU = 0x01<<6,
MP_WINDOW_STYLE_NO_BUTTONS = 0x01<<7;
typedef enum { MP_EVENT_NONE,
MP_EVENT_KEYBOARD_MODS, //TODO: remove, keep only key?
MP_EVENT_KEYBOARD_KEY,
MP_EVENT_KEYBOARD_CHAR,
MP_EVENT_MOUSE_BUTTON,
MP_EVENT_MOUSE_MOVE,
MP_EVENT_MOUSE_WHEEL,
MP_EVENT_MOUSE_ENTER,
MP_EVENT_MOUSE_LEAVE,
MP_EVENT_WINDOW_RESIZE,
MP_EVENT_WINDOW_MOVE,
MP_EVENT_WINDOW_FOCUS,
MP_EVENT_WINDOW_UNFOCUS,
MP_EVENT_WINDOW_HIDE, // rename to minimize?
MP_EVENT_WINDOW_SHOW, // rename to restore?
MP_EVENT_WINDOW_CLOSE,
MP_EVENT_PATHDROP,
MP_EVENT_FRAME,
MP_EVENT_QUIT } mp_event_type;
typedef enum { MP_KEY_NO_ACTION,
MP_KEY_PRESS,
MP_KEY_RELEASE,
MP_KEY_REPEAT } mp_key_action;
typedef enum { MP_KEY_UNKNOWN = 0,
MP_KEY_SPACE = 32,
MP_KEY_APOSTROPHE = 39, /* ' */
MP_KEY_COMMA = 44, /* , */
MP_KEY_MINUS = 45, // -
MP_KEY_PERIOD = 46, // .
MP_KEY_SLASH = 47, // /
MP_KEY_0 = 48,
MP_KEY_1 = 49,
MP_KEY_2 = 50,
MP_KEY_3 = 51,
MP_KEY_4 = 52,
MP_KEY_5 = 53,
MP_KEY_6 = 54,
MP_KEY_7 = 55,
MP_KEY_8 = 56,
MP_KEY_9 = 57,
MP_KEY_SEMICOLON = 59, // ;
MP_KEY_EQUAL = 61, // =
MP_KEY_A = 65,
MP_KEY_B = 66,
MP_KEY_C = 67,
MP_KEY_D = 68,
MP_KEY_E = 69,
MP_KEY_F = 70,
MP_KEY_G = 71,
MP_KEY_H = 72,
MP_KEY_I = 73,
MP_KEY_J = 74,
MP_KEY_K = 75,
MP_KEY_L = 76,
MP_KEY_M = 77,
MP_KEY_N = 78,
MP_KEY_O = 79,
MP_KEY_P = 80,
MP_KEY_Q = 81,
MP_KEY_R = 82,
MP_KEY_S = 83,
MP_KEY_T = 84,
MP_KEY_U = 85,
MP_KEY_V = 86,
MP_KEY_W = 87,
MP_KEY_X = 88,
MP_KEY_Y = 89,
MP_KEY_Z = 90,
MP_KEY_LEFT_BRACKET = 91, // [
MP_KEY_BACKSLASH = 92, // \ */
MP_KEY_RIGHT_BRACKET = 93, // ]
MP_KEY_GRAVE_ACCENT = 96, // `
MP_KEY_WORLD_1 = 161, // non-US #1
MP_KEY_WORLD_2 = 162, // non-US #2
MP_KEY_ESCAPE = 256,
MP_KEY_ENTER = 257,
MP_KEY_TAB = 258,
MP_KEY_BACKSPACE = 259,
MP_KEY_INSERT = 260,
MP_KEY_DELETE = 261,
MP_KEY_RIGHT = 262,
MP_KEY_LEFT = 263,
MP_KEY_DOWN = 264,
MP_KEY_UP = 265,
MP_KEY_PAGE_UP = 266,
MP_KEY_PAGE_DOWN = 267,
MP_KEY_HOME = 268,
MP_KEY_END = 269,
MP_KEY_CAPS_LOCK = 280,
MP_KEY_SCROLL_LOCK = 281,
MP_KEY_NUM_LOCK = 282,
MP_KEY_PRINT_SCREEN = 283,
MP_KEY_PAUSE = 284,
MP_KEY_F1 = 290,
MP_KEY_F2 = 291,
MP_KEY_F3 = 292,
MP_KEY_F4 = 293,
MP_KEY_F5 = 294,
MP_KEY_F6 = 295,
MP_KEY_F7 = 296,
MP_KEY_F8 = 297,
MP_KEY_F9 = 298,
MP_KEY_F10 = 299,
MP_KEY_F11 = 300,
MP_KEY_F12 = 301,
MP_KEY_F13 = 302,
MP_KEY_F14 = 303,
MP_KEY_F15 = 304,
MP_KEY_F16 = 305,
MP_KEY_F17 = 306,
MP_KEY_F18 = 307,
MP_KEY_F19 = 308,
MP_KEY_F20 = 309,
MP_KEY_F21 = 310,
MP_KEY_F22 = 311,
MP_KEY_F23 = 312,
MP_KEY_F24 = 313,
MP_KEY_F25 = 314,
MP_KEY_KP_0 = 320,
MP_KEY_KP_1 = 321,
MP_KEY_KP_2 = 322,
MP_KEY_KP_3 = 323,
MP_KEY_KP_4 = 324,
MP_KEY_KP_5 = 325,
MP_KEY_KP_6 = 326,
MP_KEY_KP_7 = 327,
MP_KEY_KP_8 = 328,
MP_KEY_KP_9 = 329,
MP_KEY_KP_DECIMAL = 330,
MP_KEY_KP_DIVIDE = 331,
MP_KEY_KP_MULTIPLY = 332,
MP_KEY_KP_SUBTRACT = 333,
MP_KEY_KP_ADD = 334,
MP_KEY_KP_ENTER = 335,
MP_KEY_KP_EQUAL = 336,
MP_KEY_LEFT_SHIFT = 340,
MP_KEY_LEFT_CONTROL = 341,
MP_KEY_LEFT_ALT = 342,
MP_KEY_LEFT_SUPER = 343,
MP_KEY_RIGHT_SHIFT = 344,
MP_KEY_RIGHT_CONTROL = 345,
MP_KEY_RIGHT_ALT = 346,
MP_KEY_RIGHT_SUPER = 347,
MP_KEY_MENU = 348,
MP_KEY_COUNT } mp_key_code;
typedef enum {
MP_KEYMOD_NONE = 0x00,
MP_KEYMOD_ALT = 0x01,
MP_KEYMOD_SHIFT = 0x02,
MP_KEYMOD_CTRL = 0x04,
MP_KEYMOD_CMD = 0x08 } mp_key_mods;
typedef enum {
MP_MOUSE_LEFT = 0x00,
MP_MOUSE_RIGHT = 0x01,
MP_MOUSE_MIDDLE = 0x02,
MP_MOUSE_EXT1 = 0x03,
MP_MOUSE_EXT2 = 0x04,
MP_MOUSE_BUTTON_COUNT } mp_mouse_button;
typedef struct mp_key_event // keyboard and mouse buttons input
{
mp_key_action action;
i32 code;
mp_key_mods mods;
char label[8];
u8 labelLen;
int clickCount;
} mp_key_event;
typedef struct mp_char_event // character input
{
utf32 codepoint;
char sequence[8];
u8 seqLen;
} mp_char_event;
typedef struct mp_move_event // mouse move/scroll
{
f32 x;
f32 y;
f32 deltaX;
f32 deltaY;
mp_key_mods mods;
} mp_move_event;
typedef struct mp_frame_event // window resize / move
{
mp_rect rect;
} mp_frame_event;
typedef struct mp_event
{
//TODO clipboard and path drop
mp_window window;
mp_event_type type;
union
{
mp_key_event key;
mp_char_event character;
mp_move_event move;
mp_frame_event frame;
str8 path;
};
//TODO(martin): chain externally ?
list_elt list;
} mp_event;
//--------------------------------------------------------------------
// app management
//--------------------------------------------------------------------
void mp_init();
void mp_terminate();
bool mp_should_quit();
void mp_cancel_quit();
void mp_request_quit();
void mp_set_cursor(mp_mouse_cursor cursor);
//--------------------------------------------------------------------
// Main loop and events handling
//--------------------------------------------------------------------
void mp_pump_events(f64 timeout);
bool mp_next_event(mp_event* event);
typedef void(*mp_live_resize_callback)(mp_event event, void* data);
void mp_set_live_resize_callback(mp_live_resize_callback callback, void* data);
//--------------------------------------------------------------------
// window management
//--------------------------------------------------------------------
bool mp_window_handle_is_null(mp_window window);
mp_window mp_window_null_handle();
mp_window mp_window_create(mp_rect contentRect, const char* title, mp_window_style style);
void mp_window_destroy(mp_window window);
void* mp_window_native_pointer(mp_window window);
bool mp_window_should_close(mp_window window);
void mp_window_request_close(mp_window window);
void mp_window_cancel_close(mp_window window);
bool mp_window_is_hidden(mp_window window);
void mp_window_hide(mp_window window);
void mp_window_show(mp_window window);
bool mp_window_is_minimized(mp_window window);
bool mp_window_is_maximized(mp_window window);
void mp_window_minimize(mp_window window);
void mp_window_maximize(mp_window window);
void mp_window_restore(mp_window window);
bool mp_window_has_focus(mp_window window);
void mp_window_focus(mp_window window);
void mp_window_unfocus(mp_window window);
void mp_window_send_to_back(mp_window window);
void mp_window_bring_to_front(mp_window window);
mp_rect mp_window_get_content_rect(mp_window window);
mp_rect mp_window_get_frame_rect(mp_window window);
void mp_window_set_content_rect(mp_window window, mp_rect contentRect);
void mp_window_set_frame_rect(mp_window window, mp_rect frameRect);
void mp_window_center(mp_window window);
mp_rect mp_window_content_rect_for_frame_rect(mp_rect frameRect, mp_window_style style);
mp_rect mp_window_frame_rect_for_content_rect(mp_rect contentRect, mp_window_style style);
//--------------------------------------------------------------------
// Input state polling
//--------------------------------------------------------------------
bool mp_input_key_down(mp_key_code key);
bool mp_input_key_pressed(mp_key_code key);
bool mp_input_key_released(mp_key_code key);
mp_key_mods mp_input_key_mods();
str8 mp_key_to_label(mp_key_code key);
mp_key_code mp_label_to_key(str8 label);
bool mp_input_mouse_down(mp_mouse_button button);
bool mp_input_mouse_pressed(mp_mouse_button button);
bool mp_input_mouse_released(mp_mouse_button button);
bool mp_input_mouse_clicked(mp_mouse_button button);
bool mp_input_mouse_double_clicked(mp_mouse_button button);
vec2 mp_input_mouse_position();
vec2 mp_input_mouse_delta();
vec2 mp_input_mouse_wheel();
str32 mp_input_text_utf32(mem_arena* arena);
str8 mp_input_text_utf8(mem_arena* arena);
//--------------------------------------------------------------------
// Clipboard
//--------------------------------------------------------------------
void mp_clipboard_clear();
void mp_clipboard_set_string(str8 string);
str8 mp_clipboard_get_string(mem_arena* arena);
str8 mp_clipboard_copy_string(str8 backing);
bool mp_clipboard_has_tag(const char* tag);
void mp_clipboard_set_data_for_tag(const char* tag, str8 data);
str8 mp_clipboard_get_data_for_tag(mem_arena* arena, const char* tag);
//--------------------------------------------------------------------
// native open/save/alert windows
//--------------------------------------------------------------------
str8 mp_open_dialog(mem_arena* arena,
const char* title,
const char* defaultPath,
int filterCount,
const char** filters,
bool directory);
str8 mp_save_dialog(mem_arena* arena,
const char* title,
const char* defaultPath,
int filterCount,
const char** filters);
int mp_alert_popup(const char* title,
const char* message,
u32 count,
const char** options);
//--------------------------------------------------------------------
// file system stuff... //TODO: move elsewhere
//--------------------------------------------------------------------
int mp_file_move(str8 from, str8 to);
int mp_file_remove(str8 path);
int mp_directory_create(str8 path);
str8 mp_app_get_resource_path(mem_arena* arena, const char* name);
str8 mp_app_get_executable_path(mem_arena* arena);
#ifdef __cplusplus
} // extern "C"
#endif
#endif //__PLATFORM_APP_H_
/************************************************************//**
*
* @file: platform_app.h
* @author: Martin Fouilleul
* @date: 16/05/2020
* @revision:
*
*****************************************************************/
#ifndef __PLATFORM_APP_H_
#define __PLATFORM_APP_H_
#include"typedefs.h"
#include"utf8.h"
#include"lists.h"
#ifdef __cplusplus
extern "C" {
#endif
//--------------------------------------------------------------------
// Typedefs, enums and constants
//--------------------------------------------------------------------
typedef struct mp_window { u64 h; } mp_window;
typedef enum { MP_MOUSE_CURSOR_ARROW,
MP_MOUSE_CURSOR_RESIZE_0,
MP_MOUSE_CURSOR_RESIZE_90,
MP_MOUSE_CURSOR_RESIZE_45,
MP_MOUSE_CURSOR_RESIZE_135,
MP_MOUSE_CURSOR_TEXT } mp_mouse_cursor;
typedef i32 mp_window_style;
static const mp_window_style MP_WINDOW_STYLE_NO_TITLE = 0x01<<0,
MP_WINDOW_STYLE_FIXED_SIZE = 0x01<<1,
MP_WINDOW_STYLE_NO_CLOSE = 0x01<<2,
MP_WINDOW_STYLE_NO_MINIFY = 0x01<<3,
MP_WINDOW_STYLE_NO_FOCUS = 0x01<<4,
MP_WINDOW_STYLE_FLOAT = 0x01<<5,
MP_WINDOW_STYLE_POPUPMENU = 0x01<<6,
MP_WINDOW_STYLE_NO_BUTTONS = 0x01<<7;
typedef enum { MP_EVENT_NONE,
MP_EVENT_KEYBOARD_MODS, //TODO: remove, keep only key?
MP_EVENT_KEYBOARD_KEY,
MP_EVENT_KEYBOARD_CHAR,
MP_EVENT_MOUSE_BUTTON,
MP_EVENT_MOUSE_MOVE,
MP_EVENT_MOUSE_WHEEL,
MP_EVENT_MOUSE_ENTER,
MP_EVENT_MOUSE_LEAVE,
MP_EVENT_WINDOW_RESIZE,
MP_EVENT_WINDOW_MOVE,
MP_EVENT_WINDOW_FOCUS,
MP_EVENT_WINDOW_UNFOCUS,
MP_EVENT_WINDOW_HIDE, // rename to minimize?
MP_EVENT_WINDOW_SHOW, // rename to restore?
MP_EVENT_WINDOW_CLOSE,
MP_EVENT_PATHDROP,
MP_EVENT_FRAME,
MP_EVENT_QUIT } mp_event_type;
typedef enum { MP_KEY_NO_ACTION,
MP_KEY_PRESS,
MP_KEY_RELEASE,
MP_KEY_REPEAT } mp_key_action;
typedef enum { MP_KEY_UNKNOWN = 0,
MP_KEY_SPACE = 32,
MP_KEY_APOSTROPHE = 39, /* ' */
MP_KEY_COMMA = 44, /* , */
MP_KEY_MINUS = 45, // -
MP_KEY_PERIOD = 46, // .
MP_KEY_SLASH = 47, // /
MP_KEY_0 = 48,
MP_KEY_1 = 49,
MP_KEY_2 = 50,
MP_KEY_3 = 51,
MP_KEY_4 = 52,
MP_KEY_5 = 53,
MP_KEY_6 = 54,
MP_KEY_7 = 55,
MP_KEY_8 = 56,
MP_KEY_9 = 57,
MP_KEY_SEMICOLON = 59, // ;
MP_KEY_EQUAL = 61, // =
MP_KEY_A = 65,
MP_KEY_B = 66,
MP_KEY_C = 67,
MP_KEY_D = 68,
MP_KEY_E = 69,
MP_KEY_F = 70,
MP_KEY_G = 71,
MP_KEY_H = 72,
MP_KEY_I = 73,
MP_KEY_J = 74,
MP_KEY_K = 75,
MP_KEY_L = 76,
MP_KEY_M = 77,
MP_KEY_N = 78,
MP_KEY_O = 79,
MP_KEY_P = 80,
MP_KEY_Q = 81,
MP_KEY_R = 82,
MP_KEY_S = 83,
MP_KEY_T = 84,
MP_KEY_U = 85,
MP_KEY_V = 86,
MP_KEY_W = 87,
MP_KEY_X = 88,
MP_KEY_Y = 89,
MP_KEY_Z = 90,
MP_KEY_LEFT_BRACKET = 91, // [
MP_KEY_BACKSLASH = 92, // \ */
MP_KEY_RIGHT_BRACKET = 93, // ]
MP_KEY_GRAVE_ACCENT = 96, // `
MP_KEY_WORLD_1 = 161, // non-US #1
MP_KEY_WORLD_2 = 162, // non-US #2
MP_KEY_ESCAPE = 256,
MP_KEY_ENTER = 257,
MP_KEY_TAB = 258,
MP_KEY_BACKSPACE = 259,
MP_KEY_INSERT = 260,
MP_KEY_DELETE = 261,
MP_KEY_RIGHT = 262,
MP_KEY_LEFT = 263,
MP_KEY_DOWN = 264,
MP_KEY_UP = 265,
MP_KEY_PAGE_UP = 266,
MP_KEY_PAGE_DOWN = 267,
MP_KEY_HOME = 268,
MP_KEY_END = 269,
MP_KEY_CAPS_LOCK = 280,
MP_KEY_SCROLL_LOCK = 281,
MP_KEY_NUM_LOCK = 282,
MP_KEY_PRINT_SCREEN = 283,
MP_KEY_PAUSE = 284,
MP_KEY_F1 = 290,
MP_KEY_F2 = 291,
MP_KEY_F3 = 292,
MP_KEY_F4 = 293,
MP_KEY_F5 = 294,
MP_KEY_F6 = 295,
MP_KEY_F7 = 296,
MP_KEY_F8 = 297,
MP_KEY_F9 = 298,
MP_KEY_F10 = 299,
MP_KEY_F11 = 300,
MP_KEY_F12 = 301,
MP_KEY_F13 = 302,
MP_KEY_F14 = 303,
MP_KEY_F15 = 304,
MP_KEY_F16 = 305,
MP_KEY_F17 = 306,
MP_KEY_F18 = 307,
MP_KEY_F19 = 308,
MP_KEY_F20 = 309,
MP_KEY_F21 = 310,
MP_KEY_F22 = 311,
MP_KEY_F23 = 312,
MP_KEY_F24 = 313,
MP_KEY_F25 = 314,
MP_KEY_KP_0 = 320,
MP_KEY_KP_1 = 321,
MP_KEY_KP_2 = 322,
MP_KEY_KP_3 = 323,
MP_KEY_KP_4 = 324,
MP_KEY_KP_5 = 325,
MP_KEY_KP_6 = 326,
MP_KEY_KP_7 = 327,
MP_KEY_KP_8 = 328,
MP_KEY_KP_9 = 329,
MP_KEY_KP_DECIMAL = 330,
MP_KEY_KP_DIVIDE = 331,
MP_KEY_KP_MULTIPLY = 332,
MP_KEY_KP_SUBTRACT = 333,
MP_KEY_KP_ADD = 334,
MP_KEY_KP_ENTER = 335,
MP_KEY_KP_EQUAL = 336,
MP_KEY_LEFT_SHIFT = 340,
MP_KEY_LEFT_CONTROL = 341,
MP_KEY_LEFT_ALT = 342,
MP_KEY_LEFT_SUPER = 343,
MP_KEY_RIGHT_SHIFT = 344,
MP_KEY_RIGHT_CONTROL = 345,
MP_KEY_RIGHT_ALT = 346,
MP_KEY_RIGHT_SUPER = 347,
MP_KEY_MENU = 348,
MP_KEY_COUNT } mp_key_code;
typedef enum {
MP_KEYMOD_NONE = 0x00,
MP_KEYMOD_ALT = 0x01,
MP_KEYMOD_SHIFT = 0x02,
MP_KEYMOD_CTRL = 0x04,
MP_KEYMOD_CMD = 0x08 } mp_key_mods;
typedef enum {
MP_MOUSE_LEFT = 0x00,
MP_MOUSE_RIGHT = 0x01,
MP_MOUSE_MIDDLE = 0x02,
MP_MOUSE_EXT1 = 0x03,
MP_MOUSE_EXT2 = 0x04,
MP_MOUSE_BUTTON_COUNT } mp_mouse_button;
typedef struct mp_key_event // keyboard and mouse buttons input
{
mp_key_action action;
i32 code;
mp_key_mods mods;
char label[8];
u8 labelLen;
int clickCount;
} mp_key_event;
typedef struct mp_char_event // character input
{
utf32 codepoint;
char sequence[8];
u8 seqLen;
} mp_char_event;
typedef struct mp_move_event // mouse move/scroll
{
f32 x;
f32 y;
f32 deltaX;
f32 deltaY;
mp_key_mods mods;
} mp_move_event;
typedef struct mp_frame_event // window resize / move
{
mp_rect rect;
} mp_frame_event;
typedef struct mp_event
{
//TODO clipboard and path drop
mp_window window;
mp_event_type type;
union
{
mp_key_event key;
mp_char_event character;
mp_move_event move;
mp_frame_event frame;
str8 path;
};
//TODO(martin): chain externally ?
list_elt list;
} mp_event;
//--------------------------------------------------------------------
// app management
//--------------------------------------------------------------------
MP_API void mp_init(void);
MP_API void mp_terminate(void);
MP_API bool mp_should_quit(void);
MP_API void mp_cancel_quit(void);
MP_API void mp_request_quit(void);
MP_API void mp_set_cursor(mp_mouse_cursor cursor);
//--------------------------------------------------------------------
// Main loop and events handling
//--------------------------------------------------------------------
MP_API void mp_pump_events(f64 timeout);
MP_API bool mp_next_event(mp_event* event);
typedef void(*mp_live_resize_callback)(mp_event event, void* data);
MP_API void mp_set_live_resize_callback(mp_live_resize_callback callback, void* data);
//--------------------------------------------------------------------
// window management
//--------------------------------------------------------------------
MP_API bool mp_window_handle_is_null(mp_window window);
MP_API mp_window mp_window_null_handle(void);
MP_API mp_window mp_window_create(mp_rect contentRect, const char* title, mp_window_style style);
MP_API void mp_window_destroy(mp_window window);
MP_API void* mp_window_native_pointer(mp_window window);
MP_API bool mp_window_should_close(mp_window window);
MP_API void mp_window_request_close(mp_window window);
MP_API void mp_window_cancel_close(mp_window window);
MP_API bool mp_window_is_hidden(mp_window window);
MP_API void mp_window_hide(mp_window window);
MP_API void mp_window_show(mp_window window);
MP_API bool mp_window_is_minimized(mp_window window);
MP_API bool mp_window_is_maximized(mp_window window);
MP_API void mp_window_minimize(mp_window window);
MP_API void mp_window_maximize(mp_window window);
MP_API void mp_window_restore(mp_window window);
MP_API bool mp_window_has_focus(mp_window window);
MP_API void mp_window_focus(mp_window window);
MP_API void mp_window_unfocus(mp_window window);
MP_API void mp_window_send_to_back(mp_window window);
MP_API void mp_window_bring_to_front(mp_window window);
MP_API mp_rect mp_window_get_content_rect(mp_window window);
MP_API mp_rect mp_window_get_frame_rect(mp_window window);
MP_API void mp_window_set_content_rect(mp_window window, mp_rect contentRect);
MP_API void mp_window_set_frame_rect(mp_window window, mp_rect frameRect);
MP_API void mp_window_center(mp_window window);
MP_API mp_rect mp_window_content_rect_for_frame_rect(mp_rect frameRect, mp_window_style style);
MP_API mp_rect mp_window_frame_rect_for_content_rect(mp_rect contentRect, mp_window_style style);
//--------------------------------------------------------------------
// Input state polling
//--------------------------------------------------------------------
MP_API bool mp_input_key_down(mp_key_code key);
MP_API bool mp_input_key_pressed(mp_key_code key);
MP_API bool mp_input_key_released(mp_key_code key);
MP_API mp_key_mods mp_input_key_mods(void);
MP_API str8 mp_key_to_label(mp_key_code key);
MP_API mp_key_code mp_label_to_key(str8 label);
MP_API bool mp_input_mouse_down(mp_mouse_button button);
MP_API bool mp_input_mouse_pressed(mp_mouse_button button);
MP_API bool mp_input_mouse_released(mp_mouse_button button);
MP_API bool mp_input_mouse_clicked(mp_mouse_button button);
MP_API bool mp_input_mouse_double_clicked(mp_mouse_button button);
MP_API vec2 mp_input_mouse_position(void);
MP_API vec2 mp_input_mouse_delta(void);
MP_API vec2 mp_input_mouse_wheel(void);
MP_API str32 mp_input_text_utf32(mem_arena* arena);
MP_API str8 mp_input_text_utf8(mem_arena* arena);
//--------------------------------------------------------------------
// Clipboard
//--------------------------------------------------------------------
MP_API void mp_clipboard_clear(void);
MP_API void mp_clipboard_set_string(str8 string);
MP_API str8 mp_clipboard_get_string(mem_arena* arena);
MP_API str8 mp_clipboard_copy_string(str8 backing);
MP_API bool mp_clipboard_has_tag(const char* tag);
MP_API void mp_clipboard_set_data_for_tag(const char* tag, str8 data);
MP_API str8 mp_clipboard_get_data_for_tag(mem_arena* arena, const char* tag);
//--------------------------------------------------------------------
// native open/save/alert windows
//--------------------------------------------------------------------
MP_API str8 mp_open_dialog(mem_arena* arena,
const char* title,
const char* defaultPath,
int filterCount,
const char** filters,
bool directory);
MP_API str8 mp_save_dialog(mem_arena* arena,
const char* title,
const char* defaultPath,
int filterCount,
const char** filters);
MP_API int mp_alert_popup(const char* title,
const char* message,
u32 count,
const char** options);
//--------------------------------------------------------------------
// file system stuff... //TODO: move elsewhere
//--------------------------------------------------------------------
MP_API int mp_file_move(str8 from, str8 to);
MP_API int mp_file_remove(str8 path);
MP_API int mp_directory_create(str8 path);
MP_API str8 mp_app_get_resource_path(mem_arena* arena, const char* name);
MP_API str8 mp_app_get_executable_path(mem_arena* arena);
#ifdef __cplusplus
} // extern "C"
#endif
#endif //__PLATFORM_APP_H_

View File

@ -1,85 +1,93 @@
//*****************************************************************
//
// $file: platform.h $
// $author: Martin Fouilleul $
// $date: 22/12/2022 $
// $revision: $
// $note: (C) 2022 by Martin Fouilleul - all rights reserved $
//
//*****************************************************************
#ifndef __PLATFORM_H_
#define __PLATFORM_H_
//-----------------------------------------------------------------
// Compiler identification
//-----------------------------------------------------------------
#if defined(__clang__)
#define COMPILER_CLANG 1
#if defined(__apple_build_version__)
#define COMPILER_CLANG_APPLE 1
#elif defined(_MSC_VER)
#define COMPILER_CLANG_CL 1
#endif
#elif defined(_MSC_VER)
#define COMPILER_CL 1
#elif defined(__GNUC__)
#define COMPILER_GCC 1
#else
#error "Can't identify compiler"
#endif
//-----------------------------------------------------------------
// OS identification
//-----------------------------------------------------------------
#if defined(_WIN64)
#define OS_WIN64 1
#elif defined(_WIN32)
#error "Unsupported OS (32bit only version of Windows)"
#elif defined(__APPLE__) && defined(__MACH__)
#define OS_MACOS 1
#elif defined(__gnu_linux__)
#define OS_LINUX 1
#else
#error "Can't identify OS"
#endif
//-----------------------------------------------------------------
// Architecture identification
//-----------------------------------------------------------------
#if defined(COMPILER_CL)
#if defined(_M_AMD64)
#define ARCH_X64 1
#elif defined(_M_I86)
#define ARCH_X86 1
#elif defined(_M_ARM64)
#define ARCH_ARM64 1
#elif defined(_M_ARM)
#define ARCH_ARM32 1
#else
#error "Can't identify architecture"
#endif
#else
#if defined(__x86_64__)
#define ARCH_X64 1
#elif defined(__i386__)
#define ARCH_X86 1
#elif defined(__arm__)
#define ARCH_ARM32 1
#elif defined(__aarch64__)
#define ARCH_ARM64 1
#else
#error "Can't identify architecture"
#endif
#endif
//-----------------------------------------------------------------
// platform helper macros
//-----------------------------------------------------------------
#if defined(COMPILER_CL)
#define mp_thread_local __declspec(thread)
#elif defined(COMPILER_GCC) || defined(COMPILER_CLANG)
#define mp_thread_local __thread
#endif
#endif // __PLATFORM_H_
//*****************************************************************
//
// $file: platform.h $
// $author: Martin Fouilleul $
// $date: 22/12/2022 $
// $revision: $
// $note: (C) 2022 by Martin Fouilleul - all rights reserved $
//
//*****************************************************************
#ifndef __PLATFORM_H_
#define __PLATFORM_H_
//-----------------------------------------------------------------
// Compiler identification
//-----------------------------------------------------------------
#if defined(__clang__)
#define COMPILER_CLANG 1
#if defined(__apple_build_version__)
#define COMPILER_CLANG_APPLE 1
#elif defined(_MSC_VER)
#define COMPILER_CLANG_CL 1
#endif
#elif defined(_MSC_VER)
#define COMPILER_CL 1
#elif defined(__GNUC__)
#define COMPILER_GCC 1
#else
#error "Can't identify compiler"
#endif
//-----------------------------------------------------------------
// OS identification
//-----------------------------------------------------------------
#if defined(_WIN64)
#define OS_WIN64 1
#elif defined(_WIN32)
#error "Unsupported OS (32bit only version of Windows)"
#elif defined(__APPLE__) && defined(__MACH__)
#define OS_MACOS 1
#elif defined(__gnu_linux__)
#define OS_LINUX 1
#else
#error "Can't identify OS"
#endif
//-----------------------------------------------------------------
// Architecture identification
//-----------------------------------------------------------------
#if defined(COMPILER_CL)
#if defined(_M_AMD64)
#define ARCH_X64 1
#elif defined(_M_I86)
#define ARCH_X86 1
#elif defined(_M_ARM64)
#define ARCH_ARM64 1
#elif defined(_M_ARM)
#define ARCH_ARM32 1
#else
#error "Can't identify architecture"
#endif
#else
#if defined(__x86_64__)
#define ARCH_X64 1
#elif defined(__i386__)
#define ARCH_X86 1
#elif defined(__arm__)
#define ARCH_ARM32 1
#elif defined(__aarch64__)
#define ARCH_ARM64 1
#else
#error "Can't identify architecture"
#endif
#endif
//-----------------------------------------------------------------
// platform helper macros
//-----------------------------------------------------------------
#if defined(COMPILER_CL)
#if defined(MP_BUILD_DLL)
#define MP_API __declspec(dllexport)
#else
#define MP_API __declspec(dllimport)
#endif
#define mp_thread_local __declspec(thread)
#elif defined(COMPILER_GCC) || defined(COMPILER_CLANG)
#define MP_API
#define mp_thread_local __thread
#endif
#endif // __PLATFORM_H_

View File

@ -1,34 +1,34 @@
/************************************************************//**
*
* @file: platform_clock.h
* @author: Martin Fouilleul
* @date: 07/03/2019
* @revision:
*
*****************************************************************/
#ifndef __PLATFORM_CLOCK_H_
#define __PLATFORM_CLOCK_H_
#include"typedefs.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
typedef enum {
MP_CLOCK_MONOTONIC, // clock that increment monotonically
MP_CLOCK_UPTIME, // clock that increment monotonically during uptime
MP_CLOCK_DATE // clock that is driven by the platform time
} mp_clock_kind;
void mp_clock_init(); // initialize the clock subsystem
u64 mp_get_timestamp(mp_clock_kind clock);
f64 mp_get_time(mp_clock_kind clock);
void mp_sleep_nanoseconds(u64 nanoseconds); // sleep for a given number of nanoseconds
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif //__PLATFORM_CLOCK_H_
/************************************************************//**
*
* @file: platform_clock.h
* @author: Martin Fouilleul
* @date: 07/03/2019
* @revision:
*
*****************************************************************/
#ifndef __PLATFORM_CLOCK_H_
#define __PLATFORM_CLOCK_H_
#include"typedefs.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
typedef enum {
MP_CLOCK_MONOTONIC, // clock that increment monotonically
MP_CLOCK_UPTIME, // clock that increment monotonically during uptime
MP_CLOCK_DATE // clock that is driven by the platform time
} mp_clock_kind;
MP_API void mp_clock_init(); // initialize the clock subsystem
MP_API u64 mp_get_timestamp(mp_clock_kind clock);
MP_API f64 mp_get_time(mp_clock_kind clock);
MP_API void mp_sleep_nanoseconds(u64 nanoseconds); // sleep for a given number of nanoseconds
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif //__PLATFORM_CLOCK_H_

View File

@ -1,97 +1,98 @@
/************************************************************//**
*
* @file: debug_log.h
* @author: Martin Fouilleul
* @date: 05/04/2019
* @revision:
*
*****************************************************************/
#ifndef __DEBUG_LOG_H_
#define __DEBUG_LOG_H_
#include<stdio.h>
#include"typedefs.h"
#include"macro_helpers.h"
#ifdef __cplusplus
extern "C" {
#endif
//NOTE(martin): the default logging level can be adjusted by defining LOG_DEFAULT_LEVEL. As the name suggest, it is the default, but it
// can be adjusted at runtime with LogLevel()
#ifndef LOG_DEFAULT_LEVEL
#define LOG_DEFAULT_LEVEL LOG_LEVEL_WARNING
#endif
//NOTE(martin): the default output can be adjusted by defining LOG_DEFAULT_OUTPUT. It can be adjusted at runtime with LogOutput()
#ifndef LOG_DEFAULT_OUTPUT
#define LOG_DEFAULT_OUTPUT stdout
#endif
//NOTE(martin): LOG_SUBSYSTEM can be defined in each compilation unit to associate it with a subsystem, like this:
// #define LOG_SUBSYSTEM "name"
typedef enum { LOG_LEVEL_ERROR,
LOG_LEVEL_WARNING,
LOG_LEVEL_MESSAGE,
LOG_LEVEL_DEBUG,
LOG_LEVEL_COUNT } log_level;
void LogGeneric(log_level level,
const char* subsystem,
const char* functionName,
const char* fileName,
u32 line,
const char* msg,
...);
void LogOutput(FILE* output);
void LogLevel(log_level level);
void LogFilter(const char* subsystem, log_level level);
#define LOG_GENERIC(level, func, file, line, msg, ...) LogGeneric(level, LOG_SUBSYSTEM, func, file, line, msg, ##__VA_ARGS__ )
#define LOG_ERROR(msg, ...) LOG_GENERIC(LOG_LEVEL_ERROR, __FUNCTION__, __FILE__, __LINE__, msg, ##__VA_ARGS__ )
//NOTE(martin): warnings, messages, and debug info can be enabled in debug mode by defining LOG_COMPILE_XXX, XXX being the max desired log level
// error logging is always compiled
#if defined(LOG_COMPILE_WARNING) || defined(LOG_COMPILE_MESSAGE) || defined(LOG_COMPILE_DEBUG)
#define LOG_WARNING(msg, ...) LOG_GENERIC(LOG_LEVEL_WARNING, __FUNCTION__, __FILE__, __LINE__, msg, ##__VA_ARGS__ )
#if defined(LOG_COMPILE_MESSAGE) || defined(LOG_COMPILE_DEBUG)
#define LOG_MESSAGE(msg, ...) LOG_GENERIC(LOG_LEVEL_MESSAGE, __FUNCTION__, __FILE__, __LINE__, msg, ##__VA_ARGS__ )
#if defined(LOG_COMPILE_DEBUG)
#define LOG_DEBUG(msg, ...) LOG_GENERIC(LOG_LEVEL_DEBUG, __FUNCTION__, __FILE__, __LINE__, msg, ##__VA_ARGS__ )
#else
#define LOG_DEBUG(msg, ...)
#endif
#else
#define LOG_MESSAGE(msg, ...)
#define LOG_DEBUG(msg, ...)
#endif
#else
#define LOG_WARNING(msg, ...)
#define LOG_MESSAGE(msg, ...)
#define LOG_DEBUG(msg, ...)
#endif
#ifndef NO_ASSERT
#include<assert.h>
#define _ASSERT_(x, msg) assert(x && msg)
#define ASSERT(x, ...) _ASSERT_(x, #__VA_ARGS__)
#ifdef DEBUG
#define DEBUG_ASSERT(x, ...) ASSERT(x, ##__VA_ARGS__ )
#else
#define DEBUG_ASSERT(x, ...)
#endif
#else
#define ASSERT(x, ...)
#define DEBUG_ASSERT(x, ...)
#endif
#ifdef __cplusplus
} // extern "C"
#endif
#endif //__DEBUG_LOG_H_
/************************************************************//**
*
* @file: debug_log.h
* @author: Martin Fouilleul
* @date: 05/04/2019
* @revision:
*
*****************************************************************/
#ifndef __DEBUG_LOG_H_
#define __DEBUG_LOG_H_
#include<stdio.h>
#include"platform.h"
#include"typedefs.h"
#include"macro_helpers.h"
#ifdef __cplusplus
extern "C" {
#endif
//NOTE(martin): the default logging level can be adjusted by defining LOG_DEFAULT_LEVEL. As the name suggest, it is the default, but it
// can be adjusted at runtime with LogLevel()
#ifndef LOG_DEFAULT_LEVEL
#define LOG_DEFAULT_LEVEL LOG_LEVEL_WARNING
#endif
//NOTE(martin): the default output can be adjusted by defining LOG_DEFAULT_OUTPUT. It can be adjusted at runtime with LogOutput()
#ifndef LOG_DEFAULT_OUTPUT
#define LOG_DEFAULT_OUTPUT stdout
#endif
//NOTE(martin): LOG_SUBSYSTEM can be defined in each compilation unit to associate it with a subsystem, like this:
// #define LOG_SUBSYSTEM "name"
typedef enum { LOG_LEVEL_ERROR,
LOG_LEVEL_WARNING,
LOG_LEVEL_MESSAGE,
LOG_LEVEL_DEBUG,
LOG_LEVEL_COUNT } log_level;
MP_API void LogGeneric(log_level level,
const char* subsystem,
const char* functionName,
const char* fileName,
u32 line,
const char* msg,
...);
MP_API void LogOutput(FILE* output);
MP_API void LogLevel(log_level level);
MP_API void LogFilter(const char* subsystem, log_level level);
#define LOG_GENERIC(level, func, file, line, msg, ...) LogGeneric(level, LOG_SUBSYSTEM, func, file, line, msg, ##__VA_ARGS__ )
#define LOG_ERROR(msg, ...) LOG_GENERIC(LOG_LEVEL_ERROR, __FUNCTION__, __FILE__, __LINE__, msg, ##__VA_ARGS__ )
//NOTE(martin): warnings, messages, and debug info can be enabled in debug mode by defining LOG_COMPILE_XXX, XXX being the max desired log level
// error logging is always compiled
#if defined(LOG_COMPILE_WARNING) || defined(LOG_COMPILE_MESSAGE) || defined(LOG_COMPILE_DEBUG)
#define LOG_WARNING(msg, ...) LOG_GENERIC(LOG_LEVEL_WARNING, __FUNCTION__, __FILE__, __LINE__, msg, ##__VA_ARGS__ )
#if defined(LOG_COMPILE_MESSAGE) || defined(LOG_COMPILE_DEBUG)
#define LOG_MESSAGE(msg, ...) LOG_GENERIC(LOG_LEVEL_MESSAGE, __FUNCTION__, __FILE__, __LINE__, msg, ##__VA_ARGS__ )
#if defined(LOG_COMPILE_DEBUG)
#define LOG_DEBUG(msg, ...) LOG_GENERIC(LOG_LEVEL_DEBUG, __FUNCTION__, __FILE__, __LINE__, msg, ##__VA_ARGS__ )
#else
#define LOG_DEBUG(msg, ...)
#endif
#else
#define LOG_MESSAGE(msg, ...)
#define LOG_DEBUG(msg, ...)
#endif
#else
#define LOG_WARNING(msg, ...)
#define LOG_MESSAGE(msg, ...)
#define LOG_DEBUG(msg, ...)
#endif
#ifndef NO_ASSERT
#include<assert.h>
#define _ASSERT_(x, msg) assert(x && msg)
#define ASSERT(x, ...) _ASSERT_(x, #__VA_ARGS__)
#ifdef DEBUG
#define DEBUG_ASSERT(x, ...) ASSERT(x, ##__VA_ARGS__ )
#else
#define DEBUG_ASSERT(x, ...)
#endif
#else
#define ASSERT(x, ...)
#define DEBUG_ASSERT(x, ...)
#endif
#ifdef __cplusplus
} // extern "C"
#endif
#endif //__DEBUG_LOG_H_

View File

@ -1,29 +1,29 @@
/************************************************************//**
*
* @file: hash.h
* @author: Martin Fouilleul
* @date: 08/08/2022
* @revision:
*
*****************************************************************/
#ifndef __HASH_H_
#define __HASH_H_
#include"typedefs.h"
#include"strings.h"
#ifdef __cplusplus
extern "C" {
#endif
u64 mp_hash_aes_u64(u64 x);
u64 mp_hash_aes_u64_x2(u64 x, u64 y);
u64 mp_hash_aes_string(str8 string);
u64 mp_hash_aes_string_seed(str8 string, u64 seed);
#ifdef __cplusplus
} // extern "C"
#endif
#endif //__HASH_H_
/************************************************************//**
*
* @file: hash.h
* @author: Martin Fouilleul
* @date: 08/08/2022
* @revision:
*
*****************************************************************/
#ifndef __HASH_H_
#define __HASH_H_
#include"typedefs.h"
#include"strings.h"
#ifdef __cplusplus
extern "C" {
#endif
MP_API u64 mp_hash_aes_u64(u64 x);
MP_API u64 mp_hash_aes_u64_x2(u64 x, u64 y);
MP_API u64 mp_hash_aes_string(str8 string);
MP_API u64 mp_hash_aes_string_seed(str8 string, u64 seed);
#ifdef __cplusplus
} // extern "C"
#endif
#endif //__HASH_H_

View File

@ -1,106 +1,106 @@
/************************************************************//**
*
* @file: memory.h
* @author: Martin Fouilleul
* @date: 24/10/2019
* @revision:
*
*****************************************************************/
#ifndef __MEMORY_H_
#define __MEMORY_H_
#include"typedefs.h"
#include"lists.h"
#ifdef __cplusplus
extern "C" {
#endif
//--------------------------------------------------------------------------------
//NOTE(martin): base allocator
//--------------------------------------------------------------------------------
typedef void*(*mem_reserve_function)(void* context, u64 size);
typedef void(*mem_modify_function)(void* context, void* ptr, u64 size);
typedef struct mem_base_allocator
{
mem_reserve_function reserve;
mem_modify_function commit;
mem_modify_function decommit;
mem_modify_function release;
void* context;
} mem_base_allocator;
mem_base_allocator* mem_base_allocator_default();
#define mem_base_reserve(base, size) base->reserve(base->context, size)
#define mem_base_commit(base, ptr, size) base->commit(base->context, ptr, size)
#define mem_base_decommit(base, ptr, size) base->decommit(base->context, ptr, size)
#define mem_base_release(base, ptr, size) base->release(base->context, ptr, size)
//--------------------------------------------------------------------------------
//NOTE(martin): memory arena
//--------------------------------------------------------------------------------
typedef struct mem_arena
{
mem_base_allocator* base;
char* ptr;
u64 offset;
u64 committed;
u64 cap;
} mem_arena;
typedef struct mem_arena_options
{
mem_base_allocator* base;
u64 reserve;
} mem_arena_options;
void mem_arena_init(mem_arena* arena);
void mem_arena_init_with_options(mem_arena* arena, mem_arena_options* options);
void mem_arena_release(mem_arena* arena);
void* mem_arena_alloc(mem_arena* arena, u64 size);
void mem_arena_clear(mem_arena* arena);
#define mem_arena_alloc_type(arena, type) ((type*)mem_arena_alloc(arena, sizeof(type)))
#define mem_arena_alloc_array(arena, type, count) ((type*)mem_arena_alloc(arena, sizeof(type)*(count)))
//--------------------------------------------------------------------------------
//NOTE(martin): memory pool
//--------------------------------------------------------------------------------
typedef struct mem_pool
{
mem_arena arena;
list_info freeList;
u64 blockSize;
} mem_pool;
typedef struct mem_pool_options
{
mem_base_allocator* base;
u64 reserve;
} mem_pool_options;
void mem_pool_init(mem_pool* pool, u64 blockSize);
void mem_pool_init_with_options(mem_pool* pool, u64 blockSize, mem_pool_options* options);
void mem_pool_release(mem_pool* pool);
void* mem_pool_alloc(mem_pool* pool);
void mem_pool_recycle(mem_pool* pool, void* ptr);
void mem_pool_clear(mem_pool* pool);
#define mem_pool_alloc_type(arena, type) ((type*)mem_pool_alloc(arena))
//--------------------------------------------------------------------------------
//NOTE(martin): per-thread implicit scratch arena
//--------------------------------------------------------------------------------
void mem_scratch_clear();
mem_arena* mem_scratch();
#ifdef __cplusplus
} // extern "C"
#endif
#endif //__MEMORY_H_
/************************************************************//**
*
* @file: memory.h
* @author: Martin Fouilleul
* @date: 24/10/2019
* @revision:
*
*****************************************************************/
#ifndef __MEMORY_H_
#define __MEMORY_H_
#include"typedefs.h"
#include"lists.h"
#ifdef __cplusplus
extern "C" {
#endif
//--------------------------------------------------------------------------------
//NOTE(martin): base allocator
//--------------------------------------------------------------------------------
typedef void*(*mem_reserve_function)(void* context, u64 size);
typedef void(*mem_modify_function)(void* context, void* ptr, u64 size);
typedef struct mem_base_allocator
{
mem_reserve_function reserve;
mem_modify_function commit;
mem_modify_function decommit;
mem_modify_function release;
void* context;
} mem_base_allocator;
MP_API mem_base_allocator* mem_base_allocator_default();
#define mem_base_reserve(base, size) base->reserve(base->context, size)
#define mem_base_commit(base, ptr, size) base->commit(base->context, ptr, size)
#define mem_base_decommit(base, ptr, size) base->decommit(base->context, ptr, size)
#define mem_base_release(base, ptr, size) base->release(base->context, ptr, size)
//--------------------------------------------------------------------------------
//NOTE(martin): memory arena
//--------------------------------------------------------------------------------
typedef struct mem_arena
{
mem_base_allocator* base;
char* ptr;
u64 offset;
u64 committed;
u64 cap;
} mem_arena;
typedef struct mem_arena_options
{
mem_base_allocator* base;
u64 reserve;
} mem_arena_options;
MP_API void mem_arena_init(mem_arena* arena);
MP_API void mem_arena_init_with_options(mem_arena* arena, mem_arena_options* options);
MP_API void mem_arena_release(mem_arena* arena);
MP_API void* mem_arena_alloc(mem_arena* arena, u64 size);
MP_API void mem_arena_clear(mem_arena* arena);
#define mem_arena_alloc_type(arena, type) ((type*)mem_arena_alloc(arena, sizeof(type)))
#define mem_arena_alloc_array(arena, type, count) ((type*)mem_arena_alloc(arena, sizeof(type)*(count)))
//--------------------------------------------------------------------------------
//NOTE(martin): memory pool
//--------------------------------------------------------------------------------
typedef struct mem_pool
{
mem_arena arena;
list_info freeList;
u64 blockSize;
} mem_pool;
typedef struct mem_pool_options
{
mem_base_allocator* base;
u64 reserve;
} mem_pool_options;
MP_API void mem_pool_init(mem_pool* pool, u64 blockSize);
MP_API void mem_pool_init_with_options(mem_pool* pool, u64 blockSize, mem_pool_options* options);
MP_API void mem_pool_release(mem_pool* pool);
MP_API void* mem_pool_alloc(mem_pool* pool);
MP_API void mem_pool_recycle(mem_pool* pool, void* ptr);
MP_API void mem_pool_clear(mem_pool* pool);
#define mem_pool_alloc_type(arena, type) ((type*)mem_pool_alloc(arena))
//--------------------------------------------------------------------------------
//NOTE(martin): per-thread implicit scratch arena
//--------------------------------------------------------------------------------
MP_API void mem_scratch_clear();
MP_API mem_arena* mem_scratch();
#ifdef __cplusplus
} // extern "C"
#endif
#endif //__MEMORY_H_

View File

@ -1,113 +1,113 @@
/************************************************************//**
*
* @file: strings.h
* @author: Martin Fouilleul
* @date: 29/05/2021
* @revision:
*
*****************************************************************/
#ifndef __STRINGS_H_
#define __STRINGS_H_
#include"typedefs.h"
#include"lists.h"
#include"memory.h"
#ifdef __cplusplus
extern "C" {
#endif
//----------------------------------------------------------------------------------
// string slices as values
//----------------------------------------------------------------------------------
typedef struct str8
{
u64 len;
char* ptr;
} str8;
#define str8_lit(s) ((str8){.len = sizeof(s)-1, .ptr = (char*)(s)})
#define str8_unbox(s) (int)((s).len), ((s).ptr)
str8 str8_from_buffer(u64 len, char* buffer);
str8 str8_from_cstring(char* str);
str8 str8_slice(str8 s, u64 start, u64 end);
str8 str8_push_buffer(mem_arena* arena, u64 len, char* buffer);
str8 str8_push_cstring(mem_arena* arena, const char* str);
str8 str8_push_copy(mem_arena* arena, str8 s);
str8 str8_push_slice(mem_arena* arena, str8 s, u64 start, u64 end);
str8 str8_pushfv(mem_arena* arena, const char* format, va_list args);
str8 str8_pushf(mem_arena* arena, const char* format, ...);
int str8_cmp(str8 s1, str8 s2);
char* str8_to_cstring(mem_arena* arena, str8 string);
//----------------------------------------------------------------------------------
// string lists
//----------------------------------------------------------------------------------
typedef struct str8_elt
{
list_elt listElt;
str8 string;
} str8_elt;
typedef struct str8_list
{
list_info list;
u64 eltCount;
u64 len;
} str8_list;
void str8_list_push(mem_arena* arena, str8_list* list, str8 str);
void str8_list_pushf(mem_arena* arena, str8_list* list, const char* format, ...);
str8 str8_list_join(mem_arena* arena, str8_list list);
str8_list str8_split(mem_arena* arena, str8 str, str8_list separators);
//----------------------------------------------------------------------------------
// u32 strings
//----------------------------------------------------------------------------------
typedef struct str32
{
u64 len;
u32* ptr;
} str32;
str32 str32_from_buffer(u64 len, u32* buffer);
str32 str32_slice(str32 s, u64 start, u64 end);
str32 str32_push_buffer(mem_arena* arena, u64 len, u32* buffer);
str32 str32_push_copy(mem_arena* arena, str32 s);
str32 str32_push_slice(mem_arena* arena, str32 s, u64 start, u64 end);
typedef struct str32_elt
{
list_elt listElt;
str32 string;
} str32_elt;
typedef struct str32_list
{
list_info list;
u64 eltCount;
u64 len;
} str32_list;
void str32_list_push(mem_arena* arena, str32_list* list, str32 str);
str32 str32_list_join(mem_arena* arena, str32_list list);
str32_list str32_split(mem_arena* arena, str32 str, str32_list separators);
//----------------------------------------------------------------------------------
// Paths helpers
//----------------------------------------------------------------------------------
str8 mp_path_directory(str8 fullPath);
str8 mp_path_base_name(str8 fullPath);
#ifdef __cplusplus
} // extern "C"
#endif
#endif //__STRINGS_H_
/************************************************************//**
*
* @file: strings.h
* @author: Martin Fouilleul
* @date: 29/05/2021
* @revision:
*
*****************************************************************/
#ifndef __STRINGS_H_
#define __STRINGS_H_
#include"typedefs.h"
#include"lists.h"
#include"memory.h"
#ifdef __cplusplus
extern "C" {
#endif
//----------------------------------------------------------------------------------
// string slices as values
//----------------------------------------------------------------------------------
typedef struct str8
{
u64 len;
char* ptr;
} str8;
#define str8_lit(s) ((str8){.len = sizeof(s)-1, .ptr = (char*)(s)})
#define str8_unbox(s) (int)((s).len), ((s).ptr)
MP_API str8 str8_from_buffer(u64 len, char* buffer);
MP_API str8 str8_from_cstring(char* str);
MP_API str8 str8_slice(str8 s, u64 start, u64 end);
MP_API str8 str8_push_buffer(mem_arena* arena, u64 len, char* buffer);
MP_API str8 str8_push_cstring(mem_arena* arena, const char* str);
MP_API str8 str8_push_copy(mem_arena* arena, str8 s);
MP_API str8 str8_push_slice(mem_arena* arena, str8 s, u64 start, u64 end);
MP_API str8 str8_pushfv(mem_arena* arena, const char* format, va_list args);
MP_API str8 str8_pushf(mem_arena* arena, const char* format, ...);
MP_API int str8_cmp(str8 s1, str8 s2);
MP_API char* str8_to_cstring(mem_arena* arena, str8 string);
//----------------------------------------------------------------------------------
// string lists
//----------------------------------------------------------------------------------
typedef struct str8_elt
{
list_elt listElt;
str8 string;
} str8_elt;
typedef struct str8_list
{
list_info list;
u64 eltCount;
u64 len;
} str8_list;
MP_API void str8_list_push(mem_arena* arena, str8_list* list, str8 str);
MP_API void str8_list_pushf(mem_arena* arena, str8_list* list, const char* format, ...);
MP_API str8 str8_list_join(mem_arena* arena, str8_list list);
MP_API str8_list str8_split(mem_arena* arena, str8 str, str8_list separators);
//----------------------------------------------------------------------------------
// u32 strings
//----------------------------------------------------------------------------------
typedef struct str32
{
u64 len;
u32* ptr;
} str32;
MP_API str32 str32_from_buffer(u64 len, u32* buffer);
MP_API str32 str32_slice(str32 s, u64 start, u64 end);
MP_API str32 str32_push_buffer(mem_arena* arena, u64 len, u32* buffer);
MP_API str32 str32_push_copy(mem_arena* arena, str32 s);
MP_API str32 str32_push_slice(mem_arena* arena, str32 s, u64 start, u64 end);
typedef struct str32_elt
{
list_elt listElt;
str32 string;
} str32_elt;
typedef struct str32_list
{
list_info list;
u64 eltCount;
u64 len;
} str32_list;
MP_API void str32_list_push(mem_arena* arena, str32_list* list, str32 str);
MP_API str32 str32_list_join(mem_arena* arena, str32_list list);
MP_API str32_list str32_split(mem_arena* arena, str32 str, str32_list separators);
//----------------------------------------------------------------------------------
// Paths helpers
//----------------------------------------------------------------------------------
MP_API str8 mp_path_directory(str8 fullPath);
MP_API str8 mp_path_base_name(str8 fullPath);
#ifdef __cplusplus
} // extern "C"
#endif
#endif //__STRINGS_H_

View File

@ -1,283 +1,284 @@
//*****************************************************************
//
// $file: utf8.c $
// $author: Martin Fouilleul $
// $date: 05/11/2016 $
// $revision: $
// $note: (C) 2016 by Martin Fouilleul - all rights reserved $
//
//*****************************************************************
#include"utf8.h"
#include<string.h>
//-----------------------------------------------------------------
// utf-8 gore
//-----------------------------------------------------------------
const u32 offsetsFromUTF8[6] = {
0x00000000UL, 0x00003080UL, 0x000E2080UL,
0x03C82080UL, 0xFA082080UL, 0x82082080UL };
const char trailingBytesForUTF8[256] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
};
#define utf8_is_start_byte(c) (((c)&0xc0)!=0x80)
//-----------------------------------------------------------------
//NOTE: getting sizes / offsets / indices
//-----------------------------------------------------------------
u32 utf8_size_from_leading_char(char leadingChar)
{
return(trailingBytesForUTF8[(unsigned int)(unsigned char)leadingChar] + 1);
}
u32 utf8_codepoint_size(utf32 codePoint)
{
if(codePoint < 0x80)
{
return(1);
}
if(codePoint < 0x800)
{
return(2);
}
if(codePoint < 0x10000)
{
return(3);
}
if(codePoint < 0x110000)
{
return(4);
}
return(0);
}
u64 utf8_codepoint_count_for_string(str8 string)
{
u64 byteOffset = 0;
u64 codePointIndex = 0;
for(;
(byteOffset < string.len) && (string.ptr[byteOffset] != 0);
codePointIndex++)
{
utf8_dec decode = utf8_decode_at(string, byteOffset);
byteOffset += decode.size;
}
return(codePointIndex);
}
u64 utf8_byte_count_for_codepoints(str32 codePoints)
{
//NOTE(martin): return the exact number of bytes taken by the encoded
// version of codePoints. (ie do not attempt to provision
// for a zero terminator).
u64 byteCount = 0;
for(u64 i=0; i<codePoints.len; i++)
{
byteCount += utf8_codepoint_size(codePoints.ptr[i]);
}
return(byteCount);
}
u64 utf8_next_offset(str8 string, u64 byteOffset)
{
u64 res = 0;
if(byteOffset >= string.len)
{
res = string.len;
}
else
{
u64 nextOffset = byteOffset + utf8_size_from_leading_char(string.ptr[byteOffset]);
res = minimum(nextOffset, string.len);
}
return(res);
}
u64 utf8_prev_offset(str8 string, u64 byteOffset)
{
u64 res = 0;
if(byteOffset > string.len)
{
res = string.len;
}
else if(byteOffset)
{
byteOffset--;
while(byteOffset > 0 && !utf8_is_start_byte(string.ptr[byteOffset]))
{
byteOffset--;
}
res = byteOffset;
}
return(res);
}
//-----------------------------------------------------------------
//NOTE: encoding / decoding
//-----------------------------------------------------------------
utf8_dec utf8_decode_at(str8 string, u64 offset)
{
//NOTE(martin): get the first codepoint in str, and advance index to the
// next utf8 character
//TODO(martin): check for utf-16 surrogate pairs
utf32 cp = 0;
u64 sz = 0;
if(offset >= string.len || !string.ptr[offset])
{
cp = 0;
sz = 1;
}
else if( !utf8_is_start_byte(string.ptr[offset]))
{
//NOTE(martin): unexpected continuation or invalid character.
cp = 0xfffd;
sz = 1;
}
else
{
int expectedSize = utf8_size_from_leading_char(string.ptr[offset]);
do
{
/*NOTE(martin):
we shift 6 bits and add the next byte at each round.
at the end we have our utf8 codepoint, added to the shifted versions
of the utf8 leading bits for each encoded byte. These values are
precomputed in offsetsFromUTF8.
*/
unsigned char b = string.ptr[offset];
cp <<= 6;
cp += b;
offset += 1;
sz++;
if(b == 0xc0 || b == 0xc1 || b >= 0xc5)
{
//NOTE(martin): invalid byte encountered
break;
}
} while( offset < string.len
&& string.ptr[offset]
&& !utf8_is_start_byte(string.ptr[offset])
&& sz < expectedSize);
if(sz != expectedSize)
{
//NOTE(martin): if we encountered an error, we return the replacement codepoint U+FFFD
cp = 0xfffd;
}
else
{
cp -= offsetsFromUTF8[sz-1];
//NOTE(martin): check for invalid codepoints
if(cp > 0x10ffff || (cp >= 0xd800 && cp <= 0xdfff))
{
cp = 0xfffd;
}
}
}
utf8_dec res = {.codepoint = cp, .size = sz};
return(res);
}
utf8_dec utf8_decode(str8 string)
{
return(utf8_decode_at(string, 0));
}
str8 utf8_encode(char* dest, utf32 codePoint)
{
u64 sz = 0;
if (codePoint < 0x80)
{
dest[0] = (char)codePoint;
sz = 1;
}
else if (codePoint < 0x800)
{
dest[0] = (codePoint>>6) | 0xC0;
dest[1] = (codePoint & 0x3F) | 0x80;
sz = 2;
}
else if (codePoint < 0x10000)
{
dest[0] = (codePoint>>12) | 0xE0;
dest[1] = ((codePoint>>6) & 0x3F) | 0x80;
dest[2] = (codePoint & 0x3F) | 0x80;
sz = 3;
}
else if (codePoint < 0x110000)
{
dest[0] = (codePoint>>18) | 0xF0;
dest[1] = ((codePoint>>12) & 0x3F) | 0x80;
dest[2] = ((codePoint>>6) & 0x3F) | 0x80;
dest[3] = (codePoint & 0x3F) | 0x80;
sz = 4;
}
str8 res = {.len = sz, .ptr = dest};
return(res);
}
str32 utf8_to_codepoints(u64 maxCount, utf32* backing, str8 string)
{
u64 codePointIndex = 0;
u64 byteOffset = 0;
for(; codePointIndex < maxCount && byteOffset < string.len; codePointIndex++)
{
utf8_dec decode = utf8_decode_at(string, byteOffset);
backing[codePointIndex] = decode.codepoint;
byteOffset += decode.size;
}
str32 res = {.len = codePointIndex, .ptr = backing};
return(res);
}
str8 utf8_from_codepoints(u64 maxBytes, char* backing, str32 codePoints)
{
u64 byteOffset = 0;
for(u64 codePointIndex = 0; (codePointIndex < codePoints.len); codePointIndex++)
{
utf32 codePoint = codePoints.ptr[codePointIndex];
u32 byteCount = utf8_codepoint_size(codePoint);
if(byteOffset + byteCount > maxBytes)
{
break;
}
utf8_encode(backing+byteOffset, codePoint);
byteOffset += byteCount;
}
str8 res = {.len = byteOffset, .ptr = backing};
return(res);
}
str32 utf8_push_to_codepoints(mem_arena* arena, str8 string)
{
u64 count = utf8_codepoint_count_for_string(string);
utf32* backing = mem_arena_alloc_array(arena, utf32, count);
str32 res = utf8_to_codepoints(count, backing, string);
return(res);
}
str8 utf8_push_from_codepoints(mem_arena* arena, str32 codePoints)
{
u64 count = utf8_byte_count_for_codepoints(codePoints);
char* backing = mem_arena_alloc_array(arena, char, count);
str8 res = utf8_from_codepoints(count, backing, codePoints);
return(res);
}
#define UNICODE_RANGE(start, cnt, name) const unicode_range _cat2_(UNICODE_RANGE_, name) = { .firstCodePoint = start, .count = cnt };
UNICODE_RANGES
#undef UNICODE_RANGE
//*****************************************************************
//
// $file: utf8.c $
// $author: Martin Fouilleul $
// $date: 05/11/2016 $
// $revision: $
// $note: (C) 2016 by Martin Fouilleul - all rights reserved $
//
//*****************************************************************
#include"utf8.h"
#include"platform.h"
#include<string.h>
//-----------------------------------------------------------------
// utf-8 gore
//-----------------------------------------------------------------
const u32 offsetsFromUTF8[6] = {
0x00000000UL, 0x00003080UL, 0x000E2080UL,
0x03C82080UL, 0xFA082080UL, 0x82082080UL };
const char trailingBytesForUTF8[256] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
};
#define utf8_is_start_byte(c) (((c)&0xc0)!=0x80)
//-----------------------------------------------------------------
//NOTE: getting sizes / offsets / indices
//-----------------------------------------------------------------
u32 utf8_size_from_leading_char(char leadingChar)
{
return(trailingBytesForUTF8[(unsigned int)(unsigned char)leadingChar] + 1);
}
u32 utf8_codepoint_size(utf32 codePoint)
{
if(codePoint < 0x80)
{
return(1);
}
if(codePoint < 0x800)
{
return(2);
}
if(codePoint < 0x10000)
{
return(3);
}
if(codePoint < 0x110000)
{
return(4);
}
return(0);
}
u64 utf8_codepoint_count_for_string(str8 string)
{
u64 byteOffset = 0;
u64 codePointIndex = 0;
for(;
(byteOffset < string.len) && (string.ptr[byteOffset] != 0);
codePointIndex++)
{
utf8_dec decode = utf8_decode_at(string, byteOffset);
byteOffset += decode.size;
}
return(codePointIndex);
}
u64 utf8_byte_count_for_codepoints(str32 codePoints)
{
//NOTE(martin): return the exact number of bytes taken by the encoded
// version of codePoints. (ie do not attempt to provision
// for a zero terminator).
u64 byteCount = 0;
for(u64 i=0; i<codePoints.len; i++)
{
byteCount += utf8_codepoint_size(codePoints.ptr[i]);
}
return(byteCount);
}
u64 utf8_next_offset(str8 string, u64 byteOffset)
{
u64 res = 0;
if(byteOffset >= string.len)
{
res = string.len;
}
else
{
u64 nextOffset = byteOffset + utf8_size_from_leading_char(string.ptr[byteOffset]);
res = minimum(nextOffset, string.len);
}
return(res);
}
u64 utf8_prev_offset(str8 string, u64 byteOffset)
{
u64 res = 0;
if(byteOffset > string.len)
{
res = string.len;
}
else if(byteOffset)
{
byteOffset--;
while(byteOffset > 0 && !utf8_is_start_byte(string.ptr[byteOffset]))
{
byteOffset--;
}
res = byteOffset;
}
return(res);
}
//-----------------------------------------------------------------
//NOTE: encoding / decoding
//-----------------------------------------------------------------
utf8_dec utf8_decode_at(str8 string, u64 offset)
{
//NOTE(martin): get the first codepoint in str, and advance index to the
// next utf8 character
//TODO(martin): check for utf-16 surrogate pairs
utf32 cp = 0;
u64 sz = 0;
if(offset >= string.len || !string.ptr[offset])
{
cp = 0;
sz = 1;
}
else if( !utf8_is_start_byte(string.ptr[offset]))
{
//NOTE(martin): unexpected continuation or invalid character.
cp = 0xfffd;
sz = 1;
}
else
{
int expectedSize = utf8_size_from_leading_char(string.ptr[offset]);
do
{
/*NOTE(martin):
we shift 6 bits and add the next byte at each round.
at the end we have our utf8 codepoint, added to the shifted versions
of the utf8 leading bits for each encoded byte. These values are
precomputed in offsetsFromUTF8.
*/
unsigned char b = string.ptr[offset];
cp <<= 6;
cp += b;
offset += 1;
sz++;
if(b == 0xc0 || b == 0xc1 || b >= 0xc5)
{
//NOTE(martin): invalid byte encountered
break;
}
} while( offset < string.len
&& string.ptr[offset]
&& !utf8_is_start_byte(string.ptr[offset])
&& sz < expectedSize);
if(sz != expectedSize)
{
//NOTE(martin): if we encountered an error, we return the replacement codepoint U+FFFD
cp = 0xfffd;
}
else
{
cp -= offsetsFromUTF8[sz-1];
//NOTE(martin): check for invalid codepoints
if(cp > 0x10ffff || (cp >= 0xd800 && cp <= 0xdfff))
{
cp = 0xfffd;
}
}
}
utf8_dec res = {.codepoint = cp, .size = sz};
return(res);
}
utf8_dec utf8_decode(str8 string)
{
return(utf8_decode_at(string, 0));
}
str8 utf8_encode(char* dest, utf32 codePoint)
{
u64 sz = 0;
if (codePoint < 0x80)
{
dest[0] = (char)codePoint;
sz = 1;
}
else if (codePoint < 0x800)
{
dest[0] = (codePoint>>6) | 0xC0;
dest[1] = (codePoint & 0x3F) | 0x80;
sz = 2;
}
else if (codePoint < 0x10000)
{
dest[0] = (codePoint>>12) | 0xE0;
dest[1] = ((codePoint>>6) & 0x3F) | 0x80;
dest[2] = (codePoint & 0x3F) | 0x80;
sz = 3;
}
else if (codePoint < 0x110000)
{
dest[0] = (codePoint>>18) | 0xF0;
dest[1] = ((codePoint>>12) & 0x3F) | 0x80;
dest[2] = ((codePoint>>6) & 0x3F) | 0x80;
dest[3] = (codePoint & 0x3F) | 0x80;
sz = 4;
}
str8 res = {.len = sz, .ptr = dest};
return(res);
}
str32 utf8_to_codepoints(u64 maxCount, utf32* backing, str8 string)
{
u64 codePointIndex = 0;
u64 byteOffset = 0;
for(; codePointIndex < maxCount && byteOffset < string.len; codePointIndex++)
{
utf8_dec decode = utf8_decode_at(string, byteOffset);
backing[codePointIndex] = decode.codepoint;
byteOffset += decode.size;
}
str32 res = {.len = codePointIndex, .ptr = backing};
return(res);
}
str8 utf8_from_codepoints(u64 maxBytes, char* backing, str32 codePoints)
{
u64 byteOffset = 0;
for(u64 codePointIndex = 0; (codePointIndex < codePoints.len); codePointIndex++)
{
utf32 codePoint = codePoints.ptr[codePointIndex];
u32 byteCount = utf8_codepoint_size(codePoint);
if(byteOffset + byteCount > maxBytes)
{
break;
}
utf8_encode(backing+byteOffset, codePoint);
byteOffset += byteCount;
}
str8 res = {.len = byteOffset, .ptr = backing};
return(res);
}
str32 utf8_push_to_codepoints(mem_arena* arena, str8 string)
{
u64 count = utf8_codepoint_count_for_string(string);
utf32* backing = mem_arena_alloc_array(arena, utf32, count);
str32 res = utf8_to_codepoints(count, backing, string);
return(res);
}
str8 utf8_push_from_codepoints(mem_arena* arena, str32 codePoints)
{
u64 count = utf8_byte_count_for_codepoints(codePoints);
char* backing = mem_arena_alloc_array(arena, char, count);
str8 res = utf8_from_codepoints(count, backing, codePoints);
return(res);
}
#define UNICODE_RANGE(start, cnt, name) MP_API extern const unicode_range _cat2_(UNICODE_RANGE_, name) = { .firstCodePoint = start, .count = cnt };
UNICODE_RANGES
#undef UNICODE_RANGE

View File

@ -1,202 +1,201 @@
//*****************************************************************
//
// $file: utf8.h $
// $author: Martin Fouilleul $
// $date: 05/11/2016 $
// $revision: $
// $note: (C) 2016 by Martin Fouilleul - all rights reserved $
//
//*****************************************************************
#ifndef __UTF8_H_
#define __UTF8_H_
#include"typedefs.h"
#include"macro_helpers.h"
#include"strings.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef u32 utf32;
//-----------------------------------------------------------------
//NOTE: getting sizes / offsets / indices
//-----------------------------------------------------------------
u32 utf8_size_from_leading_char(char leadingChar);
u32 utf8_codepoint_size(utf32 codePoint);
u64 utf8_codepoint_count_for_string(str8 string);
u64 utf8_byte_count_for_codepoints(str32 codePoints);
u64 utf8_next_offset(str8 string, u64 byteOffset);
u64 utf8_prev_offset(str8 string, u64 byteOffset);
//-----------------------------------------------------------------
//NOTE: encoding / decoding
//-----------------------------------------------------------------
typedef struct utf8_dec
{
utf32 codepoint; //NOTE: decoded codepoint
u32 size; //NOTE: size of corresponding utf8 sequence
} utf8_dec;
utf8_dec utf8_decode(str8 string); //NOTE: decode a single utf8 sequence at start of string
utf8_dec utf8_decode_at(str8 string, u64 offset); //NOTE: decode a single utf8 sequence starting at byte offset
str8 utf8_encode(char* dst, utf32 codePoint); //NOTE: encode codepoint into backing buffer dst
str32 utf8_to_codepoints(u64 maxCount, utf32* backing, str8 string);
str8 utf8_from_codepoints(u64 maxBytes, char* backing, str32 codePoints);
str32 utf8_push_to_codepoints(mem_arena* arena, str8 string);
str8 utf8_push_from_codepoints(mem_arena* arena, str32 codePoints);
//-----------------------------------------------------------------
// utf8 range struct and X-macros for defining utf8 ranges
//-----------------------------------------------------------------
typedef struct unicode_range
{
utf32 firstCodePoint;
u32 count;
} unicode_range;
//NOTE(martin): range declared here are defined in utf8.cpp
// they can be used by prefixing them with UTF8_RANGE_, as in 'UTF8_RANGE_BASIC_LATIN'
#define UNICODE_RANGES \
UNICODE_RANGE(0x0000, 127, BASIC_LATIN) \
UNICODE_RANGE(0x0080, 127, C1_CONTROLS_AND_LATIN_1_SUPPLEMENT) \
UNICODE_RANGE(0x0100, 127, LATIN_EXTENDED_A) \
UNICODE_RANGE(0x0180, 207, LATIN_EXTENDED_B) \
UNICODE_RANGE(0x0250, 95, IPA_EXTENSIONS) \
UNICODE_RANGE(0x02b0, 79, SPACING_MODIFIER_LETTERS) \
UNICODE_RANGE(0x0300, 111, COMBINING_DIACRITICAL_MARKS) \
UNICODE_RANGE(0x0370, 143, GREEK_COPTIC) \
UNICODE_RANGE(0x0400, 255, CYRILLIC) \
UNICODE_RANGE(0x0500, 47, CYRILLIC_SUPPLEMENT) \
UNICODE_RANGE(0x0530, 95, ARMENIAN) \
UNICODE_RANGE(0x0590, 111, HEBREW) \
UNICODE_RANGE(0x0600, 255, ARABIC) \
UNICODE_RANGE(0x0700, 79, SYRIAC) \
UNICODE_RANGE(0x0780, 63, THAANA) \
UNICODE_RANGE(0x0900, 127, DEVANAGARI) \
UNICODE_RANGE(0x0980, 127, BENGALI_ASSAMESE) \
UNICODE_RANGE(0x0a00, 127, GURMUKHI) \
UNICODE_RANGE(0x0a80, 127, GUJARATI) \
UNICODE_RANGE(0x0b00, 127, ORIYA) \
UNICODE_RANGE(0x0b80, 127, TAMIL) \
UNICODE_RANGE(0x0c00, 127, TELUGU) \
UNICODE_RANGE(0x0c80, 127, KANNADA) \
UNICODE_RANGE(0x0d00, 255, MALAYALAM) \
UNICODE_RANGE(0x0d80, 127, SINHALA) \
UNICODE_RANGE(0x0e00, 127, THAI) \
UNICODE_RANGE(0x0e80, 127, LAO) \
UNICODE_RANGE(0x0f00, 255, TIBETAN) \
UNICODE_RANGE(0x1000, 159, MYANMAR) \
UNICODE_RANGE(0x10a0, 95, GEORGIAN) \
UNICODE_RANGE(0x1100, 255, HANGUL_JAMO) \
UNICODE_RANGE(0x1200, 383, ETHIOPIC) \
UNICODE_RANGE(0x13a0, 95, CHEROKEE) \
UNICODE_RANGE(0x1400, 639, UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS) \
UNICODE_RANGE(0x1680, 31, OGHAM) \
UNICODE_RANGE(0x16a0, 95, RUNIC) \
UNICODE_RANGE(0x1700, 31, TAGALOG) \
UNICODE_RANGE(0x1720, 31, HANUNOO) \
UNICODE_RANGE(0x1740, 31, BUHID) \
UNICODE_RANGE(0x1760, 31, TAGBANWA) \
UNICODE_RANGE(0x1780, 127, KHMER) \
UNICODE_RANGE(0x1800, 175, MONGOLIAN) \
UNICODE_RANGE(0x1900, 79, LIMBU) \
UNICODE_RANGE(0x1950, 47, TAI_LE) \
UNICODE_RANGE(0x19e0, 31, KHMER_SYMBOLS) \
UNICODE_RANGE(0x1d00, 127, PHONETIC_EXTENSIONS) \
UNICODE_RANGE(0x1e00, 255, LATIN_EXTENDED_ADDITIONAL) \
UNICODE_RANGE(0x1f00, 255, GREEK_EXTENDED) \
UNICODE_RANGE(0x2000, 111, GENERAL_PUNCTUATION) \
UNICODE_RANGE(0x2070, 47, SUPERSCRIPTS_AND_SUBSCRIPTS) \
UNICODE_RANGE(0x20a0, 47, CURRENCY_SYMBOLS) \
UNICODE_RANGE(0x20d0, 47, COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS) \
UNICODE_RANGE(0x2100, 79, LETTERLIKE_SYMBOLS) \
UNICODE_RANGE(0x2150, 63, NUMBER_FORMS) \
UNICODE_RANGE(0x2190, 111, ARROWS) \
UNICODE_RANGE(0x2200, 255, MATHEMATICAL_OPERATORS) \
UNICODE_RANGE(0x2300, 255, MISCELLANEOUS_TECHNICAL) \
UNICODE_RANGE(0x2400, 63, CONTROL_PICTURES) \
UNICODE_RANGE(0x2440, 31, OPTICAL_CHARACTER_RECOGNITION) \
UNICODE_RANGE(0x2460, 159, ENCLOSED_ALPHANUMERICS) \
UNICODE_RANGE(0x2500, 127, BOX_DRAWING) \
UNICODE_RANGE(0x2580, 31, BLOCK_ELEMENTS) \
UNICODE_RANGE(0x25a0, 95, GEOMETRIC_SHAPES) \
UNICODE_RANGE(0x2600, 255, MISCELLANEOUS_SYMBOLS) \
UNICODE_RANGE(0x2700, 191, DINGBATS) \
UNICODE_RANGE(0x27c0, 47, MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A) \
UNICODE_RANGE(0x27f0, 15, SUPPLEMENTAL_ARROWS_A) \
UNICODE_RANGE(0x2800, 255, BRAILLE_PATTERNS) \
UNICODE_RANGE(0x2900, 127, SUPPLEMENTAL_ARROWS_B) \
UNICODE_RANGE(0x2980, 127, MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B) \
UNICODE_RANGE(0x2a00, 255, SUPPLEMENTAL_MATHEMATICAL_OPERATORS) \
UNICODE_RANGE(0x2b00, 255, MISCELLANEOUS_SYMBOLS_AND_ARROWS) \
UNICODE_RANGE(0x2e80, 127, CJK_RADICALS_SUPPLEMENT) \
UNICODE_RANGE(0x2f00, 223, KANGXI_RADICALS) \
UNICODE_RANGE(0x2ff0, 15, IDEOGRAPHIC_DESCRIPTION_CHARACTERS) \
UNICODE_RANGE(0x3000, 63, CJK_SYMBOLS_AND_PUNCTUATION) \
UNICODE_RANGE(0x3040, 95, HIRAGANA) \
UNICODE_RANGE(0x30a0, 95, KATAKANA) \
UNICODE_RANGE(0x3100, 47, BOPOMOFO) \
UNICODE_RANGE(0x3130, 95, HANGUL_COMPATIBILITY_JAMO) \
UNICODE_RANGE(0x3190, 15, KANBUN_KUNTEN) \
UNICODE_RANGE(0x31a0, 31, BOPOMOFO_EXTENDED) \
UNICODE_RANGE(0x31f0, 15, KATAKANA_PHONETIC_EXTENSIONS) \
UNICODE_RANGE(0x3200, 255, ENCLOSED_CJK_LETTERS_AND_MONTHS) \
UNICODE_RANGE(0x3300, 255, CJK_COMPATIBILITY) \
UNICODE_RANGE(0x3400, 6591, CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A) \
UNICODE_RANGE(0x4dc0, 63, YIJING_HEXAGRAM_SYMBOLS) \
UNICODE_RANGE(0x4e00, 20911, CJK_UNIFIED_IDEOGRAPHS) \
UNICODE_RANGE(0xa000, 1167, YI_SYLLABLES) \
UNICODE_RANGE(0xa490, 63, YI_RADICALS) \
UNICODE_RANGE(0xac00, 11183, HANGUL_SYLLABLES) \
UNICODE_RANGE(0xd800, 1023, HIGH_SURROGATE_AREA) \
UNICODE_RANGE(0xdc00, 1023, LOW_SURROGATE_AREA) \
UNICODE_RANGE(0xe000, 6399, PRIVATE_USE_AREA) \
UNICODE_RANGE(0xf900, 511, CJK_COMPATIBILITY_IDEOGRAPHS) \
UNICODE_RANGE(0xfb00, 79, ALPHABETIC_PRESENTATION_FORMS) \
UNICODE_RANGE(0xfb50, 687, ARABIC_PRESENTATION_FORMS_A) \
UNICODE_RANGE(0xfe00, 15, VARIATION_SELECTORS) \
UNICODE_RANGE(0xfe20, 15, COMBINING_HALF_MARKS) \
UNICODE_RANGE(0xfe30, 31, CJK_COMPATIBILITY_FORMS) \
UNICODE_RANGE(0xfe50, 31, SMALL_FORM_VARIANTS) \
UNICODE_RANGE(0xfe70, 143, ARABIC_PRESENTATION_FORMS_B) \
UNICODE_RANGE(0xff00, 239, HALFWIDTH_AND_FULLWIDTH_FORMS) \
UNICODE_RANGE(0xfff0, 15, SPECIALS) \
UNICODE_RANGE(0x10000, 127, LINEAR_B_SYLLABARY) \
UNICODE_RANGE(0x10080, 127, LINEAR_B_IDEOGRAMS) \
UNICODE_RANGE(0x10100, 63, AEGEAN_NUMBERS) \
UNICODE_RANGE(0x10300, 47, OLD_ITALIC) \
UNICODE_RANGE(0x10330, 31, GOTHIC) \
UNICODE_RANGE(0x10380, 31, UGARITIC) \
UNICODE_RANGE(0x10400, 79, DESERET) \
UNICODE_RANGE(0x10450, 47, SHAVIAN) \
UNICODE_RANGE(0x10480, 47, OSMANYA) \
UNICODE_RANGE(0x10800, 63, CYPRIOT_SYLLABARY) \
UNICODE_RANGE(0x1d000, 255, BYZANTINE_MUSICAL_SYMBOLS) \
UNICODE_RANGE(0x1d100, 255, MUSICAL_SYMBOLS) \
UNICODE_RANGE(0x1d300, 95, TAI_XUAN_JING_SYMBOLS) \
UNICODE_RANGE(0x1d400, 1023, MATHEMATICAL_ALPHANUMERIC_SYMBOLS) \
UNICODE_RANGE(0x20000, 42719, CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B) \
UNICODE_RANGE(0x2f800, 543, CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT) \
UNICODE_RANGE(0xe0000, 127, TAGS) \
UNICODE_RANGE(0xe0100, 239, VARIATION_SELECTORS_SUPPLEMENT) \
UNICODE_RANGE(0xf0000, 65533, SUPPLEMENTARY_PRIVATE_USE_AREA_A) \
UNICODE_RANGE(0x100000, 65533, SUPPLEMENTARY_PRIVATE_USE_AREA_B)
#define UNICODE_RANGE(start, count, name) \
extern const unicode_range _cat2_(UNICODE_RANGE_, name);
UNICODE_RANGES
#undef UNICODE_RANGE
#ifdef __cplusplus
} // extern "C"
#endif
#endif //__UTF8_H_
//*****************************************************************
//
// $file: utf8.h $
// $author: Martin Fouilleul $
// $date: 05/11/2016 $
// $revision: $
// $note: (C) 2016 by Martin Fouilleul - all rights reserved $
//
//*****************************************************************
#ifndef __UTF8_H_
#define __UTF8_H_
#include"typedefs.h"
#include"macro_helpers.h"
#include"strings.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef u32 utf32;
//-----------------------------------------------------------------
//NOTE: getting sizes / offsets / indices
//-----------------------------------------------------------------
MP_API u32 utf8_size_from_leading_char(char leadingChar);
MP_API u32 utf8_codepoint_size(utf32 codePoint);
MP_API u64 utf8_codepoint_count_for_string(str8 string);
MP_API u64 utf8_byte_count_for_codepoints(str32 codePoints);
MP_API u64 utf8_next_offset(str8 string, u64 byteOffset);
MP_API u64 utf8_prev_offset(str8 string, u64 byteOffset);
//-----------------------------------------------------------------
//NOTE: encoding / decoding
//-----------------------------------------------------------------
typedef struct utf8_dec
{
utf32 codepoint; //NOTE: decoded codepoint
u32 size; //NOTE: size of corresponding utf8 sequence
} utf8_dec;
MP_API utf8_dec utf8_decode(str8 string); //NOTE: decode a single utf8 sequence at start of string
MP_API utf8_dec utf8_decode_at(str8 string, u64 offset); //NOTE: decode a single utf8 sequence starting at byte offset
MP_API str8 utf8_encode(char* dst, utf32 codePoint); //NOTE: encode codepoint into backing buffer dst
MP_API str32 utf8_to_codepoints(u64 maxCount, utf32* backing, str8 string);
MP_API str8 utf8_from_codepoints(u64 maxBytes, char* backing, str32 codePoints);
MP_API str32 utf8_push_to_codepoints(mem_arena* arena, str8 string);
MP_API str8 utf8_push_from_codepoints(mem_arena* arena, str32 codePoints);
//-----------------------------------------------------------------
// utf8 range struct and X-macros for defining utf8 ranges
//-----------------------------------------------------------------
typedef struct unicode_range
{
utf32 firstCodePoint;
u32 count;
} unicode_range;
//NOTE(martin): range declared here are defined in utf8.cpp
// they can be used by prefixing them with UTF8_RANGE_, as in 'UTF8_RANGE_BASIC_LATIN'
#define UNICODE_RANGES \
UNICODE_RANGE(0x0000, 127, BASIC_LATIN) \
UNICODE_RANGE(0x0080, 127, C1_CONTROLS_AND_LATIN_1_SUPPLEMENT) \
UNICODE_RANGE(0x0100, 127, LATIN_EXTENDED_A) \
UNICODE_RANGE(0x0180, 207, LATIN_EXTENDED_B) \
UNICODE_RANGE(0x0250, 95, IPA_EXTENSIONS) \
UNICODE_RANGE(0x02b0, 79, SPACING_MODIFIER_LETTERS) \
UNICODE_RANGE(0x0300, 111, COMBINING_DIACRITICAL_MARKS) \
UNICODE_RANGE(0x0370, 143, GREEK_COPTIC) \
UNICODE_RANGE(0x0400, 255, CYRILLIC) \
UNICODE_RANGE(0x0500, 47, CYRILLIC_SUPPLEMENT) \
UNICODE_RANGE(0x0530, 95, ARMENIAN) \
UNICODE_RANGE(0x0590, 111, HEBREW) \
UNICODE_RANGE(0x0600, 255, ARABIC) \
UNICODE_RANGE(0x0700, 79, SYRIAC) \
UNICODE_RANGE(0x0780, 63, THAANA) \
UNICODE_RANGE(0x0900, 127, DEVANAGARI) \
UNICODE_RANGE(0x0980, 127, BENGALI_ASSAMESE) \
UNICODE_RANGE(0x0a00, 127, GURMUKHI) \
UNICODE_RANGE(0x0a80, 127, GUJARATI) \
UNICODE_RANGE(0x0b00, 127, ORIYA) \
UNICODE_RANGE(0x0b80, 127, TAMIL) \
UNICODE_RANGE(0x0c00, 127, TELUGU) \
UNICODE_RANGE(0x0c80, 127, KANNADA) \
UNICODE_RANGE(0x0d00, 255, MALAYALAM) \
UNICODE_RANGE(0x0d80, 127, SINHALA) \
UNICODE_RANGE(0x0e00, 127, THAI) \
UNICODE_RANGE(0x0e80, 127, LAO) \
UNICODE_RANGE(0x0f00, 255, TIBETAN) \
UNICODE_RANGE(0x1000, 159, MYANMAR) \
UNICODE_RANGE(0x10a0, 95, GEORGIAN) \
UNICODE_RANGE(0x1100, 255, HANGUL_JAMO) \
UNICODE_RANGE(0x1200, 383, ETHIOPIC) \
UNICODE_RANGE(0x13a0, 95, CHEROKEE) \
UNICODE_RANGE(0x1400, 639, UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS) \
UNICODE_RANGE(0x1680, 31, OGHAM) \
UNICODE_RANGE(0x16a0, 95, RUNIC) \
UNICODE_RANGE(0x1700, 31, TAGALOG) \
UNICODE_RANGE(0x1720, 31, HANUNOO) \
UNICODE_RANGE(0x1740, 31, BUHID) \
UNICODE_RANGE(0x1760, 31, TAGBANWA) \
UNICODE_RANGE(0x1780, 127, KHMER) \
UNICODE_RANGE(0x1800, 175, MONGOLIAN) \
UNICODE_RANGE(0x1900, 79, LIMBU) \
UNICODE_RANGE(0x1950, 47, TAI_LE) \
UNICODE_RANGE(0x19e0, 31, KHMER_SYMBOLS) \
UNICODE_RANGE(0x1d00, 127, PHONETIC_EXTENSIONS) \
UNICODE_RANGE(0x1e00, 255, LATIN_EXTENDED_ADDITIONAL) \
UNICODE_RANGE(0x1f00, 255, GREEK_EXTENDED) \
UNICODE_RANGE(0x2000, 111, GENERAL_PUNCTUATION) \
UNICODE_RANGE(0x2070, 47, SUPERSCRIPTS_AND_SUBSCRIPTS) \
UNICODE_RANGE(0x20a0, 47, CURRENCY_SYMBOLS) \
UNICODE_RANGE(0x20d0, 47, COMBINING_DIACRITICAL_MARKS_FOR_SYMBOLS) \
UNICODE_RANGE(0x2100, 79, LETTERLIKE_SYMBOLS) \
UNICODE_RANGE(0x2150, 63, NUMBER_FORMS) \
UNICODE_RANGE(0x2190, 111, ARROWS) \
UNICODE_RANGE(0x2200, 255, MATHEMATICAL_OPERATORS) \
UNICODE_RANGE(0x2300, 255, MISCELLANEOUS_TECHNICAL) \
UNICODE_RANGE(0x2400, 63, CONTROL_PICTURES) \
UNICODE_RANGE(0x2440, 31, OPTICAL_CHARACTER_RECOGNITION) \
UNICODE_RANGE(0x2460, 159, ENCLOSED_ALPHANUMERICS) \
UNICODE_RANGE(0x2500, 127, BOX_DRAWING) \
UNICODE_RANGE(0x2580, 31, BLOCK_ELEMENTS) \
UNICODE_RANGE(0x25a0, 95, GEOMETRIC_SHAPES) \
UNICODE_RANGE(0x2600, 255, MISCELLANEOUS_SYMBOLS) \
UNICODE_RANGE(0x2700, 191, DINGBATS) \
UNICODE_RANGE(0x27c0, 47, MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A) \
UNICODE_RANGE(0x27f0, 15, SUPPLEMENTAL_ARROWS_A) \
UNICODE_RANGE(0x2800, 255, BRAILLE_PATTERNS) \
UNICODE_RANGE(0x2900, 127, SUPPLEMENTAL_ARROWS_B) \
UNICODE_RANGE(0x2980, 127, MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B) \
UNICODE_RANGE(0x2a00, 255, SUPPLEMENTAL_MATHEMATICAL_OPERATORS) \
UNICODE_RANGE(0x2b00, 255, MISCELLANEOUS_SYMBOLS_AND_ARROWS) \
UNICODE_RANGE(0x2e80, 127, CJK_RADICALS_SUPPLEMENT) \
UNICODE_RANGE(0x2f00, 223, KANGXI_RADICALS) \
UNICODE_RANGE(0x2ff0, 15, IDEOGRAPHIC_DESCRIPTION_CHARACTERS) \
UNICODE_RANGE(0x3000, 63, CJK_SYMBOLS_AND_PUNCTUATION) \
UNICODE_RANGE(0x3040, 95, HIRAGANA) \
UNICODE_RANGE(0x30a0, 95, KATAKANA) \
UNICODE_RANGE(0x3100, 47, BOPOMOFO) \
UNICODE_RANGE(0x3130, 95, HANGUL_COMPATIBILITY_JAMO) \
UNICODE_RANGE(0x3190, 15, KANBUN_KUNTEN) \
UNICODE_RANGE(0x31a0, 31, BOPOMOFO_EXTENDED) \
UNICODE_RANGE(0x31f0, 15, KATAKANA_PHONETIC_EXTENSIONS) \
UNICODE_RANGE(0x3200, 255, ENCLOSED_CJK_LETTERS_AND_MONTHS) \
UNICODE_RANGE(0x3300, 255, CJK_COMPATIBILITY) \
UNICODE_RANGE(0x3400, 6591, CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A) \
UNICODE_RANGE(0x4dc0, 63, YIJING_HEXAGRAM_SYMBOLS) \
UNICODE_RANGE(0x4e00, 20911, CJK_UNIFIED_IDEOGRAPHS) \
UNICODE_RANGE(0xa000, 1167, YI_SYLLABLES) \
UNICODE_RANGE(0xa490, 63, YI_RADICALS) \
UNICODE_RANGE(0xac00, 11183, HANGUL_SYLLABLES) \
UNICODE_RANGE(0xd800, 1023, HIGH_SURROGATE_AREA) \
UNICODE_RANGE(0xdc00, 1023, LOW_SURROGATE_AREA) \
UNICODE_RANGE(0xe000, 6399, PRIVATE_USE_AREA) \
UNICODE_RANGE(0xf900, 511, CJK_COMPATIBILITY_IDEOGRAPHS) \
UNICODE_RANGE(0xfb00, 79, ALPHABETIC_PRESENTATION_FORMS) \
UNICODE_RANGE(0xfb50, 687, ARABIC_PRESENTATION_FORMS_A) \
UNICODE_RANGE(0xfe00, 15, VARIATION_SELECTORS) \
UNICODE_RANGE(0xfe20, 15, COMBINING_HALF_MARKS) \
UNICODE_RANGE(0xfe30, 31, CJK_COMPATIBILITY_FORMS) \
UNICODE_RANGE(0xfe50, 31, SMALL_FORM_VARIANTS) \
UNICODE_RANGE(0xfe70, 143, ARABIC_PRESENTATION_FORMS_B) \
UNICODE_RANGE(0xff00, 239, HALFWIDTH_AND_FULLWIDTH_FORMS) \
UNICODE_RANGE(0xfff0, 15, SPECIALS) \
UNICODE_RANGE(0x10000, 127, LINEAR_B_SYLLABARY) \
UNICODE_RANGE(0x10080, 127, LINEAR_B_IDEOGRAMS) \
UNICODE_RANGE(0x10100, 63, AEGEAN_NUMBERS) \
UNICODE_RANGE(0x10300, 47, OLD_ITALIC) \
UNICODE_RANGE(0x10330, 31, GOTHIC) \
UNICODE_RANGE(0x10380, 31, UGARITIC) \
UNICODE_RANGE(0x10400, 79, DESERET) \
UNICODE_RANGE(0x10450, 47, SHAVIAN) \
UNICODE_RANGE(0x10480, 47, OSMANYA) \
UNICODE_RANGE(0x10800, 63, CYPRIOT_SYLLABARY) \
UNICODE_RANGE(0x1d000, 255, BYZANTINE_MUSICAL_SYMBOLS) \
UNICODE_RANGE(0x1d100, 255, MUSICAL_SYMBOLS) \
UNICODE_RANGE(0x1d300, 95, TAI_XUAN_JING_SYMBOLS) \
UNICODE_RANGE(0x1d400, 1023, MATHEMATICAL_ALPHANUMERIC_SYMBOLS) \
UNICODE_RANGE(0x20000, 42719, CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B) \
UNICODE_RANGE(0x2f800, 543, CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT) \
UNICODE_RANGE(0xe0000, 127, TAGS) \
UNICODE_RANGE(0xe0100, 239, VARIATION_SELECTORS_SUPPLEMENT) \
UNICODE_RANGE(0xf0000, 65533, SUPPLEMENTARY_PRIVATE_USE_AREA_A) \
UNICODE_RANGE(0x100000, 65533, SUPPLEMENTARY_PRIVATE_USE_AREA_B)
#define UNICODE_RANGE(start, count, name) \
MP_API extern const unicode_range _cat2_(UNICODE_RANGE_, name);
UNICODE_RANGES
#undef UNICODE_RANGE
#ifdef __cplusplus
} // extern "C"
#endif
#endif //__UTF8_H_

View File

@ -16,7 +16,7 @@ Overview
[.] Make linking with libEGL optional, even if EGL backend is compiled in milepost?
[x] using weak linking on macos
[ ] use /DELAYLOAD:lib on windows?
[.] Remove the need for client apps to link with all dependent libs explicitly
[x] Remove the need for client apps to link with all dependent libs explicitly
[!] Allow controlling surface overlaying
[!] Sort out contents scaling for high dpi on osx