mirror of https://gitlab.com/nakst/essence
remove old designer source
This commit is contained in:
parent
35f361a7e4
commit
291ba3f373
24
util/build.c
24
util/build.c
|
@ -331,29 +331,9 @@ void BuildUtilities() {
|
||||||
|
|
||||||
BUILD_UTILITY("render_svg", "-lm", "");
|
BUILD_UTILITY("render_svg", "-lm", "");
|
||||||
BUILD_UTILITY("build_core", "-pthread -DPARALLEL_BUILD", "");
|
BUILD_UTILITY("build_core", "-pthread -DPARALLEL_BUILD", "");
|
||||||
|
|
||||||
#ifndef __APPLE__ // Luigi doesn't support macOS.
|
#ifndef __APPLE__ // Luigi doesn't support macOS.
|
||||||
BUILD_UTILITY("config_editor", "-lX11 -Wno-unused-parameter", "");
|
BUILD_UTILITY("config_editor", "-lX11 -Wno-unused-parameter", "");
|
||||||
#endif
|
|
||||||
#ifndef __APPLE__ // Luigi doesn't support macOS.
|
|
||||||
BUILD_UTILITY("reflect_gen", "", "designer/");
|
|
||||||
|
|
||||||
if (CheckDependencies("Utilities.DesignerHeader")) {
|
|
||||||
if (!CallSystem("bin/reflect_gen util/designer/designer.rf > bin/designer.h")) {
|
|
||||||
FILE *f = fopen("bin/designer_header.d", "wb");
|
|
||||||
fprintf(f, ": util/designer/designer.rf bin/reflect_gen\n");
|
|
||||||
fclose(f);
|
|
||||||
ParseDependencies("bin/designer_header.d", "Utilities.DesignerHeader", false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CheckDependencies("Utilities.OldDesigner1") || CheckDependencies("Utilities.OldDesigner2")) {
|
|
||||||
if (!CallSystem("gcc -MMD -o bin/designer.o -c util/designer/designer.c -g -std=c2x -fsanitize=address " WARNING_FLAGS_C)
|
|
||||||
&& !CallSystem("gcc -MMD -o bin/designer_luigi.o -c util/designer/designer_luigi.c -g -std=c2x " WARNING_FLAGS_C)
|
|
||||||
&& !CallSystem("gcc -o bin/designer -g bin/designer.o bin/designer_luigi.o -lX11 -lm -fsanitize=address ")) {
|
|
||||||
ParseDependencies("bin/designer.d", "Utilities.Designer1", false);
|
|
||||||
ParseDependencies("bin/designer_luigi.d", "Utilities.Designer2", false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CheckDependencies("Utilities.Designer")) {
|
if (CheckDependencies("Utilities.Designer")) {
|
||||||
if (!CallSystem("g++ -MMD -D UI_LINUX util/designer2.cpp -o bin/designer2 -g -lX11 -Wno-unused-parameter " WARNING_FLAGS)) {
|
if (!CallSystem("g++ -MMD -D UI_LINUX util/designer2.cpp -o bin/designer2 -g -lX11 -Wno-unused-parameter " WARNING_FLAGS)) {
|
||||||
|
@ -1396,7 +1376,7 @@ void DoCommand(const char *l) {
|
||||||
LineCountFile("", "start.sh");
|
LineCountFile("", "start.sh");
|
||||||
|
|
||||||
const char *folders[] = {
|
const char *folders[] = {
|
||||||
"desktop/", "boot/x86/", "drivers/", "kernel/", "apps/", "apps/file_manager/", "shared/", "util/", "util/designer/"
|
"desktop/", "boot/x86/", "drivers/", "kernel/", "apps/", "apps/file_manager/", "shared/", "util/"
|
||||||
};
|
};
|
||||||
|
|
||||||
for (uintptr_t i = 0; i < sizeof(folders) / sizeof(folders[0]); i++) {
|
for (uintptr_t i = 0; i < sizeof(folders) / sizeof(folders[0]); i++) {
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,432 +0,0 @@
|
||||||
type StyleColor_Type StyleColorOp;
|
|
||||||
type StyleString_Type StyleStringOp;
|
|
||||||
type StyleBool_Type StyleBoolOp;
|
|
||||||
type StyleArray_Type StyleArrayOp;
|
|
||||||
type StyleFloat_Type StyleFloatOp;
|
|
||||||
type StyleI8_Type StyleI8Op;
|
|
||||||
type StyleI16_Type StyleI16Op;
|
|
||||||
|
|
||||||
struct Property Property_Type PropertyOp {
|
|
||||||
rfNone "uint32_t *" path;
|
|
||||||
rfData RfData data;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Rectangle8 Rectangle8_Type Rectangle8Op {
|
|
||||||
StyleI8_Type int8_t l;
|
|
||||||
StyleI8_Type int8_t r;
|
|
||||||
StyleI8_Type int8_t t;
|
|
||||||
StyleI8_Type int8_t b;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Rectangle16 Rectangle16_Type Rectangle16Op {
|
|
||||||
StyleI16_Type int16_t l;
|
|
||||||
StyleI16_Type int16_t r;
|
|
||||||
StyleI16_Type int16_t t;
|
|
||||||
StyleI16_Type int16_t b;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Corners8 Corners8_Type Corners8Op {
|
|
||||||
StyleI8_Type int8_t tl;
|
|
||||||
StyleI8_Type int8_t tr;
|
|
||||||
StyleI8_Type int8_t bl;
|
|
||||||
StyleI8_Type int8_t br;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Gaps8 Gaps8_Type Gaps8Op {
|
|
||||||
StyleI8_Type int8_t major;
|
|
||||||
StyleI8_Type int8_t minor;
|
|
||||||
StyleI8_Type int8_t wrap;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Size16 Size16_Type Size16Op {
|
|
||||||
StyleI16_Type int16_t width;
|
|
||||||
StyleI16_Type int16_t height;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PaintSolid PaintSolid_Type PaintSolidOp {
|
|
||||||
StyleColor_Type uint32_t color #StringOption { "Color" };
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PaintOverwrite PaintOverwrite_Type PaintOverwriteOp {
|
|
||||||
StyleColor_Type uint32_t color #StringOption { "Color" };
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GradientStop GradientStop_Type GradientStopOp {
|
|
||||||
StyleColor_Type uint32_t color #StringOption { "Color" };
|
|
||||||
StyleI8_Type int8_t position #StringOption { "Position" };
|
|
||||||
};
|
|
||||||
|
|
||||||
enum GradientRepeat_Type StyleEnumOp {
|
|
||||||
GRADIENT_REPEAT_CLAMP #StringOption { "Clamp" };
|
|
||||||
GRADIENT_REPEAT_NORMAL #StringOption { "Normal" };
|
|
||||||
GRADIENT_REPEAT_MIRROR #StringOption { "Mirror" };
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PaintLinearGradient PaintLinearGradient_Type PaintLinearGradientOp {
|
|
||||||
Rectangle16_Type Rectangle16 range #StringOption { "Range" } to 6;
|
|
||||||
StyleBool_Type bool useGammaInterpolation #StringOption { "Use gamma-accurate color interpolation" };
|
|
||||||
StyleArray_Type "GradientStop *" stops #RfItem { &GradientStop_Type, sizeof(GradientStop), &(StringOption) { "Stops: " } };
|
|
||||||
StyleBool_Type bool useDithering #StringOption { "Use dithering" } from 4;
|
|
||||||
GradientRepeat_Type uint8_t repeat #StringOption { "Repeat mode" } from 5;
|
|
||||||
StyleFloat_Type float transformX #StringOption { "Transform X" } from 6;
|
|
||||||
StyleFloat_Type float transformY #StringOption { "Transform Y" } from 6;
|
|
||||||
StyleFloat_Type float transformStart #StringOption { "Transform start" } from 6;
|
|
||||||
StyleBool_Type bool useSystemHue #StringOption { "Use system hue" } from 20;
|
|
||||||
StyleBool_Type bool _unused #StringOption { "_unused" } from 21;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PaintRadialGradient PaintRadialGradient_Type PaintRadialGradientOp {
|
|
||||||
StyleBool_Type bool useGammaInterpolation #StringOption { "Use gamma-accurate color interpolation" };
|
|
||||||
StyleArray_Type "GradientStop *" stops #RfItem { &GradientStop_Type, sizeof(GradientStop), &(StringOption) { "Stops: " } };
|
|
||||||
GradientRepeat_Type uint8_t repeat #StringOption { "Repeat mode" };
|
|
||||||
StyleFloat_Type float transform0 #StringOption { "Transform X scale" };
|
|
||||||
StyleFloat_Type float transform2 #StringOption { "Transform X offset" };
|
|
||||||
StyleFloat_Type float transform4 #StringOption { "Transform Y scale" };
|
|
||||||
StyleFloat_Type float transform5 #StringOption { "Transform Y offset" };
|
|
||||||
StyleFloat_Type float transform1 #StringOption { "Transform X skew" } from 8;
|
|
||||||
StyleFloat_Type float transform3 #StringOption { "Transform Y skew" } from 8;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Paint Paint_Type StyleUnionOp {
|
|
||||||
rfU32 uint32_t tag;
|
|
||||||
PaintSolid_Type PaintSolid solid #StringOption { "Solid" };
|
|
||||||
PaintLinearGradient_Type PaintLinearGradient linearGradient #StringOption { "Linear gradient" };
|
|
||||||
PaintOverwrite_Type PaintOverwrite overwrite #StringOption { "Overwrite" } from 2;
|
|
||||||
PaintRadialGradient_Type PaintRadialGradient radialGradient #StringOption { "Radial gradient" } from 7;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct LayerBox LayerBox_Type LayerBoxOp {
|
|
||||||
Rectangle8_Type Rectangle8 borders #StringOption { "Borders" };
|
|
||||||
Corners8_Type Corners8 corners #StringOption { "Corners" };
|
|
||||||
Paint_Type Paint mainPaint #StringOption { "Main paint" };
|
|
||||||
Paint_Type Paint borderPaint #StringOption { "Border paint" };
|
|
||||||
StyleBool_Type bool blurred #StringOption { "Blurred" };
|
|
||||||
StyleBool_Type bool autoCorners #StringOption { "Auto corners" };
|
|
||||||
StyleBool_Type bool autoBorders #StringOption { "Auto borders" };
|
|
||||||
StyleBool_Type bool shadowHiding #StringOption { "Shadow hiding" };
|
|
||||||
StyleBool_Type bool shadowCut #StringOption { "Shadow cut (obsolete)" } from 13;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ClipMode_Type StyleEnumOp {
|
|
||||||
CLIP_MODE_ENABLED #StringOption { "Enabled" };
|
|
||||||
CLIP_MODE_DISABLED #StringOption { "Disabled" };
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Cursor_Type StyleEnumOp {
|
|
||||||
CURSOR_NORMAL #StringOption { "Normal" };
|
|
||||||
CURSOR_TEXT #StringOption { "Text" };
|
|
||||||
CURSOR_RESIZE_VERTICAL #StringOption { "Resize vertical" };
|
|
||||||
CURSOR_RESIZE_HORIZONTAL #StringOption { "Resize horizontal" };
|
|
||||||
CURSOR_RESIZE_DIAGONAL_1 #StringOption { "Diagonal 1" };
|
|
||||||
CURSOR_RESIZE_DIAGONAL_2 #StringOption { "Diagonal 2" };
|
|
||||||
CURSOR_SPLIT_VERTICAL #StringOption { "Split vertical" };
|
|
||||||
CURSOR_SPLIT_HORIZONTAL #StringOption { "Split horizontal" };
|
|
||||||
CURSOR_HAND_HOVER #StringOption { "Hand hover" };
|
|
||||||
CURSOR_HAND_DRAG #StringOption { "Hand drag" };
|
|
||||||
CURSOR_HAND_POINT #StringOption { "Hand point" };
|
|
||||||
CURSOR_SCROLL_UP_LEFT #StringOption { "Scroll up-left" };
|
|
||||||
CURSOR_SCROLL_UP #StringOption { "Scroll up" };
|
|
||||||
CURSOR_SCROLL_UP_RIGHT #StringOption { "Scroll up-right" };
|
|
||||||
CURSOR_SCROLL_LEFT #StringOption { "Scroll left" };
|
|
||||||
CURSOR_SCROLL_CENTER #StringOption { "Scroll center" };
|
|
||||||
CURSOR_SCROLL_RIGHT #StringOption { "Scroll right" };
|
|
||||||
CURSOR_SCROLL_DOWN_LEFT #StringOption { "Scroll down-left" };
|
|
||||||
CURSOR_SCROLL_DOWN #StringOption { "Scroll down" };
|
|
||||||
CURSOR_SCROLL_DOWN_RIGHT #StringOption { "Scroll down-right" };
|
|
||||||
CURSOR_SELECT_LINES #StringOption { "Select lines" };
|
|
||||||
CURSOR_DROP_TEXT #StringOption { "Drop text" };
|
|
||||||
CURSOR_CROSS_HAIR_PICK #StringOption { "Cross hair pick" };
|
|
||||||
CURSOR_CROSS_HAIR_RESIZE #StringOption { "Cross hair resize" };
|
|
||||||
CURSOR_MOVE_HOVER #StringOption { "Move hover" };
|
|
||||||
CURSOR_MOVE_DRAG #StringOption { "Move drag" };
|
|
||||||
CURSOR_ROTATE_HOVER #StringOption { "Rotate hover" };
|
|
||||||
CURSOR_ROTATE_DRAG #StringOption { "Rotate drag" };
|
|
||||||
CURSOR_BLANK #StringOption { "Blank" };
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Transition_Type StyleEnumOp {
|
|
||||||
TRANSITION_NONE #StringOption { "None" };
|
|
||||||
TRANSITION_SLIDE_UP #StringOption { "Slide up" };
|
|
||||||
TRANSITION_SLIDE_DOWN #StringOption { "Slide down" };
|
|
||||||
TRANSITION_COVER_UP #StringOption { "Cover up" };
|
|
||||||
TRANSITION_COVER_DOWN #StringOption { "Cover down" };
|
|
||||||
TRANSITION_SQUISH_UP #StringOption { "Squish up" };
|
|
||||||
TRANSITION_SQUISH_DOWN #StringOption { "Squish down" };
|
|
||||||
TRANSITION_REVEAL_UP #StringOption { "Reveal up" };
|
|
||||||
TRANSITION_REVEAL_DOWN #StringOption { "Reveal down" };
|
|
||||||
TRANSITION_ZOOM_OUT #StringOption { "Zoom out" };
|
|
||||||
TRANSITION_ZOOM_IN #StringOption { "Zoom in" };
|
|
||||||
TRANSITION_ZOOM_OUT_LIGHT #StringOption { "Zoom out (light)" };
|
|
||||||
TRANSITION_ZOOM_IN_LIGHT #StringOption { "Zoom in (light)" };
|
|
||||||
TRANSITION_FADE_OUT #StringOption { "Fade out" };
|
|
||||||
TRANSITION_FADE_IN #StringOption { "Fade in" };
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Align_Type StyleEnumOp {
|
|
||||||
ALIGN_START #StringOption { "Start" };
|
|
||||||
ALIGN_CENTER #StringOption { "Center" };
|
|
||||||
ALIGN_END #StringOption { "End" };
|
|
||||||
};
|
|
||||||
|
|
||||||
enum FontFamily_Type StyleEnumOp {
|
|
||||||
FONT_FAMILY_SANS #StringOption { "Sans" };
|
|
||||||
FONT_FAMILY_SERIF #StringOption { "Serif" };
|
|
||||||
FONT_FAMILY_MONO #StringOption { "Mono" };
|
|
||||||
};
|
|
||||||
|
|
||||||
struct LayerMetrics LayerMetrics_Type LayerMetricsOp {
|
|
||||||
Rectangle8_Type Rectangle8 insets #StringOption { "Insets" };
|
|
||||||
ClipMode_Type uint32_t clipEnabled #StringOption { "Clipping: " };
|
|
||||||
Rectangle8_Type Rectangle8 clipInsets #StringOption { "Clip insets" };
|
|
||||||
Size16_Type Size16 preferredSize #StringOption { "Preferred size" };
|
|
||||||
Size16_Type Size16 minimumSize #StringOption { "Minimum size" };
|
|
||||||
Size16_Type Size16 maximumSize #StringOption { "Maximum size" };
|
|
||||||
Gaps8_Type Gaps8 gaps #StringOption { "Gaps" };
|
|
||||||
Cursor_Type uint32_t cursor #StringOption { "Cursor" };
|
|
||||||
Transition_Type uint32_t entranceTransition #StringOption { "Entrance transition" } to 21;
|
|
||||||
StyleI16_Type int16_t entranceDuration #StringOption { "Entrance duration (ms)" } to 21;
|
|
||||||
Transition_Type uint32_t exitTransition #StringOption { "Exit transition" } to 21;
|
|
||||||
StyleI16_Type int16_t exitDuration #StringOption { "Exit duration (ms)" } to 21;
|
|
||||||
Rectangle8_Type Rectangle8 globalOffset #StringOption { "Global offset" };
|
|
||||||
Align_Type uint32_t textVerticalAlign #StringOption { "Text vertical align: " };
|
|
||||||
Align_Type uint32_t textHorizontalAlign #StringOption { "Text horizontal align: " };
|
|
||||||
StyleI8_Type int8_t textSize #StringOption { "Font size" };
|
|
||||||
FontFamily_Type uint32_t fontFamily #StringOption { "Font family: " };
|
|
||||||
StyleI8_Type int8_t fontWeight #StringOption { "Font weight" };
|
|
||||||
StyleBool_Type bool italic #StringOption { "Italic" };
|
|
||||||
StyleBool_Type bool wrapText #StringOption { "Wrap text" };
|
|
||||||
StyleBool_Type bool ellipsis #StringOption { "Ellipsis" };
|
|
||||||
StyleColor_Type uint32_t textColor #StringOption { "Text color" };
|
|
||||||
StyleColor_Type uint32_t selectedBackground #StringOption { "Selected background" };
|
|
||||||
StyleColor_Type uint32_t selectedText #StringOption { "Selected text" };
|
|
||||||
StyleI8_Type int8_t iconSize #StringOption { "Icon size" };
|
|
||||||
StyleColor_Type uint32_t iconColor #StringOption { "Icon color" };
|
|
||||||
StyleString_Type RfData inheritText #StringOption { "Inherit text properties from:" } from 11;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct LayerText LayerText_Type LayerTextOp {
|
|
||||||
StyleColor_Type uint32_t color #StringOption { "Color" };
|
|
||||||
StyleI8_Type int8_t blur #StringOption { "Blur radius" };
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PathPoint PathPoint_Type PathPointOp {
|
|
||||||
StyleFloat_Type float x0 #StringOption { "x0" };
|
|
||||||
StyleFloat_Type float y0 #StringOption { "y0" };
|
|
||||||
StyleFloat_Type float x1 #StringOption { "x1" };
|
|
||||||
StyleFloat_Type float y1 #StringOption { "y1" };
|
|
||||||
StyleFloat_Type float x2 #StringOption { "x2" };
|
|
||||||
StyleFloat_Type float y2 #StringOption { "y2" };
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PathFillSolid PathFillSolid_Type PathFillSolidOp {
|
|
||||||
};
|
|
||||||
|
|
||||||
enum JoinMode StyleEnumOp {
|
|
||||||
JOIN_MODE_MITER #StringOption { "Miter" };
|
|
||||||
JOIN_MODE_ROUND #StringOption { "Round" };
|
|
||||||
JOIN_MODE_BEVEL #StringOption { "Bevel" };
|
|
||||||
};
|
|
||||||
|
|
||||||
enum CapMode StyleEnumOp {
|
|
||||||
CAP_MODE_FLAT #StringOption { "Flat" };
|
|
||||||
CAP_MODE_ROUND #StringOption { "Round" };
|
|
||||||
CAP_MODE_SQUARE #StringOption { "Square" };
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PathFillContour PathFillContour_Type PathFillContourOp {
|
|
||||||
StyleI8_Type int8_t internalWidth #StringOption { "Internal width" };
|
|
||||||
StyleI8_Type int8_t externalWidth #StringOption { "External width" };
|
|
||||||
StyleFloat_Type float miterLimit #StringOption { "Miter limit" };
|
|
||||||
JoinMode uint8_t joinMode #StringOption { "Join mode: " };
|
|
||||||
CapMode uint8_t capMode #StringOption { "Cap mode: " };
|
|
||||||
StyleBool_Type bool integerWidthsOnly #StringOption { "Integer widths only when scaling" } from 14;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PathFillDash PathFillDash_Type PathFillDashOp {
|
|
||||||
PathFillContour_Type PathFillContour contour;
|
|
||||||
StyleI8_Type int8_t length #StringOption { "Length" };
|
|
||||||
StyleI8_Type int8_t gap #StringOption { "Gap" };
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PathFillDashed PathFillDashed_Type PathFillDashedOp {
|
|
||||||
StyleArray_Type "PathFillDash *" dashes #RfItem { &PathFillDash_Type, sizeof(PathFillDash), &(StringOption) { "Dashes: " } };
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PathFillMode PathFillMode_Type StyleUnionOp {
|
|
||||||
rfU32 uint32_t tag;
|
|
||||||
PathFillSolid_Type PathFillSolid solid #StringOption { "Solid" };
|
|
||||||
PathFillContour_Type PathFillContour contour #StringOption { "Contour" };
|
|
||||||
PathFillDashed_Type PathFillDashed dashed #StringOption { "Dashed" };
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PathFill PathFill_Type PathFillOp {
|
|
||||||
PathFillMode_Type PathFillMode mode #StringOption { "Mode" };
|
|
||||||
Paint_Type Paint paint #StringOption { "Paint" };
|
|
||||||
};
|
|
||||||
|
|
||||||
struct LayerPath LayerPath_Type LayerPathOp {
|
|
||||||
StyleBool_Type bool evenOdd #StringOption { "Even-odd fill rule" };
|
|
||||||
StyleBool_Type bool closed #StringOption { "Closed path" };
|
|
||||||
StyleI16_Type int16_t alpha #StringOption { "Alpha" };
|
|
||||||
StyleArray_Type "PathPoint *" points #RfItem { &PathPoint_Type, sizeof(PathPoint), &(StringOption) { "Points: " } };
|
|
||||||
StyleArray_Type "PathFill *" fills #RfItem { &PathFill_Type, sizeof(PathFill), &(StringOption) { "Fills: " } };
|
|
||||||
};
|
|
||||||
|
|
||||||
union LayerBase LayerBase_Type RfUnionOp {
|
|
||||||
LayerBox_Type LayerBox box;
|
|
||||||
LayerMetrics_Type LayerMetrics metrics;
|
|
||||||
rfNone bool _removed0;
|
|
||||||
rfNone bool _removed1;
|
|
||||||
LayerText_Type LayerText text;
|
|
||||||
LayerPath_Type LayerPath path;
|
|
||||||
};
|
|
||||||
|
|
||||||
type DesignerArray_Type DesignerArrayOp;
|
|
||||||
|
|
||||||
struct Keyframe Keyframe_Type RfStructOp {
|
|
||||||
StyleI8_Type int8_t progress #StringOption { "Progress (%)" };
|
|
||||||
DesignerArray_Type "Property *" properties #RfItem { &Property_Type, sizeof(Property), NULL };
|
|
||||||
};
|
|
||||||
|
|
||||||
enum PrimaryState_Type StyleEnumOp {
|
|
||||||
PRIMARY_STATE_ANY #StringOption { "Any" };
|
|
||||||
PRIMARY_STATE_IDLE #StringOption { "Idle" };
|
|
||||||
PRIMARY_STATE_HOVERED #StringOption { "Hovered" };
|
|
||||||
PRIMARY_STATE_PRESSED #StringOption { "Pressed" };
|
|
||||||
PRIMARY_STATE_DISABLED #StringOption { "Disabled" };
|
|
||||||
PRIMARY_STATE_INACTIVE #StringOption { "Inactive" };
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Sequence Sequence_Type RfStructOp {
|
|
||||||
DesignerArray_Type "Keyframe **" keyframes #RfItem { &rfObject, sizeof(Keyframe *), &(RfItem) { &Keyframe_Type, sizeof(Keyframe), NULL } };
|
|
||||||
StyleI16_Type int16_t duration #StringOption { "Duration (ms)" };
|
|
||||||
PrimaryState_Type uint32_t primaryState #StringOption { "Primary state" };
|
|
||||||
StyleBool_Type bool flagFocused #StringOption { "Focused?" };
|
|
||||||
StyleBool_Type bool flagChecked #StringOption { "Checked?" };
|
|
||||||
StyleBool_Type bool flagIndeterminate #StringOption { "Indeterminate?" };
|
|
||||||
StyleBool_Type bool flagDefault #StringOption { "Default?" };
|
|
||||||
StyleBool_Type bool flagItemFocus #StringOption { "List item focus?" };
|
|
||||||
StyleBool_Type bool flagListFocus #StringOption { "List focus?" };
|
|
||||||
StyleBool_Type bool flagSelected #StringOption { "Selected?" };
|
|
||||||
StyleBool_Type bool flagBeforeEnter #StringOption { "Before enter?" };
|
|
||||||
StyleBool_Type bool flagAfterExit #StringOption { "After exit?" };
|
|
||||||
};
|
|
||||||
|
|
||||||
enum LayerMode_Type StyleEnumOp {
|
|
||||||
LAYER_MODE_BACKGROUND #StringOption { "Background" };
|
|
||||||
LAYER_MODE_SHADOW #StringOption { "Shadow" };
|
|
||||||
LAYER_MODE_CONTENT #StringOption { "Content" };
|
|
||||||
LAYER_MODE_OVERLAY #StringOption { "Overlay" };
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Layer Layer_Type LayerOp {
|
|
||||||
rfU64 uint64_t id;
|
|
||||||
rfNone uint32_t exportOffset;
|
|
||||||
|
|
||||||
DesignerArray_Type "Sequence **" sequences #RfItem { &rfObject, sizeof(Sequence *), &(RfItem) { &Sequence_Type, sizeof(Sequence), NULL } };
|
|
||||||
StyleString_Type RfData name #StringOption { "Layer name" };
|
|
||||||
rfBool bool isMetricsLayer;
|
|
||||||
|
|
||||||
Rectangle8_Type Rectangle8 offset #StringOption { "Offset (dpx)" };
|
|
||||||
Rectangle8_Type Rectangle8 position #StringOption { "Position (%)" };
|
|
||||||
LayerMode_Type uint8_t mode #StringOption { "Mode: " };
|
|
||||||
LayerBase_Type LayerBase base;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Style Style_Type RfStructOp {
|
|
||||||
DesignerArray_Type "uint64_t *" layers #RfItem { &rfU64, sizeof(uint64_t), NULL };
|
|
||||||
rfData RfData name;
|
|
||||||
rfU64 uint64_t id from 15;
|
|
||||||
rfBool bool publicStyle from 16;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Constant Constant_Type RfStructOp {
|
|
||||||
rfData RfData key;
|
|
||||||
StyleString_Type RfData value;
|
|
||||||
StyleBool_Type bool scale from 9;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Color Color_Type RfStructOp {
|
|
||||||
rfData RfData key;
|
|
||||||
rfU32 uint32_t value;
|
|
||||||
rfU32 uint32_t id;
|
|
||||||
rfNone uint64_t object2ID;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct StyleSet StyleSet_Type StyleSetOp {
|
|
||||||
rfU64 uint64_t lastID;
|
|
||||||
DesignerArray_Type "Style **" styles #RfItem { &rfObject, sizeof(Style *), &(RfItem) { &Style_Type, sizeof(Style), NULL } };
|
|
||||||
DesignerArray_Type "Layer **" layers #RfItem { &rfObject, sizeof(Layer *), &(RfItem) { &Layer_Type, sizeof(Layer), NULL } };
|
|
||||||
DesignerArray_Type "Constant **" constants #RfItem { &rfObject, sizeof(Constant *), &(RfItem) { &Constant_Type, sizeof(Constant), NULL } };
|
|
||||||
DesignerArray_Type "Color **" colors #RfItem { &rfObject, sizeof(Color *), &(RfItem) { &Color_Type, sizeof(Color), NULL } } from 17;
|
|
||||||
};
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
struct ModAddLayer ModAddLayer_Type ModAddLayerOp {
|
|
||||||
rfObject "Layer *" layer #RfItem { &Layer_Type, sizeof(Layer), NULL };
|
|
||||||
rfI32 int index;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ModDeleteLayer ModDeleteLayer_Type ModDeleteLayerOp {
|
|
||||||
rfI32 int index;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ModSwapLayers ModSwapLayers_Type ModSwapLayersOp {
|
|
||||||
rfI32 int index;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ModSwapSequences ModSwapSequences_Type ModSwapSequencesOp {
|
|
||||||
rfI32 int index;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ModAddSequence ModAddSequence_Type ModAddSequenceOp {
|
|
||||||
rfObject "Sequence *" sequence #RfItem { &Sequence_Type, sizeof(Sequence), NULL };
|
|
||||||
rfI32 int index;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ModDeleteSequence ModDeleteSequence_Type ModDeleteSequenceOp {
|
|
||||||
rfI32 int index;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ModAddKeyframe ModAddKeyframe_Type ModAddKeyframeOp {
|
|
||||||
rfObject "Keyframe *" keyframe #RfItem { &Keyframe_Type, sizeof(Keyframe), NULL };
|
|
||||||
rfI32 int index;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ModDeleteKeyframe ModDeleteKeyframe_Type ModDeleteKeyframeOp {
|
|
||||||
rfI32 int index;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ModChangeProperty ModChangeProperty_Type ModChangePropertyOp {
|
|
||||||
Property_Type Property property;
|
|
||||||
rfNone "struct UIElement *" source;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ModArray ModArray_Type ModArrayOp {
|
|
||||||
Property_Type Property property;
|
|
||||||
rfBool bool isDelete;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ModDeleteOverride ModDeleteOverride_Type ModDeleteOverrideOp {
|
|
||||||
Property_Type Property property;
|
|
||||||
};
|
|
||||||
|
|
||||||
union ModData ModData_Type RfUnionOp {
|
|
||||||
ModAddLayer_Type ModAddLayer addLayer;
|
|
||||||
ModDeleteLayer_Type ModDeleteLayer deleteLayer;
|
|
||||||
ModSwapLayers_Type ModSwapLayers swapLayers;
|
|
||||||
ModSwapSequences_Type ModSwapSequences swapSequences;
|
|
||||||
ModAddSequence_Type ModAddSequence addSequence;
|
|
||||||
ModDeleteSequence_Type ModDeleteSequence deleteSequence;
|
|
||||||
ModAddKeyframe_Type ModAddKeyframe addKeyframe;
|
|
||||||
ModDeleteKeyframe_Type ModDeleteKeyframe deleteKeyframe;
|
|
||||||
ModChangeProperty_Type ModChangeProperty changeProperty;
|
|
||||||
ModArray_Type ModArray array;
|
|
||||||
ModDeleteOverride_Type ModDeleteOverride deleteOverride;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Mod Mod_Type RfStructOp {
|
|
||||||
rfNone ModContext context;
|
|
||||||
ModData_Type ModData data;
|
|
||||||
};
|
|
|
@ -1,8 +0,0 @@
|
||||||
#ifdef _WIN32
|
|
||||||
#define UI_WINDOWS
|
|
||||||
#else
|
|
||||||
#define UI_LINUX
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define UI_IMPLEMENTATION
|
|
||||||
#include "../luigi.h"
|
|
|
@ -1,654 +0,0 @@
|
||||||
// TODO Bitsets.
|
|
||||||
// TODO Versioning support for unions and enums.
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#ifndef RF_ASSERT
|
|
||||||
#include <assert.h>
|
|
||||||
#define RF_ASSERT assert
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef RF_MEMZERO
|
|
||||||
#include <string.h>
|
|
||||||
#define RF_MEMZERO(pointer, byteCount) memset((pointer), 0, (byteCount))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef RF_MEMCPY
|
|
||||||
#include <string.h>
|
|
||||||
#define RF_MEMCPY(destination, source, byteCount) memcpy((destination), (source), (byteCount))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef RF_REALLOC
|
|
||||||
#include <stdlib.h>
|
|
||||||
#define RF_REALLOC(previous, byteCount) realloc((previous), (byteCount))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define RF_SIZE_OF(containerType, field) sizeof(((containerType *) NULL)->field)
|
|
||||||
#define RF_FIELD(containerType, field, fieldRfType, ...) \
|
|
||||||
{ \
|
|
||||||
.item.type = &fieldRfType, \
|
|
||||||
.item.byteCount = RF_SIZE_OF(containerType, field), \
|
|
||||||
.cName = #field, \
|
|
||||||
.offset = offsetof(containerType, field), \
|
|
||||||
__VA_ARGS__ \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define RF_OP_SAVE (-1) // Set access in RfState.
|
|
||||||
#define RF_OP_LOAD (-2) // Set access and allocate in RfState.
|
|
||||||
#define RF_OP_FREE (-3) // Set allocate in RfState.
|
|
||||||
#define RF_OP_ITERATE (-4) // Pass RfIterator; set index.
|
|
||||||
#define RF_OP_COUNT (-5) // Pass RfIterator; result saved in index.
|
|
||||||
// User-defined operations use positive integers.
|
|
||||||
|
|
||||||
typedef struct RfState {
|
|
||||||
bool error;
|
|
||||||
int16_t op;
|
|
||||||
uint32_t version, flags;
|
|
||||||
void *(*allocate)(struct RfState *state, void *previous, size_t byteCount);
|
|
||||||
void (*access)(struct RfState *state, void *buffer, size_t byteCount);
|
|
||||||
} RfState;
|
|
||||||
|
|
||||||
typedef struct RfItem {
|
|
||||||
struct RfType *type;
|
|
||||||
size_t byteCount;
|
|
||||||
void *options;
|
|
||||||
} RfItem;
|
|
||||||
|
|
||||||
typedef struct RfField {
|
|
||||||
RfItem item;
|
|
||||||
const char *cName;
|
|
||||||
ptrdiff_t offset;
|
|
||||||
uint32_t firstVersion, lastVersion;
|
|
||||||
uint32_t flagsInclude, flagsExclude;
|
|
||||||
} RfField;
|
|
||||||
|
|
||||||
typedef struct RfType {
|
|
||||||
void (*op)(RfState *state, RfItem *field, void *pointer);
|
|
||||||
const char *cName;
|
|
||||||
size_t fieldCount;
|
|
||||||
RfField *fields;
|
|
||||||
} RfType;
|
|
||||||
|
|
||||||
typedef struct RfIterator {
|
|
||||||
RfState s;
|
|
||||||
void *pointer;
|
|
||||||
RfItem item;
|
|
||||||
uint32_t index;
|
|
||||||
bool includeRemovedFields;
|
|
||||||
bool isRemoved;
|
|
||||||
} RfIterator;
|
|
||||||
|
|
||||||
typedef struct RfPath {
|
|
||||||
#define RF_PATH_TERMINATOR (0xFFFFFFFF)
|
|
||||||
uint32_t indices[1];
|
|
||||||
} RfPath;
|
|
||||||
|
|
||||||
typedef struct RfUnionHeader {
|
|
||||||
uint32_t tag;
|
|
||||||
} RfUnionHeader;
|
|
||||||
|
|
||||||
typedef struct RfArrayHeader {
|
|
||||||
size_t length, capacity;
|
|
||||||
|
|
||||||
// For compatability with stb_ds.h.
|
|
||||||
void *hashTable;
|
|
||||||
ptrdiff_t temporary;
|
|
||||||
} RfArrayHeader;
|
|
||||||
|
|
||||||
typedef struct RfData {
|
|
||||||
void *buffer;
|
|
||||||
size_t byteCount;
|
|
||||||
} RfData;
|
|
||||||
|
|
||||||
typedef struct RfGrowableBuffer {
|
|
||||||
RfState s;
|
|
||||||
RfData data;
|
|
||||||
|
|
||||||
// When writing - allocated space in data.
|
|
||||||
// When reading - position in data.
|
|
||||||
size_t position;
|
|
||||||
} RfGrowableBuffer;
|
|
||||||
|
|
||||||
extern RfType rfI8, rfI16, rfI32, rfI64,
|
|
||||||
rfU8, rfU16, rfU32, rfU64,
|
|
||||||
rfF32, rfF64,
|
|
||||||
rfChar, rfBool,
|
|
||||||
rfData, rfNone,
|
|
||||||
rfObject /* options - RfItem */,
|
|
||||||
rfArray /* options - RfItem */;
|
|
||||||
|
|
||||||
bool RfPathResolve(RfPath *path, RfItem *item, void **pointer); // Returns true if successful.
|
|
||||||
void RfBroadcast(RfState *state, RfItem *item, void *pointer, bool recurse);
|
|
||||||
void RfUnionSelect(RfState *state, RfItem *item, RfUnionHeader *header, uint32_t tag);
|
|
||||||
|
|
||||||
void RfReadGrowableBuffer(RfState /* RfGrowableBuffer */ *state, void *buffer, size_t byteCount);
|
|
||||||
void RfWriteGrowableBuffer(RfState /* RfGrowableBuffer */ *state, void *buffer, size_t byteCount);
|
|
||||||
void *RfRealloc(RfState *state, void *previous, size_t byteCount);
|
|
||||||
|
|
||||||
void RfStructOp(RfState *state, RfItem *item, void *pointer);
|
|
||||||
void RfUnionOp(RfState *state, RfItem *item, void *pointer);
|
|
||||||
void RfEnumOp(RfState *state, RfItem *item, void *pointer);
|
|
||||||
void RfBitSetOp(RfState *state, RfItem *item, void *pointer);
|
|
||||||
void RfEndianOp(RfState *state, RfItem *item, void *pointer);
|
|
||||||
void RfIntegerOp(RfState *state, RfItem *item, void *pointer);
|
|
||||||
void RfNoneOp(RfState *state, RfItem *item, void *pointer);
|
|
||||||
|
|
||||||
#ifdef REFLECT_IMPLEMENTATION
|
|
||||||
|
|
||||||
void RfIntegerSave(RfState *state, void *pointer, size_t inByteCount) {
|
|
||||||
uint8_t in[16];
|
|
||||||
RF_ASSERT(inByteCount < 16);
|
|
||||||
RF_MEMCPY(in, pointer, inByteCount);
|
|
||||||
|
|
||||||
bool negative = in[inByteCount - 1] & 0x80;
|
|
||||||
size_t inBitCount = 1;
|
|
||||||
|
|
||||||
for (int i = inByteCount - 1; i >= 0; i--) {
|
|
||||||
for (int j = 7; j >= 0; j--) {
|
|
||||||
if (((in[i] >> j) & 1) != negative) {
|
|
||||||
inBitCount = i * 8 + j + 2;
|
|
||||||
goto gotBitCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gotBitCount:;
|
|
||||||
|
|
||||||
size_t outByteCount = (inBitCount + 6) / 7;
|
|
||||||
uint8_t out[16];
|
|
||||||
RF_ASSERT(outByteCount < 16);
|
|
||||||
|
|
||||||
for (uintptr_t i = 0; i < outByteCount; i++) {
|
|
||||||
uint8_t b = 0;
|
|
||||||
|
|
||||||
for (uintptr_t j = 0; j < 7; j++) {
|
|
||||||
uintptr_t bitIndex = i * 7 + j;
|
|
||||||
bool inBit = negative;
|
|
||||||
if (bitIndex < 8 * inByteCount) inBit = in[bitIndex >> 3] & (1 << (bitIndex & 7));
|
|
||||||
if (inBit) b |= 1 << j;
|
|
||||||
}
|
|
||||||
|
|
||||||
out[i] = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
out[outByteCount - 1] |= 0x80;
|
|
||||||
state->access(state, out, outByteCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RfIntegerLoad(RfState *state, void *pointer, size_t byteCount) {
|
|
||||||
uint8_t out[16];
|
|
||||||
uintptr_t outIndex = 0;
|
|
||||||
RF_ASSERT(byteCount < 16);
|
|
||||||
RF_MEMZERO(out, byteCount);
|
|
||||||
|
|
||||||
while (!state->error) {
|
|
||||||
uint8_t b;
|
|
||||||
state->access(state, &b, 1);
|
|
||||||
|
|
||||||
for (uintptr_t i = 0; i < 7; i++) {
|
|
||||||
if (outIndex == byteCount * 8) break;
|
|
||||||
if (b & (1 << i)) out[outIndex >> 3] |= 1 << (outIndex & 7);
|
|
||||||
outIndex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (b & 0x80) {
|
|
||||||
if (b & 0x40) {
|
|
||||||
for (uintptr_t i = outIndex; i < byteCount * 8; i++) {
|
|
||||||
out[i >> 3] |= 1 << (i & 7);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!state->error && pointer) {
|
|
||||||
RF_MEMCPY(pointer, out, byteCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RfStructOp(RfState *state, RfItem *item, void *pointer) {
|
|
||||||
RfType *type = item->type;
|
|
||||||
|
|
||||||
if (state->op == RF_OP_SAVE || state->op == RF_OP_LOAD || state->op == RF_OP_FREE) {
|
|
||||||
for (uintptr_t i = 0; i < type->fieldCount && !state->error; i++) {
|
|
||||||
RfField *field = type->fields + i;
|
|
||||||
|
|
||||||
if (state->flags & field->flagsExclude) continue;
|
|
||||||
if ((state->flags & field->flagsInclude) != field->flagsInclude) continue;
|
|
||||||
|
|
||||||
void *fieldPointer = pointer ? ((uint8_t *) pointer + field->offset) : NULL;
|
|
||||||
|
|
||||||
if (state->op == RF_OP_LOAD) {
|
|
||||||
if (state->version < field->firstVersion) {
|
|
||||||
// The field exists, but we're loading from a version where it did not exist.
|
|
||||||
// Ignore it.
|
|
||||||
continue;
|
|
||||||
} else if (field->lastVersion && state->version > field->lastVersion) {
|
|
||||||
// The field no longer exists, and we're from loading a version where it did not exist.
|
|
||||||
// Ignore it.
|
|
||||||
continue;
|
|
||||||
} else if (field->lastVersion) {
|
|
||||||
// The field no longer exists, but we're loading a version where it did.
|
|
||||||
// Skip over it.
|
|
||||||
fieldPointer = NULL;
|
|
||||||
} else {
|
|
||||||
// The field exists, and we're loading from a version where it exists.
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (field->lastVersion) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
field->item.type->op(state, &field->item, fieldPointer);
|
|
||||||
|
|
||||||
if (state->op == RF_OP_FREE) {
|
|
||||||
RF_MEMZERO(fieldPointer, field->item.byteCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (state->op == RF_OP_COUNT) {
|
|
||||||
RfIterator *iterator = (RfIterator *) state;
|
|
||||||
uint32_t count = 0;
|
|
||||||
|
|
||||||
for (uintptr_t i = 0; i < type->fieldCount; i++) {
|
|
||||||
if (!type->fields[i].lastVersion) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator->index = count;
|
|
||||||
} else if (state->op == RF_OP_ITERATE) {
|
|
||||||
RfIterator *iterator = (RfIterator *) state;
|
|
||||||
uint32_t count = 0;
|
|
||||||
|
|
||||||
for (uintptr_t i = 0; i < type->fieldCount; i++) {
|
|
||||||
iterator->isRemoved = type->fields[i].lastVersion;
|
|
||||||
|
|
||||||
if (!iterator->isRemoved || iterator->includeRemovedFields) {
|
|
||||||
if (iterator->index == count) {
|
|
||||||
iterator->pointer = (uint8_t *) pointer + type->fields[i].offset;
|
|
||||||
iterator->item = type->fields[i].item;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
state->error = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RfUnionOp(RfState *state, RfItem *item, void *pointer) {
|
|
||||||
RfType *type = item->type;
|
|
||||||
RfUnionHeader *header = (RfUnionHeader *) pointer;
|
|
||||||
|
|
||||||
if (state->op == RF_OP_SAVE) {
|
|
||||||
state->access(state, &header->tag, sizeof(uint32_t));
|
|
||||||
|
|
||||||
if (header->tag) {
|
|
||||||
RfField *field = type->fields + header->tag - 1;
|
|
||||||
field->item.type->op(state, &field->item, (uint8_t *) pointer + field->offset);
|
|
||||||
}
|
|
||||||
} else if (state->op == RF_OP_LOAD) {
|
|
||||||
uint32_t tag = 0;
|
|
||||||
state->access(state, &tag, sizeof(uint32_t));
|
|
||||||
|
|
||||||
if (tag > type->fieldCount) {
|
|
||||||
tag = 0;
|
|
||||||
state->error = true;
|
|
||||||
} else if (tag) {
|
|
||||||
RfField *field = type->fields + tag - 1;
|
|
||||||
if (field->lastVersion) tag = 0;
|
|
||||||
field->item.type->op(state, &field->item, pointer && !field->lastVersion ? ((uint8_t *) pointer + field->offset) : NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (header) {
|
|
||||||
header->tag = tag;
|
|
||||||
}
|
|
||||||
} else if (state->op == RF_OP_FREE) {
|
|
||||||
if (header->tag) {
|
|
||||||
RfField *field = type->fields + header->tag - 1;
|
|
||||||
field->item.type->op(state, &field->item, (uint8_t *) pointer + field->offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
header->tag = 0;
|
|
||||||
} else if (state->op == RF_OP_COUNT) {
|
|
||||||
RfIterator *iterator = (RfIterator *) state;
|
|
||||||
iterator->index = header->tag ? 1 : 0;
|
|
||||||
} else if (state->op == RF_OP_ITERATE) {
|
|
||||||
RfIterator *iterator = (RfIterator *) state;
|
|
||||||
|
|
||||||
if (!header->tag || iterator->index > 1) {
|
|
||||||
state->error = true;
|
|
||||||
} else {
|
|
||||||
RfField *field = type->fields + header->tag - 1;
|
|
||||||
iterator->pointer = (uint8_t *) pointer + field->offset;
|
|
||||||
iterator->item = field->item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RfUnionSelect(RfState *state, RfItem *item, RfUnionHeader *header, uint32_t tag) {
|
|
||||||
RF_ASSERT(header->tag < item->type->fieldCount && !item->type->fields[header->tag].lastVersion);
|
|
||||||
RF_ASSERT(tag < item->type->fieldCount && !item->type->fields[tag].lastVersion);
|
|
||||||
|
|
||||||
if (header->tag) {
|
|
||||||
RfField *field = item->type->fields + header->tag - 1;
|
|
||||||
field->item.type->op(state, &field->item, (uint8_t *) header + field->offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
header->tag = tag + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RfEnumOp(RfState *state, RfItem *item, void *pointer) {
|
|
||||||
if (state->op == RF_OP_SAVE) {
|
|
||||||
RfIntegerSave(state, pointer, item->byteCount);
|
|
||||||
} else if (state->op == RF_OP_LOAD) {
|
|
||||||
RfIntegerLoad(state, pointer, item->byteCount);
|
|
||||||
|
|
||||||
if (pointer) {
|
|
||||||
uint32_t value = 0;
|
|
||||||
|
|
||||||
if (item->byteCount == 1) {
|
|
||||||
value = *(uint8_t *) pointer;
|
|
||||||
} else if (item->byteCount == 2) {
|
|
||||||
value = *(uint16_t *) pointer;
|
|
||||||
} else if (item->byteCount == 4) {
|
|
||||||
value = *(uint32_t *) pointer;
|
|
||||||
} else {
|
|
||||||
RF_ASSERT(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value >= item->type->fieldCount) {
|
|
||||||
state->error = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RfEndianOp(RfState *state, RfItem *item, void *pointer) {
|
|
||||||
if (state->op == RF_OP_SAVE || state->op == RF_OP_LOAD) {
|
|
||||||
state->access(state, pointer, item->byteCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RfBoolOp(RfState *state, RfItem *item, void *pointer) {
|
|
||||||
RfEndianOp(state, item, pointer);
|
|
||||||
|
|
||||||
if (state->op == RF_OP_LOAD) {
|
|
||||||
if (pointer && *(uint8_t *) pointer > 1) {
|
|
||||||
state->error = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RfIntegerOp(RfState *state, RfItem *item, void *pointer) {
|
|
||||||
if (state->op == RF_OP_SAVE) {
|
|
||||||
RfIntegerSave(state, pointer, item->byteCount);
|
|
||||||
} else if (state->op == RF_OP_LOAD) {
|
|
||||||
RfIntegerLoad(state, pointer, item->byteCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RfDataOp(RfState *state, RfItem *item, void *pointer) {
|
|
||||||
(void) item;
|
|
||||||
RfData *data = (RfData *) pointer;
|
|
||||||
|
|
||||||
if (state->op == RF_OP_SAVE) {
|
|
||||||
uint32_t byteCount = data->byteCount;
|
|
||||||
RfIntegerSave(state, &byteCount, sizeof(uint32_t));
|
|
||||||
state->access(state, data->buffer, data->byteCount);
|
|
||||||
} else if (state->op == RF_OP_LOAD) {
|
|
||||||
uint32_t byteCount = 0;
|
|
||||||
RfIntegerLoad(state, &byteCount, sizeof(uint32_t));
|
|
||||||
|
|
||||||
if (data) {
|
|
||||||
RF_ASSERT(!data->buffer);
|
|
||||||
data->buffer = state->allocate(state, NULL, byteCount);
|
|
||||||
if (!data->buffer) { state->error = true; return; }
|
|
||||||
data->byteCount = byteCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
state->access(state, data ? data->buffer : NULL, data->byteCount);
|
|
||||||
} else if (state->op == RF_OP_FREE) {
|
|
||||||
state->allocate(state, data->buffer, 0);
|
|
||||||
data->buffer = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RfObjectOp(RfState *state, RfItem *item, void *pointer) {
|
|
||||||
RfItem *objectItem = (RfItem *) item->options;
|
|
||||||
void **object = (void **) pointer;
|
|
||||||
|
|
||||||
if (state->op == RF_OP_SAVE) {
|
|
||||||
uint8_t present = *object != NULL;
|
|
||||||
state->access(state, &present, sizeof(uint8_t));
|
|
||||||
if (present) objectItem->type->op(state, objectItem, *object);
|
|
||||||
} else if (state->op == RF_OP_LOAD) {
|
|
||||||
uint8_t present = 0;
|
|
||||||
state->access(state, &present, sizeof(uint8_t));
|
|
||||||
|
|
||||||
if (object) {
|
|
||||||
RF_ASSERT(!(*object));
|
|
||||||
|
|
||||||
if (present) {
|
|
||||||
*object = state->allocate(state, NULL, objectItem->byteCount);
|
|
||||||
if (!(*object)) { state->error = true; return; }
|
|
||||||
RF_MEMZERO(*object, objectItem->byteCount);
|
|
||||||
objectItem->type->op(state, objectItem, *object);
|
|
||||||
}
|
|
||||||
} else if (present) {
|
|
||||||
objectItem->type->op(state, objectItem, NULL);
|
|
||||||
}
|
|
||||||
} else if (state->op == RF_OP_FREE) {
|
|
||||||
if (*object) {
|
|
||||||
objectItem->type->op(state, objectItem, *object);
|
|
||||||
state->allocate(state, *object, 0);
|
|
||||||
*object = NULL;
|
|
||||||
}
|
|
||||||
} else if (state->op == RF_OP_COUNT) {
|
|
||||||
RfIterator *iterator = (RfIterator *) state;
|
|
||||||
iterator->index = *object ? 1 : 0;
|
|
||||||
} else if (state->op == RF_OP_ITERATE) {
|
|
||||||
RfIterator *iterator = (RfIterator *) state;
|
|
||||||
|
|
||||||
if (!(*object) || iterator->index > 1) {
|
|
||||||
state->error = true;
|
|
||||||
} else {
|
|
||||||
iterator->pointer = *object;
|
|
||||||
iterator->item = *objectItem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RfNoneOp(RfState *state, RfItem *item, void *pointer) {
|
|
||||||
(void) state;
|
|
||||||
(void) item;
|
|
||||||
(void) pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RfArrayOp(RfState *state, RfItem *item, void *_pointer) {
|
|
||||||
RfArrayHeader **pointer = (RfArrayHeader **) _pointer;
|
|
||||||
RfItem *objectItem = (RfItem *) item->options;
|
|
||||||
|
|
||||||
if (state->op == RF_OP_SAVE) {
|
|
||||||
uint32_t length = 0;
|
|
||||||
|
|
||||||
if (*pointer) {
|
|
||||||
length = (*pointer)[-1].length;
|
|
||||||
}
|
|
||||||
|
|
||||||
RfIntegerSave(state, &length, sizeof(uint32_t));
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < length; i++) {
|
|
||||||
objectItem->type->op(state, objectItem, (uint8_t *) (*pointer) + i * objectItem->byteCount);
|
|
||||||
}
|
|
||||||
} else if (state->op == RF_OP_LOAD) {
|
|
||||||
RF_ASSERT(!pointer || !(*pointer));
|
|
||||||
|
|
||||||
uint32_t length = 0;
|
|
||||||
RfIntegerLoad(state, &length, sizeof(uint32_t));
|
|
||||||
|
|
||||||
if (length >= 0xFFFFFFFF / objectItem->byteCount) {
|
|
||||||
state->error = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pointer) {
|
|
||||||
void *allocation = state->allocate(state, NULL, length * objectItem->byteCount + sizeof(RfArrayHeader));
|
|
||||||
|
|
||||||
if (!allocation) {
|
|
||||||
state->error = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
*pointer = (RfArrayHeader *) allocation + 1;
|
|
||||||
|
|
||||||
(*pointer)[-1].length = 0;
|
|
||||||
(*pointer)[-1].capacity = length;
|
|
||||||
(*pointer)[-1].hashTable = NULL;
|
|
||||||
(*pointer)[-1].temporary = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < length && !state->error; i++) {
|
|
||||||
if (pointer) {
|
|
||||||
uint32_t index = (*pointer)[-1].length;
|
|
||||||
(*pointer)[-1].length++;
|
|
||||||
uint8_t *p = (uint8_t *) (*pointer) + index * objectItem->byteCount;
|
|
||||||
RF_MEMZERO(p, objectItem->byteCount);
|
|
||||||
objectItem->type->op(state, objectItem, p);
|
|
||||||
} else {
|
|
||||||
objectItem->type->op(state, objectItem, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (state->op == RF_OP_FREE) {
|
|
||||||
if (*pointer) {
|
|
||||||
state->allocate(state, (*pointer) - 1, 0);
|
|
||||||
(*pointer) = NULL;
|
|
||||||
}
|
|
||||||
} else if (state->op == RF_OP_COUNT) {
|
|
||||||
RfIterator *iterator = (RfIterator *) state;
|
|
||||||
iterator->index = *pointer ? (*pointer)[-1].length : 0;
|
|
||||||
} else if (state->op == RF_OP_ITERATE) {
|
|
||||||
RfIterator *iterator = (RfIterator *) state;
|
|
||||||
|
|
||||||
if (!(*pointer) || iterator->index > (*pointer)[-1].length) {
|
|
||||||
state->error = true;
|
|
||||||
} else {
|
|
||||||
iterator->pointer = (uint8_t *) (*pointer) + iterator->index * objectItem->byteCount;
|
|
||||||
iterator->item = *objectItem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RfPathResolve(RfPath *path, RfItem *item, void **pointer) {
|
|
||||||
RfIterator iterator = { 0 };
|
|
||||||
iterator.s.op = RF_OP_ITERATE;
|
|
||||||
iterator.item = *item;
|
|
||||||
iterator.pointer = *pointer;
|
|
||||||
iterator.includeRemovedFields = true;
|
|
||||||
|
|
||||||
for (int i = 0; path->indices[i] != RF_PATH_TERMINATOR && !iterator.s.error; i++) {
|
|
||||||
iterator.index = path->indices[i];
|
|
||||||
RfItem _item = iterator.item;
|
|
||||||
_item.type->op(&iterator.s, &_item, iterator.pointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
*item = iterator.item;
|
|
||||||
*pointer = iterator.pointer;
|
|
||||||
return !iterator.s.error;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RfBroadcast(RfState *state, RfItem *item, void *pointer, bool recurse) {
|
|
||||||
RfIterator iterator = { 0 };
|
|
||||||
iterator.s.op = RF_OP_COUNT;
|
|
||||||
item->type->op(&iterator.s, item, pointer);
|
|
||||||
iterator.s.op = RF_OP_ITERATE;
|
|
||||||
uint32_t count = iterator.index;
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < count; i++) {
|
|
||||||
iterator.index = i;
|
|
||||||
item->type->op(&iterator.s, item, pointer);
|
|
||||||
if (iterator.s.error) return;
|
|
||||||
|
|
||||||
iterator.item.type->op(state, &iterator.item, iterator.pointer);
|
|
||||||
|
|
||||||
if (recurse) {
|
|
||||||
RfBroadcast(state, &iterator.item, iterator.pointer, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RfWriteGrowableBuffer(RfState *state, void *source, size_t byteCount) {
|
|
||||||
if (state->error) return;
|
|
||||||
|
|
||||||
RfGrowableBuffer *destination = (RfGrowableBuffer *) state;
|
|
||||||
|
|
||||||
if (destination->data.byteCount + byteCount > destination->position) {
|
|
||||||
destination->position = destination->position * 2;
|
|
||||||
|
|
||||||
if (destination->data.byteCount + byteCount > destination->position) {
|
|
||||||
destination->position = destination->data.byteCount + byteCount + 64;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *old = destination->data.buffer;
|
|
||||||
destination->data.buffer = state->allocate(state, destination->data.buffer, destination->position);
|
|
||||||
|
|
||||||
if (!destination->data.buffer) {
|
|
||||||
state->allocate(state, old, 0);
|
|
||||||
state->error = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RF_MEMCPY((uint8_t *) destination->data.buffer + destination->data.byteCount, source, byteCount);
|
|
||||||
destination->data.byteCount += byteCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RfReadGrowableBuffer(RfState *state, void *destination, size_t byteCount) {
|
|
||||||
if (state->error) return;
|
|
||||||
|
|
||||||
RfGrowableBuffer *source = (RfGrowableBuffer *) state;
|
|
||||||
|
|
||||||
if (source->position + byteCount > source->data.byteCount) {
|
|
||||||
state->error = true;
|
|
||||||
} else {
|
|
||||||
if (destination) {
|
|
||||||
RF_MEMCPY(destination, (uint8_t *) source->data.buffer + source->position, byteCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
source->position += byteCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void *RfRealloc(RfState *state, void *previous, size_t byteCount) {
|
|
||||||
(void) state;
|
|
||||||
return RF_REALLOC(previous, byteCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
RfType rfI8 = { .op = RfEndianOp, .cName = "I8" };
|
|
||||||
RfType rfI16 = { .op = RfIntegerOp, .cName = "I16" };
|
|
||||||
RfType rfI32 = { .op = RfIntegerOp, .cName = "I32" };
|
|
||||||
RfType rfI64 = { .op = RfIntegerOp, .cName = "I64" };
|
|
||||||
RfType rfU8 = { .op = RfEndianOp, .cName = "U8" };
|
|
||||||
RfType rfU16 = { .op = RfIntegerOp, .cName = "U16" };
|
|
||||||
RfType rfU32 = { .op = RfIntegerOp, .cName = "U32" };
|
|
||||||
RfType rfU64 = { .op = RfIntegerOp, .cName = "U64" };
|
|
||||||
RfType rfChar = { .op = RfEndianOp, .cName = "Char" };
|
|
||||||
RfType rfBool = { .op = RfBoolOp, .cName = "Bool" };
|
|
||||||
RfType rfF32 = { .op = RfEndianOp, .cName = "F32" };
|
|
||||||
RfType rfF64 = { .op = RfEndianOp, .cName = "F64" };
|
|
||||||
RfType rfData = { .op = RfDataOp, .cName = "Data" };
|
|
||||||
RfType rfObject = { .op = RfObjectOp, .cName = "Object" };
|
|
||||||
RfType rfArray = { .op = RfArrayOp, .cName = "Array" };
|
|
||||||
RfType rfNone = { .op = RfNoneOp, .cName = "None" };
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,531 +0,0 @@
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#define STB_DS_IMPLEMENTATION
|
|
||||||
#include "../stb_ds.h"
|
|
||||||
|
|
||||||
#define TOKEN_BLOCK (0)
|
|
||||||
#define TOKEN_LEFT_BRACE (1)
|
|
||||||
#define TOKEN_RIGHT_BRACE (2)
|
|
||||||
#define TOKEN_LEFT_PAREN (3)
|
|
||||||
#define TOKEN_RIGHT_PAREN (4)
|
|
||||||
#define TOKEN_SEMICOLON (5)
|
|
||||||
#define TOKEN_IDENTIFIER (6)
|
|
||||||
#define TOKEN_STRING (7)
|
|
||||||
#define TOKEN_EOF (8)
|
|
||||||
#define TOKEN_COMMA (9)
|
|
||||||
#define TOKEN_NUMBER (10)
|
|
||||||
#define TOKEN_HASH (11)
|
|
||||||
#define TOKEN_QUESTION (12)
|
|
||||||
#define TOKEN_EQUALS (13)
|
|
||||||
#define TOKEN_LEFT_BRACKET (14)
|
|
||||||
#define TOKEN_RIGHT_BRACKET (15)
|
|
||||||
#define TOKEN_COLON (16)
|
|
||||||
#define TOKEN_EXCLAMATION (17)
|
|
||||||
|
|
||||||
typedef struct Parse {
|
|
||||||
const char *position;
|
|
||||||
int line;
|
|
||||||
bool success;
|
|
||||||
} Parse;
|
|
||||||
|
|
||||||
typedef struct Token {
|
|
||||||
int type;
|
|
||||||
double number;
|
|
||||||
char *string;
|
|
||||||
} Token;
|
|
||||||
|
|
||||||
typedef struct ParsedField {
|
|
||||||
char *rfType, *cTypeBefore, *fieldName, *cTypeAfter;
|
|
||||||
int firstVersion, lastVersion;
|
|
||||||
char **flagsInclude, **flagsExclude;
|
|
||||||
char *optionsType, *optionsBlock;
|
|
||||||
} ParsedField;
|
|
||||||
|
|
||||||
typedef struct ParsedType {
|
|
||||||
bool isStruct, isUnion, isCustom, isEnum;
|
|
||||||
char *cName, *rfName, *opFunction;
|
|
||||||
ParsedField *fields;
|
|
||||||
} ParsedType;
|
|
||||||
|
|
||||||
ParsedType *parsedTypes;
|
|
||||||
|
|
||||||
bool IsDigit(char c) { return (c >= '0' && c <= '9'); }
|
|
||||||
bool IsAlpha(char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
|
|
||||||
bool IsAlnum(char c) { return (IsDigit(c) || IsAlpha(c)); }
|
|
||||||
|
|
||||||
bool _NextToken(Parse *parse, Token *token) {
|
|
||||||
if (!parse->success) return false;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
char c = *parse->position;
|
|
||||||
parse->position++;
|
|
||||||
|
|
||||||
if (c == ' ' || c == '\t' || c == '\r') {
|
|
||||||
continue;
|
|
||||||
} else if (c == '\n') {
|
|
||||||
parse->line++;
|
|
||||||
continue;
|
|
||||||
} else if (c == '/' && *parse->position == '/') {
|
|
||||||
while (*parse->position != '\n') parse->position++;
|
|
||||||
continue;
|
|
||||||
} else if (c == '/' && *parse->position == '*') {
|
|
||||||
while (parse->position[0] != '*' || parse->position[1] != '/') parse->position++;
|
|
||||||
parse->position += 2;
|
|
||||||
continue;
|
|
||||||
#define PARSE_CHARACTER(a, b) \
|
|
||||||
} else if (c == a) { \
|
|
||||||
Token t = {}; \
|
|
||||||
t.type = b; \
|
|
||||||
*token = t; \
|
|
||||||
return true
|
|
||||||
PARSE_CHARACTER('{', TOKEN_LEFT_BRACE );
|
|
||||||
PARSE_CHARACTER('}', TOKEN_RIGHT_BRACE );
|
|
||||||
PARSE_CHARACTER('(', TOKEN_LEFT_PAREN );
|
|
||||||
PARSE_CHARACTER(')', TOKEN_RIGHT_PAREN );
|
|
||||||
PARSE_CHARACTER('[', TOKEN_LEFT_BRACKET );
|
|
||||||
PARSE_CHARACTER(']', TOKEN_RIGHT_BRACKET );
|
|
||||||
PARSE_CHARACTER(';', TOKEN_SEMICOLON );
|
|
||||||
PARSE_CHARACTER(':', TOKEN_COLON );
|
|
||||||
PARSE_CHARACTER(',', TOKEN_COMMA );
|
|
||||||
PARSE_CHARACTER('#', TOKEN_HASH );
|
|
||||||
PARSE_CHARACTER('?', TOKEN_QUESTION );
|
|
||||||
PARSE_CHARACTER('=', TOKEN_EQUALS );
|
|
||||||
PARSE_CHARACTER('!', TOKEN_EXCLAMATION );
|
|
||||||
} else if (IsAlpha(c) || c == '_') {
|
|
||||||
const char *start = parse->position - 1;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
char c2 = *parse->position;
|
|
||||||
if (c2 == 0) break;
|
|
||||||
if (!IsAlnum(c2) && c2 != '_') break;
|
|
||||||
parse->position++;
|
|
||||||
}
|
|
||||||
|
|
||||||
Token _token = { 0 };
|
|
||||||
_token.type = TOKEN_IDENTIFIER;
|
|
||||||
_token.string = malloc(parse->position - start + 1);
|
|
||||||
if (!_token.string) { parse->success = false; return false; }
|
|
||||||
memcpy(_token.string, start, parse->position - start);
|
|
||||||
_token.string[parse->position - start] = 0;
|
|
||||||
*token = _token;
|
|
||||||
return true;
|
|
||||||
} else if (IsDigit(c) || c == '-') {
|
|
||||||
const char *start = parse->position - 1;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
char c2 = *parse->position;
|
|
||||||
if (c2 == 0) break;
|
|
||||||
if (!IsAlnum(c2) && c2 != '.') break;
|
|
||||||
parse->position++;
|
|
||||||
}
|
|
||||||
|
|
||||||
Token _token = { 0 };
|
|
||||||
_token.type = TOKEN_NUMBER;
|
|
||||||
_token.string = malloc(parse->position - start + 1);
|
|
||||||
if (!_token.string) { parse->success = false; return false; }
|
|
||||||
memcpy(_token.string, start, parse->position - start);
|
|
||||||
_token.string[parse->position - start] = 0;
|
|
||||||
|
|
||||||
bool negate = _token.string[0] == '-';
|
|
||||||
bool afterDot = false;
|
|
||||||
bool hexadecimal = false;
|
|
||||||
double fraction = 0.1;
|
|
||||||
|
|
||||||
for (uintptr_t i = negate ? 1 : 0; _token.string[i]; i++) {
|
|
||||||
char c = _token.string[i];
|
|
||||||
|
|
||||||
if (c == '.') {
|
|
||||||
if (hexadecimal) {
|
|
||||||
parse->success = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
afterDot = true;
|
|
||||||
} else if (c == 'x') {
|
|
||||||
if (i != 1 || _token.string[0] != '0' || afterDot) {
|
|
||||||
parse->success = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
hexadecimal = true;
|
|
||||||
} else if (afterDot) {
|
|
||||||
if (!IsDigit(c)) {
|
|
||||||
parse->success = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_token.number += (c - '0') * fraction;
|
|
||||||
fraction *= 0.1;
|
|
||||||
} else {
|
|
||||||
if (hexadecimal) {
|
|
||||||
_token.number *= 16;
|
|
||||||
|
|
||||||
if (c >= '0' && c <= '9') {
|
|
||||||
_token.number += c - '0';
|
|
||||||
} else if (c >= 'a' && c <= 'f') {
|
|
||||||
_token.number += c - 'a' + 10;
|
|
||||||
} else if (c >= 'A' && c <= 'F') {
|
|
||||||
_token.number += c - 'A' + 10;
|
|
||||||
} else {
|
|
||||||
parse->success = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!IsDigit(c)) {
|
|
||||||
parse->success = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_token.number *= 10;
|
|
||||||
_token.number += c - '0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (negate) _token.number = -_token.number;
|
|
||||||
*token = _token;
|
|
||||||
return true;
|
|
||||||
} else if (c == '"') {
|
|
||||||
const char *start = parse->position;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
char c2 = *parse->position;
|
|
||||||
if (c2 == 0) break;
|
|
||||||
parse->position++;
|
|
||||||
if (c2 == '"') break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Token _token = { 0 };
|
|
||||||
_token.type = TOKEN_STRING;
|
|
||||||
_token.string = (char *) malloc(parse->position - start);
|
|
||||||
if (!_token.string) { parse->success = false; return false; }
|
|
||||||
memcpy(_token.string, start, parse->position - start - 1);
|
|
||||||
_token.string[parse->position - start - 1] = 0;
|
|
||||||
*token = _token;
|
|
||||||
return true;
|
|
||||||
} else if (c == 0) {
|
|
||||||
Token t = {};
|
|
||||||
t.type = TOKEN_EOF;
|
|
||||||
*token = t;
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
parse->success = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Token NextToken(Parse *parse) {
|
|
||||||
Token token = { 0 };
|
|
||||||
bool success = _NextToken(parse, &token);
|
|
||||||
|
|
||||||
if (!success) {
|
|
||||||
fprintf(stderr, "error: invalid token on line %d\n", parse->line);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *NextString(Parse *parse) {
|
|
||||||
Token token = NextToken(parse);
|
|
||||||
|
|
||||||
if (token.type == TOKEN_IDENTIFIER || token.type == TOKEN_STRING) {
|
|
||||||
return token.string;
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "error: expected string or identifier on line %d\n", parse->line);
|
|
||||||
exit(1);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Token ExpectToken(Parse *parse, int type) {
|
|
||||||
Token token = NextToken(parse);
|
|
||||||
|
|
||||||
if (token.type == type) {
|
|
||||||
return token;
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "error: expected token of type %d of line %d\n", type, parse->line);
|
|
||||||
exit(1);
|
|
||||||
return (Token) { 0 };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char *NextBlock(Parse *parse) {
|
|
||||||
ExpectToken(parse, TOKEN_LEFT_BRACE);
|
|
||||||
|
|
||||||
int depth = 1;
|
|
||||||
const char *start = parse->position;
|
|
||||||
|
|
||||||
while (depth) {
|
|
||||||
if (*parse->position == '{') {
|
|
||||||
depth++;
|
|
||||||
parse->position++;
|
|
||||||
} else if (*parse->position == '}') {
|
|
||||||
depth--;
|
|
||||||
parse->position++;
|
|
||||||
} else if (*parse->position == '"') {
|
|
||||||
ExpectToken(parse, TOKEN_STRING);
|
|
||||||
} else if (*parse->position == 0) {
|
|
||||||
fprintf(stderr, "error: unexpected end of file during block\n");
|
|
||||||
exit(1);
|
|
||||||
} else {
|
|
||||||
parse->position++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char *result = malloc(parse->position - start);
|
|
||||||
memcpy(result, start, parse->position - start - 1);
|
|
||||||
result[parse->position - start - 1] = 0;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Token PeekToken(Parse *parse) {
|
|
||||||
Parse old = *parse;
|
|
||||||
Token token = NextToken(parse);
|
|
||||||
*parse = old;
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *LoadFile(const char *inputFileName, size_t *byteCount) {
|
|
||||||
FILE *inputFile = fopen(inputFileName, "rb");
|
|
||||||
|
|
||||||
if (!inputFile) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
fseek(inputFile, 0, SEEK_END);
|
|
||||||
size_t inputFileBytes = ftell(inputFile);
|
|
||||||
fseek(inputFile, 0, SEEK_SET);
|
|
||||||
|
|
||||||
char *inputBuffer = (char *) malloc(inputFileBytes + 1);
|
|
||||||
size_t inputBytesRead = fread(inputBuffer, 1, inputFileBytes, inputFile);
|
|
||||||
inputBuffer[inputBytesRead] = 0;
|
|
||||||
fclose(inputFile);
|
|
||||||
|
|
||||||
if (byteCount) *byteCount = inputBytesRead;
|
|
||||||
return inputBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ParseAdditionalFieldInformation(Parse *parse, ParsedField *field) {
|
|
||||||
while (PeekToken(parse).type != TOKEN_SEMICOLON) {
|
|
||||||
Token token = NextToken(parse);
|
|
||||||
|
|
||||||
if (token.type == TOKEN_IDENTIFIER && 0 == strcmp(token.string, "from") && !field->firstVersion) {
|
|
||||||
field->firstVersion = ExpectToken(parse, TOKEN_NUMBER).number;
|
|
||||||
} else if (token.type == TOKEN_IDENTIFIER && 0 == strcmp(token.string, "to") && !field->lastVersion) {
|
|
||||||
field->lastVersion = ExpectToken(parse, TOKEN_NUMBER).number;
|
|
||||||
} else if (token.type == TOKEN_IDENTIFIER && 0 == strcmp(token.string, "if") && !field->flagsInclude && !field->flagsExclude) {
|
|
||||||
ExpectToken(parse, TOKEN_LEFT_PAREN);
|
|
||||||
|
|
||||||
while (PeekToken(parse).type != TOKEN_RIGHT_PAREN) {
|
|
||||||
if (PeekToken(parse).type == TOKEN_EXCLAMATION) {
|
|
||||||
ExpectToken(parse, TOKEN_EXCLAMATION);
|
|
||||||
arrput(field->flagsExclude, NextString(parse));
|
|
||||||
} else {
|
|
||||||
arrput(field->flagsInclude, NextString(parse));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ExpectToken(parse, TOKEN_RIGHT_PAREN);
|
|
||||||
} else if (token.type == TOKEN_HASH) {
|
|
||||||
field->optionsType = NextString(parse);
|
|
||||||
field->optionsBlock = NextBlock(parse);
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "error: unexpected token in field on line %d\n", parse->line);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
|
||||||
if (argc != 2) {
|
|
||||||
fprintf(stderr, "usage: reflect_gen <input file>\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *input = LoadFile(argv[1], NULL);
|
|
||||||
|
|
||||||
if (!input) {
|
|
||||||
fprintf(stderr, "error: could not open input file '%s'\n", argv[1]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Parse parse = { 0 };
|
|
||||||
parse.position = input;
|
|
||||||
parse.line = 1;
|
|
||||||
parse.success = true;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
Token token = NextToken(&parse);
|
|
||||||
|
|
||||||
if (token.type == TOKEN_EOF) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (token.type == TOKEN_IDENTIFIER && (0 == strcmp(token.string, "struct") || 0 == strcmp(token.string, "union"))) {
|
|
||||||
ParsedType type = { 0 };
|
|
||||||
type.isStruct = 0 == strcmp(token.string, "struct");
|
|
||||||
type.isUnion = 0 == strcmp(token.string, "union");
|
|
||||||
type.cName = NextString(&parse);
|
|
||||||
type.rfName = NextString(&parse);
|
|
||||||
type.opFunction = NextString(&parse);
|
|
||||||
ExpectToken(&parse, TOKEN_LEFT_BRACE);
|
|
||||||
|
|
||||||
while (PeekToken(&parse).type != TOKEN_RIGHT_BRACE) {
|
|
||||||
ParsedField field = { 0 };
|
|
||||||
field.rfType = NextString(&parse);
|
|
||||||
field.cTypeBefore = NextString(&parse);
|
|
||||||
field.fieldName = NextString(&parse);
|
|
||||||
|
|
||||||
if (PeekToken(&parse).type == TOKEN_STRING) {
|
|
||||||
field.cTypeAfter = NextString(&parse);
|
|
||||||
}
|
|
||||||
|
|
||||||
ParseAdditionalFieldInformation(&parse, &field);
|
|
||||||
ExpectToken(&parse, TOKEN_SEMICOLON);
|
|
||||||
arrput(type.fields, field);
|
|
||||||
}
|
|
||||||
|
|
||||||
ExpectToken(&parse, TOKEN_RIGHT_BRACE);
|
|
||||||
ExpectToken(&parse, TOKEN_SEMICOLON);
|
|
||||||
arrput(parsedTypes, type);
|
|
||||||
} else if (token.type == TOKEN_IDENTIFIER && 0 == strcmp(token.string, "type")) {
|
|
||||||
ParsedType type = { 0 };
|
|
||||||
type.isCustom = true;
|
|
||||||
type.rfName = NextString(&parse);
|
|
||||||
type.opFunction = NextString(&parse);
|
|
||||||
ExpectToken(&parse, TOKEN_SEMICOLON);
|
|
||||||
arrput(parsedTypes, type);
|
|
||||||
} else if (token.type == TOKEN_IDENTIFIER && 0 == strcmp(token.string, "enum")) {
|
|
||||||
ParsedType type = { 0 };
|
|
||||||
type.isEnum = true;
|
|
||||||
type.rfName = NextString(&parse);
|
|
||||||
type.opFunction = NextString(&parse);
|
|
||||||
ExpectToken(&parse, TOKEN_LEFT_BRACE);
|
|
||||||
|
|
||||||
while (PeekToken(&parse).type != TOKEN_RIGHT_BRACE) {
|
|
||||||
ParsedField field = { 0 };
|
|
||||||
field.fieldName = NextString(&parse);
|
|
||||||
ParseAdditionalFieldInformation(&parse, &field);
|
|
||||||
ExpectToken(&parse, TOKEN_SEMICOLON);
|
|
||||||
arrput(type.fields, field);
|
|
||||||
}
|
|
||||||
|
|
||||||
ExpectToken(&parse, TOKEN_RIGHT_BRACE);
|
|
||||||
ExpectToken(&parse, TOKEN_SEMICOLON);
|
|
||||||
arrput(parsedTypes, type);
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "error: unexpected token at root on line %d\n", parse.line);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Output C type declarations.
|
|
||||||
|
|
||||||
for (uintptr_t i = 0; i < arrlenu(parsedTypes); i++) {
|
|
||||||
ParsedType *type = parsedTypes + i;
|
|
||||||
|
|
||||||
if (type->isCustom) {
|
|
||||||
continue;
|
|
||||||
} else if (type->isEnum) {
|
|
||||||
for (uintptr_t j = 0; j < arrlenu(type->fields); j++) {
|
|
||||||
ParsedField *field = type->fields + j;
|
|
||||||
printf("#define %s (%d)\n", field->fieldName, (int) j);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("typedef struct %s {\n", type->cName);
|
|
||||||
const char *indent = "\t";
|
|
||||||
|
|
||||||
if (type->isUnion) {
|
|
||||||
printf("\tuint32_t tag;\n\n\tunion {\n");
|
|
||||||
indent = "\t\t";
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uintptr_t j = 0; j < arrlenu(type->fields); j++) {
|
|
||||||
ParsedField *field = type->fields + j;
|
|
||||||
printf("%s%s %s %s;\n", indent, field->cTypeBefore, field->fieldName, field->cTypeAfter ? field->cTypeAfter : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type->isUnion) {
|
|
||||||
printf("\t};\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("} %s;\n\n", type->cName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Forward-declare op functions.
|
|
||||||
|
|
||||||
for (uintptr_t i = 0; i < arrlenu(parsedTypes); i++) {
|
|
||||||
ParsedType *type = parsedTypes + i;
|
|
||||||
printf("void %s(RfState *state, RfItem *item, void *pointer);\n", type->opFunction);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Output reflect type information.
|
|
||||||
|
|
||||||
for (uintptr_t i = 0; i < arrlenu(parsedTypes); i++) {
|
|
||||||
ParsedType *type = parsedTypes + i;
|
|
||||||
|
|
||||||
printf("#ifdef REFLECT_IMPLEMENTATION\n");
|
|
||||||
printf("RfType %s = {\n", type->rfName);
|
|
||||||
printf("\t.op = %s,\n\t.cName = \"%s\",\n\t.fieldCount = %d,\n", type->opFunction, type->cName, (int) arrlen(type->fields));
|
|
||||||
|
|
||||||
if (arrlenu(type->fields)) {
|
|
||||||
printf("\n\t.fields = (RfField []) {\n");
|
|
||||||
|
|
||||||
for (uintptr_t j = 0; j < arrlenu(type->fields); j++) {
|
|
||||||
ParsedField *field = type->fields + j;
|
|
||||||
|
|
||||||
if (type->isEnum) {
|
|
||||||
printf("\t\t{ .cName = \"%s\", ", field->fieldName);
|
|
||||||
} else {
|
|
||||||
printf("\t\t{ .item.type = &%s, .item.byteCount = RF_SIZE_OF(%s, %s), .cName = \"%s\", .offset = offsetof(%s, %s), ",
|
|
||||||
field->rfType, type->cName, field->fieldName, field->fieldName, type->cName, field->fieldName);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf(".firstVersion = %d, .lastVersion = %d, .flagsInclude = 0", field->firstVersion, field->lastVersion);
|
|
||||||
|
|
||||||
for (uintptr_t k = 0; k < arrlenu(field->flagsInclude); k++) {
|
|
||||||
printf(" | %s", field->flagsInclude[k]);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf(", .flagsExclude = 0");
|
|
||||||
|
|
||||||
for (uintptr_t k = 0; k < arrlenu(field->flagsExclude); k++) {
|
|
||||||
printf(" | %s", field->flagsExclude[k]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (field->optionsType) {
|
|
||||||
printf(", .item.options = &(%s) { %s }", field->optionsType, field->optionsBlock);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf(" },\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\t},\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("};\n\n");
|
|
||||||
printf("#else\nextern RfType %s;\n#endif\n", type->rfName);
|
|
||||||
|
|
||||||
if (!type->isEnum) {
|
|
||||||
for (uintptr_t j = 0; j < arrlenu(type->fields); j++) {
|
|
||||||
ParsedField *field = type->fields + j;
|
|
||||||
|
|
||||||
printf("#define %s_%s (%d)\n", type->cName, field->fieldName, (int) j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
Loading…
Reference in New Issue