mirror of
https://github.com/Ed94/metadesk.git
synced 2026-06-13 07:52:22 -07:00
Bring over RADDBG's mdesk and metagen modules
This commit is contained in:
+1200
File diff suppressed because it is too large
Load Diff
+325
@@ -0,0 +1,325 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef MDESK_H
|
||||
#define MDESK_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Messages
|
||||
|
||||
typedef enum MD_MsgKind
|
||||
{
|
||||
MD_MsgKind_Null,
|
||||
MD_MsgKind_Note,
|
||||
MD_MsgKind_Warning,
|
||||
MD_MsgKind_Error,
|
||||
MD_MsgKind_FatalError,
|
||||
}
|
||||
MD_MsgKind;
|
||||
|
||||
typedef struct MD_Msg MD_Msg;
|
||||
struct MD_Msg
|
||||
{
|
||||
MD_Msg *next;
|
||||
struct MD_Node *node;
|
||||
MD_MsgKind kind;
|
||||
String8 string;
|
||||
};
|
||||
|
||||
typedef struct MD_MsgList MD_MsgList;
|
||||
struct MD_MsgList
|
||||
{
|
||||
MD_Msg *first;
|
||||
MD_Msg *last;
|
||||
U64 count;
|
||||
MD_MsgKind worst_message_kind;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Token Types
|
||||
|
||||
typedef U32 MD_TokenFlags;
|
||||
enum
|
||||
{
|
||||
// rjf: base kind info
|
||||
MD_TokenFlag_Identifier = (1<<0),
|
||||
MD_TokenFlag_Numeric = (1<<1),
|
||||
MD_TokenFlag_StringLiteral = (1<<2),
|
||||
MD_TokenFlag_Symbol = (1<<3),
|
||||
MD_TokenFlag_Reserved = (1<<4),
|
||||
MD_TokenFlag_Comment = (1<<5),
|
||||
MD_TokenFlag_Whitespace = (1<<6),
|
||||
MD_TokenFlag_Newline = (1<<7),
|
||||
|
||||
// rjf: decoration info
|
||||
MD_TokenFlag_StringSingleQuote = (1<<8),
|
||||
MD_TokenFlag_StringDoubleQuote = (1<<9),
|
||||
MD_TokenFlag_StringTick = (1<<10),
|
||||
MD_TokenFlag_StringTriplet = (1<<11),
|
||||
|
||||
// rjf: error info
|
||||
MD_TokenFlag_BrokenComment = (1<<12),
|
||||
MD_TokenFlag_BrokenStringLiteral = (1<<13),
|
||||
MD_TokenFlag_BadCharacter = (1<<14),
|
||||
};
|
||||
|
||||
typedef U32 MD_TokenGroups;
|
||||
enum
|
||||
{
|
||||
MD_TokenGroup_Comment = MD_TokenFlag_Comment,
|
||||
MD_TokenGroup_Whitespace = (MD_TokenFlag_Whitespace|
|
||||
MD_TokenFlag_Newline),
|
||||
MD_TokenGroup_Irregular = (MD_TokenGroup_Comment|
|
||||
MD_TokenGroup_Whitespace),
|
||||
MD_TokenGroup_Regular = ~MD_TokenGroup_Irregular,
|
||||
MD_TokenGroup_Label = (MD_TokenFlag_Identifier|
|
||||
MD_TokenFlag_Numeric|
|
||||
MD_TokenFlag_StringLiteral|
|
||||
MD_TokenFlag_Symbol),
|
||||
MD_TokenGroup_Error = (MD_TokenFlag_BrokenComment|
|
||||
MD_TokenFlag_BrokenStringLiteral|
|
||||
MD_TokenFlag_BadCharacter),
|
||||
};
|
||||
|
||||
typedef struct MD_Token MD_Token;
|
||||
struct MD_Token
|
||||
{
|
||||
Rng1U64 range;
|
||||
MD_TokenFlags flags;
|
||||
};
|
||||
|
||||
typedef struct MD_TokenChunkNode MD_TokenChunkNode;
|
||||
struct MD_TokenChunkNode
|
||||
{
|
||||
MD_TokenChunkNode *next;
|
||||
MD_Token *v;
|
||||
U64 count;
|
||||
U64 cap;
|
||||
};
|
||||
|
||||
typedef struct MD_TokenChunkList MD_TokenChunkList;
|
||||
struct MD_TokenChunkList
|
||||
{
|
||||
MD_TokenChunkNode *first;
|
||||
MD_TokenChunkNode *last;
|
||||
U64 chunk_count;
|
||||
U64 total_token_count;
|
||||
};
|
||||
|
||||
typedef struct MD_TokenArray MD_TokenArray;
|
||||
struct MD_TokenArray
|
||||
{
|
||||
MD_Token *v;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Node Types
|
||||
|
||||
typedef enum MD_NodeKind
|
||||
{
|
||||
MD_NodeKind_Nil,
|
||||
MD_NodeKind_File,
|
||||
MD_NodeKind_ErrorMarker,
|
||||
MD_NodeKind_Main,
|
||||
MD_NodeKind_Tag,
|
||||
MD_NodeKind_List,
|
||||
MD_NodeKind_Reference,
|
||||
MD_NodeKind_COUNT
|
||||
}
|
||||
MD_NodeKind;
|
||||
|
||||
typedef U32 MD_NodeFlags;
|
||||
enum
|
||||
{
|
||||
MD_NodeFlag_MaskSetDelimiters = (0x3F<<0),
|
||||
MD_NodeFlag_HasParenLeft = (1<<0),
|
||||
MD_NodeFlag_HasParenRight = (1<<1),
|
||||
MD_NodeFlag_HasBracketLeft = (1<<2),
|
||||
MD_NodeFlag_HasBracketRight = (1<<3),
|
||||
MD_NodeFlag_HasBraceLeft = (1<<4),
|
||||
MD_NodeFlag_HasBraceRight = (1<<5),
|
||||
|
||||
MD_NodeFlag_MaskSeparators = (0xF<<6),
|
||||
MD_NodeFlag_IsBeforeSemicolon = (1<<6),
|
||||
MD_NodeFlag_IsAfterSemicolon = (1<<7),
|
||||
MD_NodeFlag_IsBeforeComma = (1<<8),
|
||||
MD_NodeFlag_IsAfterComma = (1<<9),
|
||||
|
||||
MD_NodeFlag_MaskStringDelimiters = (0xF<<10),
|
||||
MD_NodeFlag_StringSingleQuote = (1<<10),
|
||||
MD_NodeFlag_StringDoubleQuote = (1<<11),
|
||||
MD_NodeFlag_StringTick = (1<<12),
|
||||
MD_NodeFlag_StringTriplet = (1<<13),
|
||||
|
||||
MD_NodeFlag_MaskLabelKind = (0xF<<14),
|
||||
MD_NodeFlag_Numeric = (1<<14),
|
||||
MD_NodeFlag_Identifier = (1<<15),
|
||||
MD_NodeFlag_StringLiteral = (1<<16),
|
||||
MD_NodeFlag_Symbol = (1<<17),
|
||||
};
|
||||
#define MD_NodeFlag_AfterFromBefore(f) ((f) << 1)
|
||||
|
||||
typedef struct MD_Node MD_Node;
|
||||
struct MD_Node
|
||||
{
|
||||
// rjf: tree links
|
||||
MD_Node *next;
|
||||
MD_Node *prev;
|
||||
MD_Node *parent;
|
||||
MD_Node *first;
|
||||
MD_Node *last;
|
||||
|
||||
// rjf: tag links
|
||||
MD_Node *first_tag;
|
||||
MD_Node *last_tag;
|
||||
|
||||
// rjf: node info
|
||||
MD_NodeKind kind;
|
||||
MD_NodeFlags flags;
|
||||
String8 string;
|
||||
String8 raw_string;
|
||||
|
||||
// rjf: source code info
|
||||
U64 src_offset;
|
||||
|
||||
// rjf: user-controlled generation number
|
||||
//
|
||||
// (unused by mdesk layer, but can be used by usage code to use MD_Node trees
|
||||
// in a "retained mode" way, where stable generational handles can be formed
|
||||
// to nodes)
|
||||
U64 user_gen;
|
||||
|
||||
// rjf: extra padding to 128 bytes
|
||||
U64 _unused_[2];
|
||||
};
|
||||
|
||||
typedef struct MD_NodeRec MD_NodeRec;
|
||||
struct MD_NodeRec
|
||||
{
|
||||
MD_Node *next;
|
||||
S32 push_count;
|
||||
S32 pop_count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Text -> Tokens Types
|
||||
|
||||
typedef struct MD_TokenizeResult MD_TokenizeResult;
|
||||
struct MD_TokenizeResult
|
||||
{
|
||||
MD_TokenArray tokens;
|
||||
MD_MsgList msgs;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Tokens -> Tree Types
|
||||
|
||||
typedef struct MD_ParseResult MD_ParseResult;
|
||||
struct MD_ParseResult
|
||||
{
|
||||
MD_Node *root;
|
||||
MD_MsgList msgs;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Globals
|
||||
|
||||
global read_only MD_Node md_nil_node =
|
||||
{
|
||||
&md_nil_node,
|
||||
&md_nil_node,
|
||||
&md_nil_node,
|
||||
&md_nil_node,
|
||||
&md_nil_node,
|
||||
&md_nil_node,
|
||||
&md_nil_node,
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Message Type Functions
|
||||
|
||||
internal void md_msg_list_push(Arena *arena, MD_MsgList *msgs, MD_Node *node, MD_MsgKind kind, String8 string);
|
||||
internal void md_msg_list_pushf(Arena *arena, MD_MsgList *msgs, MD_Node *node, MD_MsgKind kind, char *fmt, ...);
|
||||
internal void md_msg_list_concat_in_place(MD_MsgList *dst, MD_MsgList *to_push);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Token Type Functions
|
||||
|
||||
internal MD_Token md_token_make(Rng1U64 range, MD_TokenFlags flags);
|
||||
internal B32 md_token_match(MD_Token a, MD_Token b);
|
||||
internal String8List md_string_list_from_token_flags(Arena *arena, MD_TokenFlags flags);
|
||||
internal void md_token_chunk_list_push(Arena *arena, MD_TokenChunkList *list, U64 cap, MD_Token token);
|
||||
internal MD_TokenArray md_token_array_from_chunk_list(Arena *arena, MD_TokenChunkList *chunks);
|
||||
internal String8 md_content_string_from_token_flags_str8(MD_TokenFlags flags, String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Node Type Functions
|
||||
|
||||
//- rjf: flag conversions
|
||||
internal MD_NodeFlags md_node_flags_from_token_flags(MD_TokenFlags flags);
|
||||
|
||||
//- rjf: nil
|
||||
internal B32 md_node_is_nil(MD_Node *node);
|
||||
|
||||
//- rjf: iteration
|
||||
#define MD_EachNode(it, first) (MD_Node *it = first; !md_node_is_nil(it); it = it->next)
|
||||
internal MD_NodeRec md_node_rec_depth_first(MD_Node *node, MD_Node *subtree_root, U64 child_off, U64 sib_off);
|
||||
#define md_node_rec_depth_first_pre(node, subtree_root) md_node_rec_depth_first((node), (subtree_root), OffsetOf(MD_Node, first), OffsetOf(MD_Node, next))
|
||||
#define md_node_rec_depth_first_pre_rev(node, subtree_root) md_node_rec_depth_first((node), (subtree_root), OffsetOf(MD_Node, last), OffsetOf(MD_Node, prev))
|
||||
|
||||
//- rjf: tree building
|
||||
internal MD_Node *md_push_node(Arena *arena, MD_NodeKind kind, MD_NodeFlags flags, String8 string, String8 raw_string, U64 src_offset);
|
||||
internal void md_node_insert_child(MD_Node *parent, MD_Node *prev_child, MD_Node *node);
|
||||
internal void md_node_insert_tag(MD_Node *parent, MD_Node *prev_child, MD_Node *node);
|
||||
internal void md_node_push_child(MD_Node *parent, MD_Node *node);
|
||||
internal void md_node_push_tag(MD_Node *parent, MD_Node *node);
|
||||
internal void md_unhook(MD_Node *node);
|
||||
|
||||
//- rjf: tree introspection
|
||||
internal MD_Node * md_node_from_chain_string(MD_Node *first, MD_Node *opl, String8 string, StringMatchFlags flags);
|
||||
internal MD_Node * md_node_from_chain_index(MD_Node *first, MD_Node *opl, U64 index);
|
||||
internal MD_Node * md_node_from_chain_flags(MD_Node *first, MD_Node *opl, MD_NodeFlags flags);
|
||||
internal U64 md_index_from_node(MD_Node *node);
|
||||
internal MD_Node * md_root_from_node(MD_Node *node);
|
||||
internal MD_Node * md_child_from_string(MD_Node *node, String8 child_string, StringMatchFlags flags);
|
||||
internal MD_Node * md_tag_from_string(MD_Node *node, String8 tag_string, StringMatchFlags flags);
|
||||
internal MD_Node * md_child_from_index(MD_Node *node, U64 index);
|
||||
internal MD_Node * md_tag_from_index(MD_Node *node, U64 index);
|
||||
internal MD_Node * md_tag_arg_from_index(MD_Node *node, String8 tag_string, StringMatchFlags flags, U64 index);
|
||||
internal MD_Node * md_tag_arg_from_string(MD_Node *node, String8 tag_string, StringMatchFlags tag_str_flags, String8 arg_string, StringMatchFlags arg_str_flags);
|
||||
internal B32 md_node_has_child(MD_Node *node, String8 string, StringMatchFlags flags);
|
||||
internal B32 md_node_has_tag(MD_Node *node, String8 string, StringMatchFlags flags);
|
||||
internal U64 md_child_count_from_node(MD_Node *node);
|
||||
internal U64 md_tag_count_from_node(MD_Node *node);
|
||||
internal String8 md_string_from_children(Arena *arena, MD_Node *root);
|
||||
|
||||
//- rjf: tree comparison
|
||||
internal B32 md_tree_match(MD_Node *a, MD_Node *b, StringMatchFlags flags);
|
||||
internal B32 md_node_match(MD_Node *a, MD_Node *b, StringMatchFlags flags);
|
||||
|
||||
//- rjf: tree duplication
|
||||
internal MD_Node *md_tree_copy(Arena *arena, MD_Node *src_root);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Text -> Tokens Functions
|
||||
|
||||
internal MD_TokenizeResult md_tokenize_from_text(Arena *arena, String8 text);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Tokens -> Tree Functions
|
||||
|
||||
internal MD_ParseResult md_parse_from_text_tokens(Arena *arena, String8 filename, String8 text, MD_TokenArray tokens);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Bundled Text -> Tree Functions
|
||||
|
||||
internal MD_ParseResult md_parse_from_text(Arena *arena, String8 filename, String8 text);
|
||||
#define md_tree_from_string(arena, string) (md_parse_from_text((arena), str8_zero(), (string)).root)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Tree -> Text Functions
|
||||
|
||||
internal String8List md_debug_string_list_from_tree(Arena *arena, MD_Node *root);
|
||||
|
||||
#endif // MDESK_H
|
||||
+1136
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,329 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef METAGEN_H
|
||||
#define METAGEN_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Message Type
|
||||
|
||||
typedef struct MG_Msg MG_Msg;
|
||||
struct MG_Msg
|
||||
{
|
||||
String8 location;
|
||||
String8 kind;
|
||||
String8 msg;
|
||||
};
|
||||
|
||||
typedef struct MG_MsgNode MG_MsgNode;
|
||||
struct MG_MsgNode
|
||||
{
|
||||
MG_MsgNode *next;
|
||||
MG_Msg v;
|
||||
};
|
||||
|
||||
typedef struct MG_MsgList MG_MsgList;
|
||||
struct MG_MsgList
|
||||
{
|
||||
MG_MsgNode *first;
|
||||
MG_MsgNode *last;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Parse Artifact Types
|
||||
|
||||
typedef struct MG_FileParse MG_FileParse;
|
||||
struct MG_FileParse
|
||||
{
|
||||
MD_Node *root;
|
||||
};
|
||||
|
||||
typedef struct MG_FileParseNode MG_FileParseNode;
|
||||
struct MG_FileParseNode
|
||||
{
|
||||
MG_FileParseNode *next;
|
||||
MG_FileParse v;
|
||||
};
|
||||
|
||||
typedef struct MG_FileParseList MG_FileParseList;
|
||||
struct MG_FileParseList
|
||||
{
|
||||
MG_FileParseNode *first;
|
||||
MG_FileParseNode *last;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Map Type
|
||||
|
||||
typedef struct MG_MapNode MG_MapNode;
|
||||
struct MG_MapNode
|
||||
{
|
||||
MG_MapNode *next;
|
||||
String8 key;
|
||||
void *val;
|
||||
};
|
||||
|
||||
typedef struct MG_MapSlot MG_MapSlot;
|
||||
struct MG_MapSlot
|
||||
{
|
||||
MG_MapNode *first;
|
||||
MG_MapNode *last;
|
||||
};
|
||||
|
||||
typedef struct MG_Map MG_Map;
|
||||
struct MG_Map
|
||||
{
|
||||
MG_MapSlot *slots;
|
||||
U64 slots_count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: String Expression Types
|
||||
|
||||
typedef enum MG_StrExprOpKind
|
||||
{
|
||||
MG_StrExprOpKind_Null,
|
||||
MG_StrExprOpKind_Prefix,
|
||||
MG_StrExprOpKind_Postfix,
|
||||
MG_StrExprOpKind_Binary,
|
||||
MG_StrExprOpKind_COUNT
|
||||
}
|
||||
MG_StrExprOpKind;
|
||||
|
||||
typedef enum MG_StrExprOp
|
||||
{
|
||||
MG_StrExprOp_Null,
|
||||
|
||||
#define MG_StrExprOp_FirstString MG_StrExprOp_Dot
|
||||
MG_StrExprOp_Dot,
|
||||
MG_StrExprOp_ExpandIfTrue,
|
||||
MG_StrExprOp_Concat,
|
||||
MG_StrExprOp_BumpToColumn,
|
||||
#define MG_StrExprOp_LastString MG_StrExprOp_BumpToColumn
|
||||
|
||||
#define MG_StrExprOp_FirstNumeric MG_StrExprOp_Add
|
||||
MG_StrExprOp_Add,
|
||||
MG_StrExprOp_Subtract,
|
||||
MG_StrExprOp_Multiply,
|
||||
MG_StrExprOp_Divide,
|
||||
MG_StrExprOp_Modulo,
|
||||
MG_StrExprOp_LeftShift,
|
||||
MG_StrExprOp_RightShift,
|
||||
MG_StrExprOp_BitwiseAnd,
|
||||
MG_StrExprOp_BitwiseOr,
|
||||
MG_StrExprOp_BitwiseXor,
|
||||
MG_StrExprOp_BitwiseNegate,
|
||||
MG_StrExprOp_BooleanAnd,
|
||||
MG_StrExprOp_BooleanOr,
|
||||
MG_StrExprOp_BooleanNot,
|
||||
MG_StrExprOp_Equals,
|
||||
MG_StrExprOp_DoesNotEqual,
|
||||
#define MG_StrExprOp_LastNumeric MG_StrExprOp_DoesNotEqual
|
||||
|
||||
MG_StrExprOp_COUNT,
|
||||
}
|
||||
MG_StrExprOp;
|
||||
|
||||
typedef struct MG_StrExpr MG_StrExpr;
|
||||
struct MG_StrExpr
|
||||
{
|
||||
MG_StrExpr *parent;
|
||||
MG_StrExpr *left;
|
||||
MG_StrExpr *right;
|
||||
MG_StrExprOp op;
|
||||
MD_Node *node;
|
||||
};
|
||||
|
||||
typedef struct MG_StrExprParseResult MG_StrExprParseResult;
|
||||
struct MG_StrExprParseResult
|
||||
{
|
||||
MG_StrExpr *root;
|
||||
MD_MsgList msgs;
|
||||
MD_Node *next_node;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Table Generation Types
|
||||
|
||||
typedef struct MG_NodeArray MG_NodeArray;
|
||||
struct MG_NodeArray
|
||||
{
|
||||
MD_Node **v;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
typedef struct MG_NodeGrid MG_NodeGrid;
|
||||
struct MG_NodeGrid
|
||||
{
|
||||
U64 x_stride;
|
||||
U64 y_stride;
|
||||
MG_NodeArray cells;
|
||||
MG_NodeArray row_parents;
|
||||
};
|
||||
|
||||
typedef enum MG_ColumnKind
|
||||
{
|
||||
MG_ColumnKind_DirectCell,
|
||||
MG_ColumnKind_CheckForTag,
|
||||
MG_ColumnKind_TagChild,
|
||||
MG_ColumnKind_COUNT
|
||||
}
|
||||
MG_ColumnKind;
|
||||
|
||||
typedef struct MG_ColumnDesc MG_ColumnDesc;
|
||||
struct MG_ColumnDesc
|
||||
{
|
||||
String8 name;
|
||||
MG_ColumnKind kind;
|
||||
String8 tag_name;
|
||||
};
|
||||
|
||||
typedef struct MG_ColumnDescArray MG_ColumnDescArray;
|
||||
struct MG_ColumnDescArray
|
||||
{
|
||||
U64 count;
|
||||
MG_ColumnDesc *v;
|
||||
};
|
||||
|
||||
typedef struct MG_TableExpandTask MG_TableExpandTask;
|
||||
struct MG_TableExpandTask
|
||||
{
|
||||
MG_TableExpandTask *next;
|
||||
String8 expansion_label;
|
||||
MG_NodeGrid *grid;
|
||||
MG_ColumnDescArray column_descs;
|
||||
U64 count;
|
||||
U64 idx;
|
||||
};
|
||||
|
||||
typedef struct MG_TableExpandInfo MG_TableExpandInfo;
|
||||
struct MG_TableExpandInfo
|
||||
{
|
||||
MG_TableExpandTask *first_expand_task;
|
||||
String8 missing_value_fallback;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Main Output Path Types
|
||||
|
||||
typedef struct MG_Layer MG_Layer;
|
||||
struct MG_Layer
|
||||
{
|
||||
String8 key;
|
||||
B32 is_library;
|
||||
String8 gen_folder_name;
|
||||
String8 h_name_override;
|
||||
String8 c_name_override;
|
||||
String8List enums;
|
||||
String8List structs;
|
||||
String8List h_functions;
|
||||
String8List h_tables;
|
||||
String8List h_catchall;
|
||||
String8List h_header;
|
||||
String8List h_footer;
|
||||
String8List c_functions;
|
||||
String8List c_tables;
|
||||
String8List c_catchall;
|
||||
String8List c_header;
|
||||
String8List c_footer;
|
||||
};
|
||||
|
||||
typedef struct MG_LayerNode MG_LayerNode;
|
||||
struct MG_LayerNode
|
||||
{
|
||||
MG_LayerNode *next;
|
||||
MG_Layer v;
|
||||
};
|
||||
|
||||
typedef struct MG_LayerSlot MG_LayerSlot;
|
||||
struct MG_LayerSlot
|
||||
{
|
||||
MG_LayerNode *first;
|
||||
MG_LayerNode *last;
|
||||
};
|
||||
|
||||
typedef struct MG_State MG_State;
|
||||
struct MG_State
|
||||
{
|
||||
U64 slots_count;
|
||||
MG_LayerSlot *slots;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Globals
|
||||
|
||||
global Arena *mg_arena = 0;
|
||||
global MG_State *mg_state = 0;
|
||||
read_only global MG_StrExpr mg_str_expr_nil = {&mg_str_expr_nil, &mg_str_expr_nil, &mg_str_expr_nil};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Basic Helpers
|
||||
|
||||
internal U64 mg_hash_from_string(String8 string);
|
||||
internal TxtPt mg_txt_pt_from_string_off(String8 string, U64 off);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Message Lists
|
||||
|
||||
internal void mg_msg_list_push(Arena *arena, MG_MsgList *msgs, MG_Msg *msg);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: String Escaping
|
||||
|
||||
internal String8 mg_escaped_from_str8(Arena *arena, String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: String Wrapping
|
||||
|
||||
internal String8List mg_wrapped_lines_from_string(Arena *arena, String8 string, U64 first_line_max_width, U64 max_width, U64 wrap_indent);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: C-String-Izing
|
||||
|
||||
internal String8 mg_c_string_literal_from_multiline_string(String8 string);
|
||||
internal String8 mg_c_array_literal_contents_from_data(String8 data);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Map Functions
|
||||
|
||||
internal MG_Map mg_push_map(Arena *arena, U64 slot_count);
|
||||
internal void *mg_map_ptr_from_string(MG_Map *map, String8 string);
|
||||
internal void mg_map_insert_ptr(Arena *arena, MG_Map *map, String8 string, void *val);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: String Expression Parsing
|
||||
|
||||
internal MG_StrExpr *mg_push_str_expr(Arena *arena, MG_StrExprOp op, MD_Node *node);
|
||||
internal MG_StrExprParseResult mg_str_expr_parse_from_first_opl__min_prec(Arena *arena, MD_Node *first, MD_Node *opl, S8 min_prec);
|
||||
internal MG_StrExprParseResult mg_str_expr_parse_from_first_opl(Arena *arena, MD_Node *first, MD_Node *opl);
|
||||
internal MG_StrExprParseResult mg_str_expr_parse_from_root(Arena *arena, MD_Node *root);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Table Generation Functions
|
||||
|
||||
internal MG_NodeArray mg_node_array_make(Arena *arena, U64 count);
|
||||
internal MG_NodeArray mg_child_array_from_node(Arena *arena, MD_Node *node);
|
||||
internal MG_NodeGrid mg_node_grid_make_from_node(Arena *arena, MD_Node *root);
|
||||
internal MG_NodeArray mg_row_from_index(MG_NodeGrid grid, U64 index);
|
||||
internal MG_NodeArray mg_column_from_index(Arena *arena, MG_NodeGrid grid, U64 index);
|
||||
internal MD_Node *mg_node_from_grid_xy(MG_NodeGrid grid, U64 x, U64 y);
|
||||
|
||||
internal MG_ColumnDescArray mg_column_desc_array_make(Arena *arena, U64 count, MG_ColumnDesc *descs);
|
||||
internal MG_ColumnDescArray mg_column_desc_array_from_tag(Arena *arena, MD_Node *tag);
|
||||
internal U64 mg_column_index_from_name(MG_ColumnDescArray descs, String8 name);
|
||||
internal String8 mg_string_from_row_desc_idx(MD_Node *row_parent, MG_ColumnDescArray descs, U64 idx);
|
||||
|
||||
internal S64 mg_eval_table_expand_expr__numeric(MG_StrExpr *expr, MG_TableExpandInfo *info);
|
||||
internal void mg_eval_table_expand_expr__string(Arena *arena, MG_StrExpr *expr, MG_TableExpandInfo *info, String8List *out);
|
||||
internal void mg_loop_table_column_expansion(Arena *arena, String8 strexpr, MG_TableExpandInfo *info, MG_TableExpandTask *task, String8List *out);
|
||||
internal String8List mg_string_list_from_table_gen(Arena *arena, MG_Map grid_name_map, MG_Map grid_column_desc_map, String8 fallback, MD_Node *gen);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Layer Lookup Functions
|
||||
|
||||
internal String8 mg_layer_key_from_path(String8 path);
|
||||
internal MG_Layer *mg_layer_from_key(String8 key);
|
||||
|
||||
#endif //METAGEN_H
|
||||
@@ -0,0 +1,195 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Arena Functions
|
||||
|
||||
//- rjf: arena creation/destruction
|
||||
|
||||
internal Arena *
|
||||
arena_alloc_(ArenaParams *params)
|
||||
{
|
||||
// rjf: round up reserve/commit sizes
|
||||
U64 reserve_size = params->reserve_size;
|
||||
U64 commit_size = params->commit_size;
|
||||
if(params->flags & ArenaFlag_LargePages)
|
||||
{
|
||||
reserve_size = AlignPow2(reserve_size, os_get_system_info()->large_page_size);
|
||||
commit_size = AlignPow2(commit_size, os_get_system_info()->large_page_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
reserve_size = AlignPow2(reserve_size, os_get_system_info()->page_size);
|
||||
commit_size = AlignPow2(commit_size, os_get_system_info()->page_size);
|
||||
}
|
||||
|
||||
// rjf: reserve/commit initial block
|
||||
void *base = params->optional_backing_buffer;
|
||||
if(base == 0)
|
||||
{
|
||||
if(params->flags & ArenaFlag_LargePages)
|
||||
{
|
||||
base = os_reserve_large(reserve_size);
|
||||
os_commit_large(base, commit_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
base = os_reserve(reserve_size);
|
||||
os_commit(base, commit_size);
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: panic on arena creation failure
|
||||
#if OS_FEATURE_GRAPHICAL
|
||||
if(Unlikely(base == 0))
|
||||
{
|
||||
os_graphical_message(1, str8_lit("Fatal Allocation Failure"), str8_lit("Unexpected memory allocation failure."));
|
||||
os_abort(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
// rjf: extract arena header & fill
|
||||
Arena *arena = (Arena *)base;
|
||||
arena->current = arena;
|
||||
arena->flags = params->flags;
|
||||
arena->cmt_size = (U32)params->commit_size;
|
||||
arena->res_size = params->reserve_size;
|
||||
arena->base_pos = 0;
|
||||
arena->pos = ARENA_HEADER_SIZE;
|
||||
arena->cmt = commit_size;
|
||||
arena->res = reserve_size;
|
||||
AsanPoisonMemoryRegion(base, commit_size);
|
||||
AsanUnpoisonMemoryRegion(base, ARENA_HEADER_SIZE);
|
||||
return arena;
|
||||
}
|
||||
|
||||
internal void
|
||||
arena_release(Arena *arena)
|
||||
{
|
||||
for(Arena *n = arena->current, *prev = 0; n != 0; n = prev)
|
||||
{
|
||||
prev = n->prev;
|
||||
os_release(n, n->res);
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: arena push/pop core functions
|
||||
|
||||
internal void *
|
||||
arena_push(Arena *arena, U64 size, U64 align)
|
||||
{
|
||||
Arena *current = arena->current;
|
||||
U64 pos_pre = AlignPow2(current->pos, align);
|
||||
U64 pos_pst = pos_pre + size;
|
||||
|
||||
// rjf: chain, if needed
|
||||
if(current->res < pos_pst && !(arena->flags & ArenaFlag_NoChain))
|
||||
{
|
||||
U64 res_size = current->res_size;
|
||||
U64 cmt_size = current->cmt_size;
|
||||
if(size + ARENA_HEADER_SIZE > res_size)
|
||||
{
|
||||
res_size = size + ARENA_HEADER_SIZE;
|
||||
cmt_size = size + ARENA_HEADER_SIZE;
|
||||
}
|
||||
Arena *new_block = arena_alloc(.reserve_size = res_size,
|
||||
.commit_size = cmt_size,
|
||||
.flags = current->flags);
|
||||
new_block->base_pos = current->base_pos + current->res;
|
||||
SLLStackPush_N(arena->current, new_block, prev);
|
||||
current = new_block;
|
||||
pos_pre = AlignPow2(current->pos, align);
|
||||
pos_pst = pos_pre + size;
|
||||
}
|
||||
|
||||
// rjf: commit new pages, if needed
|
||||
if(current->cmt < pos_pst && !(current->flags & ArenaFlag_LargePages))
|
||||
{
|
||||
U64 cmt_pst_aligned = AlignPow2(pos_pst, current->cmt_size);
|
||||
U64 cmt_pst_clamped = ClampTop(cmt_pst_aligned, current->res);
|
||||
U64 cmt_size = cmt_pst_clamped - current->cmt;
|
||||
os_commit((U8 *)current + current->cmt, cmt_size);
|
||||
current->cmt = cmt_pst_clamped;
|
||||
}
|
||||
|
||||
// rjf: push onto current block
|
||||
void *result = 0;
|
||||
if(current->cmt >= pos_pst)
|
||||
{
|
||||
result = (U8 *)current+pos_pre;
|
||||
current->pos = pos_pst;
|
||||
AsanUnpoisonMemoryRegion(result, size);
|
||||
}
|
||||
|
||||
// rjf: panic on failure
|
||||
#if OS_FEATURE_GRAPHICAL
|
||||
if(Unlikely(result == 0))
|
||||
{
|
||||
os_graphical_message(1, str8_lit("Fatal Allocation Failure"), str8_lit("Unexpected memory allocation failure."));
|
||||
os_abort(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64
|
||||
arena_pos(Arena *arena)
|
||||
{
|
||||
Arena *current = arena->current;
|
||||
U64 pos = current->base_pos + current->pos;
|
||||
return pos;
|
||||
}
|
||||
|
||||
internal void
|
||||
arena_pop_to(Arena *arena, U64 pos)
|
||||
{
|
||||
U64 big_pos = ClampBot(ARENA_HEADER_SIZE, pos);
|
||||
Arena *current = arena->current;
|
||||
for(Arena *prev = 0; current->base_pos >= big_pos; current = prev)
|
||||
{
|
||||
prev = current->prev;
|
||||
os_release(current, current->res);
|
||||
}
|
||||
arena->current = current;
|
||||
U64 new_pos = big_pos - current->base_pos;
|
||||
AssertAlways(new_pos <= current->pos);
|
||||
AsanPoisonMemoryRegion((U8*)current + new_pos, (current->pos - new_pos));
|
||||
current->pos = new_pos;
|
||||
}
|
||||
|
||||
//- rjf: arena push/pop helpers
|
||||
|
||||
internal void
|
||||
arena_clear(Arena *arena)
|
||||
{
|
||||
arena_pop_to(arena, 0);
|
||||
}
|
||||
|
||||
internal void
|
||||
arena_pop(Arena *arena, U64 amt)
|
||||
{
|
||||
U64 pos_old = arena_pos(arena);
|
||||
U64 pos_new = pos_old;
|
||||
if(amt < pos_old)
|
||||
{
|
||||
pos_new = pos_old - amt;
|
||||
}
|
||||
arena_pop_to(arena, pos_new);
|
||||
}
|
||||
|
||||
//- rjf: temporary arena scopes
|
||||
|
||||
internal Temp
|
||||
temp_begin(Arena *arena)
|
||||
{
|
||||
U64 pos = arena_pos(arena);
|
||||
Temp temp = {arena, pos};
|
||||
return temp;
|
||||
}
|
||||
|
||||
internal void
|
||||
temp_end(Temp temp)
|
||||
{
|
||||
arena_pop_to(temp.arena, temp.pos);
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef BASE_ARENA_H
|
||||
#define BASE_ARENA_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Constants
|
||||
|
||||
#define ARENA_HEADER_SIZE 64
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Types
|
||||
|
||||
typedef U32 ArenaFlags;
|
||||
enum
|
||||
{
|
||||
ArenaFlag_NoChain = (1<<0),
|
||||
ArenaFlag_LargePages = (1<<1),
|
||||
};
|
||||
|
||||
typedef struct ArenaParams ArenaParams;
|
||||
struct ArenaParams
|
||||
{
|
||||
ArenaFlags flags;
|
||||
U64 reserve_size;
|
||||
U64 commit_size;
|
||||
void *optional_backing_buffer;
|
||||
};
|
||||
|
||||
typedef struct Arena Arena;
|
||||
struct Arena
|
||||
{
|
||||
Arena *prev; // previous arena in chain
|
||||
Arena *current; // current arena in chain
|
||||
ArenaFlags flags;
|
||||
U32 cmt_size;
|
||||
U64 res_size;
|
||||
U64 base_pos;
|
||||
U64 pos;
|
||||
U64 cmt;
|
||||
U64 res;
|
||||
};
|
||||
StaticAssert(sizeof(Arena) <= ARENA_HEADER_SIZE, arena_header_size_check);
|
||||
|
||||
typedef struct Temp Temp;
|
||||
struct Temp
|
||||
{
|
||||
Arena *arena;
|
||||
U64 pos;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Arena Functions
|
||||
|
||||
//- rjf: arena creation/destruction
|
||||
internal Arena *arena_alloc_(ArenaParams *params);
|
||||
#define arena_alloc(...) arena_alloc_(&(ArenaParams){.reserve_size = MB(64), .commit_size = KB(64), __VA_ARGS__})
|
||||
internal void arena_release(Arena *arena);
|
||||
|
||||
//- rjf: arena push/pop/pos core functions
|
||||
internal void *arena_push(Arena *arena, U64 size, U64 align);
|
||||
internal U64 arena_pos(Arena *arena);
|
||||
internal void arena_pop_to(Arena *arena, U64 pos);
|
||||
|
||||
//- rjf: arena push/pop helpers
|
||||
internal void arena_clear(Arena *arena);
|
||||
internal void arena_pop(Arena *arena, U64 amt);
|
||||
|
||||
//- rjf: temporary arena scopes
|
||||
internal Temp temp_begin(Arena *arena);
|
||||
internal void temp_end(Temp temp);
|
||||
|
||||
//- rjf: push helper macros
|
||||
#define push_array_no_zero_aligned(a, T, c, align) (T *)arena_push((a), sizeof(T)*(c), (align))
|
||||
#define push_array_aligned(a, T, c, align) (T *)MemoryZero(push_array_no_zero_aligned(a, T, c, align), sizeof(T)*(c))
|
||||
#define push_array_no_zero(a, T, c) push_array_no_zero_aligned(a, T, c, Max(8, AlignOf(T)))
|
||||
#define push_array(a, T, c) push_array_aligned(a, T, c, Max(8, AlignOf(T)))
|
||||
|
||||
#endif // BASE_ARENA_H
|
||||
@@ -0,0 +1,232 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
//~ NOTE(rjf): Command Line Option Parsing
|
||||
|
||||
internal U64
|
||||
cmd_line_hash_from_string(String8 string)
|
||||
{
|
||||
U64 result = 5381;
|
||||
for(U64 i = 0; i < string.size; i += 1)
|
||||
{
|
||||
result = ((result << 5) + result) + string.str[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal CmdLineOpt **
|
||||
cmd_line_slot_from_string(CmdLine *cmd_line, String8 string)
|
||||
{
|
||||
CmdLineOpt **slot = 0;
|
||||
if(cmd_line->option_table_size != 0)
|
||||
{
|
||||
U64 hash = cmd_line_hash_from_string(string);
|
||||
U64 bucket = hash % cmd_line->option_table_size;
|
||||
slot = &cmd_line->option_table[bucket];
|
||||
}
|
||||
return slot;
|
||||
}
|
||||
|
||||
internal CmdLineOpt *
|
||||
cmd_line_opt_from_slot(CmdLineOpt **slot, String8 string)
|
||||
{
|
||||
CmdLineOpt *result = 0;
|
||||
for(CmdLineOpt *var = *slot; var; var = var->hash_next)
|
||||
{
|
||||
if(str8_match(string, var->string, 0))
|
||||
{
|
||||
result = var;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void
|
||||
cmd_line_push_opt(CmdLineOptList *list, CmdLineOpt *var)
|
||||
{
|
||||
SLLQueuePush(list->first, list->last, var);
|
||||
list->count += 1;
|
||||
}
|
||||
|
||||
internal CmdLineOpt *
|
||||
cmd_line_insert_opt(Arena *arena, CmdLine *cmd_line, String8 string, String8List values)
|
||||
{
|
||||
CmdLineOpt *var = 0;
|
||||
CmdLineOpt **slot = cmd_line_slot_from_string(cmd_line, string);
|
||||
CmdLineOpt *existing_var = cmd_line_opt_from_slot(slot, string);
|
||||
if(existing_var != 0)
|
||||
{
|
||||
var = existing_var;
|
||||
}
|
||||
else
|
||||
{
|
||||
var = push_array(arena, CmdLineOpt, 1);
|
||||
var->hash_next = *slot;
|
||||
var->hash = cmd_line_hash_from_string(string);
|
||||
var->string = push_str8_copy(arena, string);
|
||||
var->value_strings = values;
|
||||
StringJoin join = {0};
|
||||
join.pre = str8_lit("");
|
||||
join.sep = str8_lit(",");
|
||||
join.post = str8_lit("");
|
||||
var->value_string = str8_list_join(arena, &var->value_strings, &join);
|
||||
*slot = var;
|
||||
cmd_line_push_opt(&cmd_line->options, var);
|
||||
}
|
||||
return var;
|
||||
}
|
||||
|
||||
internal CmdLine
|
||||
cmd_line_from_string_list(Arena *arena, String8List command_line)
|
||||
{
|
||||
CmdLine parsed = {0};
|
||||
parsed.exe_name = command_line.first->string;
|
||||
|
||||
// NOTE(rjf): Set up config option table.
|
||||
{
|
||||
parsed.option_table_size = 4096;
|
||||
parsed.option_table = push_array(arena, CmdLineOpt *, parsed.option_table_size);
|
||||
}
|
||||
|
||||
// NOTE(rjf): Parse command line.
|
||||
B32 after_passthrough_option = 0;
|
||||
B32 first_passthrough = 1;
|
||||
for(String8Node *node = command_line.first->next, *next = 0; node != 0; node = next)
|
||||
{
|
||||
next = node->next;
|
||||
String8 option_name = node->string;
|
||||
|
||||
// NOTE(rjf): Look at -- or - at the start of an argument to determine if it's
|
||||
// a flag option. All arguments after a single "--" (with no trailing string
|
||||
// on the command line will be considered as input files.
|
||||
B32 is_option = 1;
|
||||
if(after_passthrough_option == 0)
|
||||
{
|
||||
if(str8_match(node->string, str8_lit("--"), 0))
|
||||
{
|
||||
after_passthrough_option = 1;
|
||||
is_option = 0;
|
||||
}
|
||||
else if(str8_match(str8_prefix(node->string, 2), str8_lit("--"), 0))
|
||||
{
|
||||
option_name = str8_skip(option_name, 2);
|
||||
}
|
||||
else if(str8_match(str8_prefix(node->string, 1), str8_lit("-"), 0))
|
||||
{
|
||||
option_name = str8_skip(option_name, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
is_option = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
is_option = 0;
|
||||
}
|
||||
|
||||
// NOTE(rjf): This string is an option.
|
||||
if(is_option)
|
||||
{
|
||||
B32 has_arguments = 0;
|
||||
U64 arg_signifier_position1 = str8_find_needle(option_name, 0, str8_lit(":"), 0);
|
||||
U64 arg_signifier_position2 = str8_find_needle(option_name, 0, str8_lit("="), 0);
|
||||
U64 arg_signifier_position = Min(arg_signifier_position1, arg_signifier_position2);
|
||||
String8 arg_portion_this_string = str8_skip(option_name, arg_signifier_position+1);
|
||||
if(arg_signifier_position < option_name.size)
|
||||
{
|
||||
has_arguments = 1;
|
||||
}
|
||||
option_name = str8_prefix(option_name, arg_signifier_position);
|
||||
|
||||
String8List arguments = {0};
|
||||
|
||||
// NOTE(rjf): Parse arguments.
|
||||
if(has_arguments)
|
||||
{
|
||||
for(String8Node *n = node; n; n = n->next)
|
||||
{
|
||||
next = n->next;
|
||||
|
||||
String8 string = n->string;
|
||||
if(n == node)
|
||||
{
|
||||
string = arg_portion_this_string;
|
||||
}
|
||||
|
||||
U8 splits[] = { ',' };
|
||||
String8List args_in_this_string = str8_split(arena, string, splits, ArrayCount(splits), 0);
|
||||
for(String8Node *sub_arg = args_in_this_string.first; sub_arg; sub_arg = sub_arg->next)
|
||||
{
|
||||
str8_list_push(arena, &arguments, sub_arg->string);
|
||||
}
|
||||
if(!str8_match(str8_postfix(n->string, 1), str8_lit(","), 0) &&
|
||||
(n != node || arg_portion_this_string.size != 0))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE(rjf): Register config variable.
|
||||
cmd_line_insert_opt(arena, &parsed, option_name, arguments);
|
||||
}
|
||||
|
||||
// NOTE(rjf): Default path, treat as a passthrough config option to be
|
||||
// handled by tool-specific code.
|
||||
else if(!str8_match(node->string, str8_lit("--"), 0) || !first_passthrough)
|
||||
{
|
||||
str8_list_push(arena, &parsed.inputs, node->string);
|
||||
after_passthrough_option = 1;
|
||||
first_passthrough = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
internal CmdLineOpt *
|
||||
cmd_line_opt_from_string(CmdLine *cmd_line, String8 name)
|
||||
{
|
||||
return cmd_line_opt_from_slot(cmd_line_slot_from_string(cmd_line, name), name);
|
||||
}
|
||||
|
||||
internal String8List
|
||||
cmd_line_strings(CmdLine *cmd_line, String8 name)
|
||||
{
|
||||
String8List result = {0};
|
||||
CmdLineOpt *var = cmd_line_opt_from_string(cmd_line, name);
|
||||
if(var != 0)
|
||||
{
|
||||
result = var->value_strings;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8
|
||||
cmd_line_string(CmdLine *cmd_line, String8 name)
|
||||
{
|
||||
String8 result = {0};
|
||||
CmdLineOpt *var = cmd_line_opt_from_string(cmd_line, name);
|
||||
if(var != 0)
|
||||
{
|
||||
result = var->value_string;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal B32
|
||||
cmd_line_has_flag(CmdLine *cmd_line, String8 name)
|
||||
{
|
||||
CmdLineOpt *var = cmd_line_opt_from_string(cmd_line, name);
|
||||
return(var != 0);
|
||||
}
|
||||
|
||||
internal B32
|
||||
cmd_line_has_argument(CmdLine *cmd_line, String8 name)
|
||||
{
|
||||
CmdLineOpt *var = cmd_line_opt_from_string(cmd_line, name);
|
||||
return(var != 0 && var->value_strings.node_count > 0);
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef BASE_COMMAND_LINE_H
|
||||
#define BASE_COMMAND_LINE_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Parsed Command Line Types
|
||||
|
||||
typedef struct CmdLineOpt CmdLineOpt;
|
||||
struct CmdLineOpt
|
||||
{
|
||||
CmdLineOpt *next;
|
||||
CmdLineOpt *hash_next;
|
||||
U64 hash;
|
||||
String8 string;
|
||||
String8List value_strings;
|
||||
String8 value_string;
|
||||
};
|
||||
|
||||
typedef struct CmdLineOptList CmdLineOptList;
|
||||
struct CmdLineOptList
|
||||
{
|
||||
U64 count;
|
||||
CmdLineOpt *first;
|
||||
CmdLineOpt *last;
|
||||
};
|
||||
|
||||
typedef struct CmdLine CmdLine;
|
||||
struct CmdLine
|
||||
{
|
||||
String8 exe_name;
|
||||
CmdLineOptList options;
|
||||
String8List inputs;
|
||||
U64 option_table_size;
|
||||
CmdLineOpt **option_table;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ NOTE(rjf): Command Line Option Parsing
|
||||
|
||||
internal U64 cmd_line_hash_from_string(String8 string);
|
||||
internal CmdLineOpt** cmd_line_slot_from_string(CmdLine *cmd_line, String8 string);
|
||||
internal CmdLineOpt* cmd_line_opt_from_slot(CmdLineOpt **slot, String8 string);
|
||||
internal void cmd_line_push_opt(CmdLineOptList *list, CmdLineOpt *var);
|
||||
internal CmdLineOpt* cmd_line_insert_opt(Arena *arena, CmdLine *cmd_line, String8 string, String8List values);
|
||||
internal CmdLine cmd_line_from_string_list(Arena *arena, String8List arguments);
|
||||
internal CmdLineOpt* cmd_line_opt_from_string(CmdLine *cmd_line, String8 name);
|
||||
internal String8List cmd_line_strings(CmdLine *cmd_line, String8 name);
|
||||
internal String8 cmd_line_string(CmdLine *cmd_line, String8 name);
|
||||
internal B32 cmd_line_has_flag(CmdLine *cmd_line, String8 name);
|
||||
internal B32 cmd_line_has_argument(CmdLine *cmd_line, String8 name);
|
||||
|
||||
#endif // BASE_COMMAND_LINE_H
|
||||
@@ -0,0 +1,247 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef BASE_CONTEXT_CRACKING_H
|
||||
#define BASE_CONTEXT_CRACKING_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Clang OS/Arch Cracking
|
||||
|
||||
#if defined(__clang__)
|
||||
|
||||
# define COMPILER_CLANG 1
|
||||
|
||||
# if defined(_WIN32)
|
||||
# define OS_WINDOWS 1
|
||||
# elif defined(__gnu_linux__) || defined(__linux__)
|
||||
# define OS_LINUX 1
|
||||
# elif defined(__APPLE__) && defined(__MACH__)
|
||||
# define OS_MAC 1
|
||||
# else
|
||||
# error This compiler/OS combo is not supported.
|
||||
# endif
|
||||
|
||||
# if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
|
||||
# define ARCH_X64 1
|
||||
# elif defined(i386) || defined(__i386) || defined(__i386__)
|
||||
# define ARCH_X86 1
|
||||
# elif defined(__aarch64__)
|
||||
# define ARCH_ARM64 1
|
||||
# elif defined(__arm__)
|
||||
# define ARCH_ARM32 1
|
||||
# else
|
||||
# error Architecture not supported.
|
||||
# endif
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: MSVC OS/Arch Cracking
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
|
||||
# define COMPILER_MSVC 1
|
||||
|
||||
# if _MSC_VER >= 1920
|
||||
# define COMPILER_MSVC_YEAR 2019
|
||||
# elif _MSC_VER >= 1910
|
||||
# define COMPILER_MSVC_YEAR 2017
|
||||
# elif _MSC_VER >= 1900
|
||||
# define COMPILER_MSVC_YEAR 2015
|
||||
# elif _MSC_VER >= 1800
|
||||
# define COMPILER_MSVC_YEAR 2013
|
||||
# elif _MSC_VER >= 1700
|
||||
# define COMPILER_MSVC_YEAR 2012
|
||||
# elif _MSC_VER >= 1600
|
||||
# define COMPILER_MSVC_YEAR 2010
|
||||
# elif _MSC_VER >= 1500
|
||||
# define COMPILER_MSVC_YEAR 2008
|
||||
# elif _MSC_VER >= 1400
|
||||
# define COMPILER_MSVC_YEAR 2005
|
||||
# else
|
||||
# define COMPILER_MSVC_YEAR 0
|
||||
# endif
|
||||
|
||||
# if defined(_WIN32)
|
||||
# define OS_WINDOWS 1
|
||||
# else
|
||||
# error This compiler/OS combo is not supported.
|
||||
# endif
|
||||
|
||||
# if defined(_M_AMD64)
|
||||
# define ARCH_X64 1
|
||||
# elif defined(_M_IX86)
|
||||
# define ARCH_X86 1
|
||||
# elif defined(_M_ARM64)
|
||||
# define ARCH_ARM64 1
|
||||
# elif defined(_M_ARM)
|
||||
# define ARCH_ARM32 1
|
||||
# else
|
||||
# error Architecture not supported.
|
||||
# endif
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: GCC OS/Arch Cracking
|
||||
|
||||
#elif defined(__GNUC__) || defined(__GNUG__)
|
||||
|
||||
# define COMPILER_GCC 1
|
||||
|
||||
# if defined(__gnu_linux__) || defined(__linux__)
|
||||
# define OS_LINUX 1
|
||||
# else
|
||||
# error This compiler/OS combo is not supported.
|
||||
# endif
|
||||
|
||||
# if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
|
||||
# define ARCH_X64 1
|
||||
# elif defined(i386) || defined(__i386) || defined(__i386__)
|
||||
# define ARCH_X86 1
|
||||
# elif defined(__aarch64__)
|
||||
# define ARCH_ARM64 1
|
||||
# elif defined(__arm__)
|
||||
# define ARCH_ARM32 1
|
||||
# else
|
||||
# error Architecture not supported.
|
||||
# endif
|
||||
|
||||
#else
|
||||
# error Compiler not supported.
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Arch Cracking
|
||||
|
||||
#if defined(ARCH_X64)
|
||||
# define ARCH_64BIT 1
|
||||
#elif defined(ARCH_X86)
|
||||
# define ARCH_32BIT 1
|
||||
#endif
|
||||
|
||||
#if ARCH_ARM32 || ARCH_ARM64 || ARCH_X64 || ARCH_X86
|
||||
# define ARCH_LITTLE_ENDIAN 1
|
||||
#else
|
||||
# error Endianness of this architecture not understood by context cracker.
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Language Cracking
|
||||
|
||||
#if defined(__cplusplus)
|
||||
# define LANG_CPP 1
|
||||
#else
|
||||
# define LANG_C 1
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Build Option Cracking
|
||||
|
||||
#if !defined(BUILD_DEBUG)
|
||||
# define BUILD_DEBUG 1
|
||||
#endif
|
||||
|
||||
#if !defined(BUILD_SUPPLEMENTARY_UNIT)
|
||||
# define BUILD_SUPPLEMENTARY_UNIT 0
|
||||
#endif
|
||||
|
||||
#if !defined(BUILD_ENTRY_DEFINING_UNIT)
|
||||
# define BUILD_ENTRY_DEFINING_UNIT 1
|
||||
#endif
|
||||
|
||||
#if !defined(BUILD_CONSOLE_INTERFACE)
|
||||
# define BUILD_CONSOLE_INTERFACE 0
|
||||
#endif
|
||||
|
||||
#if !defined(BUILD_VERSION_MAJOR)
|
||||
# define BUILD_VERSION_MAJOR 0
|
||||
#endif
|
||||
|
||||
#if !defined(BUILD_VERSION_MINOR)
|
||||
# define BUILD_VERSION_MINOR 0
|
||||
#endif
|
||||
|
||||
#if !defined(BUILD_VERSION_PATCH)
|
||||
# define BUILD_VERSION_PATCH 0
|
||||
#endif
|
||||
|
||||
#define BUILD_VERSION_STRING_LITERAL Stringify(BUILD_VERSION_MAJOR) "." Stringify(BUILD_VERSION_MINOR) "." Stringify(BUILD_VERSION_PATCH)
|
||||
#if BUILD_DEBUG
|
||||
# define BUILD_MODE_STRING_LITERAL_APPEND " [Debug]"
|
||||
#else
|
||||
# define BUILD_MODE_STRING_LITERAL_APPEND ""
|
||||
#endif
|
||||
#if defined(BUILD_GIT_HASH)
|
||||
# define BUILD_GIT_HASH_STRING_LITERAL_APPEND " [" BUILD_GIT_HASH "]"
|
||||
#else
|
||||
# define BUILD_GIT_HASH_STRING_LITERAL_APPEND ""
|
||||
#endif
|
||||
|
||||
#if !defined(BUILD_TITLE)
|
||||
# define BUILD_TITLE "Untitled"
|
||||
#endif
|
||||
|
||||
#if !defined(BUILD_RELEASE_PHASE_STRING_LITERAL)
|
||||
# define BUILD_RELEASE_PHASE_STRING_LITERAL "ALPHA"
|
||||
#endif
|
||||
|
||||
#if !defined(BUILD_ISSUES_LINK_STRING_LITERAL)
|
||||
# define BUILD_ISSUES_LINK_STRING_LITERAL "https://github.com/EpicGames/raddebugger/issues"
|
||||
#endif
|
||||
|
||||
#define BUILD_TITLE_STRING_LITERAL BUILD_TITLE " (" BUILD_VERSION_STRING_LITERAL " " BUILD_RELEASE_PHASE_STRING_LITERAL ") - " __DATE__ "" BUILD_GIT_HASH_STRING_LITERAL_APPEND BUILD_MODE_STRING_LITERAL_APPEND
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Zero All Undefined Options
|
||||
|
||||
#if !defined(ARCH_32BIT)
|
||||
# define ARCH_32BIT 0
|
||||
#endif
|
||||
#if !defined(ARCH_64BIT)
|
||||
# define ARCH_64BIT 0
|
||||
#endif
|
||||
#if !defined(ARCH_X64)
|
||||
# define ARCH_X64 0
|
||||
#endif
|
||||
#if !defined(ARCH_X86)
|
||||
# define ARCH_X86 0
|
||||
#endif
|
||||
#if !defined(ARCH_ARM64)
|
||||
# define ARCH_ARM64 0
|
||||
#endif
|
||||
#if !defined(ARCH_ARM32)
|
||||
# define ARCH_ARM32 0
|
||||
#endif
|
||||
#if !defined(COMPILER_MSVC)
|
||||
# define COMPILER_MSVC 0
|
||||
#endif
|
||||
#if !defined(COMPILER_GCC)
|
||||
# define COMPILER_GCC 0
|
||||
#endif
|
||||
#if !defined(COMPILER_CLANG)
|
||||
# define COMPILER_CLANG 0
|
||||
#endif
|
||||
#if !defined(OS_WINDOWS)
|
||||
# define OS_WINDOWS 0
|
||||
#endif
|
||||
#if !defined(OS_LINUX)
|
||||
# define OS_LINUX 0
|
||||
#endif
|
||||
#if !defined(OS_MAC)
|
||||
# define OS_MAC 0
|
||||
#endif
|
||||
#if !defined(LANG_CPP)
|
||||
# define LANG_CPP 0
|
||||
#endif
|
||||
#if !defined(LANG_C)
|
||||
# define LANG_C 0
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Unsupported Errors
|
||||
|
||||
#if ARCH_X86
|
||||
# error You tried to build in x86 (32 bit) mode, but currently, only building in x64 (64 bit) mode is supported.
|
||||
#endif
|
||||
#if !ARCH_X64
|
||||
# error You tried to build with an unsupported architecture. Currently, only building in x64 mode is supported.
|
||||
#endif
|
||||
|
||||
#endif // BASE_CONTEXT_CRACKING_H
|
||||
@@ -0,0 +1,562 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Safe Casts
|
||||
|
||||
internal U16
|
||||
safe_cast_u16(U32 x)
|
||||
{
|
||||
AssertAlways(x <= max_U16);
|
||||
U16 result = (U16)x;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U32
|
||||
safe_cast_u32(U64 x)
|
||||
{
|
||||
AssertAlways(x <= max_U32);
|
||||
U32 result = (U32)x;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal S32
|
||||
safe_cast_s32(S64 x)
|
||||
{
|
||||
AssertAlways(x <= max_S32);
|
||||
S32 result = (S32)x;
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Large Base Type Functions
|
||||
|
||||
internal U128
|
||||
u128_zero(void)
|
||||
{
|
||||
U128 v = {0};
|
||||
return v;
|
||||
}
|
||||
|
||||
internal U128
|
||||
u128_make(U64 v0, U64 v1)
|
||||
{
|
||||
U128 v = {v0, v1};
|
||||
return v;
|
||||
}
|
||||
|
||||
internal B32
|
||||
u128_match(U128 a, U128 b)
|
||||
{
|
||||
return MemoryMatchStruct(&a, &b);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Bit Patterns
|
||||
|
||||
internal U32
|
||||
u32_from_u64_saturate(U64 x){
|
||||
U32 x32 = (x > max_U32)?max_U32:(U32)x;
|
||||
return(x32);
|
||||
}
|
||||
|
||||
internal U64
|
||||
u64_up_to_pow2(U64 x){
|
||||
if (x == 0){
|
||||
x = 1;
|
||||
}
|
||||
else{
|
||||
x -= 1;
|
||||
x |= (x >> 1);
|
||||
x |= (x >> 2);
|
||||
x |= (x >> 4);
|
||||
x |= (x >> 8);
|
||||
x |= (x >> 16);
|
||||
x |= (x >> 32);
|
||||
x += 1;
|
||||
}
|
||||
return(x);
|
||||
}
|
||||
|
||||
internal S32
|
||||
extend_sign32(U32 x, U32 size){
|
||||
U32 high_bit = size * 8;
|
||||
U32 shift = 32 - high_bit;
|
||||
S32 result = ((S32)x << shift) >> shift;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal S64
|
||||
extend_sign64(U64 x, U64 size){
|
||||
U64 high_bit = size * 8;
|
||||
U64 shift = 64 - high_bit;
|
||||
S64 result = ((S64)x << shift) >> shift;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal F32
|
||||
inf32(void){
|
||||
union { U32 u; F32 f; } x;
|
||||
x.u = exponent32;
|
||||
return(x.f);
|
||||
}
|
||||
|
||||
internal F32
|
||||
neg_inf32(void){
|
||||
union { U32 u; F32 f; } x;
|
||||
x.u = sign32 | exponent32;
|
||||
return(x.f);
|
||||
}
|
||||
|
||||
internal U16
|
||||
bswap_u16(U16 x)
|
||||
{
|
||||
U16 result = (((x & 0xFF00) >> 8) |
|
||||
((x & 0x00FF) << 8));
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U32
|
||||
bswap_u32(U32 x)
|
||||
{
|
||||
U32 result = (((x & 0xFF000000) >> 24) |
|
||||
((x & 0x00FF0000) >> 8) |
|
||||
((x & 0x0000FF00) << 8) |
|
||||
((x & 0x000000FF) << 24));
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64
|
||||
bswap_u64(U64 x)
|
||||
{
|
||||
// TODO(nick): naive bswap, replace with something that is faster like an intrinsic
|
||||
U64 result = (((x & 0xFF00000000000000ULL) >> 56) |
|
||||
((x & 0x00FF000000000000ULL) >> 40) |
|
||||
((x & 0x0000FF0000000000ULL) >> 24) |
|
||||
((x & 0x000000FF00000000ULL) >> 8) |
|
||||
((x & 0x00000000FF000000ULL) << 8) |
|
||||
((x & 0x0000000000FF0000ULL) << 24) |
|
||||
((x & 0x000000000000FF00ULL) << 40) |
|
||||
((x & 0x00000000000000FFULL) << 56));
|
||||
return result;
|
||||
}
|
||||
|
||||
#if COMPILER_MSVC || (COMPILER_CLANG && OS_WINDOWS)
|
||||
|
||||
internal U64
|
||||
count_bits_set16(U16 val)
|
||||
{
|
||||
return __popcnt16(val);
|
||||
}
|
||||
|
||||
internal U64
|
||||
count_bits_set32(U32 val)
|
||||
{
|
||||
return __popcnt(val);
|
||||
}
|
||||
|
||||
internal U64
|
||||
count_bits_set64(U64 val)
|
||||
{
|
||||
return __popcnt64(val);
|
||||
}
|
||||
|
||||
internal U64
|
||||
ctz32(U32 mask)
|
||||
{
|
||||
unsigned long idx;
|
||||
_BitScanForward(&idx, mask);
|
||||
return idx;
|
||||
}
|
||||
|
||||
internal U64
|
||||
ctz64(U64 mask)
|
||||
{
|
||||
unsigned long idx;
|
||||
_BitScanForward64(&idx, mask);
|
||||
return idx;
|
||||
}
|
||||
|
||||
internal U64
|
||||
clz32(U32 mask)
|
||||
{
|
||||
unsigned long idx;
|
||||
_BitScanReverse(&idx, mask);
|
||||
return 31 - idx;
|
||||
}
|
||||
|
||||
internal U64
|
||||
clz64(U64 mask)
|
||||
{
|
||||
unsigned long idx;
|
||||
_BitScanReverse64(&idx, mask);
|
||||
return 63 - idx;
|
||||
}
|
||||
|
||||
#elif COMPILER_CLANG || COMPILER_GCC
|
||||
|
||||
internal U64
|
||||
count_bits_set16(U16 val)
|
||||
{
|
||||
NotImplemented;
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal U64
|
||||
count_bits_set32(U32 val)
|
||||
{
|
||||
NotImplemented;
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal U64
|
||||
count_bits_set64(U64 val)
|
||||
{
|
||||
NotImplemented;
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal U64
|
||||
ctz32(U32 val)
|
||||
{
|
||||
NotImplemented;
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal U64
|
||||
clz32(U32 val)
|
||||
{
|
||||
NotImplemented;
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal U64
|
||||
clz64(U64 val)
|
||||
{
|
||||
NotImplemented;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
# error "Bit intrinsic functions not defined for this compiler."
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Enum -> Sign
|
||||
|
||||
internal S32
|
||||
sign_from_side_S32(Side side){
|
||||
return((side == Side_Min)?-1:1);
|
||||
}
|
||||
|
||||
internal F32
|
||||
sign_from_side_F32(Side side){
|
||||
return((side == Side_Min)?-1.f:1.f);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Memory Functions
|
||||
|
||||
internal B32
|
||||
memory_is_zero(void *ptr, U64 size){
|
||||
B32 result = 1;
|
||||
|
||||
// break down size
|
||||
U64 extra = (size&0x7);
|
||||
U64 count8 = (size >> 3);
|
||||
|
||||
// check with 8-byte stride
|
||||
U64 *p64 = (U64*)ptr;
|
||||
if(result)
|
||||
{
|
||||
for (U64 i = 0; i < count8; i += 1, p64 += 1){
|
||||
if (*p64 != 0){
|
||||
result = 0;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check extra
|
||||
if(result)
|
||||
{
|
||||
U8 *p8 = (U8*)p64;
|
||||
for (U64 i = 0; i < extra; i += 1, p8 += 1){
|
||||
if (*p8 != 0){
|
||||
result = 0;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:;
|
||||
return(result);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Text 2D Coordinate/Range Functions
|
||||
|
||||
internal TxtPt
|
||||
txt_pt(S64 line, S64 column)
|
||||
{
|
||||
TxtPt p = {0};
|
||||
p.line = line;
|
||||
p.column = column;
|
||||
return p;
|
||||
}
|
||||
|
||||
internal B32
|
||||
txt_pt_match(TxtPt a, TxtPt b)
|
||||
{
|
||||
return a.line == b.line && a.column == b.column;
|
||||
}
|
||||
|
||||
internal B32
|
||||
txt_pt_less_than(TxtPt a, TxtPt b)
|
||||
{
|
||||
B32 result = 0;
|
||||
if(a.line < b.line)
|
||||
{
|
||||
result = 1;
|
||||
}
|
||||
else if(a.line == b.line)
|
||||
{
|
||||
result = a.column < b.column;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal TxtPt
|
||||
txt_pt_min(TxtPt a, TxtPt b)
|
||||
{
|
||||
TxtPt result = b;
|
||||
if(txt_pt_less_than(a, b))
|
||||
{
|
||||
result = a;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal TxtPt
|
||||
txt_pt_max(TxtPt a, TxtPt b)
|
||||
{
|
||||
TxtPt result = a;
|
||||
if(txt_pt_less_than(a, b))
|
||||
{
|
||||
result = b;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal TxtRng
|
||||
txt_rng(TxtPt min, TxtPt max)
|
||||
{
|
||||
TxtRng range = {0};
|
||||
if(txt_pt_less_than(min, max))
|
||||
{
|
||||
range.min = min;
|
||||
range.max = max;
|
||||
}
|
||||
else
|
||||
{
|
||||
range.min = max;
|
||||
range.max = min;
|
||||
}
|
||||
return range;
|
||||
}
|
||||
|
||||
internal TxtRng
|
||||
txt_rng_intersect(TxtRng a, TxtRng b)
|
||||
{
|
||||
TxtRng result = {0};
|
||||
result.min = txt_pt_max(a.min, b.min);
|
||||
result.max = txt_pt_min(a.max, b.max);
|
||||
if(txt_pt_less_than(result.max, result.min))
|
||||
{
|
||||
MemoryZeroStruct(&result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal TxtRng
|
||||
txt_rng_union(TxtRng a, TxtRng b)
|
||||
{
|
||||
TxtRng result = {0};
|
||||
result.min = txt_pt_min(a.min, b.min);
|
||||
result.max = txt_pt_max(a.max, b.max);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal B32
|
||||
txt_rng_contains(TxtRng r, TxtPt pt)
|
||||
{
|
||||
B32 result = ((txt_pt_less_than(r.min, pt) || txt_pt_match(r.min, pt)) &&
|
||||
txt_pt_less_than(pt, r.max));
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Toolchain/Environment Enum Functions
|
||||
|
||||
internal U64
|
||||
bit_size_from_arch(Architecture arch)
|
||||
{
|
||||
// TODO(rjf): metacode
|
||||
U64 arch_bitsize = 0;
|
||||
switch(arch)
|
||||
{
|
||||
case Architecture_x64: arch_bitsize = 64; break;
|
||||
case Architecture_x86: arch_bitsize = 32; break;
|
||||
case Architecture_arm64: arch_bitsize = 64; break;
|
||||
case Architecture_arm32: arch_bitsize = 32; break;
|
||||
default: break;
|
||||
}
|
||||
return arch_bitsize;
|
||||
}
|
||||
|
||||
internal U64
|
||||
max_instruction_size_from_arch(Architecture arch)
|
||||
{
|
||||
// TODO(rjf): make this real
|
||||
return 64;
|
||||
}
|
||||
|
||||
internal OperatingSystem
|
||||
operating_system_from_context(void){
|
||||
OperatingSystem os = OperatingSystem_Null;
|
||||
#if OS_WINDOWS
|
||||
os = OperatingSystem_Windows;
|
||||
#elif OS_LINUX
|
||||
os = OperatingSystem_Linux;
|
||||
#elif OS_MAC
|
||||
os = OperatingSystem_Mac;
|
||||
#endif
|
||||
return os;
|
||||
}
|
||||
|
||||
internal Architecture
|
||||
architecture_from_context(void){
|
||||
Architecture arch = Architecture_Null;
|
||||
#if ARCH_X64
|
||||
arch = Architecture_x64;
|
||||
#elif ARCH_X86
|
||||
arch = Architecture_x86;
|
||||
#elif ARCH_ARM64
|
||||
arch = Architecture_arm64;
|
||||
#elif ARCH_ARM32
|
||||
arch = Architecture_arm32;
|
||||
#endif
|
||||
return arch;
|
||||
}
|
||||
|
||||
internal Compiler
|
||||
compiler_from_context(void){
|
||||
Compiler compiler = Compiler_Null;
|
||||
#if COMPILER_MSVC
|
||||
compiler = Compiler_msvc;
|
||||
#elif COMPILER_GCC
|
||||
compiler = Compiler_gcc;
|
||||
#elif COMPILER_CLANG
|
||||
compiler = Compiler_clang;
|
||||
#endif
|
||||
return compiler;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Time Functions
|
||||
|
||||
internal DenseTime
|
||||
dense_time_from_date_time(DateTime date_time){
|
||||
DenseTime result = 0;
|
||||
result += date_time.year;
|
||||
result *= 12;
|
||||
result += date_time.mon;
|
||||
result *= 31;
|
||||
result += date_time.day;
|
||||
result *= 24;
|
||||
result += date_time.hour;
|
||||
result *= 60;
|
||||
result += date_time.min;
|
||||
result *= 61;
|
||||
result += date_time.sec;
|
||||
result *= 1000;
|
||||
result += date_time.msec;
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal DateTime
|
||||
date_time_from_dense_time(DenseTime time){
|
||||
DateTime result = {0};
|
||||
result.msec = time%1000;
|
||||
time /= 1000;
|
||||
result.sec = time%61;
|
||||
time /= 61;
|
||||
result.min = time%60;
|
||||
time /= 60;
|
||||
result.hour = time%24;
|
||||
time /= 24;
|
||||
result.day = time%31;
|
||||
time /= 31;
|
||||
result.mon = time%12;
|
||||
time /= 12;
|
||||
Assert(time <= max_U32);
|
||||
result.year = (U32)time;
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal DateTime
|
||||
date_time_from_micro_seconds(U64 time){
|
||||
DateTime result = {0};
|
||||
result.micro_sec = time%1000;
|
||||
time /= 1000;
|
||||
result.msec = time%1000;
|
||||
time /= 1000;
|
||||
result.sec = time%60;
|
||||
time /= 60;
|
||||
result.min = time%60;
|
||||
time /= 60;
|
||||
result.hour = time%24;
|
||||
time /= 24;
|
||||
result.day = time%31;
|
||||
time /= 31;
|
||||
result.mon = time%12;
|
||||
time /= 12;
|
||||
Assert(time <= max_U32);
|
||||
result.year = (U32)time;
|
||||
return(result);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Non-Fancy Ring Buffer Reads/Writes
|
||||
|
||||
internal U64
|
||||
ring_write(U8 *ring_base, U64 ring_size, U64 ring_pos, void *src_data, U64 src_data_size)
|
||||
{
|
||||
Assert(src_data_size <= ring_size);
|
||||
{
|
||||
U64 ring_off = ring_pos%ring_size;
|
||||
U64 bytes_before_split = ring_size-ring_off;
|
||||
U64 pre_split_bytes = Min(bytes_before_split, src_data_size);
|
||||
U64 pst_split_bytes = src_data_size-pre_split_bytes;
|
||||
void *pre_split_data = src_data;
|
||||
void *pst_split_data = ((U8 *)src_data + pre_split_bytes);
|
||||
MemoryCopy(ring_base+ring_off, pre_split_data, pre_split_bytes);
|
||||
MemoryCopy(ring_base+0, pst_split_data, pst_split_bytes);
|
||||
}
|
||||
return src_data_size;
|
||||
}
|
||||
|
||||
internal U64
|
||||
ring_read(U8 *ring_base, U64 ring_size, U64 ring_pos, void *dst_data, U64 read_size)
|
||||
{
|
||||
Assert(read_size <= ring_size);
|
||||
{
|
||||
U64 ring_off = ring_pos%ring_size;
|
||||
U64 bytes_before_split = ring_size-ring_off;
|
||||
U64 pre_split_bytes = Min(bytes_before_split, read_size);
|
||||
U64 pst_split_bytes = read_size-pre_split_bytes;
|
||||
MemoryCopy(dst_data, ring_base+ring_off, pre_split_bytes);
|
||||
MemoryCopy((U8 *)dst_data + pre_split_bytes, ring_base+0, pst_split_bytes);
|
||||
}
|
||||
return read_size;
|
||||
}
|
||||
@@ -0,0 +1,800 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef BASE_CORE_H
|
||||
#define BASE_CORE_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Foreign Includes
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Codebase Keywords
|
||||
|
||||
#define internal static
|
||||
#define global static
|
||||
#define local_persist static
|
||||
|
||||
#if COMPILER_MSVC || (COMPILER_CLANG && OS_WINDOWS)
|
||||
# pragma section(".rdata$", read)
|
||||
# define read_only __declspec(allocate(".rdata$"))
|
||||
#elif (COMPILER_CLANG && OS_LINUX)
|
||||
# define read_only __attribute__((section(".rodata")))
|
||||
#else
|
||||
// NOTE(rjf): I don't know of a useful way to do this in GCC land.
|
||||
// __attribute__((section(".rodata"))) looked promising, but it introduces a
|
||||
// strange warning about malformed section attributes, and it doesn't look
|
||||
// like writing to that section reliably produces access violations, strangely
|
||||
// enough. (It does on Clang)
|
||||
# define read_only
|
||||
#endif
|
||||
|
||||
#if COMPILER_MSVC
|
||||
# define thread_static __declspec(thread)
|
||||
#elif COMPILER_CLANG || COMPILER_GCC
|
||||
# define thread_static __thread
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Linkage Keyword Macros
|
||||
|
||||
#if OS_WINDOWS
|
||||
# define shared_function C_LINKAGE __declspec(dllexport)
|
||||
#else
|
||||
# define shared_function C_LINKAGE
|
||||
#endif
|
||||
|
||||
#if LANG_CPP
|
||||
# define C_LINKAGE_BEGIN extern "C"{
|
||||
# define C_LINKAGE_END }
|
||||
# define C_LINKAGE extern "C"
|
||||
#else
|
||||
# define C_LINKAGE_BEGIN
|
||||
# define C_LINKAGE_END
|
||||
# define C_LINKAGE
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Units
|
||||
|
||||
#define KB(n) (((U64)(n)) << 10)
|
||||
#define MB(n) (((U64)(n)) << 20)
|
||||
#define GB(n) (((U64)(n)) << 30)
|
||||
#define TB(n) (((U64)(n)) << 40)
|
||||
#define Thousand(n) ((n)*1000)
|
||||
#define Million(n) ((n)*1000000)
|
||||
#define Billion(n) ((n)*1000000000)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Branch Predictor Hints
|
||||
|
||||
#if defined(__clang__)
|
||||
# define Expect(expr, val) __builtin_expect((expr), (val))
|
||||
#else
|
||||
# define Expect(expr, val) (expr)
|
||||
#endif
|
||||
|
||||
#define Likely(expr) Expect(expr,1)
|
||||
#define Unlikely(expr) Expect(expr,0)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Clamps, Mins, Maxes
|
||||
|
||||
#define Min(A,B) (((A)<(B))?(A):(B))
|
||||
#define Max(A,B) (((A)>(B))?(A):(B))
|
||||
#define ClampTop(A,X) Min(A,X)
|
||||
#define ClampBot(X,B) Max(X,B)
|
||||
#define Clamp(A,X,B) (((X)<(A))?(A):((X)>(B))?(B):(X))
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Type -> Alignment
|
||||
|
||||
#if COMPILER_MSVC
|
||||
# define AlignOf(T) __alignof(T)
|
||||
#elif COMPILER_CLANG
|
||||
# define AlignOf(T) __alignof(T)
|
||||
#elif COMPILER_GCC
|
||||
# define AlignOf(T) __alignof__(T)
|
||||
#else
|
||||
# error AlignOf not defined for this compiler.
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Member Offsets
|
||||
|
||||
#define Member(T,m) (((T*)0)->m)
|
||||
#define OffsetOf(T,m) IntFromPtr(&Member(T,m))
|
||||
#define MemberFromOffset(T,ptr,off) (T)((((U8 *)ptr)+(off)))
|
||||
#define CastFromMember(T,m,ptr) (T*)(((U8*)ptr) - OffsetOf(T,m))
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: For-Loop Construct Macros
|
||||
|
||||
#define DeferLoop(begin, end) for(int _i_ = ((begin), 0); !_i_; _i_ += 1, (end))
|
||||
#define DeferLoopChecked(begin, end) for(int _i_ = 2 * !(begin); (_i_ == 2 ? ((end), 0) : !_i_); _i_ += 1, (end))
|
||||
|
||||
#define EachEnumVal(type, it) type it = (type)0; it < type##_COUNT; it = (type)(it+1)
|
||||
#define EachNonZeroEnumVal(type, it) type it = (type)1; it < type##_COUNT; it = (type)(it+1)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Memory Operation Macros
|
||||
|
||||
#define MemoryCopy(dst, src, size) memmove((dst), (src), (size))
|
||||
#define MemorySet(dst, byte, size) memset((dst), (byte), (size))
|
||||
#define MemoryCompare(a, b, size) memcmp((a), (b), (size))
|
||||
#define MemoryStrlen(ptr) strlen(ptr)
|
||||
|
||||
#define MemoryCopyStruct(d,s) MemoryCopy((d),(s),sizeof(*(d)))
|
||||
#define MemoryCopyArray(d,s) MemoryCopy((d),(s),sizeof(d))
|
||||
#define MemoryCopyTyped(d,s,c) MemoryCopy((d),(s),sizeof(*(d))*(c))
|
||||
|
||||
#define MemoryZero(s,z) memset((s),0,(z))
|
||||
#define MemoryZeroStruct(s) MemoryZero((s),sizeof(*(s)))
|
||||
#define MemoryZeroArray(a) MemoryZero((a),sizeof(a))
|
||||
#define MemoryZeroTyped(m,c) MemoryZero((m),sizeof(*(m))*(c))
|
||||
|
||||
#define MemoryMatch(a,b,z) (MemoryCompare((a),(b),(z)) == 0)
|
||||
#define MemoryMatchStruct(a,b) MemoryMatch((a),(b),sizeof(*(a)))
|
||||
#define MemoryMatchArray(a,b) MemoryMatch((a),(b),sizeof(a))
|
||||
|
||||
#define MemoryRead(T,p,e) ( ((p)+sizeof(T)<=(e))?(*(T*)(p)):(0) )
|
||||
#define MemoryConsume(T,p,e) ( ((p)+sizeof(T)<=(e))?((p)+=sizeof(T),*(T*)((p)-sizeof(T))):((p)=(e),0) )
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Asserts
|
||||
|
||||
#if COMPILER_MSVC
|
||||
# define Trap() __debugbreak()
|
||||
#elif COMPILER_CLANG || COMPILER_GCC
|
||||
# define Trap() __builtin_trap()
|
||||
#else
|
||||
# error Unknown trap intrinsic for this compiler.
|
||||
#endif
|
||||
|
||||
#define AssertAlways(x) do{if(!(x)) {Trap();}}while(0)
|
||||
#if BUILD_DEBUG
|
||||
# define Assert(x) AssertAlways(x)
|
||||
#else
|
||||
# define Assert(x) (void)(x)
|
||||
#endif
|
||||
#define InvalidPath Assert(!"Invalid Path!")
|
||||
#define NotImplemented Assert(!"Not Implemented!")
|
||||
#define NoOp ((void)0)
|
||||
#define StaticAssert(C, ID) global U8 Glue(ID, __LINE__)[(C)?1:-1]
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Atomic Operations
|
||||
|
||||
#if OS_WINDOWS
|
||||
# include <windows.h>
|
||||
# include <tmmintrin.h>
|
||||
# include <wmmintrin.h>
|
||||
# include <intrin.h>
|
||||
# if ARCH_X64
|
||||
# define ins_atomic_u64_eval(x) InterlockedAdd64((volatile __int64 *)(x), 0)
|
||||
# define ins_atomic_u64_inc_eval(x) InterlockedIncrement64((volatile __int64 *)(x))
|
||||
# define ins_atomic_u64_dec_eval(x) InterlockedDecrement64((volatile __int64 *)(x))
|
||||
# define ins_atomic_u64_eval_assign(x,c) InterlockedExchange64((volatile __int64 *)(x),(c))
|
||||
# define ins_atomic_u64_add_eval(x,c) InterlockedAdd64((volatile __int64 *)(x), c)
|
||||
# define ins_atomic_u64_eval_cond_assign(x,k,c) InterlockedCompareExchange64((volatile __int64 *)(x),(k),(c))
|
||||
# define ins_atomic_u32_eval(x,c) InterlockedAdd((volatile LONG *)(x), 0)
|
||||
# define ins_atomic_u32_eval_assign(x,c) InterlockedExchange((volatile LONG *)(x),(c))
|
||||
# define ins_atomic_u32_eval_cond_assign(x,k,c) InterlockedCompareExchange((volatile LONG *)(x),(k),(c))
|
||||
# define ins_atomic_ptr_eval_assign(x,c) (void*)ins_atomic_u64_eval_assign((volatile __int64 *)(x), (__int64)(c))
|
||||
# else
|
||||
# error Atomic intrinsics not defined for this operating system / architecture combination.
|
||||
# endif
|
||||
#elif OS_LINUX
|
||||
# if ARCH_X64
|
||||
# define ins_atomic_u64_inc_eval(x) __sync_fetch_and_add((volatile U64 *)(x), 1)
|
||||
# else
|
||||
# error Atomic intrinsics not defined for this operating system / architecture combination.
|
||||
# endif
|
||||
#else
|
||||
# error Atomic intrinsics not defined for this operating system.
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Linked List Building Macros
|
||||
|
||||
//- rjf: linked list macro helpers
|
||||
#define CheckNil(nil,p) ((p) == 0 || (p) == nil)
|
||||
#define SetNil(nil,p) ((p) = nil)
|
||||
|
||||
//- rjf: doubly-linked-lists
|
||||
#define DLLInsert_NPZ(nil,f,l,p,n,next,prev) (CheckNil(nil,f) ? \
|
||||
((f) = (l) = (n), SetNil(nil,(n)->next), SetNil(nil,(n)->prev)) :\
|
||||
CheckNil(nil,p) ? \
|
||||
((n)->next = (f), (f)->prev = (n), (f) = (n), SetNil(nil,(n)->prev)) :\
|
||||
((p)==(l)) ? \
|
||||
((l)->next = (n), (n)->prev = (l), (l) = (n), SetNil(nil, (n)->next)) :\
|
||||
(((!CheckNil(nil,p) && CheckNil(nil,(p)->next)) ? (0) : ((p)->next->prev = (n))), ((n)->next = (p)->next), ((p)->next = (n)), ((n)->prev = (p))))
|
||||
#define DLLPushBack_NPZ(nil,f,l,n,next,prev) DLLInsert_NPZ(nil,f,l,l,n,next,prev)
|
||||
#define DLLPushFront_NPZ(nil,f,l,n,next,prev) DLLInsert_NPZ(nil,l,f,f,n,prev,next)
|
||||
#define DLLRemove_NPZ(nil,f,l,n,next,prev) (((n) == (f) ? (f) = (n)->next : (0)),\
|
||||
((n) == (l) ? (l) = (l)->prev : (0)),\
|
||||
(CheckNil(nil,(n)->prev) ? (0) :\
|
||||
((n)->prev->next = (n)->next)),\
|
||||
(CheckNil(nil,(n)->next) ? (0) :\
|
||||
((n)->next->prev = (n)->prev)))
|
||||
|
||||
//- rjf: singly-linked, doubly-headed lists (queues)
|
||||
#define SLLQueuePush_NZ(nil,f,l,n,next) (CheckNil(nil,f)?\
|
||||
((f)=(l)=(n),SetNil(nil,(n)->next)):\
|
||||
((l)->next=(n),(l)=(n),SetNil(nil,(n)->next)))
|
||||
#define SLLQueuePushFront_NZ(nil,f,l,n,next) (CheckNil(nil,f)?\
|
||||
((f)=(l)=(n),SetNil(nil,(n)->next)):\
|
||||
((n)->next=(f),(f)=(n)))
|
||||
#define SLLQueuePop_NZ(nil,f,l,next) ((f)==(l)?\
|
||||
(SetNil(nil,f),SetNil(nil,l)):\
|
||||
((f)=(f)->next))
|
||||
|
||||
//- rjf: singly-linked, singly-headed lists (stacks)
|
||||
#define SLLStackPush_N(f,n,next) ((n)->next=(f), (f)=(n))
|
||||
#define SLLStackPop_N(f,next) ((f)=(f)->next)
|
||||
|
||||
//- rjf: doubly-linked-list helpers
|
||||
#define DLLInsert_NP(f,l,p,n,next,prev) DLLInsert_NPZ(0,f,l,p,n,next,prev)
|
||||
#define DLLPushBack_NP(f,l,n,next,prev) DLLPushBack_NPZ(0,f,l,n,next,prev)
|
||||
#define DLLPushFront_NP(f,l,n,next,prev) DLLPushFront_NPZ(0,f,l,n,next,prev)
|
||||
#define DLLRemove_NP(f,l,n,next,prev) DLLRemove_NPZ(0,f,l,n,next,prev)
|
||||
#define DLLInsert(f,l,p,n) DLLInsert_NPZ(0,f,l,p,n,next,prev)
|
||||
#define DLLPushBack(f,l,n) DLLPushBack_NPZ(0,f,l,n,next,prev)
|
||||
#define DLLPushFront(f,l,n) DLLPushFront_NPZ(0,f,l,n,next,prev)
|
||||
#define DLLRemove(f,l,n) DLLRemove_NPZ(0,f,l,n,next,prev)
|
||||
|
||||
//- rjf: singly-linked, doubly-headed list helpers
|
||||
#define SLLQueuePush_N(f,l,n,next) SLLQueuePush_NZ(0,f,l,n,next)
|
||||
#define SLLQueuePushFront_N(f,l,n,next) SLLQueuePushFront_NZ(0,f,l,n,next)
|
||||
#define SLLQueuePop_N(f,l,next) SLLQueuePop_NZ(0,f,l,next)
|
||||
#define SLLQueuePush(f,l,n) SLLQueuePush_NZ(0,f,l,n,next)
|
||||
#define SLLQueuePushFront(f,l,n) SLLQueuePushFront_NZ(0,f,l,n,next)
|
||||
#define SLLQueuePop(f,l) SLLQueuePop_NZ(0,f,l,next)
|
||||
|
||||
//- rjf: singly-linked, singly-headed list helpers
|
||||
#define SLLStackPush(f,n) SLLStackPush_N(f,n,next)
|
||||
#define SLLStackPop(f) SLLStackPop_N(f,next)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Address Sanitizer Markup
|
||||
|
||||
#if COMPILER_MSVC
|
||||
# if defined(__SANITIZE_ADDRESS__)
|
||||
# define ASAN_ENABLED 1
|
||||
# define NO_ASAN __declspec(no_sanitize_address)
|
||||
# else
|
||||
# define NO_ASAN
|
||||
# endif
|
||||
#elif COMPILER_CLANG
|
||||
# if defined(__has_feature)
|
||||
# if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
|
||||
# define ASAN_ENABLED 1
|
||||
# endif
|
||||
# endif
|
||||
# define NO_ASAN __attribute__((no_sanitize("address")))
|
||||
#else
|
||||
# define NO_ASAN
|
||||
#endif
|
||||
|
||||
#if ASAN_ENABLED
|
||||
#pragma comment(lib, "clang_rt.asan-x86_64.lib")
|
||||
C_LINKAGE void __asan_poison_memory_region(void const volatile *addr, size_t size);
|
||||
C_LINKAGE void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
|
||||
# define AsanPoisonMemoryRegion(addr, size) __asan_poison_memory_region((addr), (size))
|
||||
# define AsanUnpoisonMemoryRegion(addr, size) __asan_unpoison_memory_region((addr), (size))
|
||||
#else
|
||||
# define AsanPoisonMemoryRegion(addr, size) ((void)(addr), (void)(size))
|
||||
# define AsanUnpoisonMemoryRegion(addr, size) ((void)(addr), (void)(size))
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Misc. Helper Macros
|
||||
|
||||
#define Stringify_(S) #S
|
||||
#define Stringify(S) Stringify_(S)
|
||||
|
||||
#define Glue_(A,B) A##B
|
||||
#define Glue(A,B) Glue_(A,B)
|
||||
|
||||
#define ArrayCount(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
#define CeilIntegerDiv(a,b) (((a) + (b) - 1)/(b))
|
||||
|
||||
#define Swap(T,a,b) do{T t__ = a; a = b; b = t__;}while(0)
|
||||
|
||||
#if ARCH_64BIT
|
||||
# define IntFromPtr(ptr) ((U64)(ptr))
|
||||
#elif ARCH_32BIT
|
||||
# define IntFromPtr(ptr) ((U32)(ptr))
|
||||
#else
|
||||
# error Missing pointer-to-integer cast for this architecture.
|
||||
#endif
|
||||
#define PtrFromInt(i) (void*)((U8*)0 + (i))
|
||||
|
||||
#define Compose64Bit(a,b) ((((U64)a) << 32) | ((U64)b));
|
||||
#define AlignPow2(x,b) (((x) + (b) - 1)&(~((b) - 1)))
|
||||
#define AlignDownPow2(x,b) ((x)&(~((b) - 1)))
|
||||
#define AlignPadPow2(x,b) ((0-(x)) & ((b) - 1))
|
||||
#define IsPow2(x) ((x)!=0 && ((x)&((x)-1))==0)
|
||||
#define IsPow2OrZero(x) ((((x) - 1)&(x)) == 0)
|
||||
|
||||
#define ExtractBit(word, idx) (((word) >> (idx)) & 1)
|
||||
|
||||
#if LANG_CPP
|
||||
# define zero_struct {}
|
||||
#else
|
||||
# define zero_struct {0}
|
||||
#endif
|
||||
|
||||
#if COMPILER_MSVC && COMPILER_MSVC_YEAR < 2015
|
||||
# define this_function_name "unknown"
|
||||
#else
|
||||
# define this_function_name __func__
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Base Types
|
||||
|
||||
typedef uint8_t U8;
|
||||
typedef uint16_t U16;
|
||||
typedef uint32_t U32;
|
||||
typedef uint64_t U64;
|
||||
typedef int8_t S8;
|
||||
typedef int16_t S16;
|
||||
typedef int32_t S32;
|
||||
typedef int64_t S64;
|
||||
typedef S8 B8;
|
||||
typedef S16 B16;
|
||||
typedef S32 B32;
|
||||
typedef S64 B64;
|
||||
typedef float F32;
|
||||
typedef double F64;
|
||||
typedef void VoidProc(void);
|
||||
typedef struct U128 U128;
|
||||
struct U128
|
||||
{
|
||||
U64 u64[2];
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Basic Types & Spaces
|
||||
|
||||
typedef enum Dimension
|
||||
{
|
||||
Dimension_X,
|
||||
Dimension_Y,
|
||||
Dimension_Z,
|
||||
Dimension_W,
|
||||
}
|
||||
Dimension;
|
||||
|
||||
typedef enum Side
|
||||
{
|
||||
Side_Invalid = -1,
|
||||
Side_Min,
|
||||
Side_Max,
|
||||
Side_COUNT,
|
||||
}
|
||||
Side;
|
||||
#define side_flip(s) ((Side)(!(s)))
|
||||
|
||||
typedef enum Axis2
|
||||
{
|
||||
Axis2_Invalid = -1,
|
||||
Axis2_X,
|
||||
Axis2_Y,
|
||||
Axis2_COUNT,
|
||||
}
|
||||
Axis2;
|
||||
#define axis2_flip(a) ((Axis2)(!(a)))
|
||||
|
||||
typedef enum Corner
|
||||
{
|
||||
Corner_Invalid = -1,
|
||||
Corner_00,
|
||||
Corner_01,
|
||||
Corner_10,
|
||||
Corner_11,
|
||||
Corner_COUNT
|
||||
}
|
||||
Corner;
|
||||
|
||||
typedef enum Dir2
|
||||
{
|
||||
Dir2_Invalid = -1,
|
||||
Dir2_Left,
|
||||
Dir2_Up,
|
||||
Dir2_Right,
|
||||
Dir2_Down,
|
||||
Dir2_COUNT
|
||||
}
|
||||
Dir2;
|
||||
#define axis2_from_dir2(d) (((d) & 1) ? Axis2_Y : Axis2_X)
|
||||
#define side_from_dir2(d) (((d) < Dir2_Right) ? Side_Min : Side_Max)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Toolchain/Environment Enums
|
||||
|
||||
typedef enum OperatingSystem
|
||||
{
|
||||
OperatingSystem_Null,
|
||||
OperatingSystem_Windows,
|
||||
OperatingSystem_Linux,
|
||||
OperatingSystem_Mac,
|
||||
OperatingSystem_COUNT,
|
||||
}
|
||||
OperatingSystem;
|
||||
|
||||
typedef enum Architecture
|
||||
{
|
||||
Architecture_Null,
|
||||
Architecture_x64,
|
||||
Architecture_x86,
|
||||
Architecture_arm64,
|
||||
Architecture_arm32,
|
||||
Architecture_COUNT,
|
||||
}
|
||||
Architecture;
|
||||
|
||||
typedef enum Compiler
|
||||
{
|
||||
Compiler_Null,
|
||||
Compiler_msvc,
|
||||
Compiler_gcc,
|
||||
Compiler_clang,
|
||||
Compiler_COUNT,
|
||||
}
|
||||
Compiler;
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Text 2D Coordinates & Ranges
|
||||
|
||||
typedef struct TxtPt TxtPt;
|
||||
struct TxtPt
|
||||
{
|
||||
S64 line;
|
||||
S64 column;
|
||||
};
|
||||
|
||||
typedef struct TxtRng TxtRng;
|
||||
struct TxtRng
|
||||
{
|
||||
TxtPt min;
|
||||
TxtPt max;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ NOTE(allen): Constants
|
||||
|
||||
global U32 sign32 = 0x80000000;
|
||||
global U32 exponent32 = 0x7F800000;
|
||||
global U32 mantissa32 = 0x007FFFFF;
|
||||
|
||||
global F32 big_golden32 = 1.61803398875f;
|
||||
global F32 small_golden32 = 0.61803398875f;
|
||||
|
||||
global F32 pi32 = 3.1415926535897f;
|
||||
|
||||
global F64 machine_epsilon64 = 4.94065645841247e-324;
|
||||
|
||||
global U64 max_U64 = 0xffffffffffffffffull;
|
||||
global U32 max_U32 = 0xffffffff;
|
||||
global U16 max_U16 = 0xffff;
|
||||
global U8 max_U8 = 0xff;
|
||||
|
||||
global S64 max_S64 = (S64)0x7fffffffffffffffull;
|
||||
global S32 max_S32 = (S32)0x7fffffff;
|
||||
global S16 max_S16 = (S16)0x7fff;
|
||||
global S8 max_S8 = (S8)0x7f;
|
||||
|
||||
global S64 min_S64 = (S64)0xffffffffffffffffull;
|
||||
global S32 min_S32 = (S32)0xffffffff;
|
||||
global S16 min_S16 = (S16)0xffff;
|
||||
global S8 min_S8 = (S8)0xff;
|
||||
|
||||
global const U32 bitmask1 = 0x00000001;
|
||||
global const U32 bitmask2 = 0x00000003;
|
||||
global const U32 bitmask3 = 0x00000007;
|
||||
global const U32 bitmask4 = 0x0000000f;
|
||||
global const U32 bitmask5 = 0x0000001f;
|
||||
global const U32 bitmask6 = 0x0000003f;
|
||||
global const U32 bitmask7 = 0x0000007f;
|
||||
global const U32 bitmask8 = 0x000000ff;
|
||||
global const U32 bitmask9 = 0x000001ff;
|
||||
global const U32 bitmask10 = 0x000003ff;
|
||||
global const U32 bitmask11 = 0x000007ff;
|
||||
global const U32 bitmask12 = 0x00000fff;
|
||||
global const U32 bitmask13 = 0x00001fff;
|
||||
global const U32 bitmask14 = 0x00003fff;
|
||||
global const U32 bitmask15 = 0x00007fff;
|
||||
global const U32 bitmask16 = 0x0000ffff;
|
||||
global const U32 bitmask17 = 0x0001ffff;
|
||||
global const U32 bitmask18 = 0x0003ffff;
|
||||
global const U32 bitmask19 = 0x0007ffff;
|
||||
global const U32 bitmask20 = 0x000fffff;
|
||||
global const U32 bitmask21 = 0x001fffff;
|
||||
global const U32 bitmask22 = 0x003fffff;
|
||||
global const U32 bitmask23 = 0x007fffff;
|
||||
global const U32 bitmask24 = 0x00ffffff;
|
||||
global const U32 bitmask25 = 0x01ffffff;
|
||||
global const U32 bitmask26 = 0x03ffffff;
|
||||
global const U32 bitmask27 = 0x07ffffff;
|
||||
global const U32 bitmask28 = 0x0fffffff;
|
||||
global const U32 bitmask29 = 0x1fffffff;
|
||||
global const U32 bitmask30 = 0x3fffffff;
|
||||
global const U32 bitmask31 = 0x7fffffff;
|
||||
global const U32 bitmask32 = 0xffffffff;
|
||||
|
||||
global const U64 bitmask33 = 0x00000001ffffffffull;
|
||||
global const U64 bitmask34 = 0x00000003ffffffffull;
|
||||
global const U64 bitmask35 = 0x00000007ffffffffull;
|
||||
global const U64 bitmask36 = 0x0000000fffffffffull;
|
||||
global const U64 bitmask37 = 0x0000001fffffffffull;
|
||||
global const U64 bitmask38 = 0x0000003fffffffffull;
|
||||
global const U64 bitmask39 = 0x0000007fffffffffull;
|
||||
global const U64 bitmask40 = 0x000000ffffffffffull;
|
||||
global const U64 bitmask41 = 0x000001ffffffffffull;
|
||||
global const U64 bitmask42 = 0x000003ffffffffffull;
|
||||
global const U64 bitmask43 = 0x000007ffffffffffull;
|
||||
global const U64 bitmask44 = 0x00000fffffffffffull;
|
||||
global const U64 bitmask45 = 0x00001fffffffffffull;
|
||||
global const U64 bitmask46 = 0x00003fffffffffffull;
|
||||
global const U64 bitmask47 = 0x00007fffffffffffull;
|
||||
global const U64 bitmask48 = 0x0000ffffffffffffull;
|
||||
global const U64 bitmask49 = 0x0001ffffffffffffull;
|
||||
global const U64 bitmask50 = 0x0003ffffffffffffull;
|
||||
global const U64 bitmask51 = 0x0007ffffffffffffull;
|
||||
global const U64 bitmask52 = 0x000fffffffffffffull;
|
||||
global const U64 bitmask53 = 0x001fffffffffffffull;
|
||||
global const U64 bitmask54 = 0x003fffffffffffffull;
|
||||
global const U64 bitmask55 = 0x007fffffffffffffull;
|
||||
global const U64 bitmask56 = 0x00ffffffffffffffull;
|
||||
global const U64 bitmask57 = 0x01ffffffffffffffull;
|
||||
global const U64 bitmask58 = 0x03ffffffffffffffull;
|
||||
global const U64 bitmask59 = 0x07ffffffffffffffull;
|
||||
global const U64 bitmask60 = 0x0fffffffffffffffull;
|
||||
global const U64 bitmask61 = 0x1fffffffffffffffull;
|
||||
global const U64 bitmask62 = 0x3fffffffffffffffull;
|
||||
global const U64 bitmask63 = 0x7fffffffffffffffull;
|
||||
global const U64 bitmask64 = 0xffffffffffffffffull;
|
||||
|
||||
global const U32 bit1 = (1<<0);
|
||||
global const U32 bit2 = (1<<1);
|
||||
global const U32 bit3 = (1<<2);
|
||||
global const U32 bit4 = (1<<3);
|
||||
global const U32 bit5 = (1<<4);
|
||||
global const U32 bit6 = (1<<5);
|
||||
global const U32 bit7 = (1<<6);
|
||||
global const U32 bit8 = (1<<7);
|
||||
global const U32 bit9 = (1<<8);
|
||||
global const U32 bit10 = (1<<9);
|
||||
global const U32 bit11 = (1<<10);
|
||||
global const U32 bit12 = (1<<11);
|
||||
global const U32 bit13 = (1<<12);
|
||||
global const U32 bit14 = (1<<13);
|
||||
global const U32 bit15 = (1<<14);
|
||||
global const U32 bit16 = (1<<15);
|
||||
global const U32 bit17 = (1<<16);
|
||||
global const U32 bit18 = (1<<17);
|
||||
global const U32 bit19 = (1<<18);
|
||||
global const U32 bit20 = (1<<19);
|
||||
global const U32 bit21 = (1<<20);
|
||||
global const U32 bit22 = (1<<21);
|
||||
global const U32 bit23 = (1<<22);
|
||||
global const U32 bit24 = (1<<23);
|
||||
global const U32 bit25 = (1<<24);
|
||||
global const U32 bit26 = (1<<25);
|
||||
global const U32 bit27 = (1<<26);
|
||||
global const U32 bit28 = (1<<27);
|
||||
global const U32 bit29 = (1<<28);
|
||||
global const U32 bit30 = (1<<29);
|
||||
global const U32 bit31 = (1<<30);
|
||||
global const U32 bit32 = (1<<31);
|
||||
|
||||
global const U64 bit33 = (1ull<<32);
|
||||
global const U64 bit34 = (1ull<<33);
|
||||
global const U64 bit35 = (1ull<<34);
|
||||
global const U64 bit36 = (1ull<<35);
|
||||
global const U64 bit37 = (1ull<<36);
|
||||
global const U64 bit38 = (1ull<<37);
|
||||
global const U64 bit39 = (1ull<<38);
|
||||
global const U64 bit40 = (1ull<<39);
|
||||
global const U64 bit41 = (1ull<<40);
|
||||
global const U64 bit42 = (1ull<<41);
|
||||
global const U64 bit43 = (1ull<<42);
|
||||
global const U64 bit44 = (1ull<<43);
|
||||
global const U64 bit45 = (1ull<<44);
|
||||
global const U64 bit46 = (1ull<<45);
|
||||
global const U64 bit47 = (1ull<<46);
|
||||
global const U64 bit48 = (1ull<<47);
|
||||
global const U64 bit49 = (1ull<<48);
|
||||
global const U64 bit50 = (1ull<<49);
|
||||
global const U64 bit51 = (1ull<<50);
|
||||
global const U64 bit52 = (1ull<<51);
|
||||
global const U64 bit53 = (1ull<<52);
|
||||
global const U64 bit54 = (1ull<<53);
|
||||
global const U64 bit55 = (1ull<<54);
|
||||
global const U64 bit56 = (1ull<<55);
|
||||
global const U64 bit57 = (1ull<<56);
|
||||
global const U64 bit58 = (1ull<<57);
|
||||
global const U64 bit59 = (1ull<<58);
|
||||
global const U64 bit60 = (1ull<<59);
|
||||
global const U64 bit61 = (1ull<<60);
|
||||
global const U64 bit62 = (1ull<<61);
|
||||
global const U64 bit63 = (1ull<<62);
|
||||
global const U64 bit64 = (1ull<<63);
|
||||
|
||||
////////////////////////////////
|
||||
//~ allen: Time
|
||||
|
||||
typedef enum WeekDay
|
||||
{
|
||||
WeekDay_Sun,
|
||||
WeekDay_Mon,
|
||||
WeekDay_Tue,
|
||||
WeekDay_Wed,
|
||||
WeekDay_Thu,
|
||||
WeekDay_Fri,
|
||||
WeekDay_Sat,
|
||||
WeekDay_COUNT,
|
||||
}
|
||||
WeekDay;
|
||||
|
||||
typedef enum Month
|
||||
{
|
||||
Month_Jan,
|
||||
Month_Feb,
|
||||
Month_Mar,
|
||||
Month_Apr,
|
||||
Month_May,
|
||||
Month_Jun,
|
||||
Month_Jul,
|
||||
Month_Aug,
|
||||
Month_Sep,
|
||||
Month_Oct,
|
||||
Month_Nov,
|
||||
Month_Dec,
|
||||
Month_COUNT,
|
||||
}
|
||||
Month;
|
||||
|
||||
typedef struct DateTime DateTime;
|
||||
struct DateTime
|
||||
{
|
||||
U16 micro_sec; // [0,999]
|
||||
U16 msec; // [0,999]
|
||||
U16 sec; // [0,60]
|
||||
U16 min; // [0,59]
|
||||
U16 hour; // [0,24]
|
||||
U16 day; // [0,30]
|
||||
union
|
||||
{
|
||||
WeekDay week_day;
|
||||
U32 wday;
|
||||
};
|
||||
union
|
||||
{
|
||||
Month month;
|
||||
U32 mon;
|
||||
};
|
||||
U32 year; // 1 = 1 CE, 0 = 1 BC
|
||||
};
|
||||
|
||||
typedef U64 DenseTime;
|
||||
|
||||
////////////////////////////////
|
||||
//~ allen: Files
|
||||
|
||||
typedef U32 FilePropertyFlags;
|
||||
enum
|
||||
{
|
||||
FilePropertyFlag_IsFolder = (1 << 0),
|
||||
};
|
||||
|
||||
typedef struct FileProperties FileProperties;
|
||||
struct FileProperties
|
||||
{
|
||||
U64 size;
|
||||
DenseTime modified;
|
||||
DenseTime created;
|
||||
FilePropertyFlags flags;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Safe Casts
|
||||
|
||||
internal U16 safe_cast_u16(U32 x);
|
||||
internal U32 safe_cast_u32(U64 x);
|
||||
internal S32 safe_cast_s32(S64 x);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Large Base Type Functions
|
||||
|
||||
internal U128 u128_zero(void);
|
||||
internal U128 u128_make(U64 v0, U64 v1);
|
||||
internal B32 u128_match(U128 a, U128 b);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Bit Patterns
|
||||
|
||||
internal U32 u32_from_u64_saturate(U64 x);
|
||||
internal U64 u64_up_to_pow2(U64 x);
|
||||
internal S32 extend_sign32(U32 x, U32 size);
|
||||
internal S64 extend_sign64(U64 x, U64 size);
|
||||
|
||||
internal F32 inf32(void);
|
||||
internal F32 neg_inf32(void);
|
||||
|
||||
internal U16 bswap_u16(U16 x);
|
||||
internal U32 bswap_u32(U32 x);
|
||||
internal U64 bswap_u64(U64 x);
|
||||
|
||||
internal U64 count_bits_set16(U16 val);
|
||||
internal U64 count_bits_set32(U32 val);
|
||||
internal U64 count_bits_set64(U64 val);
|
||||
|
||||
internal U64 ctz32(U32 val);
|
||||
internal U64 ctz64(U64 val);
|
||||
internal U64 clz32(U32 val);
|
||||
internal U64 clz64(U64 val);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Enum -> Sign
|
||||
|
||||
internal S32 sign_from_side_S32(Side side);
|
||||
internal F32 sign_from_side_F32(Side side);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Memory Functions
|
||||
|
||||
internal B32 memory_is_zero(void *ptr, U64 size);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Text 2D Coordinate/Range Functions
|
||||
|
||||
internal TxtPt txt_pt(S64 line, S64 column);
|
||||
internal B32 txt_pt_match(TxtPt a, TxtPt b);
|
||||
internal B32 txt_pt_less_than(TxtPt a, TxtPt b);
|
||||
internal TxtPt txt_pt_min(TxtPt a, TxtPt b);
|
||||
internal TxtPt txt_pt_max(TxtPt a, TxtPt b);
|
||||
internal TxtRng txt_rng(TxtPt min, TxtPt max);
|
||||
internal TxtRng txt_rng_intersect(TxtRng a, TxtRng b);
|
||||
internal TxtRng txt_rng_union(TxtRng a, TxtRng b);
|
||||
internal B32 txt_rng_contains(TxtRng r, TxtPt pt);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Toolchain/Environment Enum Functions
|
||||
|
||||
internal U64 bit_size_from_arch(Architecture arch);
|
||||
internal U64 max_instruction_size_from_arch(Architecture arch);
|
||||
|
||||
internal OperatingSystem operating_system_from_context(void);
|
||||
internal Architecture architecture_from_context(void);
|
||||
internal Compiler compiler_from_context(void);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Time Functions
|
||||
|
||||
internal DenseTime dense_time_from_date_time(DateTime date_time);
|
||||
internal DateTime date_time_from_dense_time(DenseTime time);
|
||||
internal DateTime date_time_from_micro_seconds(U64 time);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Non-Fancy Ring Buffer Reads/Writes
|
||||
|
||||
internal U64 ring_write(U8 *ring_base, U64 ring_size, U64 ring_pos, void *src_data, U64 src_data_size);
|
||||
internal U64 ring_read(U8 *ring_base, U64 ring_size, U64 ring_pos, void *dst_data, U64 read_size);
|
||||
#define ring_write_struct(ring_base, ring_size, ring_pos, ptr) ring_write((ring_base), (ring_size), (ring_pos), (ptr), sizeof(*(ptr)))
|
||||
#define ring_read_struct(ring_base, ring_size, ring_pos, ptr) ring_read((ring_base), (ring_size), (ring_pos), (ptr), sizeof(*(ptr)))
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Sorts
|
||||
|
||||
#define quick_sort(ptr, count, element_size, cmp_function) qsort((ptr), (count), (element_size), (int (*)(const void *, const void *))(cmp_function))
|
||||
|
||||
#endif // BASE_CORE_H
|
||||
@@ -0,0 +1,92 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
internal void
|
||||
main_thread_base_entry_point(void (*entry_point)(CmdLine *cmdline), char **arguments, U64 arguments_count)
|
||||
{
|
||||
#if PROFILE_TELEMETRY
|
||||
local_persist U8 tm_data[MB(64)];
|
||||
tmLoadLibrary(TM_RELEASE);
|
||||
tmSetMaxThreadCount(256);
|
||||
tmInitialize(sizeof(tm_data), (char *)tm_data);
|
||||
#endif
|
||||
ThreadNameF("[main thread]");
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
String8List command_line_argument_strings = os_string_list_from_argcv(scratch.arena, (int)arguments_count, arguments);
|
||||
CmdLine cmdline = cmd_line_from_string_list(scratch.arena, command_line_argument_strings);
|
||||
B32 capture = cmd_line_has_flag(&cmdline, str8_lit("capture"));
|
||||
if(capture)
|
||||
{
|
||||
ProfBeginCapture(arguments[0]);
|
||||
}
|
||||
#if defined(TASK_SYSTEM_H) && !defined(TS_INIT_MANUAL)
|
||||
ts_init();
|
||||
#endif
|
||||
#if defined(HASH_STORE_H) && !defined(HS_INIT_MANUAL)
|
||||
hs_init();
|
||||
#endif
|
||||
#if defined(FILE_STREAM_H) && !defined(FS_INIT_MANUAL)
|
||||
fs_init();
|
||||
#endif
|
||||
#if defined(TEXT_CACHE_H) && !defined(TXT_INIT_MANUAL)
|
||||
txt_init();
|
||||
#endif
|
||||
#if defined(MUTABLE_TEXT_H) && !defined(MTX_INIT_MANUAL)
|
||||
mtx_init();
|
||||
#endif
|
||||
#if defined(DASM_CACHE_H) && !defined(DASM_INIT_MANUAL)
|
||||
dasm_init();
|
||||
#endif
|
||||
#if defined(DI_H) && !defined(DI_INIT_MANUAL)
|
||||
di_init();
|
||||
#endif
|
||||
#if defined(FUZZY_SEARCH_H) && !defined(FZY_INIT_MANUAL)
|
||||
fzy_init();
|
||||
#endif
|
||||
#if defined(DEMON_CORE_H) && !defined(DMN_INIT_MANUAL)
|
||||
dmn_init();
|
||||
#endif
|
||||
#if defined(CTRL_CORE_H) && !defined(CTRL_INIT_MANUAL)
|
||||
ctrl_init();
|
||||
#endif
|
||||
#if defined(OS_GRAPHICAL_H) && !defined(OS_GFX_INIT_MANUAL)
|
||||
os_gfx_init();
|
||||
#endif
|
||||
#if defined(FONT_PROVIDER_H) && !defined(FP_INIT_MANUAL)
|
||||
fp_init();
|
||||
#endif
|
||||
#if defined(RENDER_CORE_H) && !defined(R_INIT_MANUAL)
|
||||
r_init(&cmdline);
|
||||
#endif
|
||||
#if defined(TEXTURE_CACHE_H) && !defined(TEX_INIT_MANUAL)
|
||||
tex_init();
|
||||
#endif
|
||||
#if defined(GEO_CACHE_H) && !defined(GEO_INIT_MANUAL)
|
||||
geo_init();
|
||||
#endif
|
||||
#if defined(FONT_CACHE_H) && !defined(F_INIT_MANUAL)
|
||||
f_init();
|
||||
#endif
|
||||
#if defined(DF_CORE_H) && !defined(DF_INIT_MANUAL)
|
||||
DF_StateDeltaHistory *hist = df_state_delta_history_alloc();
|
||||
df_core_init(&cmdline, hist);
|
||||
#endif
|
||||
#if defined(DF_GFX_H) && !defined(DF_GFX_INIT_MANUAL)
|
||||
df_gfx_init(update_and_render, df_state_delta_history());
|
||||
#endif
|
||||
entry_point(&cmdline);
|
||||
if(capture)
|
||||
{
|
||||
ProfEndCapture();
|
||||
}
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
internal void
|
||||
supplement_thread_base_entry_point(void (*entry_point)(void *params), void *params)
|
||||
{
|
||||
TCTX tctx;
|
||||
tctx_init_and_equip(&tctx);
|
||||
entry_point(params);
|
||||
tctx_release();
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef BASE_ENTRY_POINT_H
|
||||
#define BASE_ENTRY_POINT_H
|
||||
|
||||
internal void main_thread_base_entry_point(void (*entry_point)(CmdLine *cmdline), char **arguments, U64 arguments_count);
|
||||
internal void supplement_thread_base_entry_point(void (*entry_point)(void *params), void *params);
|
||||
|
||||
#endif // BASE_ENTRY_POINT_H
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Base Includes
|
||||
|
||||
#undef RADDBG_LAYER_COLOR
|
||||
#define RADDBG_LAYER_COLOR 0.20f, 0.60f, 0.80f
|
||||
|
||||
#include "metagen_base_core.c"
|
||||
#include "metagen_base_profile.c"
|
||||
#include "metagen_base_arena.c"
|
||||
#include "metagen_base_math.c"
|
||||
#include "metagen_base_strings.c"
|
||||
#include "metagen_base_thread_context.c"
|
||||
#include "metagen_base_command_line.c"
|
||||
#include "metagen_base_markup.c"
|
||||
#include "metagen_base_log.c"
|
||||
#include "metagen_base_entry_point.c"
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef BASE_INC_H
|
||||
#define BASE_INC_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Base Includes
|
||||
|
||||
#include "metagen_base_context_cracking.h"
|
||||
|
||||
#include "metagen_base_core.h"
|
||||
#include "metagen_base_profile.h"
|
||||
#include "metagen_base_arena.h"
|
||||
#include "metagen_base_math.h"
|
||||
#include "metagen_base_strings.h"
|
||||
#include "metagen_base_thread_context.h"
|
||||
#include "metagen_base_command_line.h"
|
||||
#include "metagen_base_markup.h"
|
||||
#include "metagen_base_log.h"
|
||||
#include "metagen_base_entry_point.h"
|
||||
|
||||
#endif // BASE_INC_H
|
||||
@@ -0,0 +1,103 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Globals/Thread-Locals
|
||||
|
||||
C_LINKAGE thread_static Log *log_active;
|
||||
#if !BUILD_SUPPLEMENTARY_UNIT
|
||||
C_LINKAGE thread_static Log *log_active = 0;
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Log Creation/Selection
|
||||
|
||||
internal Log *
|
||||
log_alloc(void)
|
||||
{
|
||||
Arena *arena = arena_alloc();
|
||||
Log *log = push_array(arena, Log, 1);
|
||||
log->arena = arena;
|
||||
return log;
|
||||
}
|
||||
|
||||
internal void
|
||||
log_release(Log *log)
|
||||
{
|
||||
arena_release(log->arena);
|
||||
}
|
||||
|
||||
internal void
|
||||
log_select(Log *log)
|
||||
{
|
||||
log_active = log;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Log Building/Clearing
|
||||
|
||||
internal void
|
||||
log_msg(LogMsgKind kind, String8 string)
|
||||
{
|
||||
if(log_active != 0 && log_active->top_scope != 0)
|
||||
{
|
||||
String8 string_copy = push_str8_copy(log_active->arena, string);
|
||||
str8_list_push(log_active->arena, &log_active->top_scope->strings[kind], string_copy);
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
log_msgf(LogMsgKind kind, char *fmt, ...)
|
||||
{
|
||||
if(log_active != 0)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
String8 string = push_str8fv(scratch.arena, fmt, args);
|
||||
log_msg(kind, string);
|
||||
va_end(args);
|
||||
scratch_end(scratch);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Log Scopes
|
||||
|
||||
internal void
|
||||
log_scope_begin(void)
|
||||
{
|
||||
if(log_active != 0)
|
||||
{
|
||||
U64 pos = arena_pos(log_active->arena);
|
||||
LogScope *scope = push_array(log_active->arena, LogScope, 1);
|
||||
scope->pos = pos;
|
||||
SLLStackPush(log_active->top_scope, scope);
|
||||
}
|
||||
}
|
||||
|
||||
internal LogScopeResult
|
||||
log_scope_end(Arena *arena)
|
||||
{
|
||||
LogScopeResult result = {0};
|
||||
if(log_active != 0)
|
||||
{
|
||||
LogScope *scope = log_active->top_scope;
|
||||
if(scope != 0)
|
||||
{
|
||||
SLLStackPop(log_active->top_scope);
|
||||
if(arena != 0)
|
||||
{
|
||||
for(EachEnumVal(LogMsgKind, kind))
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
String8 result_unindented = str8_list_join(scratch.arena, &scope->strings[kind], 0);
|
||||
result.strings[kind] = indented_from_string(arena, result_unindented);
|
||||
scratch_end(scratch);
|
||||
}
|
||||
}
|
||||
arena_pop_to(log_active->arena, scope->pos);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef BASE_LOG_H
|
||||
#define BASE_LOG_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Log Types
|
||||
|
||||
typedef enum LogMsgKind
|
||||
{
|
||||
LogMsgKind_Info,
|
||||
LogMsgKind_UserError,
|
||||
LogMsgKind_COUNT
|
||||
}
|
||||
LogMsgKind;
|
||||
|
||||
typedef struct LogScope LogScope;
|
||||
struct LogScope
|
||||
{
|
||||
LogScope *next;
|
||||
U64 pos;
|
||||
String8List strings[LogMsgKind_COUNT];
|
||||
};
|
||||
|
||||
typedef struct LogScopeResult LogScopeResult;
|
||||
struct LogScopeResult
|
||||
{
|
||||
String8 strings[LogMsgKind_COUNT];
|
||||
};
|
||||
|
||||
typedef struct Log Log;
|
||||
struct Log
|
||||
{
|
||||
Arena *arena;
|
||||
LogScope *top_scope;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Log Creation/Selection
|
||||
|
||||
internal Log *log_alloc(void);
|
||||
internal void log_release(Log *log);
|
||||
internal void log_select(Log *log);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Log Building
|
||||
|
||||
internal void log_msg(LogMsgKind kind, String8 string);
|
||||
internal void log_msgf(LogMsgKind kind, char *fmt, ...);
|
||||
#define log_info(s) log_msg(LogMsgKind_Info, (s))
|
||||
#define log_infof(fmt, ...) log_msgf(LogMsgKind_Info, (fmt), __VA_ARGS__)
|
||||
#define log_user_error(s) log_msg(LogMsgKind_UserError, (s))
|
||||
#define log_user_errorf(fmt, ...) log_msgf(LogMsgKind_UserError, (fmt), __VA_ARGS__)
|
||||
|
||||
#define LogInfoNamedBlock(s) DeferLoop(log_infof("%S:\n{\n", (s)), log_infof("}\n"))
|
||||
#define LogInfoNamedBlockF(fmt, ...) DeferLoop((log_infof(fmt, __VA_ARGS__), log_infof(":\n{\n")), log_infof("}\n"))
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Log Scopes
|
||||
|
||||
internal void log_scope_begin(void);
|
||||
internal LogScopeResult log_scope_end(Arena *arena);
|
||||
|
||||
#endif // BASE_LOG_H
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
internal void
|
||||
set_thread_name(String8 string)
|
||||
{
|
||||
ProfThreadName("%.*s", str8_varg(string));
|
||||
os_set_thread_name(string);
|
||||
}
|
||||
|
||||
internal void
|
||||
set_thread_namef(char *fmt, ...)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
String8 string = push_str8fv(scratch.arena, fmt, args);
|
||||
set_thread_name(string);
|
||||
va_end(args);
|
||||
scratch_end(scratch);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef BASE_MARKUP_H
|
||||
#define BASE_MARKUP_H
|
||||
|
||||
internal void set_thread_name(String8 string);
|
||||
internal void set_thread_namef(char *fmt, ...);
|
||||
#define ThreadNameF(...) (set_thread_namef(__VA_ARGS__))
|
||||
#define ThreadName(str) (set_thread_name(str))
|
||||
|
||||
#endif // BASE_MARKUP_H
|
||||
@@ -0,0 +1,616 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Scalar Ops
|
||||
|
||||
internal F32
|
||||
mix_1f32(F32 a, F32 b, F32 t)
|
||||
{
|
||||
F32 c = (a + (b-a) * Clamp(0.f, t, 1.f));
|
||||
return c;
|
||||
}
|
||||
|
||||
internal F64
|
||||
mix_1f64(F64 a, F64 b, F64 t)
|
||||
{
|
||||
F64 c = (a + (b-a) * Clamp(0.0, t, 1.0));
|
||||
return c;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Vector Ops
|
||||
|
||||
internal Vec2F32 vec_2f32(F32 x, F32 y) {Vec2F32 v = {x, y}; return v;}
|
||||
internal Vec2F32 add_2f32(Vec2F32 a, Vec2F32 b) {Vec2F32 c = {a.x+b.x, a.y+b.y}; return c;}
|
||||
internal Vec2F32 sub_2f32(Vec2F32 a, Vec2F32 b) {Vec2F32 c = {a.x-b.x, a.y-b.y}; return c;}
|
||||
internal Vec2F32 mul_2f32(Vec2F32 a, Vec2F32 b) {Vec2F32 c = {a.x*b.x, a.y*b.y}; return c;}
|
||||
internal Vec2F32 div_2f32(Vec2F32 a, Vec2F32 b) {Vec2F32 c = {a.x/b.x, a.y/b.y}; return c;}
|
||||
internal Vec2F32 scale_2f32(Vec2F32 v, F32 s) {Vec2F32 c = {v.x*s, v.y*s}; return c;}
|
||||
internal F32 dot_2f32(Vec2F32 a, Vec2F32 b) {F32 c = a.x*b.x + a.y*b.y; return c;}
|
||||
internal F32 length_squared_2f32(Vec2F32 v) {F32 c = v.x*v.x + v.y*v.y; return c;}
|
||||
internal F32 length_2f32(Vec2F32 v) {F32 c = sqrt_f32(v.x*v.x + v.y*v.y); return c;}
|
||||
internal Vec2F32 normalize_2f32(Vec2F32 v) {v = scale_2f32(v, 1.f/length_2f32(v)); return v;}
|
||||
internal Vec2F32 mix_2f32(Vec2F32 a, Vec2F32 b, F32 t) {Vec2F32 c = {mix_1f32(a.x, b.x, t), mix_1f32(a.y, b.y, t)}; return c;}
|
||||
|
||||
internal Vec2S64 vec_2s64(S64 x, S64 y) {Vec2S64 v = {x, y}; return v;}
|
||||
internal Vec2S64 add_2s64(Vec2S64 a, Vec2S64 b) {Vec2S64 c = {a.x+b.x, a.y+b.y}; return c;}
|
||||
internal Vec2S64 sub_2s64(Vec2S64 a, Vec2S64 b) {Vec2S64 c = {a.x-b.x, a.y-b.y}; return c;}
|
||||
internal Vec2S64 mul_2s64(Vec2S64 a, Vec2S64 b) {Vec2S64 c = {a.x*b.x, a.y*b.y}; return c;}
|
||||
internal Vec2S64 div_2s64(Vec2S64 a, Vec2S64 b) {Vec2S64 c = {a.x/b.x, a.y/b.y}; return c;}
|
||||
internal Vec2S64 scale_2s64(Vec2S64 v, S64 s) {Vec2S64 c = {v.x*s, v.y*s}; return c;}
|
||||
internal S64 dot_2s64(Vec2S64 a, Vec2S64 b) {S64 c = a.x*b.x + a.y*b.y; return c;}
|
||||
internal S64 length_squared_2s64(Vec2S64 v) {S64 c = v.x*v.x + v.y*v.y; return c;}
|
||||
internal S64 length_2s64(Vec2S64 v) {S64 c = (S64)sqrt_f64((F64)(v.x*v.x + v.y*v.y)); return c;}
|
||||
internal Vec2S64 normalize_2s64(Vec2S64 v) {v = scale_2s64(v, (S64)(1.f/length_2s64(v))); return v;}
|
||||
internal Vec2S64 mix_2s64(Vec2S64 a, Vec2S64 b, F32 t) {Vec2S64 c = {(S64)mix_1f32((F32)a.x, (F32)b.x, t), (S64)mix_1f32((F32)a.y, (F32)b.y, t)}; return c;}
|
||||
|
||||
internal Vec2S32 vec_2s32(S32 x, S32 y) {Vec2S32 v = {x, y}; return v;}
|
||||
internal Vec2S32 add_2s32(Vec2S32 a, Vec2S32 b) {Vec2S32 c = {a.x+b.x, a.y+b.y}; return c;}
|
||||
internal Vec2S32 sub_2s32(Vec2S32 a, Vec2S32 b) {Vec2S32 c = {a.x-b.x, a.y-b.y}; return c;}
|
||||
internal Vec2S32 mul_2s32(Vec2S32 a, Vec2S32 b) {Vec2S32 c = {a.x*b.x, a.y*b.y}; return c;}
|
||||
internal Vec2S32 div_2s32(Vec2S32 a, Vec2S32 b) {Vec2S32 c = {a.x/b.x, a.y/b.y}; return c;}
|
||||
internal Vec2S32 scale_2s32(Vec2S32 v, S32 s) {Vec2S32 c = {v.x*s, v.y*s}; return c;}
|
||||
internal S32 dot_2s32(Vec2S32 a, Vec2S32 b) {S32 c = a.x*b.x + a.y*b.y; return c;}
|
||||
internal S32 length_squared_2s32(Vec2S32 v) {S32 c = v.x*v.x + v.y*v.y; return c;}
|
||||
internal S32 length_2s32(Vec2S32 v) {S32 c = (S32)sqrt_f32((F32)v.x*(F32)v.x + (F32)v.y*(F32)v.y); return c;}
|
||||
internal Vec2S32 normalize_2s32(Vec2S32 v) {v = scale_2s32(v, (S32)(1.f/length_2s32(v))); return v;}
|
||||
internal Vec2S32 mix_2s32(Vec2S32 a, Vec2S32 b, F32 t) {Vec2S32 c = {(S32)mix_1f32((F32)a.x, (F32)b.x, t), (S32)mix_1f32((F32)a.y, (F32)b.y, t)}; return c;}
|
||||
|
||||
internal Vec2S16 vec_2s16(S16 x, S16 y) {Vec2S16 v = {x, y}; return v;}
|
||||
internal Vec2S16 add_2s16(Vec2S16 a, Vec2S16 b) {Vec2S16 c = {(S16)(a.x+b.x), (S16)(a.y+b.y)}; return c;}
|
||||
internal Vec2S16 sub_2s16(Vec2S16 a, Vec2S16 b) {Vec2S16 c = {(S16)(a.x-b.x), (S16)(a.y-b.y)}; return c;}
|
||||
internal Vec2S16 mul_2s16(Vec2S16 a, Vec2S16 b) {Vec2S16 c = {(S16)(a.x*b.x), (S16)(a.y*b.y)}; return c;}
|
||||
internal Vec2S16 div_2s16(Vec2S16 a, Vec2S16 b) {Vec2S16 c = {(S16)(a.x/b.x), (S16)(a.y/b.y)}; return c;}
|
||||
internal Vec2S16 scale_2s16(Vec2S16 v, S16 s) {Vec2S16 c = {(S16)(v.x*s), (S16)(v.y*s)}; return c;}
|
||||
internal S16 dot_2s16(Vec2S16 a, Vec2S16 b) {S16 c = a.x*b.x + a.y*b.y; return c;}
|
||||
internal S16 length_squared_2s16(Vec2S16 v) {S16 c = v.x*v.x + v.y*v.y; return c;}
|
||||
internal S16 length_2s16(Vec2S16 v) {S16 c = (S16)sqrt_f32((F32)(v.x*v.x + v.y*v.y)); return c;}
|
||||
internal Vec2S16 normalize_2s16(Vec2S16 v) {v = scale_2s16(v, (S16)(1.f/length_2s16(v))); return v;}
|
||||
internal Vec2S16 mix_2s16(Vec2S16 a, Vec2S16 b, F32 t) {Vec2S16 c = {(S16)mix_1f32((F32)a.x, (F32)b.x, t), (S16)mix_1f32((F32)a.y, (F32)b.y, t)}; return c;}
|
||||
|
||||
internal Vec3F32 vec_3f32(F32 x, F32 y, F32 z) {Vec3F32 v = {x, y, z}; return v;}
|
||||
internal Vec3F32 add_3f32(Vec3F32 a, Vec3F32 b) {Vec3F32 c = {a.x+b.x, a.y+b.y, a.z+b.z}; return c;}
|
||||
internal Vec3F32 sub_3f32(Vec3F32 a, Vec3F32 b) {Vec3F32 c = {a.x-b.x, a.y-b.y, a.z-b.z}; return c;}
|
||||
internal Vec3F32 mul_3f32(Vec3F32 a, Vec3F32 b) {Vec3F32 c = {a.x*b.x, a.y*b.y, a.z*b.z}; return c;}
|
||||
internal Vec3F32 div_3f32(Vec3F32 a, Vec3F32 b) {Vec3F32 c = {a.x/b.x, a.y/b.y, a.z/b.z}; return c;}
|
||||
internal Vec3F32 scale_3f32(Vec3F32 v, F32 s) {Vec3F32 c = {v.x*s, v.y*s, v.z*s}; return c;}
|
||||
internal F32 dot_3f32(Vec3F32 a, Vec3F32 b) {F32 c = a.x*b.x + a.y*b.y + a.z*b.z; return c;}
|
||||
internal F32 length_squared_3f32(Vec3F32 v) {F32 c = v.x*v.x + v.y*v.y + v.z*v.z; return c;}
|
||||
internal F32 length_3f32(Vec3F32 v) {F32 c = sqrt_f32(v.x*v.x + v.y*v.y + v.z*v.z); return c;}
|
||||
internal Vec3F32 normalize_3f32(Vec3F32 v) {v = scale_3f32(v, 1.f/length_3f32(v)); return v;}
|
||||
internal Vec3F32 mix_3f32(Vec3F32 a, Vec3F32 b, F32 t) {Vec3F32 c = {mix_1f32(a.x, b.x, t), mix_1f32(a.y, b.y, t), mix_1f32(a.z, b.z, t)}; return c;}
|
||||
internal Vec3F32 cross_3f32(Vec3F32 a, Vec3F32 b) {Vec3F32 c = {a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x}; return c;}
|
||||
|
||||
internal Vec3S32 vec_3s32(S32 x, S32 y, S32 z) {Vec3S32 v = {x, y, z}; return v;}
|
||||
internal Vec3S32 add_3s32(Vec3S32 a, Vec3S32 b) {Vec3S32 c = {a.x+b.x, a.y+b.y, a.z+b.z}; return c;}
|
||||
internal Vec3S32 sub_3s32(Vec3S32 a, Vec3S32 b) {Vec3S32 c = {a.x-b.x, a.y-b.y, a.z-b.z}; return c;}
|
||||
internal Vec3S32 mul_3s32(Vec3S32 a, Vec3S32 b) {Vec3S32 c = {a.x*b.x, a.y*b.y, a.z*b.z}; return c;}
|
||||
internal Vec3S32 div_3s32(Vec3S32 a, Vec3S32 b) {Vec3S32 c = {a.x/b.x, a.y/b.y, a.z/b.z}; return c;}
|
||||
internal Vec3S32 scale_3s32(Vec3S32 v, S32 s) {Vec3S32 c = {v.x*s, v.y*s, v.z*s}; return c;}
|
||||
internal S32 dot_3s32(Vec3S32 a, Vec3S32 b) {S32 c = a.x*b.x + a.y*b.y + a.z*b.z; return c;}
|
||||
internal S32 length_squared_3s32(Vec3S32 v) {S32 c = v.x*v.x + v.y*v.y + v.z*v.z; return c;}
|
||||
internal S32 length_3s32(Vec3S32 v) {S32 c = (S32)sqrt_f32((F32)(v.x*v.x + v.y*v.y + v.z*v.z)); return c;}
|
||||
internal Vec3S32 normalize_3s32(Vec3S32 v) {v = scale_3s32(v, (S32)(1.f/length_3s32(v))); return v;}
|
||||
internal Vec3S32 mix_3s32(Vec3S32 a, Vec3S32 b, F32 t) {Vec3S32 c = {(S32)mix_1f32((F32)a.x, (F32)b.x, t), (S32)mix_1f32((F32)a.y, (F32)b.y, t), (S32)mix_1f32((F32)a.z, (F32)b.z, t)}; return c;}
|
||||
internal Vec3S32 cross_3s32(Vec3S32 a, Vec3S32 b) {Vec3S32 c = {a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x}; return c;}
|
||||
|
||||
internal Vec4F32 vec_4f32(F32 x, F32 y, F32 z, F32 w) {Vec4F32 v = {x, y, z, w}; return v;}
|
||||
internal Vec4F32 add_4f32(Vec4F32 a, Vec4F32 b) {Vec4F32 c = {a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w}; return c;}
|
||||
internal Vec4F32 sub_4f32(Vec4F32 a, Vec4F32 b) {Vec4F32 c = {a.x-b.x, a.y-b.y, a.z-b.z, a.w-b.w}; return c;}
|
||||
internal Vec4F32 mul_4f32(Vec4F32 a, Vec4F32 b) {Vec4F32 c = {a.x*b.x, a.y*b.y, a.z*b.z, a.w*b.w}; return c;}
|
||||
internal Vec4F32 div_4f32(Vec4F32 a, Vec4F32 b) {Vec4F32 c = {a.x/b.x, a.y/b.y, a.z/b.z, a.w/b.w}; return c;}
|
||||
internal Vec4F32 scale_4f32(Vec4F32 v, F32 s) {Vec4F32 c = {v.x*s, v.y*s, v.z*s, v.w*s}; return c;}
|
||||
internal F32 dot_4f32(Vec4F32 a, Vec4F32 b) {F32 c = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w; return c;}
|
||||
internal F32 length_squared_4f32(Vec4F32 v) {F32 c = v.x*v.x + v.y*v.y + v.z*v.z + v.w*v.w; return c;}
|
||||
internal F32 length_4f32(Vec4F32 v) {F32 c = sqrt_f32(v.x*v.x + v.y*v.y + v.z*v.z + v.w*v.w); return c;}
|
||||
internal Vec4F32 normalize_4f32(Vec4F32 v) {v = scale_4f32(v, 1.f/length_4f32(v)); return v;}
|
||||
internal Vec4F32 mix_4f32(Vec4F32 a, Vec4F32 b, F32 t) {Vec4F32 c = {mix_1f32(a.x, b.x, t), mix_1f32(a.y, b.y, t), mix_1f32(a.z, b.z, t), mix_1f32(a.w, b.w, t)}; return c;}
|
||||
|
||||
internal Vec4S32 vec_4s32(S32 x, S32 y, S32 z, S32 w) {Vec4S32 v = {x, y, z, w}; return v;}
|
||||
internal Vec4S32 add_4s32(Vec4S32 a, Vec4S32 b) {Vec4S32 c = {a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w}; return c;}
|
||||
internal Vec4S32 sub_4s32(Vec4S32 a, Vec4S32 b) {Vec4S32 c = {a.x-b.x, a.y-b.y, a.z-b.z, a.w-b.w}; return c;}
|
||||
internal Vec4S32 mul_4s32(Vec4S32 a, Vec4S32 b) {Vec4S32 c = {a.x*b.x, a.y*b.y, a.z*b.z, a.w*b.w}; return c;}
|
||||
internal Vec4S32 div_4s32(Vec4S32 a, Vec4S32 b) {Vec4S32 c = {a.x/b.x, a.y/b.y, a.z/b.z, a.w/b.w}; return c;}
|
||||
internal Vec4S32 scale_4s32(Vec4S32 v, S32 s) {Vec4S32 c = {v.x*s, v.y*s, v.z*s, v.w*s}; return c;}
|
||||
internal S32 dot_4s32(Vec4S32 a, Vec4S32 b) {S32 c = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w; return c;}
|
||||
internal S32 length_squared_4s32(Vec4S32 v) {S32 c = v.x*v.x + v.y*v.y + v.z*v.z + v.w*v.w; return c;}
|
||||
internal S32 length_4s32(Vec4S32 v) {S32 c = (S32)sqrt_f32((F32)(v.x*v.x + v.y*v.y + v.z*v.z + v.w*v.w)); return c;}
|
||||
internal Vec4S32 normalize_4s32(Vec4S32 v) {v = scale_4s32(v, (S32)(1.f/length_4s32(v))); return v;}
|
||||
internal Vec4S32 mix_4s32(Vec4S32 a, Vec4S32 b, F32 t) {Vec4S32 c = {(S32)mix_1f32((F32)a.x, (F32)b.x, t), (S32)mix_1f32((F32)a.y, (F32)b.y, t), (S32)mix_1f32((F32)a.z, (F32)b.z, t), (S32)mix_1f32((F32)a.w, (F32)b.w, t)}; return c;}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Matrix Ops
|
||||
|
||||
internal Mat3x3F32
|
||||
mat_3x3f32(F32 diagonal)
|
||||
{
|
||||
Mat3x3F32 result = {0};
|
||||
result.v[0][0] = diagonal;
|
||||
result.v[1][1] = diagonal;
|
||||
result.v[2][2] = diagonal;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal Mat3x3F32
|
||||
make_translate_3x3f32(Vec2F32 delta)
|
||||
{
|
||||
Mat3x3F32 mat = mat_3x3f32(1.f);
|
||||
mat.v[2][0] = delta.x;
|
||||
mat.v[2][1] = delta.y;
|
||||
return mat;
|
||||
}
|
||||
|
||||
internal Mat3x3F32
|
||||
make_scale_3x3f32(Vec2F32 scale)
|
||||
{
|
||||
Mat3x3F32 mat = mat_3x3f32(1.f);
|
||||
mat.v[0][0] = scale.x;
|
||||
mat.v[1][1] = scale.y;
|
||||
return mat;
|
||||
}
|
||||
|
||||
internal Mat3x3F32
|
||||
mul_3x3f32(Mat3x3F32 a, Mat3x3F32 b)
|
||||
{
|
||||
Mat3x3F32 c = {0};
|
||||
for(int j = 0; j < 3; j += 1)
|
||||
{
|
||||
for(int i = 0; i < 3; i += 1)
|
||||
{
|
||||
c.v[i][j] = (a.v[0][j]*b.v[i][0] +
|
||||
a.v[1][j]*b.v[i][1] +
|
||||
a.v[2][j]*b.v[i][2]);
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
internal Mat4x4F32
|
||||
mat_4x4f32(F32 diagonal)
|
||||
{
|
||||
Mat4x4F32 result = {0};
|
||||
result.v[0][0] = diagonal;
|
||||
result.v[1][1] = diagonal;
|
||||
result.v[2][2] = diagonal;
|
||||
result.v[3][3] = diagonal;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal Mat4x4F32
|
||||
make_translate_4x4f32(Vec3F32 delta)
|
||||
{
|
||||
Mat4x4F32 result = mat_4x4f32(1.f);
|
||||
result.v[3][0] = delta.x;
|
||||
result.v[3][1] = delta.y;
|
||||
result.v[3][2] = delta.z;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal Mat4x4F32
|
||||
make_scale_4x4f32(Vec3F32 scale)
|
||||
{
|
||||
Mat4x4F32 result = mat_4x4f32(1.f);
|
||||
result.v[0][0] = scale.x;
|
||||
result.v[1][1] = scale.y;
|
||||
result.v[2][2] = scale.z;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal Mat4x4F32
|
||||
make_perspective_4x4f32(F32 fov, F32 aspect_ratio, F32 near_z, F32 far_z)
|
||||
{
|
||||
Mat4x4F32 result = mat_4x4f32(1.f);
|
||||
F32 tan_theta_over_2 = tan_f32(fov / 2);
|
||||
result.v[0][0] = 1.f / tan_theta_over_2;
|
||||
result.v[1][1] = aspect_ratio / tan_theta_over_2;
|
||||
result.v[2][3] = 1.f;
|
||||
result.v[2][2] = -(near_z + far_z) / (near_z - far_z);
|
||||
result.v[3][2] = (2.f * near_z * far_z) / (near_z - far_z);
|
||||
result.v[3][3] = 0.f;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal Mat4x4F32
|
||||
make_orthographic_4x4f32(F32 left, F32 right, F32 bottom, F32 top, F32 near_z, F32 far_z)
|
||||
{
|
||||
Mat4x4F32 result = mat_4x4f32(1.f);
|
||||
|
||||
result.v[0][0] = 2.f / (right - left);
|
||||
result.v[1][1] = 2.f / (top - bottom);
|
||||
result.v[2][2] = 2.f / (far_z - near_z);
|
||||
result.v[3][3] = 1.f;
|
||||
|
||||
result.v[3][0] = (left + right) / (left - right);
|
||||
result.v[3][1] = (bottom + top) / (bottom - top);
|
||||
result.v[3][2] = (near_z + far_z) / (near_z - far_z);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal Mat4x4F32
|
||||
make_look_at_4x4f32(Vec3F32 eye, Vec3F32 center, Vec3F32 up)
|
||||
{
|
||||
Mat4x4F32 result;
|
||||
Vec3F32 f = normalize_3f32(sub_3f32(eye, center));
|
||||
Vec3F32 s = normalize_3f32(cross_3f32(f, up));
|
||||
Vec3F32 u = cross_3f32(s, f);
|
||||
result.v[0][0] = s.x;
|
||||
result.v[0][1] = u.x;
|
||||
result.v[0][2] = -f.x;
|
||||
result.v[0][3] = 0.0f;
|
||||
result.v[1][0] = s.y;
|
||||
result.v[1][1] = u.y;
|
||||
result.v[1][2] = -f.y;
|
||||
result.v[1][3] = 0.0f;
|
||||
result.v[2][0] = s.z;
|
||||
result.v[2][1] = u.z;
|
||||
result.v[2][2] = -f.z;
|
||||
result.v[2][3] = 0.0f;
|
||||
result.v[3][0] = -dot_3f32(s, eye);
|
||||
result.v[3][1] = -dot_3f32(u, eye);
|
||||
result.v[3][2] = dot_3f32(f, eye);
|
||||
result.v[3][3] = 1.0f;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal Mat4x4F32
|
||||
make_rotate_4x4f32(Vec3F32 axis, F32 turns)
|
||||
{
|
||||
Mat4x4F32 result = mat_4x4f32(1.f);
|
||||
axis = normalize_3f32(axis);
|
||||
F32 sin_theta = sin_f32(turns);
|
||||
F32 cos_theta = cos_f32(turns);
|
||||
F32 cos_value = 1.f - cos_theta;
|
||||
result.v[0][0] = (axis.x * axis.x * cos_value) + cos_theta;
|
||||
result.v[0][1] = (axis.x * axis.y * cos_value) + (axis.z * sin_theta);
|
||||
result.v[0][2] = (axis.x * axis.z * cos_value) - (axis.y * sin_theta);
|
||||
result.v[1][0] = (axis.y * axis.x * cos_value) - (axis.z * sin_theta);
|
||||
result.v[1][1] = (axis.y * axis.y * cos_value) + cos_theta;
|
||||
result.v[1][2] = (axis.y * axis.z * cos_value) + (axis.x * sin_theta);
|
||||
result.v[2][0] = (axis.z * axis.x * cos_value) + (axis.y * sin_theta);
|
||||
result.v[2][1] = (axis.z * axis.y * cos_value) - (axis.x * sin_theta);
|
||||
result.v[2][2] = (axis.z * axis.z * cos_value) + cos_theta;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal Mat4x4F32
|
||||
mul_4x4f32(Mat4x4F32 a, Mat4x4F32 b)
|
||||
{
|
||||
Mat4x4F32 c = {0};
|
||||
for(int j = 0; j < 4; j += 1)
|
||||
{
|
||||
for(int i = 0; i < 4; i += 1)
|
||||
{
|
||||
c.v[i][j] = (a.v[0][j]*b.v[i][0] +
|
||||
a.v[1][j]*b.v[i][1] +
|
||||
a.v[2][j]*b.v[i][2] +
|
||||
a.v[3][j]*b.v[i][3]);
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
internal Mat4x4F32
|
||||
scale_4x4f32(Mat4x4F32 m, F32 scale)
|
||||
{
|
||||
for(int j = 0; j < 4; j += 1)
|
||||
{
|
||||
for(int i = 0; i < 4; i += 1)
|
||||
{
|
||||
m.v[i][j] *= scale;
|
||||
}
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
internal Mat4x4F32
|
||||
inverse_4x4f32(Mat4x4F32 m)
|
||||
{
|
||||
F32 coef00 = m.v[2][2] * m.v[3][3] - m.v[3][2] * m.v[2][3];
|
||||
F32 coef02 = m.v[1][2] * m.v[3][3] - m.v[3][2] * m.v[1][3];
|
||||
F32 coef03 = m.v[1][2] * m.v[2][3] - m.v[2][2] * m.v[1][3];
|
||||
F32 coef04 = m.v[2][1] * m.v[3][3] - m.v[3][1] * m.v[2][3];
|
||||
F32 coef06 = m.v[1][1] * m.v[3][3] - m.v[3][1] * m.v[1][3];
|
||||
F32 coef07 = m.v[1][1] * m.v[2][3] - m.v[2][1] * m.v[1][3];
|
||||
F32 coef08 = m.v[2][1] * m.v[3][2] - m.v[3][1] * m.v[2][2];
|
||||
F32 coef10 = m.v[1][1] * m.v[3][2] - m.v[3][1] * m.v[1][2];
|
||||
F32 coef11 = m.v[1][1] * m.v[2][2] - m.v[2][1] * m.v[1][2];
|
||||
F32 coef12 = m.v[2][0] * m.v[3][3] - m.v[3][0] * m.v[2][3];
|
||||
F32 coef14 = m.v[1][0] * m.v[3][3] - m.v[3][0] * m.v[1][3];
|
||||
F32 coef15 = m.v[1][0] * m.v[2][3] - m.v[2][0] * m.v[1][3];
|
||||
F32 coef16 = m.v[2][0] * m.v[3][2] - m.v[3][0] * m.v[2][2];
|
||||
F32 coef18 = m.v[1][0] * m.v[3][2] - m.v[3][0] * m.v[1][2];
|
||||
F32 coef19 = m.v[1][0] * m.v[2][2] - m.v[2][0] * m.v[1][2];
|
||||
F32 coef20 = m.v[2][0] * m.v[3][1] - m.v[3][0] * m.v[2][1];
|
||||
F32 coef22 = m.v[1][0] * m.v[3][1] - m.v[3][0] * m.v[1][1];
|
||||
F32 coef23 = m.v[1][0] * m.v[2][1] - m.v[2][0] * m.v[1][1];
|
||||
|
||||
Vec4F32 fac0 = { coef00, coef00, coef02, coef03 };
|
||||
Vec4F32 fac1 = { coef04, coef04, coef06, coef07 };
|
||||
Vec4F32 fac2 = { coef08, coef08, coef10, coef11 };
|
||||
Vec4F32 fac3 = { coef12, coef12, coef14, coef15 };
|
||||
Vec4F32 fac4 = { coef16, coef16, coef18, coef19 };
|
||||
Vec4F32 fac5 = { coef20, coef20, coef22, coef23 };
|
||||
|
||||
Vec4F32 vec0 = { m.v[1][0], m.v[0][0], m.v[0][0], m.v[0][0] };
|
||||
Vec4F32 vec1 = { m.v[1][1], m.v[0][1], m.v[0][1], m.v[0][1] };
|
||||
Vec4F32 vec2 = { m.v[1][2], m.v[0][2], m.v[0][2], m.v[0][2] };
|
||||
Vec4F32 vec3 = { m.v[1][3], m.v[0][3], m.v[0][3], m.v[0][3] };
|
||||
|
||||
Vec4F32 inv0 = add_4f32(sub_4f32(mul_4f32(vec1, fac0), mul_4f32(vec2, fac1)), mul_4f32(vec3, fac2));
|
||||
Vec4F32 inv1 = add_4f32(sub_4f32(mul_4f32(vec0, fac0), mul_4f32(vec2, fac3)), mul_4f32(vec3, fac4));
|
||||
Vec4F32 inv2 = add_4f32(sub_4f32(mul_4f32(vec0, fac1), mul_4f32(vec1, fac3)), mul_4f32(vec3, fac5));
|
||||
Vec4F32 inv3 = add_4f32(sub_4f32(mul_4f32(vec0, fac2), mul_4f32(vec1, fac4)), mul_4f32(vec2, fac5));
|
||||
|
||||
Vec4F32 sign_a = { +1, -1, +1, -1 };
|
||||
Vec4F32 sign_b = { -1, +1, -1, +1 };
|
||||
|
||||
Mat4x4F32 inverse;
|
||||
for(U32 i = 0; i < 4; i += 1)
|
||||
{
|
||||
inverse.v[0][i] = inv0.v[i] * sign_a.v[i];
|
||||
inverse.v[1][i] = inv1.v[i] * sign_b.v[i];
|
||||
inverse.v[2][i] = inv2.v[i] * sign_a.v[i];
|
||||
inverse.v[3][i] = inv3.v[i] * sign_b.v[i];
|
||||
}
|
||||
|
||||
Vec4F32 row0 = { inverse.v[0][0], inverse.v[1][0], inverse.v[2][0], inverse.v[3][0] };
|
||||
Vec4F32 m0 = { m.v[0][0], m.v[0][1], m.v[0][2], m.v[0][3] };
|
||||
Vec4F32 dot0 = mul_4f32(m0, row0);
|
||||
F32 dot1 = (dot0.x + dot0.y) + (dot0.z + dot0.w);
|
||||
|
||||
F32 one_over_det = 1 / dot1;
|
||||
|
||||
return scale_4x4f32(inverse, one_over_det);
|
||||
}
|
||||
|
||||
internal Mat4x4F32
|
||||
derotate_4x4f32(Mat4x4F32 mat)
|
||||
{
|
||||
Vec3F32 scale =
|
||||
{
|
||||
length_3f32(v3f32(mat.v[0][0], mat.v[0][1], mat.v[0][2])),
|
||||
length_3f32(v3f32(mat.v[1][0], mat.v[1][1], mat.v[1][2])),
|
||||
length_3f32(v3f32(mat.v[2][0], mat.v[2][1], mat.v[2][2])),
|
||||
};
|
||||
mat.v[0][0] = scale.x;
|
||||
mat.v[1][0] = 0.f;
|
||||
mat.v[2][0] = 0.f;
|
||||
mat.v[0][1] = 0.f;
|
||||
mat.v[1][1] = scale.y;
|
||||
mat.v[2][1] = 0.f;
|
||||
mat.v[0][2] = 0.f;
|
||||
mat.v[1][2] = 0.f;
|
||||
mat.v[2][2] = scale.z;
|
||||
return mat;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Range Ops
|
||||
|
||||
internal Rng1U32 rng_1u32(U32 min, U32 max) {Rng1U32 r = {min, max}; if(r.min > r.max) { Swap(U32, r.min, r.max); } return r;}
|
||||
internal Rng1U32 shift_1u32(Rng1U32 r, U32 x) {r.min += x; r.max += x; return r;}
|
||||
internal Rng1U32 pad_1u32(Rng1U32 r, U32 x) {r.min -= x; r.max += x; return r;}
|
||||
internal U32 center_1u32(Rng1U32 r) {U32 c = (r.min+r.max)/2; return c;}
|
||||
internal B32 contains_1u32(Rng1U32 r, U32 x) {B32 c = (r.min <= x && x < r.max); return c;}
|
||||
internal U32 dim_1u32(Rng1U32 r) {U32 c = r.max-r.min; return c;}
|
||||
internal Rng1U32 union_1u32(Rng1U32 a, Rng1U32 b) {Rng1U32 c = {Min(a.min, b.min), Max(a.max, b.max)}; return c;}
|
||||
internal Rng1U32 intersect_1u32(Rng1U32 a, Rng1U32 b) {Rng1U32 c = {Max(a.min, b.min), Min(a.max, b.max)}; return c;}
|
||||
internal U32 clamp_1u32(Rng1U32 r, U32 v) {v = Clamp(r.min, v, r.max); return v;}
|
||||
|
||||
internal Rng1S32 rng_1s32(S32 min, S32 max) {Rng1S32 r = {min, max}; if(r.min > r.max) { Swap(S32, r.min, r.max); } return r;}
|
||||
internal Rng1S32 shift_1s32(Rng1S32 r, S32 x) {r.min += x; r.max += x; return r;}
|
||||
internal Rng1S32 pad_1s32(Rng1S32 r, S32 x) {r.min -= x; r.max += x; return r;}
|
||||
internal S32 center_1s32(Rng1S32 r) {S32 c = (r.min+r.max)/2; return c;}
|
||||
internal B32 contains_1s32(Rng1S32 r, S32 x) {B32 c = (r.min <= x && x < r.max); return c;}
|
||||
internal S32 dim_1s32(Rng1S32 r) {S32 c = r.max-r.min; return c;}
|
||||
internal Rng1S32 union_1s32(Rng1S32 a, Rng1S32 b) {Rng1S32 c = {Min(a.min, b.min), Max(a.max, b.max)}; return c;}
|
||||
internal Rng1S32 intersect_1s32(Rng1S32 a, Rng1S32 b) {Rng1S32 c = {Max(a.min, b.min), Min(a.max, b.max)}; return c;}
|
||||
internal S32 clamp_1s32(Rng1S32 r, S32 v) {v = Clamp(r.min, v, r.max); return v;}
|
||||
|
||||
internal Rng1U64 rng_1u64(U64 min, U64 max) {Rng1U64 r = {min, max}; if(r.min > r.max) { Swap(U64, r.min, r.max); } return r;}
|
||||
internal Rng1U64 shift_1u64(Rng1U64 r, U64 x) {r.min += x; r.max += x; return r;}
|
||||
internal Rng1U64 pad_1u64(Rng1U64 r, U64 x) {r.min -= x; r.max += x; return r;}
|
||||
internal U64 center_1u64(Rng1U64 r) {U64 c = (r.min+r.max)/2; return c;}
|
||||
internal B32 contains_1u64(Rng1U64 r, U64 x) {B32 c = (r.min <= x && x < r.max); return c;}
|
||||
internal U64 dim_1u64(Rng1U64 r) {U64 c = r.max-r.min; return c;}
|
||||
internal Rng1U64 union_1u64(Rng1U64 a, Rng1U64 b) {Rng1U64 c = {Min(a.min, b.min), Max(a.max, b.max)}; return c;}
|
||||
internal Rng1U64 intersect_1u64(Rng1U64 a, Rng1U64 b) {Rng1U64 c = {Max(a.min, b.min), Min(a.max, b.max)}; return c;}
|
||||
internal U64 clamp_1u64(Rng1U64 r, U64 v) {v = Clamp(r.min, v, r.max); return v;}
|
||||
|
||||
internal Rng1S64 rng_1s64(S64 min, S64 max) {Rng1S64 r = {min, max}; if(r.min > r.max) { Swap(S64, r.min, r.max); } return r;}
|
||||
internal Rng1S64 shift_1s64(Rng1S64 r, S64 x) {r.min += x; r.max += x; return r;}
|
||||
internal Rng1S64 pad_1s64(Rng1S64 r, S64 x) {r.min -= x; r.max += x; return r;}
|
||||
internal S64 center_1s64(Rng1S64 r) {S64 c = (r.min+r.max)/2; return c;}
|
||||
internal B32 contains_1s64(Rng1S64 r, S64 x) {B32 c = (r.min <= x && x < r.max); return c;}
|
||||
internal S64 dim_1s64(Rng1S64 r) {S64 c = r.max-r.min; return c;}
|
||||
internal Rng1S64 union_1s64(Rng1S64 a, Rng1S64 b) {Rng1S64 c = {Min(a.min, b.min), Max(a.max, b.max)}; return c;}
|
||||
internal Rng1S64 intersect_1s64(Rng1S64 a, Rng1S64 b) {Rng1S64 c = {Max(a.min, b.min), Min(a.max, b.max)}; return c;}
|
||||
internal S64 clamp_1s64(Rng1S64 r, S64 v) {v = Clamp(r.min, v, r.max); return v;}
|
||||
|
||||
internal Rng1F32 rng_1f32(F32 min, F32 max) {Rng1F32 r = {min, max}; if(r.min > r.max) { Swap(F32, r.min, r.max); } return r;}
|
||||
internal Rng1F32 shift_1f32(Rng1F32 r, F32 x) {r.min += x; r.max += x; return r;}
|
||||
internal Rng1F32 pad_1f32(Rng1F32 r, F32 x) {r.min -= x; r.max += x; return r;}
|
||||
internal F32 center_1f32(Rng1F32 r) {F32 c = (r.min+r.max)/2; return c;}
|
||||
internal B32 contains_1f32(Rng1F32 r, F32 x) {B32 c = (r.min <= x && x < r.max); return c;}
|
||||
internal F32 dim_1f32(Rng1F32 r) {F32 c = r.max-r.min; return c;}
|
||||
internal Rng1F32 union_1f32(Rng1F32 a, Rng1F32 b) {Rng1F32 c = {Min(a.min, b.min), Max(a.max, b.max)}; return c;}
|
||||
internal Rng1F32 intersect_1f32(Rng1F32 a, Rng1F32 b) {Rng1F32 c = {Max(a.min, b.min), Min(a.max, b.max)}; return c;}
|
||||
internal F32 clamp_1f32(Rng1F32 r, F32 v) {v = Clamp(r.min, v, r.max); return v;}
|
||||
|
||||
internal Rng2S16 rng_2s16(Vec2S16 min, Vec2S16 max) {Rng2S16 r = {min, max}; return r;}
|
||||
internal Rng2S16 shift_2s16(Rng2S16 r, Vec2S16 x) {r.min = add_2s16(r.min, x); r.max = add_2s16(r.max, x); return r;}
|
||||
internal Rng2S16 pad_2s16(Rng2S16 r, S16 x) {Vec2S16 xv = {x, x}; r.min = sub_2s16(r.min, xv); r.max = add_2s16(r.max, xv); return r;}
|
||||
internal Vec2S16 center_2s16(Rng2S16 r) {Vec2S16 c = {(S16)((r.min.x+r.max.x)/2), (S16)((r.min.y+r.max.y)/2)}; return c;}
|
||||
internal B32 contains_2s16(Rng2S16 r, Vec2S16 x) {B32 c = (r.min.x <= x.x && x.x < r.max.x && r.min.y <= x.y && x.y < r.max.y); return c;}
|
||||
internal Vec2S16 dim_2s16(Rng2S16 r) {Vec2S16 dim = {(S16)(r.max.x-r.min.x), (S16)(r.max.y-r.min.y)}; return dim;}
|
||||
internal Rng2S16 union_2s16(Rng2S16 a, Rng2S16 b) {Rng2S16 c; c.p0.x = Min(a.min.x, b.min.x); c.p0.y = Min(a.min.y, b.min.y); c.p1.x = Max(a.max.x, b.max.x); c.p1.y = Max(a.max.y, b.max.y); return c;}
|
||||
internal Rng2S16 intersect_2s16(Rng2S16 a, Rng2S16 b) {Rng2S16 c; c.p0.x = Max(a.min.x, b.min.x); c.p0.y = Max(a.min.y, b.min.y); c.p1.x = Min(a.max.x, b.max.x); c.p1.y = Min(a.max.y, b.max.y); return c;}
|
||||
internal Vec2S16 clamp_2s16(Rng2S16 r, Vec2S16 v) {v.x = Clamp(r.min.x, v.x, r.max.x); v.y = Clamp(r.min.y, v.y, r.max.y); return v;}
|
||||
|
||||
internal Rng2S32 rng_2s32(Vec2S32 min, Vec2S32 max) {Rng2S32 r = {min, max}; return r;}
|
||||
internal Rng2S32 shift_2s32(Rng2S32 r, Vec2S32 x) {r.min = add_2s32(r.min, x); r.max = add_2s32(r.max, x); return r;}
|
||||
internal Rng2S32 pad_2s32(Rng2S32 r, S32 x) {Vec2S32 xv = {x, x}; r.min = sub_2s32(r.min, xv); r.max = add_2s32(r.max, xv); return r;}
|
||||
internal Vec2S32 center_2s32(Rng2S32 r) {Vec2S32 c = {(r.min.x+r.max.x)/2, (r.min.y+r.max.y)/2}; return c;}
|
||||
internal B32 contains_2s32(Rng2S32 r, Vec2S32 x) {B32 c = (r.min.x <= x.x && x.x < r.max.x && r.min.y <= x.y && x.y < r.max.y); return c;}
|
||||
internal Vec2S32 dim_2s32(Rng2S32 r) {Vec2S32 dim = {r.max.x-r.min.x, r.max.y-r.min.y}; return dim;}
|
||||
internal Rng2S32 union_2s32(Rng2S32 a, Rng2S32 b) {Rng2S32 c; c.p0.x = Min(a.min.x, b.min.x); c.p0.y = Min(a.min.y, b.min.y); c.p1.x = Max(a.max.x, b.max.x); c.p1.y = Max(a.max.y, b.max.y); return c;}
|
||||
internal Rng2S32 intersect_2s32(Rng2S32 a, Rng2S32 b) {Rng2S32 c; c.p0.x = Max(a.min.x, b.min.x); c.p0.y = Max(a.min.y, b.min.y); c.p1.x = Min(a.max.x, b.max.x); c.p1.y = Min(a.max.y, b.max.y); return c;}
|
||||
internal Vec2S32 clamp_2s32(Rng2S32 r, Vec2S32 v) {v.x = Clamp(r.min.x, v.x, r.max.x); v.y = Clamp(r.min.y, v.y, r.max.y); return v;}
|
||||
|
||||
internal Rng2S64 rng_2s64(Vec2S64 min, Vec2S64 max) {Rng2S64 r = {min, max}; return r;}
|
||||
internal Rng2S64 shift_2s64(Rng2S64 r, Vec2S64 x) {r.min = add_2s64(r.min, x); r.max = add_2s64(r.max, x); return r;}
|
||||
internal Rng2S64 pad_2s64(Rng2S64 r, S64 x) {Vec2S64 xv = {x, x}; r.min = sub_2s64(r.min, xv); r.max = add_2s64(r.max, xv); return r;}
|
||||
internal Vec2S64 center_2s64(Rng2S64 r) {Vec2S64 c = {(r.min.x+r.max.x)/2, (r.min.y+r.max.y)/2}; return c;}
|
||||
internal B32 contains_2s64(Rng2S64 r, Vec2S64 x) {B32 c = (r.min.x <= x.x && x.x < r.max.x && r.min.y <= x.y && x.y < r.max.y); return c;}
|
||||
internal Vec2S64 dim_2s64(Rng2S64 r) {Vec2S64 dim = {r.max.x-r.min.x, r.max.y-r.min.y}; return dim;}
|
||||
internal Rng2S64 union_2s64(Rng2S64 a, Rng2S64 b) {Rng2S64 c; c.p0.x = Min(a.min.x, b.min.x); c.p0.y = Min(a.min.y, b.min.y); c.p1.x = Max(a.max.x, b.max.x); c.p1.y = Max(a.max.y, b.max.y); return c;}
|
||||
internal Rng2S64 intersect_2s64(Rng2S64 a, Rng2S64 b) {Rng2S64 c; c.p0.x = Max(a.min.x, b.min.x); c.p0.y = Max(a.min.y, b.min.y); c.p1.x = Min(a.max.x, b.max.x); c.p1.y = Min(a.max.y, b.max.y); return c;}
|
||||
internal Vec2S64 clamp_2s64(Rng2S64 r, Vec2S64 v) {v.x = Clamp(r.min.x, v.x, r.max.x); v.y = Clamp(r.min.y, v.y, r.max.y); return v;}
|
||||
|
||||
internal Rng2F32 rng_2f32(Vec2F32 min, Vec2F32 max) {Rng2F32 r = {min, max}; return r;}
|
||||
internal Rng2F32 shift_2f32(Rng2F32 r, Vec2F32 x) {r.min = add_2f32(r.min, x); r.max = add_2f32(r.max, x); return r;}
|
||||
internal Rng2F32 pad_2f32(Rng2F32 r, F32 x) {Vec2F32 xv = {x, x}; r.min = sub_2f32(r.min, xv); r.max = add_2f32(r.max, xv); return r;}
|
||||
internal Vec2F32 center_2f32(Rng2F32 r) {Vec2F32 c = {(r.min.x+r.max.x)/2, (r.min.y+r.max.y)/2}; return c;}
|
||||
internal B32 contains_2f32(Rng2F32 r, Vec2F32 x) {B32 c = (r.min.x <= x.x && x.x < r.max.x && r.min.y <= x.y && x.y < r.max.y); return c;}
|
||||
internal Vec2F32 dim_2f32(Rng2F32 r) {Vec2F32 dim = {r.max.x-r.min.x, r.max.y-r.min.y}; return dim;}
|
||||
internal Rng2F32 union_2f32(Rng2F32 a, Rng2F32 b) {Rng2F32 c; c.p0.x = Min(a.min.x, b.min.x); c.p0.y = Min(a.min.y, b.min.y); c.p1.x = Max(a.max.x, b.max.x); c.p1.y = Max(a.max.y, b.max.y); return c;}
|
||||
internal Rng2F32 intersect_2f32(Rng2F32 a, Rng2F32 b) {Rng2F32 c; c.p0.x = Max(a.min.x, b.min.x); c.p0.y = Max(a.min.y, b.min.y); c.p1.x = Min(a.max.x, b.max.x); c.p1.y = Min(a.max.y, b.max.y); return c;}
|
||||
internal Vec2F32 clamp_2f32(Rng2F32 r, Vec2F32 v) {v.x = Clamp(r.min.x, v.x, r.max.x); v.y = Clamp(r.min.y, v.y, r.max.y); return v;}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Miscellaneous Ops
|
||||
|
||||
internal Vec3F32
|
||||
hsv_from_rgb(Vec3F32 rgb)
|
||||
{
|
||||
F32 c_max = Max(rgb.x, Max(rgb.y, rgb.z));
|
||||
F32 c_min = Min(rgb.x, Min(rgb.y, rgb.z));
|
||||
F32 delta = c_max - c_min;
|
||||
F32 h = ((delta == 0.f) ? 0.f :
|
||||
(c_max == rgb.x) ? mod_f32((rgb.y - rgb.z)/delta + 6.f, 6.f) :
|
||||
(c_max == rgb.y) ? (rgb.z - rgb.x)/delta + 2.f :
|
||||
(c_max == rgb.z) ? (rgb.x - rgb.y)/delta + 4.f :
|
||||
0.f);
|
||||
F32 s = (c_max == 0.f) ? 0.f : (delta/c_max);
|
||||
F32 v = c_max;
|
||||
Vec3F32 hsv = {h/6.f, s, v};
|
||||
return hsv;
|
||||
}
|
||||
|
||||
internal Vec3F32
|
||||
rgb_from_hsv(Vec3F32 hsv)
|
||||
{
|
||||
F32 h = mod_f32(hsv.x * 360.f, 360.f);
|
||||
F32 s = hsv.y;
|
||||
F32 v = hsv.z;
|
||||
|
||||
F32 c = v*s;
|
||||
F32 x = c*(1.f - abs_f32(mod_f32(h/60.f, 2.f) - 1.f));
|
||||
F32 m = v - c;
|
||||
|
||||
F32 r = 0;
|
||||
F32 g = 0;
|
||||
F32 b = 0;
|
||||
|
||||
if ((h >= 0.f && h < 60.f) || (h >= 360.f && h < 420.f)){
|
||||
r = c;
|
||||
g = x;
|
||||
b = 0;
|
||||
}
|
||||
else if (h >= 60.f && h < 120.f){
|
||||
r = x;
|
||||
g = c;
|
||||
b = 0;
|
||||
}
|
||||
else if (h >= 120.f && h < 180.f){
|
||||
r = 0;
|
||||
g = c;
|
||||
b = x;
|
||||
}
|
||||
else if (h >= 180.f && h < 240.f){
|
||||
r = 0;
|
||||
g = x;
|
||||
b = c;
|
||||
}
|
||||
else if (h >= 240.f && h < 300.f){
|
||||
r = x;
|
||||
g = 0;
|
||||
b = c;
|
||||
}
|
||||
else if ((h >= 300.f && h <= 360.f) || (h >= -60.f && h <= 0.f)){
|
||||
r = c;
|
||||
g = 0;
|
||||
b = x;
|
||||
}
|
||||
|
||||
Vec3F32 rgb = {r + m, g + m, b + m};
|
||||
return(rgb);
|
||||
}
|
||||
|
||||
internal Vec4F32
|
||||
hsva_from_rgba(Vec4F32 rgba)
|
||||
{
|
||||
Vec3F32 rgb = v3f32(rgba.x, rgba.y, rgba.z);
|
||||
Vec3F32 hsv = hsv_from_rgb(rgb);
|
||||
Vec4F32 hsva = v4f32(hsv.x, hsv.y, hsv.z, rgba.w);
|
||||
return hsva;
|
||||
}
|
||||
|
||||
internal Vec4F32
|
||||
rgba_from_hsva(Vec4F32 hsva)
|
||||
{
|
||||
Vec3F32 hsv = v3f32(hsva.x, hsva.y, hsva.z);
|
||||
Vec3F32 rgb = rgb_from_hsv(hsv);
|
||||
Vec4F32 rgba = v4f32(rgb.x, rgb.y, rgb.z, hsva.w);
|
||||
return rgba;
|
||||
}
|
||||
|
||||
internal Vec4F32
|
||||
rgba_from_u32(U32 hex)
|
||||
{
|
||||
Vec4F32 result = v4f32(((hex&0xff000000)>>24)/255.f,
|
||||
((hex&0x00ff0000)>>16)/255.f,
|
||||
((hex&0x0000ff00)>> 8)/255.f,
|
||||
((hex&0x000000ff)>> 0)/255.f);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U32
|
||||
u32_from_rgba(Vec4F32 rgba)
|
||||
{
|
||||
U32 result = 0;
|
||||
result |= ((U32)((U8)(rgba.x*255.f))) << 24;
|
||||
result |= ((U32)((U8)(rgba.y*255.f))) << 16;
|
||||
result |= ((U32)((U8)(rgba.z*255.f))) << 8;
|
||||
result |= ((U32)((U8)(rgba.w*255.f))) << 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: List Type Functions
|
||||
|
||||
internal void
|
||||
rng1s64_list_push(Arena *arena, Rng1S64List *list, Rng1S64 rng)
|
||||
{
|
||||
Rng1S64Node *n = push_array(arena, Rng1S64Node, 1);
|
||||
MemoryCopyStruct(&n->v, &rng);
|
||||
SLLQueuePush(list->first, list->last, n);
|
||||
list->count += 1;
|
||||
}
|
||||
|
||||
internal Rng1S64Array
|
||||
rng1s64_array_from_list(Arena *arena, Rng1S64List *list)
|
||||
{
|
||||
Rng1S64Array arr = {0};
|
||||
arr.count = list->count;
|
||||
arr.v = push_array_no_zero(arena, Rng1S64, arr.count);
|
||||
U64 idx = 0;
|
||||
for(Rng1S64Node *n = list->first; n != 0; n = n->next)
|
||||
{
|
||||
arr.v[idx] = n->v;
|
||||
idx += 1;
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
@@ -0,0 +1,649 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef BASE_MATH_H
|
||||
#define BASE_MATH_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Vector Types
|
||||
|
||||
//- rjf: 2-vectors
|
||||
|
||||
typedef union Vec2F32 Vec2F32;
|
||||
union Vec2F32
|
||||
{
|
||||
struct
|
||||
{
|
||||
F32 x;
|
||||
F32 y;
|
||||
};
|
||||
F32 v[2];
|
||||
};
|
||||
|
||||
typedef union Vec2S64 Vec2S64;
|
||||
union Vec2S64
|
||||
{
|
||||
struct
|
||||
{
|
||||
S64 x;
|
||||
S64 y;
|
||||
};
|
||||
S64 v[2];
|
||||
};
|
||||
|
||||
typedef union Vec2S32 Vec2S32;
|
||||
union Vec2S32
|
||||
{
|
||||
struct
|
||||
{
|
||||
S32 x;
|
||||
S32 y;
|
||||
};
|
||||
S32 v[2];
|
||||
};
|
||||
|
||||
typedef union Vec2S16 Vec2S16;
|
||||
union Vec2S16
|
||||
{
|
||||
struct
|
||||
{
|
||||
S16 x;
|
||||
S16 y;
|
||||
};
|
||||
S16 v[2];
|
||||
};
|
||||
|
||||
//- rjf: 3-vectors
|
||||
|
||||
typedef union Vec3F32 Vec3F32;
|
||||
union Vec3F32
|
||||
{
|
||||
struct
|
||||
{
|
||||
F32 x;
|
||||
F32 y;
|
||||
F32 z;
|
||||
};
|
||||
struct
|
||||
{
|
||||
Vec2F32 xy;
|
||||
F32 _z0;
|
||||
};
|
||||
struct
|
||||
{
|
||||
F32 _x0;
|
||||
Vec2F32 yz;
|
||||
};
|
||||
F32 v[3];
|
||||
};
|
||||
|
||||
typedef union Vec3S32 Vec3S32;
|
||||
union Vec3S32
|
||||
{
|
||||
struct
|
||||
{
|
||||
S32 x;
|
||||
S32 y;
|
||||
S32 z;
|
||||
};
|
||||
struct
|
||||
{
|
||||
Vec2S32 xy;
|
||||
S32 _z0;
|
||||
};
|
||||
struct
|
||||
{
|
||||
S32 _x0;
|
||||
Vec2S32 yz;
|
||||
};
|
||||
S32 v[3];
|
||||
};
|
||||
|
||||
//- rjf: 4-vectors
|
||||
|
||||
typedef union Vec4F32 Vec4F32;
|
||||
union Vec4F32
|
||||
{
|
||||
struct
|
||||
{
|
||||
F32 x;
|
||||
F32 y;
|
||||
F32 z;
|
||||
F32 w;
|
||||
};
|
||||
struct
|
||||
{
|
||||
Vec2F32 xy;
|
||||
Vec2F32 zw;
|
||||
};
|
||||
struct
|
||||
{
|
||||
Vec3F32 xyz;
|
||||
F32 _z0;
|
||||
};
|
||||
struct
|
||||
{
|
||||
F32 _x0;
|
||||
Vec3F32 yzw;
|
||||
};
|
||||
F32 v[4];
|
||||
};
|
||||
|
||||
typedef union Vec4S32 Vec4S32;
|
||||
union Vec4S32
|
||||
{
|
||||
struct
|
||||
{
|
||||
S32 x;
|
||||
S32 y;
|
||||
S32 z;
|
||||
S32 w;
|
||||
};
|
||||
struct
|
||||
{
|
||||
Vec2S32 xy;
|
||||
Vec2S32 zw;
|
||||
};
|
||||
struct
|
||||
{
|
||||
Vec3S32 xyz;
|
||||
S32 _z0;
|
||||
};
|
||||
struct
|
||||
{
|
||||
S32 _x0;
|
||||
Vec3S32 yzw;
|
||||
};
|
||||
S32 v[4];
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Matrix Types
|
||||
|
||||
typedef struct Mat3x3F32 Mat3x3F32;
|
||||
struct Mat3x3F32
|
||||
{
|
||||
F32 v[3][3];
|
||||
};
|
||||
|
||||
typedef struct Mat4x4F32 Mat4x4F32;
|
||||
struct Mat4x4F32
|
||||
{
|
||||
F32 v[4][4];
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Range Types
|
||||
|
||||
//- rjf: 1-range
|
||||
|
||||
typedef union Rng1U32 Rng1U32;
|
||||
union Rng1U32
|
||||
{
|
||||
struct
|
||||
{
|
||||
U32 min;
|
||||
U32 max;
|
||||
};
|
||||
U32 v[2];
|
||||
};
|
||||
|
||||
typedef union Rng1S32 Rng1S32;
|
||||
union Rng1S32
|
||||
{
|
||||
struct
|
||||
{
|
||||
S32 min;
|
||||
S32 max;
|
||||
};
|
||||
S32 v[2];
|
||||
};
|
||||
|
||||
typedef union Rng1U64 Rng1U64;
|
||||
union Rng1U64
|
||||
{
|
||||
struct
|
||||
{
|
||||
U64 min;
|
||||
U64 max;
|
||||
};
|
||||
U64 v[2];
|
||||
};
|
||||
|
||||
typedef union Rng1S64 Rng1S64;
|
||||
union Rng1S64
|
||||
{
|
||||
struct
|
||||
{
|
||||
S64 min;
|
||||
S64 max;
|
||||
};
|
||||
S64 v[2];
|
||||
};
|
||||
|
||||
typedef union Rng1F32 Rng1F32;
|
||||
union Rng1F32
|
||||
{
|
||||
struct
|
||||
{
|
||||
F32 min;
|
||||
F32 max;
|
||||
};
|
||||
F32 v[2];
|
||||
};
|
||||
|
||||
//- rjf: 2-range (rectangles)
|
||||
|
||||
typedef union Rng2S16 Rng2S16;
|
||||
union Rng2S16
|
||||
{
|
||||
struct
|
||||
{
|
||||
Vec2S16 min;
|
||||
Vec2S16 max;
|
||||
};
|
||||
struct
|
||||
{
|
||||
Vec2S16 p0;
|
||||
Vec2S16 p1;
|
||||
};
|
||||
struct
|
||||
{
|
||||
S16 x0;
|
||||
S16 y0;
|
||||
S16 x1;
|
||||
S16 y1;
|
||||
};
|
||||
Vec2S16 v[2];
|
||||
};
|
||||
|
||||
typedef union Rng2S32 Rng2S32;
|
||||
union Rng2S32
|
||||
{
|
||||
struct
|
||||
{
|
||||
Vec2S32 min;
|
||||
Vec2S32 max;
|
||||
};
|
||||
struct
|
||||
{
|
||||
Vec2S32 p0;
|
||||
Vec2S32 p1;
|
||||
};
|
||||
struct
|
||||
{
|
||||
S32 x0;
|
||||
S32 y0;
|
||||
S32 x1;
|
||||
S32 y1;
|
||||
};
|
||||
Vec2S32 v[2];
|
||||
};
|
||||
|
||||
typedef union Rng2F32 Rng2F32;
|
||||
union Rng2F32
|
||||
{
|
||||
struct
|
||||
{
|
||||
Vec2F32 min;
|
||||
Vec2F32 max;
|
||||
};
|
||||
struct
|
||||
{
|
||||
Vec2F32 p0;
|
||||
Vec2F32 p1;
|
||||
};
|
||||
struct
|
||||
{
|
||||
F32 x0;
|
||||
F32 y0;
|
||||
F32 x1;
|
||||
F32 y1;
|
||||
};
|
||||
Vec2F32 v[2];
|
||||
};
|
||||
|
||||
typedef union Rng2S64 Rng2S64;
|
||||
union Rng2S64
|
||||
{
|
||||
struct
|
||||
{
|
||||
Vec2S64 min;
|
||||
Vec2S64 max;
|
||||
};
|
||||
struct
|
||||
{
|
||||
Vec2S64 p0;
|
||||
Vec2S64 p1;
|
||||
};
|
||||
struct
|
||||
{
|
||||
S64 x0;
|
||||
S64 y0;
|
||||
S64 x1;
|
||||
S64 y1;
|
||||
};
|
||||
Vec2S64 v[2];
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: List Types
|
||||
|
||||
typedef struct Rng1S64Node Rng1S64Node;
|
||||
struct Rng1S64Node
|
||||
{
|
||||
Rng1S64Node *next;
|
||||
Rng1S64 v;
|
||||
};
|
||||
|
||||
typedef struct Rng1S64List Rng1S64List;
|
||||
struct Rng1S64List
|
||||
{
|
||||
Rng1S64Node *first;
|
||||
Rng1S64Node *last;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
typedef struct Rng1S64Array Rng1S64Array;
|
||||
struct Rng1S64Array
|
||||
{
|
||||
Rng1S64 *v;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Scalar Ops
|
||||
|
||||
#define abs_s64(v) (S64)llabs(v)
|
||||
|
||||
#define sqrt_f32(v) sqrtf(v)
|
||||
#define mod_f32(a, b) fmodf((a), (b))
|
||||
#define pow_f32(b, e) powf((b), (e))
|
||||
#define ceil_f32(v) ceilf(v)
|
||||
#define floor_f32(v) floorf(v)
|
||||
#define round_f32(v) roundf(v)
|
||||
#define abs_f32(v) fabsf(v)
|
||||
#define radians_from_turns_f32(v) ((v)*2*3.1415926535897f)
|
||||
#define turns_from_radians_f32(v) ((v)/2*3.1415926535897f)
|
||||
#define degrees_from_turns_f32(v) ((v)*360.f)
|
||||
#define turns_from_degrees_f32(v) ((v)/360.f)
|
||||
#define degrees_from_radians_f32(v) (degrees_from_turns_f32(turns_from_radians_f32(v)))
|
||||
#define radians_from_degrees_f32(v) (radians_from_turns_f32(turns_from_degrees_f32(v)))
|
||||
#define sin_f32(v) sinf(radians_from_turns_f32(v))
|
||||
#define cos_f32(v) cosf(radians_from_turns_f32(v))
|
||||
#define tan_f32(v) tanf(radians_from_turns_f32(v))
|
||||
|
||||
#define sqrt_f64(v) sqrt(v)
|
||||
#define mod_f64(a, b) fmod((a), (b))
|
||||
#define pow_f64(b, e) pow((b), (e))
|
||||
#define ceil_f64(v) ceil(v)
|
||||
#define floor_f64(v) floor(v)
|
||||
#define round_f64(v) round(v)
|
||||
#define abs_f64(v) fabs(v)
|
||||
#define radians_from_turns_f64(v) ((v)*2*3.1415926535897)
|
||||
#define turns_from_radians_f64(v) ((v)/2*3.1415926535897)
|
||||
#define degrees_from_turns_f64(v) ((v)*360.0)
|
||||
#define turns_from_degrees_f64(v) ((v)/360.0)
|
||||
#define degrees_from_radians_f64(v) (degrees_from_turns_f64(turns_from_radians_f64(v)))
|
||||
#define radians_from_degrees_f64(v) (radians_from_turns_f64(turns_from_degrees_f64(v)))
|
||||
#define sin_f64(v) sin(radians_from_turns_f64(v))
|
||||
#define cos_f64(v) cos(radians_from_turns_f64(v))
|
||||
#define tan_f64(v) tan(radians_from_turns_f64(v))
|
||||
|
||||
internal F32 mix_1f32(F32 a, F32 b, F32 t);
|
||||
internal F64 mix_1f64(F64 a, F64 b, F64 t);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Vector Ops
|
||||
|
||||
#define v2f32(x, y) vec_2f32((x), (y))
|
||||
internal Vec2F32 vec_2f32(F32 x, F32 y);
|
||||
internal Vec2F32 add_2f32(Vec2F32 a, Vec2F32 b);
|
||||
internal Vec2F32 sub_2f32(Vec2F32 a, Vec2F32 b);
|
||||
internal Vec2F32 mul_2f32(Vec2F32 a, Vec2F32 b);
|
||||
internal Vec2F32 div_2f32(Vec2F32 a, Vec2F32 b);
|
||||
internal Vec2F32 scale_2f32(Vec2F32 v, F32 s);
|
||||
internal F32 dot_2f32(Vec2F32 a, Vec2F32 b);
|
||||
internal F32 length_squared_2f32(Vec2F32 v);
|
||||
internal F32 length_2f32(Vec2F32 v);
|
||||
internal Vec2F32 normalize_2f32(Vec2F32 v);
|
||||
internal Vec2F32 mix_2f32(Vec2F32 a, Vec2F32 b, F32 t);
|
||||
|
||||
#define v2s64(x, y) vec_2s64((x), (y))
|
||||
internal Vec2S64 vec_2s64(S64 x, S64 y);
|
||||
internal Vec2S64 add_2s64(Vec2S64 a, Vec2S64 b);
|
||||
internal Vec2S64 sub_2s64(Vec2S64 a, Vec2S64 b);
|
||||
internal Vec2S64 mul_2s64(Vec2S64 a, Vec2S64 b);
|
||||
internal Vec2S64 div_2s64(Vec2S64 a, Vec2S64 b);
|
||||
internal Vec2S64 scale_2s64(Vec2S64 v, S64 s);
|
||||
internal S64 dot_2s64(Vec2S64 a, Vec2S64 b);
|
||||
internal S64 length_squared_2s64(Vec2S64 v);
|
||||
internal S64 length_2s64(Vec2S64 v);
|
||||
internal Vec2S64 normalize_2s64(Vec2S64 v);
|
||||
internal Vec2S64 mix_2s64(Vec2S64 a, Vec2S64 b, F32 t);
|
||||
|
||||
#define v2s32(x, y) vec_2s32((x), (y))
|
||||
internal Vec2S32 vec_2s32(S32 x, S32 y);
|
||||
internal Vec2S32 add_2s32(Vec2S32 a, Vec2S32 b);
|
||||
internal Vec2S32 sub_2s32(Vec2S32 a, Vec2S32 b);
|
||||
internal Vec2S32 mul_2s32(Vec2S32 a, Vec2S32 b);
|
||||
internal Vec2S32 div_2s32(Vec2S32 a, Vec2S32 b);
|
||||
internal Vec2S32 scale_2s32(Vec2S32 v, S32 s);
|
||||
internal S32 dot_2s32(Vec2S32 a, Vec2S32 b);
|
||||
internal S32 length_squared_2s32(Vec2S32 v);
|
||||
internal S32 length_2s32(Vec2S32 v);
|
||||
internal Vec2S32 normalize_2s32(Vec2S32 v);
|
||||
internal Vec2S32 mix_2s32(Vec2S32 a, Vec2S32 b, F32 t);
|
||||
|
||||
#define v2s16(x, y) vec_2s16((x), (y))
|
||||
internal Vec2S16 vec_2s16(S16 x, S16 y);
|
||||
internal Vec2S16 add_2s16(Vec2S16 a, Vec2S16 b);
|
||||
internal Vec2S16 sub_2s16(Vec2S16 a, Vec2S16 b);
|
||||
internal Vec2S16 mul_2s16(Vec2S16 a, Vec2S16 b);
|
||||
internal Vec2S16 div_2s16(Vec2S16 a, Vec2S16 b);
|
||||
internal Vec2S16 scale_2s16(Vec2S16 v, S16 s);
|
||||
internal S16 dot_2s16(Vec2S16 a, Vec2S16 b);
|
||||
internal S16 length_squared_2s16(Vec2S16 v);
|
||||
internal S16 length_2s16(Vec2S16 v);
|
||||
internal Vec2S16 normalize_2s16(Vec2S16 v);
|
||||
internal Vec2S16 mix_2s16(Vec2S16 a, Vec2S16 b, F32 t);
|
||||
|
||||
#define v3f32(x, y, z) vec_3f32((x), (y), (z))
|
||||
internal Vec3F32 vec_3f32(F32 x, F32 y, F32 z);
|
||||
internal Vec3F32 add_3f32(Vec3F32 a, Vec3F32 b);
|
||||
internal Vec3F32 sub_3f32(Vec3F32 a, Vec3F32 b);
|
||||
internal Vec3F32 mul_3f32(Vec3F32 a, Vec3F32 b);
|
||||
internal Vec3F32 div_3f32(Vec3F32 a, Vec3F32 b);
|
||||
internal Vec3F32 scale_3f32(Vec3F32 v, F32 s);
|
||||
internal F32 dot_3f32(Vec3F32 a, Vec3F32 b);
|
||||
internal F32 length_squared_3f32(Vec3F32 v);
|
||||
internal F32 length_3f32(Vec3F32 v);
|
||||
internal Vec3F32 normalize_3f32(Vec3F32 v);
|
||||
internal Vec3F32 mix_3f32(Vec3F32 a, Vec3F32 b, F32 t);
|
||||
internal Vec3F32 cross_3f32(Vec3F32 a, Vec3F32 b);
|
||||
|
||||
#define v3s32(x, y, z) vec_3s32((x), (y), (z))
|
||||
internal Vec3S32 vec_3s32(S32 x, S32 y, S32 z);
|
||||
internal Vec3S32 add_3s32(Vec3S32 a, Vec3S32 b);
|
||||
internal Vec3S32 sub_3s32(Vec3S32 a, Vec3S32 b);
|
||||
internal Vec3S32 mul_3s32(Vec3S32 a, Vec3S32 b);
|
||||
internal Vec3S32 div_3s32(Vec3S32 a, Vec3S32 b);
|
||||
internal Vec3S32 scale_3s32(Vec3S32 v, S32 s);
|
||||
internal S32 dot_3s32(Vec3S32 a, Vec3S32 b);
|
||||
internal S32 length_squared_3s32(Vec3S32 v);
|
||||
internal S32 length_3s32(Vec3S32 v);
|
||||
internal Vec3S32 normalize_3s32(Vec3S32 v);
|
||||
internal Vec3S32 mix_3s32(Vec3S32 a, Vec3S32 b, F32 t);
|
||||
internal Vec3S32 cross_3s32(Vec3S32 a, Vec3S32 b);
|
||||
|
||||
#define v4f32(x, y, z, w) vec_4f32((x), (y), (z), (w))
|
||||
internal Vec4F32 vec_4f32(F32 x, F32 y, F32 z, F32 w);
|
||||
internal Vec4F32 add_4f32(Vec4F32 a, Vec4F32 b);
|
||||
internal Vec4F32 sub_4f32(Vec4F32 a, Vec4F32 b);
|
||||
internal Vec4F32 mul_4f32(Vec4F32 a, Vec4F32 b);
|
||||
internal Vec4F32 div_4f32(Vec4F32 a, Vec4F32 b);
|
||||
internal Vec4F32 scale_4f32(Vec4F32 v, F32 s);
|
||||
internal F32 dot_4f32(Vec4F32 a, Vec4F32 b);
|
||||
internal F32 length_squared_4f32(Vec4F32 v);
|
||||
internal F32 length_4f32(Vec4F32 v);
|
||||
internal Vec4F32 normalize_4f32(Vec4F32 v);
|
||||
internal Vec4F32 mix_4f32(Vec4F32 a, Vec4F32 b, F32 t);
|
||||
|
||||
#define v4s32(x, y, z, w) vec_4s32((x), (y), (z), (w))
|
||||
internal Vec4S32 vec_4s32(S32 x, S32 y, S32 z, S32 w);
|
||||
internal Vec4S32 add_4s32(Vec4S32 a, Vec4S32 b);
|
||||
internal Vec4S32 sub_4s32(Vec4S32 a, Vec4S32 b);
|
||||
internal Vec4S32 mul_4s32(Vec4S32 a, Vec4S32 b);
|
||||
internal Vec4S32 div_4s32(Vec4S32 a, Vec4S32 b);
|
||||
internal Vec4S32 scale_4s32(Vec4S32 v, S32 s);
|
||||
internal S32 dot_4s32(Vec4S32 a, Vec4S32 b);
|
||||
internal S32 length_squared_4s32(Vec4S32 v);
|
||||
internal S32 length_4s32(Vec4S32 v);
|
||||
internal Vec4S32 normalize_4s32(Vec4S32 v);
|
||||
internal Vec4S32 mix_4s32(Vec4S32 a, Vec4S32 b, F32 t);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Matrix Ops
|
||||
|
||||
internal Mat3x3F32 mat_3x3f32(F32 diagonal);
|
||||
internal Mat3x3F32 make_translate_3x3f32(Vec2F32 delta);
|
||||
internal Mat3x3F32 make_scale_3x3f32(Vec2F32 scale);
|
||||
internal Mat3x3F32 mul_3x3f32(Mat3x3F32 a, Mat3x3F32 b);
|
||||
|
||||
internal Mat4x4F32 mat_4x4f32(F32 diagonal);
|
||||
internal Mat4x4F32 make_translate_4x4f32(Vec3F32 delta);
|
||||
internal Mat4x4F32 make_scale_4x4f32(Vec3F32 scale);
|
||||
internal Mat4x4F32 make_perspective_4x4f32(F32 fov, F32 aspect_ratio, F32 near_z, F32 far_z);
|
||||
internal Mat4x4F32 make_orthographic_4x4f32(F32 left, F32 right, F32 bottom, F32 top, F32 near_z, F32 far_z);
|
||||
internal Mat4x4F32 make_look_at_4x4f32(Vec3F32 eye, Vec3F32 center, Vec3F32 up);
|
||||
internal Mat4x4F32 make_rotate_4x4f32(Vec3F32 axis, F32 turns);
|
||||
internal Mat4x4F32 mul_4x4f32(Mat4x4F32 a, Mat4x4F32 b);
|
||||
internal Mat4x4F32 scale_4x4f32(Mat4x4F32 m, F32 scale);
|
||||
internal Mat4x4F32 inverse_4x4f32(Mat4x4F32 m);
|
||||
internal Mat4x4F32 derotate_4x4f32(Mat4x4F32 mat);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Range Ops
|
||||
|
||||
#define r1u32(min, max) rng_1u32((min), (max))
|
||||
internal Rng1U32 rng_1u32(U32 min, U32 max);
|
||||
internal Rng1U32 shift_1u32(Rng1U32 r, U32 x);
|
||||
internal Rng1U32 pad_1u32(Rng1U32 r, U32 x);
|
||||
internal U32 center_1u32(Rng1U32 r);
|
||||
internal B32 contains_1u32(Rng1U32 r, U32 x);
|
||||
internal U32 dim_1u32(Rng1U32 r);
|
||||
internal Rng1U32 union_1u32(Rng1U32 a, Rng1U32 b);
|
||||
internal Rng1U32 intersect_1u32(Rng1U32 a, Rng1U32 b);
|
||||
internal U32 clamp_1u32(Rng1U32 r, U32 v);
|
||||
|
||||
#define r1s32(min, max) rng_1s32((min), (max))
|
||||
internal Rng1S32 rng_1s32(S32 min, S32 max);
|
||||
internal Rng1S32 shift_1s32(Rng1S32 r, S32 x);
|
||||
internal Rng1S32 pad_1s32(Rng1S32 r, S32 x);
|
||||
internal S32 center_1s32(Rng1S32 r);
|
||||
internal B32 contains_1s32(Rng1S32 r, S32 x);
|
||||
internal S32 dim_1s32(Rng1S32 r);
|
||||
internal Rng1S32 union_1s32(Rng1S32 a, Rng1S32 b);
|
||||
internal Rng1S32 intersect_1s32(Rng1S32 a, Rng1S32 b);
|
||||
internal S32 clamp_1s32(Rng1S32 r, S32 v);
|
||||
|
||||
#define r1u64(min, max) rng_1u64((min), (max))
|
||||
internal Rng1U64 rng_1u64(U64 min, U64 max);
|
||||
internal Rng1U64 shift_1u64(Rng1U64 r, U64 x);
|
||||
internal Rng1U64 pad_1u64(Rng1U64 r, U64 x);
|
||||
internal U64 center_1u64(Rng1U64 r);
|
||||
internal B32 contains_1u64(Rng1U64 r, U64 x);
|
||||
internal U64 dim_1u64(Rng1U64 r);
|
||||
internal Rng1U64 union_1u64(Rng1U64 a, Rng1U64 b);
|
||||
internal Rng1U64 intersect_1u64(Rng1U64 a, Rng1U64 b);
|
||||
internal U64 clamp_1u64(Rng1U64 r, U64 v);
|
||||
|
||||
#define r1s64(min, max) rng_1s64((min), (max))
|
||||
internal Rng1S64 rng_1s64(S64 min, S64 max);
|
||||
internal Rng1S64 shift_1s64(Rng1S64 r, S64 x);
|
||||
internal Rng1S64 pad_1s64(Rng1S64 r, S64 x);
|
||||
internal S64 center_1s64(Rng1S64 r);
|
||||
internal B32 contains_1s64(Rng1S64 r, S64 x);
|
||||
internal S64 dim_1s64(Rng1S64 r);
|
||||
internal Rng1S64 union_1s64(Rng1S64 a, Rng1S64 b);
|
||||
internal Rng1S64 intersect_1s64(Rng1S64 a, Rng1S64 b);
|
||||
internal S64 clamp_1s64(Rng1S64 r, S64 v);
|
||||
|
||||
#define r1f32(min, max) rng_1f32((min), (max))
|
||||
internal Rng1F32 rng_1f32(F32 min, F32 max);
|
||||
internal Rng1F32 shift_1f32(Rng1F32 r, F32 x);
|
||||
internal Rng1F32 pad_1f32(Rng1F32 r, F32 x);
|
||||
internal F32 center_1f32(Rng1F32 r);
|
||||
internal B32 contains_1f32(Rng1F32 r, F32 x);
|
||||
internal F32 dim_1f32(Rng1F32 r);
|
||||
internal Rng1F32 union_1f32(Rng1F32 a, Rng1F32 b);
|
||||
internal Rng1F32 intersect_1f32(Rng1F32 a, Rng1F32 b);
|
||||
internal F32 clamp_1f32(Rng1F32 r, F32 v);
|
||||
|
||||
#define r2s16(min, max) rng_2s16((min), (max))
|
||||
#define r2s16p(x, y, z, w) r2s16(v2s16((x), (y)), v2s16((z), (w)))
|
||||
internal Rng2S16 rng_2s16(Vec2S16 min, Vec2S16 max);
|
||||
internal Rng2S16 shift_2s16(Rng2S16 r, Vec2S16 x);
|
||||
internal Rng2S16 pad_2s16(Rng2S16 r, S16 x);
|
||||
internal Vec2S16 center_2s16(Rng2S16 r);
|
||||
internal B32 contains_2s16(Rng2S16 r, Vec2S16 x);
|
||||
internal Vec2S16 dim_2s16(Rng2S16 r);
|
||||
internal Rng2S16 union_2s16(Rng2S16 a, Rng2S16 b);
|
||||
internal Rng2S16 intersect_2s16(Rng2S16 a, Rng2S16 b);
|
||||
internal Vec2S16 clamp_2s16(Rng2S16 r, Vec2S16 v);
|
||||
|
||||
#define r2s32(min, max) rng_2s32((min), (max))
|
||||
#define r2s32p(x, y, z, w) r2s32(v2s32((x), (y)), v2s32((z), (w)))
|
||||
internal Rng2S32 rng_2s32(Vec2S32 min, Vec2S32 max);
|
||||
internal Rng2S32 shift_2s32(Rng2S32 r, Vec2S32 x);
|
||||
internal Rng2S32 pad_2s32(Rng2S32 r, S32 x);
|
||||
internal Vec2S32 center_2s32(Rng2S32 r);
|
||||
internal B32 contains_2s32(Rng2S32 r, Vec2S32 x);
|
||||
internal Vec2S32 dim_2s32(Rng2S32 r);
|
||||
internal Rng2S32 union_2s32(Rng2S32 a, Rng2S32 b);
|
||||
internal Rng2S32 intersect_2s32(Rng2S32 a, Rng2S32 b);
|
||||
internal Vec2S32 clamp_2s32(Rng2S32 r, Vec2S32 v);
|
||||
|
||||
#define r2s64(min, max) rng_2s64((min), (max))
|
||||
#define r2s64p(x, y, z, w) r2s64(v2s64((x), (y)), v2s64((z), (w)))
|
||||
internal Rng2S64 rng_2s64(Vec2S64 min, Vec2S64 max);
|
||||
internal Rng2S64 shift_2s64(Rng2S64 r, Vec2S64 x);
|
||||
internal Rng2S64 pad_2s64(Rng2S64 r, S64 x);
|
||||
internal Vec2S64 center_2s64(Rng2S64 r);
|
||||
internal B32 contains_2s64(Rng2S64 r, Vec2S64 x);
|
||||
internal Vec2S64 dim_2s64(Rng2S64 r);
|
||||
internal Rng2S64 union_2s64(Rng2S64 a, Rng2S64 b);
|
||||
internal Rng2S64 intersect_2s64(Rng2S64 a, Rng2S64 b);
|
||||
internal Vec2S64 clamp_2s64(Rng2S64 r, Vec2S64 v);
|
||||
|
||||
#define r2f32(min, max) rng_2f32((min), (max))
|
||||
#define r2f32p(x, y, z, w) r2f32(v2f32((x), (y)), v2f32((z), (w)))
|
||||
internal Rng2F32 rng_2f32(Vec2F32 min, Vec2F32 max);
|
||||
internal Rng2F32 shift_2f32(Rng2F32 r, Vec2F32 x);
|
||||
internal Rng2F32 pad_2f32(Rng2F32 r, F32 x);
|
||||
internal Vec2F32 center_2f32(Rng2F32 r);
|
||||
internal B32 contains_2f32(Rng2F32 r, Vec2F32 x);
|
||||
internal Vec2F32 dim_2f32(Rng2F32 r);
|
||||
internal Rng2F32 union_2f32(Rng2F32 a, Rng2F32 b);
|
||||
internal Rng2F32 intersect_2f32(Rng2F32 a, Rng2F32 b);
|
||||
internal Vec2F32 clamp_2f32(Rng2F32 r, Vec2F32 v);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Miscellaneous Ops
|
||||
|
||||
internal Vec3F32 hsv_from_rgb(Vec3F32 rgb);
|
||||
internal Vec3F32 rgb_from_hsv(Vec3F32 hsv);
|
||||
internal Vec4F32 hsva_from_rgba(Vec4F32 rgba);
|
||||
internal Vec4F32 rgba_from_hsva(Vec4F32 hsva);
|
||||
internal Vec4F32 rgba_from_u32(U32 hex);
|
||||
internal U32 u32_from_rgba(Vec4F32 rgba);
|
||||
|
||||
#define rgba_from_u32_lit_comp(h) { (((h)&0xff000000)>>24)/255.f, (((h)&0x00ff0000)>>16)/255.f, (((h)&0x0000ff00)>> 8)/255.f, (((h)&0x000000ff)>> 0)/255.f }
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: List Type Functions
|
||||
|
||||
internal void rng1s64_list_push(Arena *arena, Rng1S64List *list, Rng1S64 rng);
|
||||
internal Rng1S64Array rng1s64_array_from_list(Arena *arena, Rng1S64List *list);
|
||||
|
||||
#endif // BASE_MATH_H
|
||||
@@ -0,0 +1,2 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
@@ -0,0 +1,74 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef BASE_PROFILE_H
|
||||
#define BASE_PROFILE_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Zero Settings
|
||||
|
||||
#if !defined(PROFILE_TELEMETRY)
|
||||
# define PROFILE_TELEMETRY 0
|
||||
#endif
|
||||
|
||||
#if !defined(MARKUP_LAYER_COLOR)
|
||||
# define MARKUP_LAYER_COLOR 1.00f, 0.00f, 1.00f
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Third Party Includes
|
||||
|
||||
#if PROFILE_TELEMETRY
|
||||
# include "rad_tm.h"
|
||||
# if OS_WINDOWS
|
||||
# pragma comment(lib, "rad_tm_win64.lib")
|
||||
# endif
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Telemetry Profile Defines
|
||||
|
||||
#if PROFILE_TELEMETRY
|
||||
# define ProfBegin(...) tmEnter(0, 0, __VA_ARGS__)
|
||||
# define ProfBeginDynamic(...) (TM_API_PTR ? TM_API_PTR->_tmEnterZoneV_Core(0, 0, __FILE__, &g_telemetry_filename_id, __LINE__, __VA_ARGS__) : (void)0)
|
||||
# define ProfEnd(...) (TM_API_PTR ? TM_API_PTR->_tmLeaveZone(0) : (void)0)
|
||||
# define ProfTick(...) tmTick(0)
|
||||
# define ProfIsCapturing(...) tmRunning()
|
||||
# define ProfBeginCapture(...) tmOpen(0, __VA_ARGS__, __DATE__, "localhost", TMCT_TCP, TELEMETRY_DEFAULT_PORT, TMOF_INIT_NETWORKING|TMOF_CAPTURE_CONTEXT_SWITCHES, 100)
|
||||
# define ProfEndCapture(...) tmClose(0)
|
||||
# define ProfThreadName(...) (TM_API_PTR ? TM_API_PTR->_tmThreadName(0, 0, __VA_ARGS__) : (void)0)
|
||||
# define ProfMsg(...) (TM_API_PTR ? TM_API_PTR->_tmMessageV_Core(0, TMMF_ICON_NOTE, __FILE__, &g_telemetry_filename_id, __LINE__, __VA_ARGS__) : (void)0)
|
||||
# define ProfBeginLockWait(...) tmStartWaitForLock(0, 0, __VA_ARGS__)
|
||||
# define ProfEndLockWait(...) tmEndWaitForLock(0)
|
||||
# define ProfLockTake(...) tmAcquiredLock(0, 0, __VA_ARGS__)
|
||||
# define ProfLockDrop(...) tmReleasedLock(0, __VA_ARGS__)
|
||||
# define ProfColor(color) tmZoneColorSticky(color)
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Zeroify Undefined Defines
|
||||
|
||||
#if !defined(ProfBegin)
|
||||
# define ProfBegin(...) (0)
|
||||
# define ProfBeginDynamic(...) (0)
|
||||
# define ProfEnd(...) (0)
|
||||
# define ProfTick(...) (0)
|
||||
# define ProfIsCapturing(...) (0)
|
||||
# define ProfBeginCapture(...) (0)
|
||||
# define ProfEndCapture(...) (0)
|
||||
# define ProfThreadName(...) (0)
|
||||
# define ProfMsg(...) (0)
|
||||
# define ProfBeginLockWait(...) (0)
|
||||
# define ProfEndLockWait(...) (0)
|
||||
# define ProfLockTake(...) (0)
|
||||
# define ProfLockDrop(...) (0)
|
||||
# define ProfColor(...) (0)
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Helper Wrappers
|
||||
|
||||
#define ProfBeginFunction(...) ProfBegin(this_function_name)
|
||||
#define ProfScope(...) DeferLoop(ProfBeginDynamic(__VA_ARGS__), ProfEnd())
|
||||
|
||||
#endif // BASE_PROFILE_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,381 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef BASE_STRINGS_H
|
||||
#define BASE_STRINGS_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Third Party Includes
|
||||
|
||||
#define STB_SPRINTF_DECORATE(name) raddbg_##name
|
||||
#include "third_party/stb/stb_sprintf.h"
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: String Types
|
||||
|
||||
typedef struct String8 String8;
|
||||
struct String8
|
||||
{
|
||||
U8 *str;
|
||||
U64 size;
|
||||
};
|
||||
|
||||
typedef struct String16 String16;
|
||||
struct String16
|
||||
{
|
||||
U16 *str;
|
||||
U64 size;
|
||||
};
|
||||
|
||||
typedef struct String32 String32;
|
||||
struct String32
|
||||
{
|
||||
U32 *str;
|
||||
U64 size;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: String List & Array Types
|
||||
|
||||
typedef struct String8Node String8Node;
|
||||
struct String8Node
|
||||
{
|
||||
String8Node *next;
|
||||
String8 string;
|
||||
};
|
||||
|
||||
typedef struct String8MetaNode String8MetaNode;
|
||||
struct String8MetaNode
|
||||
{
|
||||
String8MetaNode *next;
|
||||
String8Node *node;
|
||||
};
|
||||
|
||||
typedef struct String8List String8List;
|
||||
struct String8List
|
||||
{
|
||||
String8Node *first;
|
||||
String8Node *last;
|
||||
U64 node_count;
|
||||
U64 total_size;
|
||||
};
|
||||
|
||||
typedef struct String8Array String8Array;
|
||||
struct String8Array
|
||||
{
|
||||
String8 *v;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: String Matching, Splitting, & Joining Types
|
||||
|
||||
typedef U32 StringMatchFlags;
|
||||
enum
|
||||
{
|
||||
StringMatchFlag_CaseInsensitive = (1 << 0),
|
||||
StringMatchFlag_RightSideSloppy = (1 << 1),
|
||||
StringMatchFlag_SlashInsensitive = (1 << 2),
|
||||
};
|
||||
|
||||
typedef U32 StringSplitFlags;
|
||||
enum
|
||||
{
|
||||
StringSplitFlag_KeepEmpties = (1 << 0),
|
||||
};
|
||||
|
||||
typedef enum PathStyle
|
||||
{
|
||||
PathStyle_Relative,
|
||||
PathStyle_WindowsAbsolute,
|
||||
PathStyle_UnixAbsolute,
|
||||
|
||||
#if OS_WINDOWS
|
||||
PathStyle_SystemAbsolute = PathStyle_WindowsAbsolute
|
||||
#elif OS_LINUX
|
||||
PathStyle_SystemAbsolute = PathStyle_UnixAbsolute
|
||||
#else
|
||||
# error "absolute path style is undefined for this OS"
|
||||
#endif
|
||||
}
|
||||
PathStyle;
|
||||
|
||||
typedef struct StringJoin StringJoin;
|
||||
struct StringJoin
|
||||
{
|
||||
String8 pre;
|
||||
String8 sep;
|
||||
String8 post;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: String Pair Types
|
||||
|
||||
typedef struct String8TxtPtPair String8TxtPtPair;
|
||||
struct String8TxtPtPair
|
||||
{
|
||||
String8 string;
|
||||
TxtPt pt;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: UTF Decoding Types
|
||||
|
||||
typedef struct UnicodeDecode UnicodeDecode;
|
||||
struct UnicodeDecode
|
||||
{
|
||||
U32 inc;
|
||||
U32 codepoint;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: String Fuzzy Matching Types
|
||||
|
||||
typedef struct FuzzyMatchRangeNode FuzzyMatchRangeNode;
|
||||
struct FuzzyMatchRangeNode
|
||||
{
|
||||
FuzzyMatchRangeNode *next;
|
||||
Rng1U64 range;
|
||||
};
|
||||
|
||||
typedef struct FuzzyMatchRangeList FuzzyMatchRangeList;
|
||||
struct FuzzyMatchRangeList
|
||||
{
|
||||
FuzzyMatchRangeNode *first;
|
||||
FuzzyMatchRangeNode *last;
|
||||
U64 count;
|
||||
U64 needle_part_count;
|
||||
U64 total_dim;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Character Classification & Conversion Functions
|
||||
|
||||
internal B32 char_is_space(U8 c);
|
||||
internal B32 char_is_upper(U8 c);
|
||||
internal B32 char_is_lower(U8 c);
|
||||
internal B32 char_is_alpha(U8 c);
|
||||
internal B32 char_is_slash(U8 c);
|
||||
internal B32 char_is_digit(U8 c, U32 base);
|
||||
internal U8 char_to_lower(U8 c);
|
||||
internal U8 char_to_upper(U8 c);
|
||||
internal U8 char_to_correct_slash(U8 c);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: C-String Measurement
|
||||
|
||||
internal U64 cstring8_length(U8 *c);
|
||||
internal U64 cstring16_length(U16 *c);
|
||||
internal U64 cstring32_length(U32 *c);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: String Constructors
|
||||
|
||||
#define str8_lit(S) str8((U8*)(S), sizeof(S) - 1)
|
||||
#define str8_lit_comp(S) {(U8*)(S), sizeof(S) - 1,}
|
||||
#define str8_varg(S) (int)((S).size), ((S).str)
|
||||
|
||||
#define str8_array(S,C) str8((U8*)(S), sizeof(*(S))*(C))
|
||||
#define str8_array_fixed(S) str8((U8*)(S), sizeof(S))
|
||||
#define str8_struct(S) str8((U8*)(S), sizeof(*(S)))
|
||||
|
||||
internal String8 str8(U8 *str, U64 size);
|
||||
internal String8 str8_range(U8 *first, U8 *one_past_last);
|
||||
internal String8 str8_zero(void);
|
||||
internal String16 str16(U16 *str, U64 size);
|
||||
internal String16 str16_range(U16 *first, U16 *one_past_last);
|
||||
internal String16 str16_zero(void);
|
||||
internal String32 str32(U32 *str, U64 size);
|
||||
internal String32 str32_range(U32 *first, U32 *one_past_last);
|
||||
internal String32 str32_zero(void);
|
||||
internal String8 str8_cstring(char *c);
|
||||
internal String16 str16_cstring(U16 *c);
|
||||
internal String32 str32_cstring(U32 *c);
|
||||
internal String8 str8_cstring_capped(void *cstr, void *cap);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: String Stylization
|
||||
|
||||
internal String8 upper_from_str8(Arena *arena, String8 string);
|
||||
internal String8 lower_from_str8(Arena *arena, String8 string);
|
||||
internal String8 backslashed_from_str8(Arena *arena, String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: String Matching
|
||||
|
||||
internal B32 str8_match(String8 a, String8 b, StringMatchFlags flags);
|
||||
internal U64 str8_find_needle(String8 string, U64 start_pos, String8 needle, StringMatchFlags flags);
|
||||
internal B32 str8_ends_with(String8 string, String8 end, StringMatchFlags flags);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: String Slicing
|
||||
|
||||
internal String8 str8_substr(String8 str, Rng1U64 range);
|
||||
internal String8 str8_prefix(String8 str, U64 size);
|
||||
internal String8 str8_skip(String8 str, U64 amt);
|
||||
internal String8 str8_postfix(String8 str, U64 size);
|
||||
internal String8 str8_chop(String8 str, U64 amt);
|
||||
internal String8 str8_skip_chop_whitespace(String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: String Formatting & Copying
|
||||
|
||||
internal String8 push_str8_cat(Arena *arena, String8 s1, String8 s2);
|
||||
internal String8 push_str8_copy(Arena *arena, String8 s);
|
||||
internal String8 push_str8fv(Arena *arena, char *fmt, va_list args);
|
||||
internal String8 push_str8f(Arena *arena, char *fmt, ...);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: String <=> Integer Conversions
|
||||
|
||||
//- rjf: string -> integer
|
||||
internal S64 sign_from_str8(String8 string, String8 *string_tail);
|
||||
internal B32 str8_is_integer(String8 string, U32 radix);
|
||||
internal U64 u64_from_str8(String8 string, U32 radix);
|
||||
internal S64 s64_from_str8(String8 string, U32 radix);
|
||||
internal B32 try_u64_from_str8_c_rules(String8 string, U64 *x);
|
||||
internal B32 try_s64_from_str8_c_rules(String8 string, S64 *x);
|
||||
|
||||
//- rjf: integer -> string
|
||||
internal String8 str8_from_memory_size(Arena *arena, U64 z);
|
||||
internal String8 str8_from_u64(Arena *arena, U64 u64, U32 radix, U8 min_digits, U8 digit_group_separator);
|
||||
internal String8 str8_from_s64(Arena *arena, S64 s64, U32 radix, U8 min_digits, U8 digit_group_separator);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: String <=> Float Conversions
|
||||
|
||||
internal F64 f64_from_str8(String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: String List Construction Functions
|
||||
|
||||
internal String8Node* str8_list_push_node(String8List *list, String8Node *node);
|
||||
internal String8Node* str8_list_push_node_set_string(String8List *list, String8Node *node, String8 string);
|
||||
internal String8Node* str8_list_push_node_front(String8List *list, String8Node *node);
|
||||
internal String8Node* str8_list_push_node_front_set_string(String8List *list, String8Node *node, String8 string);
|
||||
internal String8Node* str8_list_push(Arena *arena, String8List *list, String8 string);
|
||||
internal String8Node* str8_list_push_front(Arena *arena, String8List *list, String8 string);
|
||||
internal void str8_list_concat_in_place(String8List *list, String8List *to_push);
|
||||
internal String8Node* str8_list_push_aligner(Arena *arena, String8List *list, U64 min, U64 align);
|
||||
internal String8Node* str8_list_pushf(Arena *arena, String8List *list, char *fmt, ...);
|
||||
internal String8Node* str8_list_push_frontf(Arena *arena, String8List *list, char *fmt, ...);
|
||||
internal String8List str8_list_copy(Arena *arena, String8List *list);
|
||||
#define str8_list_first(list) ((list)->first ? (list)->first->string : str8_zero())
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: String Splitting & Joining
|
||||
|
||||
internal String8List str8_split(Arena *arena, String8 string, U8 *split_chars, U64 split_char_count, StringSplitFlags flags);
|
||||
internal String8List str8_split_by_string_chars(Arena *arena, String8 string, String8 split_chars, StringSplitFlags flags);
|
||||
internal String8List str8_list_split_by_string_chars(Arena *arena, String8List list, String8 split_chars, StringSplitFlags flags);
|
||||
internal String8 str8_list_join(Arena *arena, String8List *list, StringJoin *optional_params);
|
||||
internal void str8_list_from_flags(Arena *arena, String8List *list, U32 flags, String8 *flag_string_table, U32 flag_string_count);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf; String Arrays
|
||||
|
||||
internal String8Array str8_array_from_list(Arena *arena, String8List *list);
|
||||
internal String8Array str8_array_reserve(Arena *arena, U64 count);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: String Path Helpers
|
||||
|
||||
internal String8 str8_chop_last_slash(String8 string);
|
||||
internal String8 str8_skip_last_slash(String8 string);
|
||||
internal String8 str8_chop_last_dot(String8 string);
|
||||
internal String8 str8_skip_last_dot(String8 string);
|
||||
|
||||
internal PathStyle path_style_from_str8(String8 string);
|
||||
internal String8List str8_split_path(Arena *arena, String8 string);
|
||||
internal void str8_path_list_resolve_dots_in_place(String8List *path, PathStyle style);
|
||||
internal String8 str8_path_list_join_by_style(Arena *arena, String8List *path, PathStyle style);
|
||||
|
||||
internal String8TxtPtPair str8_txt_pt_pair_from_string(String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: UTF-8 & UTF-16 Decoding/Encoding
|
||||
|
||||
internal UnicodeDecode utf8_decode(U8 *str, U64 max);
|
||||
internal UnicodeDecode utf16_decode(U16 *str, U64 max);
|
||||
internal U32 utf8_encode(U8 *str, U32 codepoint);
|
||||
internal U32 utf16_encode(U16 *str, U32 codepoint);
|
||||
internal U32 utf8_from_utf32_single(U8 *buffer, U32 character);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Unicode String Conversions
|
||||
|
||||
internal String8 str8_from_16(Arena *arena, String16 in);
|
||||
internal String16 str16_from_8(Arena *arena, String8 in);
|
||||
internal String8 str8_from_32(Arena *arena, String32 in);
|
||||
internal String32 str32_from_8(Arena *arena, String8 in);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Basic Types & Space Enum -> String Conversions
|
||||
|
||||
internal String8 string_from_dimension(Dimension dimension);
|
||||
internal String8 string_from_side(Side side);
|
||||
internal String8 string_from_operating_system(OperatingSystem os);
|
||||
internal String8 string_from_architecture(Architecture arch);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Time Types -> String
|
||||
|
||||
internal String8 string_from_week_day(WeekDay week_day);
|
||||
internal String8 string_from_month(Month month);
|
||||
internal String8 push_date_time_string(Arena *arena, DateTime *date_time);
|
||||
internal String8 push_file_name_date_time_string(Arena *arena, DateTime *date_time);
|
||||
internal String8 string_from_elapsed_time(Arena *arena, DateTime dt);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Basic Text Indentation
|
||||
|
||||
internal String8 indented_from_string(Arena *arena, String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Text Wrapping
|
||||
|
||||
internal String8List wrapped_lines_from_string(Arena *arena, String8 string, U64 first_line_max_width, U64 max_width, U64 wrap_indent);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: String <-> Color
|
||||
|
||||
internal String8 hex_string_from_rgba_4f32(Arena *arena, Vec4F32 rgba);
|
||||
internal Vec4F32 rgba_from_hex_string_4f32(String8 hex_string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: String Fuzzy Matching
|
||||
|
||||
internal FuzzyMatchRangeList fuzzy_match_find(Arena *arena, String8 needle, String8 haystack);
|
||||
internal FuzzyMatchRangeList fuzzy_match_range_list_copy(Arena *arena, FuzzyMatchRangeList *src);
|
||||
|
||||
////////////////////////////////
|
||||
//~ NOTE(allen): Serialization Helpers
|
||||
|
||||
internal void str8_serial_begin(Arena *arena, String8List *srl);
|
||||
internal String8 str8_serial_end(Arena *arena, String8List *srl);
|
||||
internal void str8_serial_write_to_dst(String8List *srl, void *out);
|
||||
internal U64 str8_serial_push_align(Arena *arena, String8List *srl, U64 align);
|
||||
internal void * str8_serial_push_size(Arena *arena, String8List *srl, U64 size);
|
||||
internal void * str8_serial_push_data(Arena *arena, String8List *srl, void *data, U64 size);
|
||||
internal void str8_serial_push_data_list(Arena *arena, String8List *srl, String8Node *first);
|
||||
internal void str8_serial_push_u64(Arena *arena, String8List *srl, U64 x);
|
||||
internal void str8_serial_push_u32(Arena *arena, String8List *srl, U32 x);
|
||||
internal void str8_serial_push_u16(Arena *arena, String8List *srl, U16 x);
|
||||
internal void str8_serial_push_u8(Arena *arena, String8List *srl, U8 x);
|
||||
internal void str8_serial_push_cstr(Arena *arena, String8List *srl, String8 str);
|
||||
internal void str8_serial_push_string(Arena *arena, String8List *srl, String8 str);
|
||||
#define str8_serial_push_array(arena, srl, ptr, count) str8_serial_push_data(arena, srl, ptr, sizeof(*(ptr)) * (count))
|
||||
#define str8_serial_push_struct(arena, srl, ptr) str8_serial_push_array(arena, srl, ptr, 1)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Deserialization Helpers
|
||||
|
||||
internal U64 str8_deserial_read(String8 string, U64 off, void *read_dst, U64 read_size, U64 granularity);
|
||||
internal U64 str8_deserial_find_first_match(String8 string, U64 off, U16 scan_val);
|
||||
internal void * str8_deserial_get_raw_ptr(String8 string, U64 off, U64 size);internal U64 str8_deserial_read_cstr(String8 string, U64 off, String8 *cstr_out);
|
||||
internal U64 str8_deserial_read_windows_utf16_string16(String8 string, U64 off, String16 *str_out);
|
||||
internal U64 str8_deserial_read_block(String8 string, U64 off, U64 size, String8 *block_out);
|
||||
#define str8_deserial_read_array(string, off, ptr, count) str8_deserial_read((string), (off), (ptr), sizeof(*(ptr))*(count), sizeof(*(ptr)))
|
||||
#define str8_deserial_read_struct(string, off, ptr) str8_deserial_read((string), (off), (ptr), sizeof(*(ptr)), sizeof(*(ptr)))
|
||||
|
||||
#endif // BASE_STRINGS_H
|
||||
@@ -0,0 +1,87 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
// NOTE(allen): Thread Context Functions
|
||||
|
||||
C_LINKAGE thread_static TCTX* tctx_thread_local;
|
||||
#if !BUILD_SUPPLEMENTARY_UNIT
|
||||
C_LINKAGE thread_static TCTX* tctx_thread_local = 0;
|
||||
#endif
|
||||
|
||||
internal void
|
||||
tctx_init_and_equip(TCTX *tctx){
|
||||
MemoryZeroStruct(tctx);
|
||||
Arena **arena_ptr = tctx->arenas;
|
||||
for (U64 i = 0; i < ArrayCount(tctx->arenas); i += 1, arena_ptr += 1){
|
||||
*arena_ptr = arena_alloc();
|
||||
}
|
||||
tctx_thread_local = tctx;
|
||||
}
|
||||
|
||||
internal void
|
||||
tctx_release(void)
|
||||
{
|
||||
for(U64 i = 0; i < ArrayCount(tctx_thread_local->arenas); i += 1)
|
||||
{
|
||||
arena_release(tctx_thread_local->arenas[i]);
|
||||
}
|
||||
}
|
||||
|
||||
internal TCTX*
|
||||
tctx_get_equipped(void){
|
||||
return(tctx_thread_local);
|
||||
}
|
||||
|
||||
internal Arena*
|
||||
tctx_get_scratch(Arena **conflicts, U64 count){
|
||||
TCTX *tctx = tctx_get_equipped();
|
||||
|
||||
Arena *result = 0;
|
||||
Arena **arena_ptr = tctx->arenas;
|
||||
for (U64 i = 0; i < ArrayCount(tctx->arenas); i += 1, arena_ptr += 1){
|
||||
Arena **conflict_ptr = conflicts;
|
||||
B32 has_conflict = 0;
|
||||
for (U64 j = 0; j < count; j += 1, conflict_ptr += 1){
|
||||
if (*arena_ptr == *conflict_ptr){
|
||||
has_conflict = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!has_conflict){
|
||||
result = *arena_ptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal void
|
||||
tctx_set_thread_name(String8 string){
|
||||
TCTX *tctx = tctx_get_equipped();
|
||||
U64 size = ClampTop(string.size, sizeof(tctx->thread_name));
|
||||
MemoryCopy(tctx->thread_name, string.str, size);
|
||||
tctx->thread_name_size = size;
|
||||
}
|
||||
|
||||
internal String8
|
||||
tctx_get_thread_name(void){
|
||||
TCTX *tctx = tctx_get_equipped();
|
||||
String8 result = str8(tctx->thread_name, tctx->thread_name_size);
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal void
|
||||
tctx_write_srcloc(char *file_name, U64 line_number){
|
||||
TCTX *tctx = tctx_get_equipped();
|
||||
tctx->file_name = file_name;
|
||||
tctx->line_number = line_number;
|
||||
}
|
||||
|
||||
internal void
|
||||
tctx_read_srcloc(char **file_name, U64 *line_number){
|
||||
TCTX *tctx = tctx_get_equipped();
|
||||
*file_name = tctx->file_name;
|
||||
*line_number = tctx->line_number;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef BASE_THREAD_CONTEXT_H
|
||||
#define BASE_THREAD_CONTEXT_H
|
||||
|
||||
////////////////////////////////
|
||||
// NOTE(allen): Thread Context
|
||||
|
||||
typedef struct TCTX TCTX;
|
||||
struct TCTX
|
||||
{
|
||||
Arena *arenas[2];
|
||||
|
||||
U8 thread_name[32];
|
||||
U64 thread_name_size;
|
||||
|
||||
char *file_name;
|
||||
U64 line_number;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
// NOTE(allen): Thread Context Functions
|
||||
|
||||
internal void tctx_init_and_equip(TCTX *tctx);
|
||||
internal void tctx_release(void);
|
||||
internal TCTX* tctx_get_equipped(void);
|
||||
|
||||
internal Arena* tctx_get_scratch(Arena **conflicts, U64 count);
|
||||
|
||||
internal void tctx_set_thread_name(String8 name);
|
||||
internal String8 tctx_get_thread_name(void);
|
||||
|
||||
internal void tctx_write_srcloc(char *file_name, U64 line_number);
|
||||
internal void tctx_read_srcloc(char **file_name, U64 *line_number);
|
||||
#define tctx_write_this_srcloc() tctx_write_srcloc(__FILE__, __LINE__)
|
||||
|
||||
#define scratch_begin(conflicts, count) temp_begin(tctx_get_scratch((conflicts), (count)))
|
||||
#define scratch_end(scratch) temp_end(scratch)
|
||||
|
||||
#endif // BASE_THREAD_CONTEXT_H
|
||||
@@ -0,0 +1,656 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Build Options
|
||||
|
||||
#define BUILD_CONSOLE_INTERFACE 1
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Includes
|
||||
|
||||
//- rjf: headers
|
||||
#include "metagen/metagen_base/metagen_base_inc.h"
|
||||
#include "metagen/metagen_os/metagen_os_inc.h"
|
||||
#include "mdesk/mdesk.h"
|
||||
#include "metagen.h"
|
||||
|
||||
//- rjf: impls
|
||||
#include "metagen/metagen_base/metagen_base_inc.c"
|
||||
#include "metagen/metagen_os/metagen_os_inc.c"
|
||||
#include "mdesk/mdesk.c"
|
||||
#include "metagen.c"
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Entry Point
|
||||
|
||||
internal void
|
||||
entry_point(CmdLine *cmdline)
|
||||
{
|
||||
//////////////////////////////
|
||||
//- rjf: set up state
|
||||
//
|
||||
MG_MsgList msgs = {0};
|
||||
mg_arena = arena_alloc(.reserve_size = GB(64), .commit_size = MB(64));
|
||||
mg_state = push_array(mg_arena, MG_State, 1);
|
||||
mg_state->slots_count = 256;
|
||||
mg_state->slots = push_array(mg_arena, MG_LayerSlot, mg_state->slots_count);
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: extract paths
|
||||
//
|
||||
String8 build_dir_path = os_get_process_info()->binary_path;
|
||||
String8 project_dir_path = str8_chop_last_slash(build_dir_path);
|
||||
String8 code_dir_path = push_str8f(mg_arena, "%S/src", project_dir_path);
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: search code directories for all files to consider
|
||||
//
|
||||
String8List file_paths = {0};
|
||||
DeferLoop(printf("searching %.*s...", str8_varg(code_dir_path)), printf(" %i files found\n", (int)file_paths.node_count))
|
||||
{
|
||||
typedef struct Task Task;
|
||||
struct Task
|
||||
{
|
||||
Task *next;
|
||||
String8 path;
|
||||
};
|
||||
Task start_task = {0, code_dir_path};
|
||||
Task *first_task = &start_task;
|
||||
Task *last_task = &start_task;
|
||||
for(Task *task = first_task; task != 0; task = task->next)
|
||||
{
|
||||
OS_FileIter *it = os_file_iter_begin(mg_arena, task->path, 0);
|
||||
for(OS_FileInfo info = {0}; os_file_iter_next(mg_arena, it, &info);)
|
||||
{
|
||||
String8 file_path = push_str8f(mg_arena, "%S/%S", task->path, info.name);
|
||||
if(info.props.flags & FilePropertyFlag_IsFolder)
|
||||
{
|
||||
Task *next_task = push_array(mg_arena, Task, 1);
|
||||
SLLQueuePush(first_task, last_task, next_task);
|
||||
next_task->path = file_path;
|
||||
}
|
||||
else
|
||||
{
|
||||
str8_list_push(mg_arena, &file_paths, file_path);
|
||||
}
|
||||
}
|
||||
os_file_iter_end(it);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: parse all metadesk files
|
||||
//
|
||||
MG_FileParseList parses = {0};
|
||||
DeferLoop(printf("parsing metadesk..."), printf(" %i metadesk files parsed\n", (int)parses.count))
|
||||
{
|
||||
for(String8Node *n = file_paths.first; n != 0; n = n->next)
|
||||
{
|
||||
String8 file_path = n->string;
|
||||
String8 file_ext = str8_skip_last_dot(file_path);
|
||||
if(str8_match(file_ext, str8_lit("mdesk"), 0))
|
||||
{
|
||||
String8 data = os_data_from_file_path(mg_arena, file_path);
|
||||
MD_TokenizeResult tokenize = md_tokenize_from_text(mg_arena, data);
|
||||
MD_ParseResult parse = md_parse_from_text_tokens(mg_arena, file_path, data, tokenize.tokens);
|
||||
for(MD_Msg *m = parse.msgs.first; m != 0; m = m->next)
|
||||
{
|
||||
TxtPt pt = mg_txt_pt_from_string_off(data, m->node->src_offset);
|
||||
String8 msg_kind_string = {0};
|
||||
switch(m->kind)
|
||||
{
|
||||
default:{}break;
|
||||
case MD_MsgKind_Note: {msg_kind_string = str8_lit("note");}break;
|
||||
case MD_MsgKind_Warning: {msg_kind_string = str8_lit("warning");}break;
|
||||
case MD_MsgKind_Error: {msg_kind_string = str8_lit("error");}break;
|
||||
case MD_MsgKind_FatalError: {msg_kind_string = str8_lit("fatal error");}break;
|
||||
}
|
||||
String8 location = push_str8f(mg_arena, "%S:%I64d:%I64d", file_path, pt.line, pt.column);
|
||||
MG_Msg dst_m = {location, msg_kind_string, m->string};
|
||||
mg_msg_list_push(mg_arena, &msgs, &dst_m);
|
||||
}
|
||||
MG_FileParseNode *parse_n = push_array(mg_arena, MG_FileParseNode, 1);
|
||||
SLLQueuePush(parses.first, parses.last, parse_n);
|
||||
parse_n->v.root = parse.root;
|
||||
parses.count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: gather tables
|
||||
//
|
||||
MG_Map table_grid_map = mg_push_map(mg_arena, 1024);
|
||||
MG_Map table_col_map = mg_push_map(mg_arena, 1024);
|
||||
U64 table_count = 0;
|
||||
DeferLoop(printf("gathering tables..."), printf(" %i tables found\n", (int)table_count))
|
||||
{
|
||||
for(MG_FileParseNode *n = parses.first; n != 0; n = n->next)
|
||||
{
|
||||
MD_Node *file = n->v.root;
|
||||
for MD_EachNode(node, file->first)
|
||||
{
|
||||
MD_Node *table_tag = md_tag_from_string(node, str8_lit("table"), 0);
|
||||
if(!md_node_is_nil(table_tag))
|
||||
{
|
||||
MG_NodeGrid *table = push_array(mg_arena, MG_NodeGrid, 1);
|
||||
MG_ColumnDescArray *col_descs = push_array(mg_arena, MG_ColumnDescArray, 1);
|
||||
*table = mg_node_grid_make_from_node(mg_arena, node);
|
||||
*col_descs = mg_column_desc_array_from_tag(mg_arena, table_tag);
|
||||
mg_map_insert_ptr(mg_arena, &table_grid_map, node->string, table);
|
||||
mg_map_insert_ptr(mg_arena, &table_col_map, node->string, col_descs);
|
||||
table_count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: gather layer options
|
||||
//
|
||||
for(MG_FileParseNode *n = parses.first; n != 0; n = n->next)
|
||||
{
|
||||
MD_Node *file = n->v.root;
|
||||
String8 layer_key = mg_layer_key_from_path(file->string);
|
||||
MG_Layer *layer = mg_layer_from_key(layer_key);
|
||||
for MD_EachNode(node, file->first)
|
||||
{
|
||||
if(md_node_has_tag(node, str8_lit("option"), 0))
|
||||
{
|
||||
if(str8_match(node->string, str8_lit("library"), 0))
|
||||
{
|
||||
layer->is_library = 1;
|
||||
}
|
||||
}
|
||||
if(md_node_has_tag(node, str8_lit("gen_folder"), 0))
|
||||
{
|
||||
layer->gen_folder_name = node->string;
|
||||
}
|
||||
if(md_node_has_tag(node, str8_lit("h_name"), 0))
|
||||
{
|
||||
layer->h_name_override = node->string;
|
||||
}
|
||||
if(md_node_has_tag(node, str8_lit("c_name"), 0))
|
||||
{
|
||||
layer->c_name_override = node->string;
|
||||
}
|
||||
if(md_node_has_tag(node, str8_lit("h_header"), 0))
|
||||
{
|
||||
String8List gen_strings = mg_string_list_from_table_gen(mg_arena, table_grid_map, table_col_map, str8_lit(""), node);
|
||||
for(String8Node *n = gen_strings.first; n != 0; n = n->next)
|
||||
{
|
||||
str8_list_push(mg_arena, &layer->h_header, n->string);
|
||||
str8_list_push(mg_arena, &layer->h_header, str8_lit("\n"));
|
||||
}
|
||||
}
|
||||
if(md_node_has_tag(node, str8_lit("h_footer"), 0))
|
||||
{
|
||||
String8List gen_strings = mg_string_list_from_table_gen(mg_arena, table_grid_map, table_col_map, str8_lit(""), node);
|
||||
for(String8Node *n = gen_strings.first; n != 0; n = n->next)
|
||||
{
|
||||
str8_list_push(mg_arena, &layer->h_footer, n->string);
|
||||
str8_list_push(mg_arena, &layer->h_footer, str8_lit("\n"));
|
||||
}
|
||||
}
|
||||
if(md_node_has_tag(node, str8_lit("c_header"), 0))
|
||||
{
|
||||
String8List gen_strings = mg_string_list_from_table_gen(mg_arena, table_grid_map, table_col_map, str8_lit(""), node);
|
||||
for(String8Node *n = gen_strings.first; n != 0; n = n->next)
|
||||
{
|
||||
str8_list_push(mg_arena, &layer->c_header, n->string);
|
||||
str8_list_push(mg_arena, &layer->c_header, str8_lit("\n"));
|
||||
}
|
||||
}
|
||||
if(md_node_has_tag(node, str8_lit("c_footer"), 0))
|
||||
{
|
||||
String8List gen_strings = mg_string_list_from_table_gen(mg_arena, table_grid_map, table_col_map, str8_lit(""), node);
|
||||
for(String8Node *n = gen_strings.first; n != 0; n = n->next)
|
||||
{
|
||||
str8_list_push(mg_arena, &layer->c_footer, n->string);
|
||||
str8_list_push(mg_arena, &layer->c_footer, str8_lit("\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: generate enums
|
||||
//
|
||||
for(MG_FileParseNode *n = parses.first; n != 0; n = n->next)
|
||||
{
|
||||
MD_Node *file = n->v.root;
|
||||
for MD_EachNode(node, file->first)
|
||||
{
|
||||
MD_Node *tag = md_tag_from_string(node, str8_lit("enum"), 0);
|
||||
if(!md_node_is_nil(tag))
|
||||
{
|
||||
String8 enum_name = node->string;
|
||||
String8 enum_member_prefix = enum_name;
|
||||
if(str8_match(str8_postfix(enum_name, 5), str8_lit("Flags"), 0))
|
||||
{
|
||||
enum_member_prefix = str8_chop(enum_name, 1);
|
||||
}
|
||||
String8 enum_base_type_name = tag->first->string;
|
||||
String8 layer_key = mg_layer_key_from_path(file->string);
|
||||
MG_Layer *layer = mg_layer_from_key(layer_key);
|
||||
String8List gen_strings = mg_string_list_from_table_gen(mg_arena, table_grid_map, table_col_map, str8_lit(""), node);
|
||||
if(enum_base_type_name.size == 0)
|
||||
{
|
||||
str8_list_pushf(mg_arena, &layer->enums, "typedef enum %S\n{\n", enum_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
str8_list_pushf(mg_arena, &layer->enums, "typedef %S %S;\n", enum_base_type_name, enum_name);
|
||||
str8_list_pushf(mg_arena, &layer->enums, "typedef enum %SEnum\n{\n", enum_name);
|
||||
}
|
||||
for(String8Node *n = gen_strings.first; n != 0; n = n->next)
|
||||
{
|
||||
String8 escaped = mg_escaped_from_str8(mg_arena, n->string);
|
||||
str8_list_pushf(mg_arena, &layer->enums, "%S_%S,\n", enum_member_prefix, escaped);
|
||||
}
|
||||
if(enum_base_type_name.size == 0)
|
||||
{
|
||||
str8_list_pushf(mg_arena, &layer->enums, "} %S;\n\n", enum_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
str8_list_pushf(mg_arena, &layer->enums, "} %SEnum;\n\n", enum_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: generate xlists
|
||||
//
|
||||
for(MG_FileParseNode *n = parses.first; n != 0; n = n->next)
|
||||
{
|
||||
MD_Node *file = n->v.root;
|
||||
for MD_EachNode(node, file->first)
|
||||
{
|
||||
MD_Node *tag = md_tag_from_string(node, str8_lit("xlist"), 0);
|
||||
if(!md_node_is_nil(tag))
|
||||
{
|
||||
String8 layer_key = mg_layer_key_from_path(file->string);
|
||||
MG_Layer *layer = mg_layer_from_key(layer_key);
|
||||
String8List gen_strings = mg_string_list_from_table_gen(mg_arena, table_grid_map, table_col_map, str8_lit(""), node);
|
||||
str8_list_pushf(mg_arena, &layer->enums, "#define %S \\\n", node->string);
|
||||
for(String8Node *n = gen_strings.first; n != 0; n = n->next)
|
||||
{
|
||||
String8 escaped = mg_escaped_from_str8(mg_arena, n->string);
|
||||
str8_list_pushf(mg_arena, &layer->enums, "X(%S)\\\n", escaped);
|
||||
}
|
||||
str8_list_push(mg_arena, &layer->enums, str8_lit("\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: generate structs
|
||||
//
|
||||
for(MG_FileParseNode *n = parses.first; n != 0; n = n->next)
|
||||
{
|
||||
MD_Node *file = n->v.root;
|
||||
for MD_EachNode(node, file->first)
|
||||
{
|
||||
if(md_node_has_tag(node, str8_lit("struct"), 0))
|
||||
{
|
||||
String8 layer_key = mg_layer_key_from_path(file->string);
|
||||
MG_Layer *layer = mg_layer_from_key(layer_key);
|
||||
String8List gen_strings = mg_string_list_from_table_gen(mg_arena, table_grid_map, table_col_map, str8_lit(""), node);
|
||||
str8_list_pushf(mg_arena, &layer->structs, "typedef struct %S %S;\n", node->string, node->string);
|
||||
str8_list_pushf(mg_arena, &layer->structs, "struct %S\n{\n", node->string);
|
||||
for(String8Node *n = gen_strings.first; n != 0; n = n->next)
|
||||
{
|
||||
String8 escaped = mg_escaped_from_str8(mg_arena, n->string);
|
||||
str8_list_pushf(mg_arena, &layer->structs, "%S;\n", escaped);
|
||||
}
|
||||
str8_list_pushf(mg_arena, &layer->structs, "};\n\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: generate data tables
|
||||
//
|
||||
for(MG_FileParseNode *n = parses.first; n != 0; n = n->next)
|
||||
{
|
||||
MD_Node *file = n->v.root;
|
||||
for MD_EachNode(node, file->first)
|
||||
{
|
||||
MD_Node *tag = md_tag_from_string(node, str8_lit("data"), 0);
|
||||
if(!md_node_is_nil(tag))
|
||||
{
|
||||
String8 element_type = tag->first->string;
|
||||
String8 layer_key = mg_layer_key_from_path(file->string);
|
||||
MG_Layer *layer = mg_layer_from_key(layer_key);
|
||||
String8List gen_strings = mg_string_list_from_table_gen(mg_arena, table_grid_map, table_col_map, str8_lit(""), node);
|
||||
if(!md_node_has_tag(node, str8_lit("c_file"), 0))
|
||||
{
|
||||
str8_list_pushf(mg_arena, &layer->h_tables, "extern %S %S[%I64u];\n", element_type, node->string, gen_strings.node_count);
|
||||
}
|
||||
str8_list_pushf(mg_arena, &layer->c_tables, "%S %S[%I64u] =\n{\n", element_type, node->string, gen_strings.node_count);
|
||||
for(String8Node *n = gen_strings.first; n != 0; n = n->next)
|
||||
{
|
||||
String8 escaped = mg_escaped_from_str8(mg_arena, n->string);
|
||||
str8_list_pushf(mg_arena, &layer->c_tables, "%S,\n", escaped);
|
||||
}
|
||||
str8_list_push(mg_arena, &layer->c_tables, str8_lit("};\n\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: generate enum -> string mapping functions
|
||||
//
|
||||
for(MG_FileParseNode *n = parses.first; n != 0; n = n->next)
|
||||
{
|
||||
MD_Node *file = n->v.root;
|
||||
for MD_EachNode(node, file->first)
|
||||
{
|
||||
MD_Node *tag = md_tag_from_string(node, str8_lit("enum2string_switch"), 0);
|
||||
if(!md_node_is_nil(tag))
|
||||
{
|
||||
String8 enum_type = tag->first->string;
|
||||
String8 layer_key = mg_layer_key_from_path(file->string);
|
||||
MG_Layer *layer = mg_layer_from_key(layer_key);
|
||||
String8List gen_strings = mg_string_list_from_table_gen(mg_arena, table_grid_map, table_col_map, str8_lit(""), node);
|
||||
str8_list_pushf(mg_arena, &layer->h_functions, "internal String8 %S(%S v);\n", node->string, enum_type);
|
||||
str8_list_pushf(mg_arena, &layer->c_functions, "internal String8\n%S(%S v)\n{\n", node->string, enum_type);
|
||||
str8_list_pushf(mg_arena, &layer->c_functions, "String8 result = str8_lit(\"<Unknown %S>\");\n", enum_type);
|
||||
str8_list_pushf(mg_arena, &layer->c_functions, "switch(v)\n");
|
||||
str8_list_pushf(mg_arena, &layer->c_functions, "{\n");
|
||||
str8_list_pushf(mg_arena, &layer->c_functions, "default:{}break;\n");
|
||||
for(String8Node *n = gen_strings.first; n != 0; n = n->next)
|
||||
{
|
||||
String8 escaped = mg_escaped_from_str8(mg_arena, n->string);
|
||||
str8_list_pushf(mg_arena, &layer->c_functions, "%S;\n", escaped);
|
||||
}
|
||||
str8_list_pushf(mg_arena, &layer->c_functions, "}\n");
|
||||
str8_list_pushf(mg_arena, &layer->c_functions, "return result;\n");
|
||||
str8_list_pushf(mg_arena, &layer->c_functions, "}\n\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: generate catch-all generations
|
||||
//
|
||||
for(MG_FileParseNode *n = parses.first; n != 0; n = n->next)
|
||||
{
|
||||
MD_Node *file = n->v.root;
|
||||
for MD_EachNode(node, file->first)
|
||||
{
|
||||
MD_Node *tag = md_tag_from_string(node, str8_lit("gen"), 0);
|
||||
if(!md_node_is_nil(tag))
|
||||
{
|
||||
String8 layer_key = mg_layer_key_from_path(file->string);
|
||||
MG_Layer *layer = mg_layer_from_key(layer_key);
|
||||
B32 prefer_c_file = md_node_has_tag(node, str8_lit("c_file"), 0);
|
||||
String8List *out = prefer_c_file ? &layer->c_catchall : &layer->h_catchall;
|
||||
if(tag->first->string.size == 0){}
|
||||
else if(str8_match(tag->first->string, str8_lit("enums"), 0)) { out = &layer->enums; }
|
||||
else if(str8_match(tag->first->string, str8_lit("structs"), 0)) { out = &layer->structs; }
|
||||
else if(str8_match(tag->first->string, str8_lit("functions"), 0)) { out = prefer_c_file ? &layer->c_functions : &layer->h_functions; }
|
||||
else if(str8_match(tag->first->string, str8_lit("tables"), 0)) { out = prefer_c_file ? &layer->c_tables : &layer->h_tables; }
|
||||
String8List gen_strings = mg_string_list_from_table_gen(mg_arena, table_grid_map, table_col_map, str8_lit(""), node);
|
||||
for(String8Node *n = gen_strings.first; n != 0; n = n->next)
|
||||
{
|
||||
String8 trimmed = str8_skip_chop_whitespace(n->string);
|
||||
String8 escaped = mg_escaped_from_str8(mg_arena, trimmed);
|
||||
str8_list_push(mg_arena, out, escaped);
|
||||
str8_list_push(mg_arena, out, str8_lit("\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: gather & generate all embeds
|
||||
//
|
||||
for(MG_FileParseNode *n = parses.first; n != 0; n = n->next)
|
||||
{
|
||||
MD_Node *file = n->v.root;
|
||||
for MD_EachNode(node, file->first)
|
||||
{
|
||||
if(md_node_has_tag(node, str8_lit("embed_string"), 0))
|
||||
{
|
||||
String8 layer_key = mg_layer_key_from_path(file->string);
|
||||
MG_Layer *layer = mg_layer_from_key(layer_key);
|
||||
String8 embed_string = mg_c_string_literal_from_multiline_string(node->first->string);
|
||||
str8_list_pushf(mg_arena, &layer->h_tables, "read_only global String8 %S =\nstr8_lit_comp(\n", node->string);
|
||||
str8_list_push (mg_arena, &layer->h_tables, embed_string);
|
||||
str8_list_pushf(mg_arena, &layer->h_tables, ");\n\n");
|
||||
}
|
||||
if(md_node_has_tag(node, str8_lit("embed_file"), 0))
|
||||
{
|
||||
String8 layer_key = mg_layer_key_from_path(file->string);
|
||||
MG_Layer *layer = mg_layer_from_key(layer_key);
|
||||
String8 data = os_data_from_file_path(mg_arena, node->first->string);
|
||||
String8 embed_string = mg_c_array_literal_contents_from_data(data);
|
||||
str8_list_pushf(mg_arena, &layer->h_tables, "read_only global U8 %S__data[] =\n{\n", node->string);
|
||||
str8_list_push (mg_arena, &layer->h_tables, embed_string);
|
||||
str8_list_pushf(mg_arena, &layer->h_tables, "};\n\n");
|
||||
str8_list_pushf(mg_arena, &layer->h_tables, "read_only global String8 %S = {%S__data, sizeof(%S__data)};\n",
|
||||
node->string,
|
||||
node->string,
|
||||
node->string);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: generate all markdown in build folder
|
||||
//
|
||||
for(MG_FileParseNode *n = parses.first; n != 0; n = n->next)
|
||||
{
|
||||
MD_Node *file = n->v.root;
|
||||
for MD_EachNode(node, file->first)
|
||||
{
|
||||
//- rjf: generate markdown page
|
||||
if(md_node_has_tag(node, str8_lit("markdown"), 0))
|
||||
{
|
||||
String8List md_strs = {0};
|
||||
for(MD_Node *piece = node->first; !md_node_is_nil(piece); piece = piece->next)
|
||||
{
|
||||
if(md_node_has_tag(piece, str8_lit("title"), 0))
|
||||
{
|
||||
str8_list_pushf(mg_arena, &md_strs, "# %S\n\n", piece->string);
|
||||
}
|
||||
if(md_node_has_tag(piece, str8_lit("subtitle"), 0))
|
||||
{
|
||||
str8_list_pushf(mg_arena, &md_strs, "## %S\n\n", piece->string);
|
||||
}
|
||||
if(md_node_has_tag(piece, str8_lit("p"), 0))
|
||||
{
|
||||
String8 paragraph_text = piece->string;
|
||||
String8List paragraph_lines = mg_wrapped_lines_from_string(mg_arena, paragraph_text, 80, 80, 0);
|
||||
for(String8Node *n = paragraph_lines.first; n != 0; n = n->next)
|
||||
{
|
||||
str8_list_push(mg_arena, &md_strs, n->string);
|
||||
str8_list_push(mg_arena, &md_strs, str8_lit("\n"));
|
||||
}
|
||||
str8_list_push(mg_arena, &md_strs, str8_lit("\n"));
|
||||
}
|
||||
if(md_node_has_tag(piece, str8_lit("unordered_list"), 0))
|
||||
{
|
||||
String8List gen_strings = mg_string_list_from_table_gen(mg_arena, table_grid_map, table_col_map, str8_lit(""), piece);
|
||||
for(String8Node *n = gen_strings.first; n != 0; n = n->next)
|
||||
{
|
||||
str8_list_pushf(mg_arena, &md_strs, " - ");
|
||||
String8 item_text = n->string;
|
||||
String8List item_lines = mg_wrapped_lines_from_string(mg_arena, item_text, 80-3, 80, 3);
|
||||
for(String8Node *line_n = item_lines.first; line_n != 0; line_n = line_n->next)
|
||||
{
|
||||
str8_list_push(mg_arena, &md_strs, line_n->string);
|
||||
str8_list_pushf(mg_arena, &md_strs, "\n");
|
||||
}
|
||||
}
|
||||
str8_list_pushf(mg_arena, &md_strs, "\n");
|
||||
}
|
||||
}
|
||||
String8 output_path = push_str8f(mg_arena, "%S/%S.md", build_dir_path, node->string);
|
||||
FILE *file = fopen((char *)output_path.str, "w");
|
||||
for(String8Node *n = md_strs.first; n != 0; n = n->next)
|
||||
{
|
||||
fwrite(n->string.str, n->string.size, 1, file);
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: write all layer output files
|
||||
//
|
||||
DeferLoop(printf("generating layer code..."), printf("\n"))
|
||||
{
|
||||
for(U64 slot_idx = 0; slot_idx < mg_state->slots_count; slot_idx += 1)
|
||||
{
|
||||
MG_LayerSlot *slot = &mg_state->slots[slot_idx];
|
||||
for(MG_LayerNode *n = slot->first; n != 0; n = n->next)
|
||||
{
|
||||
MG_Layer *layer = &n->v;
|
||||
String8 layer_generated_folder = {0};
|
||||
if(layer->gen_folder_name.size != 0)
|
||||
{
|
||||
String8 gen_folder = layer->gen_folder_name;
|
||||
layer_generated_folder = push_str8f(mg_arena, "%S/%S", code_dir_path, gen_folder);
|
||||
}
|
||||
else
|
||||
{
|
||||
String8 gen_folder = str8_lit("generated");
|
||||
layer_generated_folder = push_str8f(mg_arena, "%S/%S/%S", code_dir_path, layer->key, gen_folder);
|
||||
}
|
||||
if(os_make_directory(layer_generated_folder))
|
||||
{
|
||||
String8List layer_key_parts = str8_split_path(mg_arena, layer->key);
|
||||
StringJoin join = {0};
|
||||
join.sep = str8_lit("_");
|
||||
String8 layer_key_filename = str8_list_join(mg_arena, &layer_key_parts, &join);
|
||||
String8 layer_key_filename_upper = upper_from_str8(mg_arena, layer_key_filename);
|
||||
String8 h_path = push_str8f(mg_arena, "%S/%S.meta.h", layer_generated_folder, layer_key_filename);
|
||||
String8 c_path = push_str8f(mg_arena, "%S/%S.meta.c", layer_generated_folder, layer_key_filename);
|
||||
if(layer->h_name_override.size != 0)
|
||||
{
|
||||
h_path = push_str8f(mg_arena, "%S/%S", layer_generated_folder, str8_skip_last_slash(layer->h_name_override));
|
||||
}
|
||||
if(layer->c_name_override.size != 0)
|
||||
{
|
||||
c_path = push_str8f(mg_arena, "%S/%S", layer_generated_folder, str8_skip_last_slash(layer->c_name_override));
|
||||
}
|
||||
{
|
||||
FILE *h = fopen((char *)h_path.str, "w");
|
||||
fprintf(h, "// Copyright (c) 2024 Epic Games Tools\n");
|
||||
fprintf(h, "// Licensed under the MIT license (https://opensource.org/license/mit/)\n\n");
|
||||
if(layer->h_header.first == 0)
|
||||
{
|
||||
fprintf(h, "//- GENERATED CODE\n\n");
|
||||
fprintf(h, "#ifndef %.*s_META_H\n", str8_varg(layer_key_filename_upper));
|
||||
fprintf(h, "#define %.*s_META_H\n\n", str8_varg(layer_key_filename_upper));
|
||||
}
|
||||
else for(String8Node *n = layer->h_header.first; n != 0; n = n->next)
|
||||
{
|
||||
fwrite(n->string.str, n->string.size, 1, h);
|
||||
}
|
||||
for(String8Node *n = layer->enums.first; n != 0; n = n->next)
|
||||
{
|
||||
fwrite(n->string.str, n->string.size, 1, h);
|
||||
}
|
||||
for(String8Node *n = layer->structs.first; n != 0; n = n->next)
|
||||
{
|
||||
fwrite(n->string.str, n->string.size, 1, h);
|
||||
}
|
||||
for(String8Node *n = layer->h_catchall.first; n != 0; n = n->next)
|
||||
{
|
||||
fwrite(n->string.str, n->string.size, 1, h);
|
||||
}
|
||||
for(String8Node *n = layer->h_functions.first; n != 0; n = n->next)
|
||||
{
|
||||
fwrite(n->string.str, n->string.size, 1, h);
|
||||
}
|
||||
if(layer->h_tables.first != 0)
|
||||
{
|
||||
if(!layer->is_library)
|
||||
{
|
||||
fprintf(h, "C_LINKAGE_BEGIN\n");
|
||||
}
|
||||
for(String8Node *n = layer->h_tables.first; n != 0; n = n->next)
|
||||
{
|
||||
fwrite(n->string.str, n->string.size, 1, h);
|
||||
}
|
||||
fprintf(h, "\n");
|
||||
if(!layer->is_library)
|
||||
{
|
||||
fprintf(h, "C_LINKAGE_END\n\n");
|
||||
}
|
||||
}
|
||||
if(layer->h_footer.first == 0)
|
||||
{
|
||||
fprintf(h, "#endif // %.*s_META_H\n", str8_varg(layer_key_filename_upper));
|
||||
}
|
||||
else for(String8Node *n = layer->h_footer.first; n != 0; n = n->next)
|
||||
{
|
||||
fwrite(n->string.str, n->string.size, 1, h);
|
||||
}
|
||||
fclose(h);
|
||||
}
|
||||
{
|
||||
FILE *c = fopen((char *)c_path.str, "w");
|
||||
fprintf(c, "// Copyright (c) 2024 Epic Games Tools\n");
|
||||
fprintf(c, "// Licensed under the MIT license (https://opensource.org/license/mit/)\n\n");
|
||||
if(layer->c_header.first == 0)
|
||||
{
|
||||
fprintf(c, "//- GENERATED CODE\n\n");
|
||||
}
|
||||
else for(String8Node *n = layer->c_header.first; n != 0; n = n->next)
|
||||
{
|
||||
fwrite(n->string.str, n->string.size, 1, c);
|
||||
}
|
||||
for(String8Node *n = layer->c_catchall.first; n != 0; n = n->next)
|
||||
{
|
||||
fwrite(n->string.str, n->string.size, 1, c);
|
||||
}
|
||||
if(layer->c_tables.first != 0)
|
||||
{
|
||||
if(!layer->is_library)
|
||||
{
|
||||
fprintf(c, "C_LINKAGE_BEGIN\n");
|
||||
}
|
||||
for(String8Node *n = layer->c_tables.first; n != 0; n = n->next)
|
||||
{
|
||||
fwrite(n->string.str, n->string.size, 1, c);
|
||||
}
|
||||
if(!layer->is_library)
|
||||
{
|
||||
fprintf(c, "C_LINKAGE_END\n\n");
|
||||
}
|
||||
}
|
||||
for(String8Node *n = layer->c_functions.first; n != 0; n = n->next)
|
||||
{
|
||||
fwrite(n->string.str, n->string.size, 1, c);
|
||||
}
|
||||
if(layer->c_footer.first != 0)
|
||||
{
|
||||
for(String8Node *n = layer->c_footer.first; n != 0; n = n->next)
|
||||
{
|
||||
fwrite(n->string.str, n->string.size, 1, c);
|
||||
}
|
||||
}
|
||||
fclose(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: write out all messages to stderr
|
||||
//
|
||||
for(MG_MsgNode *n = msgs.first; n != 0; n = n->next)
|
||||
{
|
||||
MG_Msg *msg = &n->v;
|
||||
fprintf(stderr, "%.*s: %.*s: %.*s\n", str8_varg(msg->location), str8_varg(msg->kind), str8_varg(msg->msg));
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,134 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef OS_CORE_LINUX_H
|
||||
#define OS_CORE_LINUX_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Includes
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <features.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/limits.h>
|
||||
#include <time.h>
|
||||
#include <dirent.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <dlfcn.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <sys/random.h>
|
||||
|
||||
int pthread_setname_np(pthread_t thread, const char *name);
|
||||
int pthread_getname_np(pthread_t thread, char *name, size_t size);
|
||||
|
||||
typedef struct tm tm;
|
||||
typedef struct timespec timespec;
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: File Iterator
|
||||
|
||||
typedef struct OS_LNX_FileIter OS_LNX_FileIter;
|
||||
struct OS_LNX_FileIter
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *dp;
|
||||
String8 path;
|
||||
};
|
||||
StaticAssert(sizeof(Member(OS_FileIter, memory)) >= sizeof(OS_LNX_FileIter), os_lnx_file_iter_size_check);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Safe Call Handler Chain
|
||||
|
||||
typedef struct OS_LNX_SafeCallChain OS_LNX_SafeCallChain;
|
||||
struct OS_LNX_SafeCallChain
|
||||
{
|
||||
OS_LNX_SafeCallChain *next;
|
||||
OS_ThreadFunctionType *fail_handler;
|
||||
void *ptr;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Entities
|
||||
|
||||
typedef enum OS_LNX_EntityKind
|
||||
{
|
||||
OS_LNX_EntityKind_Thread,
|
||||
OS_LNX_EntityKind_Mutex,
|
||||
OS_LNX_EntityKind_RWMutex,
|
||||
OS_LNX_EntityKind_ConditionVariable,
|
||||
}
|
||||
OS_LNX_EntityKind;
|
||||
|
||||
typedef struct OS_LNX_Entity OS_LNX_Entity;
|
||||
struct OS_LNX_Entity
|
||||
{
|
||||
OS_LNX_Entity *next;
|
||||
OS_LNX_EntityKind kind;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
pthread_t handle;
|
||||
OS_ThreadFunctionType *func;
|
||||
void *ptr;
|
||||
} thread;
|
||||
pthread_mutex_t mutex_handle;
|
||||
pthread_rwlock_t rwmutex_handle;
|
||||
struct
|
||||
{
|
||||
pthread_cond_t cond_handle;
|
||||
pthread_mutex_t rwlock_mutex_handle;
|
||||
} cv;
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: State
|
||||
|
||||
typedef struct OS_LNX_State OS_LNX_State;
|
||||
struct OS_LNX_State
|
||||
{
|
||||
Arena *arena;
|
||||
OS_SystemInfo system_info;
|
||||
OS_ProcessInfo process_info;
|
||||
pthread_mutex_t entity_mutex;
|
||||
Arena *entity_arena;
|
||||
OS_LNX_Entity *entity_free;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Globals
|
||||
|
||||
global OS_LNX_State os_lnx_state = {0};
|
||||
thread_static OS_LNX_SafeCallChain *os_lnx_safe_call_chain = 0;
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Helpers
|
||||
|
||||
internal DateTime os_lnx_date_time_from_tm(tm in, U32 msec);
|
||||
internal tm os_lnx_tm_from_date_time(DateTime dt);
|
||||
internal timespec os_lnx_timespec_from_date_time(DateTime dt);
|
||||
internal DenseTime os_lnx_dense_time_from_timespec(timespec in);
|
||||
internal FileProperties os_lnx_file_properties_from_stat(struct stat *s);
|
||||
internal void os_lnx_safe_call_sig_handler(int x);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Entities
|
||||
|
||||
internal OS_LNX_Entity *os_lnx_entity_alloc(OS_LNX_EntityKind kind);
|
||||
internal void os_lnx_entity_release(OS_LNX_Entity *entity);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Thread Entry Point
|
||||
|
||||
internal void *os_lnx_thread_entry_point(void *ptr);
|
||||
|
||||
#endif // OS_CORE_LINUX_H
|
||||
@@ -0,0 +1,173 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Handle Type Functions (Helpers, Implemented Once)
|
||||
|
||||
internal OS_Handle
|
||||
os_handle_zero(void)
|
||||
{
|
||||
OS_Handle handle = {0};
|
||||
return handle;
|
||||
}
|
||||
|
||||
internal B32
|
||||
os_handle_match(OS_Handle a, OS_Handle b)
|
||||
{
|
||||
return a.u64[0] == b.u64[0];
|
||||
}
|
||||
|
||||
internal void
|
||||
os_handle_list_push(Arena *arena, OS_HandleList *handles, OS_Handle handle)
|
||||
{
|
||||
OS_HandleNode *n = push_array(arena, OS_HandleNode, 1);
|
||||
n->v = handle;
|
||||
SLLQueuePush(handles->first, handles->last, n);
|
||||
handles->count += 1;
|
||||
}
|
||||
|
||||
internal OS_HandleArray
|
||||
os_handle_array_from_list(Arena *arena, OS_HandleList *list)
|
||||
{
|
||||
OS_HandleArray result = {0};
|
||||
result.count = list->count;
|
||||
result.v = push_array_no_zero(arena, OS_Handle, result.count);
|
||||
U64 idx = 0;
|
||||
for(OS_HandleNode *n = list->first; n != 0; n = n->next, idx += 1)
|
||||
{
|
||||
result.v[idx] = n->v;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Command Line Argc/Argv Helper (Helper, Implemented Once)
|
||||
|
||||
internal String8List
|
||||
os_string_list_from_argcv(Arena *arena, int argc, char **argv)
|
||||
{
|
||||
String8List result = {0};
|
||||
for(int i = 0; i < argc; i += 1)
|
||||
{
|
||||
String8 str = str8_cstring(argv[i]);
|
||||
str8_list_push(arena, &result, str);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Filesystem Helpers (Helpers, Implemented Once)
|
||||
|
||||
internal String8
|
||||
os_data_from_file_path(Arena *arena, String8 path)
|
||||
{
|
||||
OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead, path);
|
||||
FileProperties props = os_properties_from_file(file);
|
||||
String8 data = os_string_from_file_range(arena, file, r1u64(0, props.size));
|
||||
os_file_close(file);
|
||||
return data;
|
||||
}
|
||||
|
||||
internal B32
|
||||
os_write_data_to_file_path(String8 path, String8 data)
|
||||
{
|
||||
B32 good = 0;
|
||||
OS_Handle file = os_file_open(OS_AccessFlag_Write, path);
|
||||
if(!os_handle_match(file, os_handle_zero()))
|
||||
{
|
||||
good = 1;
|
||||
os_file_write(file, r1u64(0, data.size), data.str);
|
||||
os_file_close(file);
|
||||
}
|
||||
return good;
|
||||
}
|
||||
|
||||
internal B32
|
||||
os_write_data_list_to_file_path(String8 path, String8List list)
|
||||
{
|
||||
B32 good = 0;
|
||||
OS_Handle file = os_file_open(OS_AccessFlag_Write, path);
|
||||
if(!os_handle_match(file, os_handle_zero()))
|
||||
{
|
||||
good = 1;
|
||||
U64 off = 0;
|
||||
for(String8Node *n = list.first; n != 0; n = n->next)
|
||||
{
|
||||
os_file_write(file, r1u64(off, off+n->string.size), n->string.str);
|
||||
off += n->string.size;
|
||||
}
|
||||
os_file_close(file);
|
||||
}
|
||||
return good;
|
||||
}
|
||||
|
||||
internal B32
|
||||
os_append_data_to_file_path(String8 path, String8 data)
|
||||
{
|
||||
B32 good = 0;
|
||||
if(data.size != 0)
|
||||
{
|
||||
OS_Handle file = os_file_open(OS_AccessFlag_Write|OS_AccessFlag_Append, path);
|
||||
if(!os_handle_match(file, os_handle_zero()))
|
||||
{
|
||||
good = 1;
|
||||
U64 pos = os_properties_from_file(file).size;
|
||||
os_file_write(file, r1u64(pos, pos+data.size), data.str);
|
||||
os_file_close(file);
|
||||
}
|
||||
}
|
||||
return good;
|
||||
}
|
||||
|
||||
internal OS_FileID
|
||||
os_id_from_file_path(String8 path)
|
||||
{
|
||||
OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead, path);
|
||||
OS_FileID id = os_id_from_file(file);
|
||||
os_file_close(file);
|
||||
return id;
|
||||
}
|
||||
|
||||
internal S64
|
||||
os_file_id_compare(OS_FileID a, OS_FileID b)
|
||||
{
|
||||
S64 cmp = MemoryCompare((void*)&a.v[0], (void*)&b.v[0], sizeof(a.v));
|
||||
return cmp;
|
||||
}
|
||||
|
||||
internal String8
|
||||
os_string_from_file_range(Arena *arena, OS_Handle file, Rng1U64 range)
|
||||
{
|
||||
U64 pre_pos = arena_pos(arena);
|
||||
String8 result;
|
||||
result.size = dim_1u64(range);
|
||||
result.str = push_array_no_zero(arena, U8, result.size);
|
||||
U64 actual_read_size = os_file_read(file, range, result.str);
|
||||
if(actual_read_size < result.size)
|
||||
{
|
||||
arena_pop_to(arena, pre_pos + actual_read_size);
|
||||
result.size = actual_read_size;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: GUID Helpers (Helpers, Implemented Once)
|
||||
|
||||
internal String8
|
||||
os_string_from_guid(Arena *arena, OS_Guid guid)
|
||||
{
|
||||
String8 result = push_str8f(arena, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
|
||||
guid.data1,
|
||||
guid.data2,
|
||||
guid.data3,
|
||||
guid.data4[0],
|
||||
guid.data4[1],
|
||||
guid.data4[2],
|
||||
guid.data4[3],
|
||||
guid.data4[4],
|
||||
guid.data4[5],
|
||||
guid.data4[6],
|
||||
guid.data4[7]);
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,336 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef OS_CORE_H
|
||||
#define OS_CORE_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: System Info
|
||||
|
||||
typedef struct OS_SystemInfo OS_SystemInfo;
|
||||
struct OS_SystemInfo
|
||||
{
|
||||
U32 logical_processor_count;
|
||||
U64 page_size;
|
||||
U64 large_page_size;
|
||||
U64 allocation_granularity;
|
||||
String8 machine_name;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Process Info
|
||||
|
||||
typedef struct OS_ProcessInfo OS_ProcessInfo;
|
||||
struct OS_ProcessInfo
|
||||
{
|
||||
U32 pid;
|
||||
String8 binary_path;
|
||||
String8 initial_path;
|
||||
String8 user_program_data_path;
|
||||
String8List module_load_paths;
|
||||
String8List environment;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Access Flags
|
||||
|
||||
typedef U32 OS_AccessFlags;
|
||||
enum
|
||||
{
|
||||
OS_AccessFlag_Read = (1<<0),
|
||||
OS_AccessFlag_Write = (1<<1),
|
||||
OS_AccessFlag_Execute = (1<<2),
|
||||
OS_AccessFlag_Append = (1<<3),
|
||||
OS_AccessFlag_ShareRead = (1<<4),
|
||||
OS_AccessFlag_ShareWrite = (1<<5),
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Files
|
||||
|
||||
typedef U32 OS_FileIterFlags;
|
||||
enum
|
||||
{
|
||||
OS_FileIterFlag_SkipFolders = (1 << 0),
|
||||
OS_FileIterFlag_SkipFiles = (1 << 1),
|
||||
OS_FileIterFlag_SkipHiddenFiles = (1 << 2),
|
||||
OS_FileIterFlag_Done = (1 << 31),
|
||||
};
|
||||
|
||||
typedef struct OS_FileIter OS_FileIter;
|
||||
struct OS_FileIter
|
||||
{
|
||||
OS_FileIterFlags flags;
|
||||
U8 memory[800];
|
||||
};
|
||||
|
||||
typedef struct OS_FileInfo OS_FileInfo;
|
||||
struct OS_FileInfo
|
||||
{
|
||||
String8 name;
|
||||
FileProperties props;
|
||||
};
|
||||
|
||||
// nick: on-disk file identifier
|
||||
typedef struct OS_FileID OS_FileID;
|
||||
struct OS_FileID
|
||||
{
|
||||
U64 v[3];
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Process Launch Parameters
|
||||
|
||||
typedef struct OS_ProcessLaunchParams OS_ProcessLaunchParams;
|
||||
struct OS_ProcessLaunchParams
|
||||
{
|
||||
String8List cmd_line;
|
||||
String8 path;
|
||||
String8List env;
|
||||
B32 inherit_env;
|
||||
B32 consoleless;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Handle Type
|
||||
|
||||
typedef struct OS_Handle OS_Handle;
|
||||
struct OS_Handle
|
||||
{
|
||||
U64 u64[1];
|
||||
};
|
||||
|
||||
typedef struct OS_HandleNode OS_HandleNode;
|
||||
struct OS_HandleNode
|
||||
{
|
||||
OS_HandleNode *next;
|
||||
OS_Handle v;
|
||||
};
|
||||
|
||||
typedef struct OS_HandleList OS_HandleList;
|
||||
struct OS_HandleList
|
||||
{
|
||||
OS_HandleNode *first;
|
||||
OS_HandleNode *last;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
typedef struct OS_HandleArray OS_HandleArray;
|
||||
struct OS_HandleArray
|
||||
{
|
||||
OS_Handle *v;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Globally Unique IDs
|
||||
|
||||
typedef struct OS_Guid OS_Guid;
|
||||
struct OS_Guid
|
||||
{
|
||||
U32 data1;
|
||||
U16 data2;
|
||||
U16 data3;
|
||||
U8 data4[8];
|
||||
};
|
||||
StaticAssert(sizeof(OS_Guid) == 16, os_guid_check);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Thread Types
|
||||
|
||||
typedef void OS_ThreadFunctionType(void *ptr);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Handle Type Functions (Helpers, Implemented Once)
|
||||
|
||||
internal OS_Handle os_handle_zero(void);
|
||||
internal B32 os_handle_match(OS_Handle a, OS_Handle b);
|
||||
internal void os_handle_list_push(Arena *arena, OS_HandleList *handles, OS_Handle handle);
|
||||
internal OS_HandleArray os_handle_array_from_list(Arena *arena, OS_HandleList *list);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Command Line Argc/Argv Helper (Helper, Implemented Once)
|
||||
|
||||
internal String8List os_string_list_from_argcv(Arena *arena, int argc, char **argv);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Filesystem Helpers (Helpers, Implemented Once)
|
||||
|
||||
internal String8 os_data_from_file_path(Arena *arena, String8 path);
|
||||
internal B32 os_write_data_to_file_path(String8 path, String8 data);
|
||||
internal B32 os_write_data_list_to_file_path(String8 path, String8List list);
|
||||
internal B32 os_append_data_to_file_path(String8 path, String8 data);
|
||||
internal OS_FileID os_id_from_file_path(String8 path);
|
||||
internal S64 os_file_id_compare(OS_FileID a, OS_FileID b);
|
||||
internal String8 os_string_from_file_range(Arena *arena, OS_Handle file, Rng1U64 range);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: GUID Helpers (Helpers, Implemented Once)
|
||||
|
||||
internal String8 os_string_from_guid(Arena *arena, OS_Guid guid);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks System/Process Info (Implemented Per-OS)
|
||||
|
||||
internal OS_SystemInfo *os_get_system_info(void);
|
||||
internal OS_ProcessInfo *os_get_process_info(void);
|
||||
internal String8 os_get_current_path(Arena *arena);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Memory Allocation (Implemented Per-OS)
|
||||
|
||||
//- rjf: basic
|
||||
internal void *os_reserve(U64 size);
|
||||
internal B32 os_commit(void *ptr, U64 size);
|
||||
internal void os_decommit(void *ptr, U64 size);
|
||||
internal void os_release(void *ptr, U64 size);
|
||||
|
||||
//- rjf: large pages
|
||||
internal void *os_reserve_large(U64 size);
|
||||
internal B32 os_commit_large(void *ptr, U64 size);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Thread Info (Implemented Per-OS)
|
||||
|
||||
internal U32 os_tid(void);
|
||||
internal void os_set_thread_name(String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Aborting (Implemented Per-OS)
|
||||
|
||||
internal void os_abort(S32 exit_code);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks File System (Implemented Per-OS)
|
||||
|
||||
//- rjf: files
|
||||
internal OS_Handle os_file_open(OS_AccessFlags flags, String8 path);
|
||||
internal void os_file_close(OS_Handle file);
|
||||
internal U64 os_file_read(OS_Handle file, Rng1U64 rng, void *out_data);
|
||||
internal U64 os_file_write(OS_Handle file, Rng1U64 rng, void *data);
|
||||
internal B32 os_file_set_times(OS_Handle file, DateTime time);
|
||||
internal FileProperties os_properties_from_file(OS_Handle file);
|
||||
internal OS_FileID os_id_from_file(OS_Handle file);
|
||||
internal B32 os_delete_file_at_path(String8 path);
|
||||
internal B32 os_copy_file_path(String8 dst, String8 src);
|
||||
internal String8 os_full_path_from_path(Arena *arena, String8 path);
|
||||
internal B32 os_file_path_exists(String8 path);
|
||||
internal FileProperties os_properties_from_file_path(String8 path);
|
||||
|
||||
//- rjf: file maps
|
||||
internal OS_Handle os_file_map_open(OS_AccessFlags flags, OS_Handle file);
|
||||
internal void os_file_map_close(OS_Handle map);
|
||||
internal void * os_file_map_view_open(OS_Handle map, OS_AccessFlags flags, Rng1U64 range);
|
||||
internal void os_file_map_view_close(OS_Handle map, void *ptr, Rng1U64 range);
|
||||
|
||||
//- rjf: directory iteration
|
||||
internal OS_FileIter *os_file_iter_begin(Arena *arena, String8 path, OS_FileIterFlags flags);
|
||||
internal B32 os_file_iter_next(Arena *arena, OS_FileIter *iter, OS_FileInfo *info_out);
|
||||
internal void os_file_iter_end(OS_FileIter *iter);
|
||||
|
||||
//- rjf: directory creation
|
||||
internal B32 os_make_directory(String8 path);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Shared Memory (Implemented Per-OS)
|
||||
|
||||
internal OS_Handle os_shared_memory_alloc(U64 size, String8 name);
|
||||
internal OS_Handle os_shared_memory_open(String8 name);
|
||||
internal void os_shared_memory_close(OS_Handle handle);
|
||||
internal void * os_shared_memory_view_open(OS_Handle handle, Rng1U64 range);
|
||||
internal void os_shared_memory_view_close(OS_Handle handle, void *ptr, Rng1U64 range);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Time (Implemented Per-OS)
|
||||
|
||||
internal U64 os_now_microseconds(void);
|
||||
internal U32 os_now_unix(void);
|
||||
internal DateTime os_now_universal_time(void);
|
||||
internal DateTime os_universal_time_from_local(DateTime *local_time);
|
||||
internal DateTime os_local_time_from_universal(DateTime *universal_time);
|
||||
internal void os_sleep_milliseconds(U32 msec);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Child Processes (Implemented Per-OS)
|
||||
|
||||
internal OS_Handle os_process_launch(OS_ProcessLaunchParams *params);
|
||||
internal B32 os_process_join(OS_Handle handle, U64 endt_us);
|
||||
internal void os_process_detach(OS_Handle handle);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Threads (Implemented Per-OS)
|
||||
|
||||
internal OS_Handle os_thread_launch(OS_ThreadFunctionType *func, void *ptr, void *params);
|
||||
internal B32 os_thread_join(OS_Handle handle, U64 endt_us);
|
||||
internal void os_thread_detach(OS_Handle handle);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Synchronization Primitives (Implemented Per-OS)
|
||||
|
||||
//- rjf: recursive mutexes
|
||||
internal OS_Handle os_mutex_alloc(void);
|
||||
internal void os_mutex_release(OS_Handle mutex);
|
||||
internal void os_mutex_take(OS_Handle mutex);
|
||||
internal void os_mutex_drop(OS_Handle mutex);
|
||||
|
||||
//- rjf: reader/writer mutexes
|
||||
internal OS_Handle os_rw_mutex_alloc(void);
|
||||
internal void os_rw_mutex_release(OS_Handle rw_mutex);
|
||||
internal void os_rw_mutex_take_r(OS_Handle mutex);
|
||||
internal void os_rw_mutex_drop_r(OS_Handle mutex);
|
||||
internal void os_rw_mutex_take_w(OS_Handle mutex);
|
||||
internal void os_rw_mutex_drop_w(OS_Handle mutex);
|
||||
|
||||
//- rjf: condition variables
|
||||
internal OS_Handle os_condition_variable_alloc(void);
|
||||
internal void os_condition_variable_release(OS_Handle cv);
|
||||
// returns false on timeout, true on signal, (max_wait_ms = max_U64) -> no timeout
|
||||
internal B32 os_condition_variable_wait(OS_Handle cv, OS_Handle mutex, U64 endt_us);
|
||||
internal B32 os_condition_variable_wait_rw_r(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us);
|
||||
internal B32 os_condition_variable_wait_rw_w(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us);
|
||||
internal void os_condition_variable_signal(OS_Handle cv);
|
||||
internal void os_condition_variable_broadcast(OS_Handle cv);
|
||||
|
||||
//- rjf: cross-process semaphores
|
||||
internal OS_Handle os_semaphore_alloc(U32 initial_count, U32 max_count, String8 name);
|
||||
internal void os_semaphore_release(OS_Handle semaphore);
|
||||
internal OS_Handle os_semaphore_open(String8 name);
|
||||
internal void os_semaphore_close(OS_Handle semaphore);
|
||||
internal B32 os_semaphore_take(OS_Handle semaphore, U64 endt_us);
|
||||
internal void os_semaphore_drop(OS_Handle semaphore);
|
||||
|
||||
//- rjf: scope macros
|
||||
#define OS_MutexScope(mutex) DeferLoop(os_mutex_take(mutex), os_mutex_drop(mutex))
|
||||
#define OS_MutexScopeR(mutex) DeferLoop(os_rw_mutex_take_r(mutex), os_rw_mutex_drop_r(mutex))
|
||||
#define OS_MutexScopeW(mutex) DeferLoop(os_rw_mutex_take_w(mutex), os_rw_mutex_drop_w(mutex))
|
||||
#define OS_MutexScopeRWPromote(mutex) DeferLoop((os_rw_mutex_drop_r(mutex), os_rw_mutex_take_w(mutex)), (os_rw_mutex_drop_w(mutex), os_rw_mutex_take_r(mutex)))
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Dynamically-Loaded Libraries (Implemented Per-OS)
|
||||
|
||||
internal OS_Handle os_library_open(String8 path);
|
||||
internal void os_library_close(OS_Handle lib);
|
||||
internal VoidProc *os_library_load_proc(OS_Handle lib, String8 name);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Safe Calls (Implemented Per-OS)
|
||||
|
||||
internal void os_safe_call(OS_ThreadFunctionType *func, OS_ThreadFunctionType *fail_handler, void *ptr);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks GUIDs (Implemented Per-OS)
|
||||
|
||||
internal OS_Guid os_make_guid(void);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Entry Points (Implemented Per-OS)
|
||||
|
||||
// NOTE(rjf): The implementation of `os_core` will define low-level entry
|
||||
// points if BUILD_ENTRY_DEFINING_UNIT is defined to 1. These will call
|
||||
// into the standard codebase program entry points, named "entry_point".
|
||||
|
||||
#if BUILD_ENTRY_DEFINING_UNIT
|
||||
internal void entry_point(CmdLine *cmdline);
|
||||
#endif
|
||||
|
||||
#endif // OS_CORE_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,122 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef OS_CORE_WIN32_H
|
||||
#define OS_CORE_WIN32_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Includes / Libraries
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
#include <timeapi.h>
|
||||
#include <tlhelp32.h>
|
||||
#include <Shlobj.h>
|
||||
#include <processthreadsapi.h>
|
||||
#pragma comment(lib, "user32")
|
||||
#pragma comment(lib, "winmm")
|
||||
#pragma comment(lib, "shell32")
|
||||
#pragma comment(lib, "advapi32")
|
||||
#pragma comment(lib, "rpcrt4")
|
||||
#pragma comment(lib, "shlwapi")
|
||||
#pragma comment(lib, "comctl32")
|
||||
#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") // this is required for loading correct comctl32 dll file
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: File Iterator Types
|
||||
|
||||
typedef struct OS_W32_FileIter OS_W32_FileIter;
|
||||
struct OS_W32_FileIter
|
||||
{
|
||||
HANDLE handle;
|
||||
WIN32_FIND_DATAW find_data;
|
||||
B32 is_volume_iter;
|
||||
String8Array drive_strings;
|
||||
U64 drive_strings_iter_idx;
|
||||
};
|
||||
StaticAssert(sizeof(Member(OS_FileIter, memory)) >= sizeof(OS_W32_FileIter), file_iter_memory_size);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Entity Types
|
||||
|
||||
typedef enum OS_W32_EntityKind
|
||||
{
|
||||
OS_W32_EntityKind_Null,
|
||||
OS_W32_EntityKind_Thread,
|
||||
OS_W32_EntityKind_Mutex,
|
||||
OS_W32_EntityKind_RWMutex,
|
||||
OS_W32_EntityKind_ConditionVariable,
|
||||
}
|
||||
OS_W32_EntityKind;
|
||||
|
||||
typedef struct OS_W32_Entity OS_W32_Entity;
|
||||
struct OS_W32_Entity
|
||||
{
|
||||
OS_W32_Entity *next;
|
||||
OS_W32_EntityKind kind;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
OS_ThreadFunctionType *func;
|
||||
void *ptr;
|
||||
HANDLE handle;
|
||||
DWORD tid;
|
||||
} thread;
|
||||
CRITICAL_SECTION mutex;
|
||||
SRWLOCK rw_mutex;
|
||||
CONDITION_VARIABLE cv;
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: State
|
||||
|
||||
typedef struct OS_W32_State OS_W32_State;
|
||||
struct OS_W32_State
|
||||
{
|
||||
Arena *arena;
|
||||
|
||||
// rjf: info
|
||||
OS_SystemInfo system_info;
|
||||
OS_ProcessInfo process_info;
|
||||
U64 microsecond_resolution;
|
||||
|
||||
// rjf: entity storage
|
||||
CRITICAL_SECTION entity_mutex;
|
||||
Arena *entity_arena;
|
||||
OS_W32_Entity *entity_free;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Globals
|
||||
|
||||
global OS_W32_State os_w32_state = {0};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: File Info Conversion Helpers
|
||||
|
||||
internal FilePropertyFlags os_w32_file_property_flags_from_dwFileAttributes(DWORD dwFileAttributes);
|
||||
internal void os_w32_file_properties_from_attribute_data(FileProperties *properties, WIN32_FILE_ATTRIBUTE_DATA *attributes);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Time Conversion Helpers
|
||||
|
||||
internal void os_w32_date_time_from_system_time(DateTime *out, SYSTEMTIME *in);
|
||||
internal void os_w32_system_time_from_date_time(SYSTEMTIME *out, DateTime *in);
|
||||
internal void os_w32_dense_time_from_file_time(DenseTime *out, FILETIME *in);
|
||||
internal U32 os_w32_sleep_ms_from_endt_us(U64 endt_us);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Entity Functions
|
||||
|
||||
internal OS_W32_Entity *os_w32_entity_alloc(OS_W32_EntityKind kind);
|
||||
internal void os_w32_entity_release(OS_W32_Entity *entity);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Thread Entry Point
|
||||
|
||||
internal DWORD os_w32_thread_entry_point(void *ptr);
|
||||
|
||||
#endif // OS_CORE_WIN32_H
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#include "metagen/metagen_os/core/metagen_os_core.c"
|
||||
|
||||
#if OS_WINDOWS
|
||||
# include "metagen/metagen_os/core/win32/metagen_os_core_win32.c"
|
||||
#elif OS_LINUX
|
||||
# include "metagen/metagen_os/core/linux/metagen_os_core_linux.c"
|
||||
#else
|
||||
# error OS core layer not implemented for this operating system.
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef OS_INC_H
|
||||
#define OS_INC_H
|
||||
|
||||
#if !defined(OS_FEATURE_GRAPHICAL)
|
||||
# define OS_FEATURE_GRAPHICAL 0
|
||||
#endif
|
||||
|
||||
#if !defined(OS_GFX_STUB)
|
||||
# define OS_GFX_STUB 0
|
||||
#endif
|
||||
|
||||
#include "metagen/metagen_os/core/metagen_os_core.h"
|
||||
|
||||
#if OS_WINDOWS
|
||||
# include "metagen/metagen_os/core/win32/metagen_os_core_win32.h"
|
||||
#elif OS_LINUX
|
||||
# include "metagen/metagen_os/core/linux/metagen_os_core_linux.h"
|
||||
#else
|
||||
# error OS core layer not implemented for this operating system.
|
||||
#endif
|
||||
|
||||
#endif // OS_INC_H
|
||||
Reference in New Issue
Block a user