diff options
Diffstat (limited to 'tools/odinfmt/flag/flag.odin')
| -rw-r--r-- | tools/odinfmt/flag/flag.odin | 216 |
1 files changed, 0 insertions, 216 deletions
diff --git a/tools/odinfmt/flag/flag.odin b/tools/odinfmt/flag/flag.odin deleted file mode 100644 index b52e359..0000000 --- a/tools/odinfmt/flag/flag.odin +++ /dev/null @@ -1,216 +0,0 @@ -package flag - -import "base:runtime" - -import "core:strings" -import "core:reflect" -import "core:fmt" -import "core:mem" -import "core:strconv" - -Flag_Error :: enum { - None, - No_Base_Struct, - Arg_Error, - Arg_Unsupported_Field_Type, - Arg_Not_Defined, - Arg_Non_Optional, - Value_Parse_Error, - Tag_Error, -} - -Flag :: struct { - optional: bool, - type: ^runtime.Type_Info, - data: rawptr, - tag_ptr: rawptr, - parsed: bool, - offset: uintptr, -} - -Flag_Context :: struct { - seen_flags: map[string]Flag, -} - -parse_args :: proc(ctx: ^Flag_Context, args: []string) -> Flag_Error { - - using runtime; - - args := args; - - for { - if len(args) == 0 { - return .None; - } - - arg := args[0]; - - if len(arg) < 2 || arg[0] != '-' { - return .Arg_Error; - } - - minus_count := 1; - - if arg[1] == '-' { - minus_count += 1; - - if len(arg) == 2 { - return .Arg_Error; - } - } - - name := arg[minus_count:]; - - if len(name) == 0 { - return .Arg_Error; - } - - args = args[1:]; - - assign_index := strings.index(name, "="); - - value := ""; - - if assign_index > 0 { - value = name[assign_index + 1:]; - name = name[0:assign_index]; - } - - flag := &ctx.seen_flags[name]; - - if flag == nil { - return .Arg_Not_Defined; - } - - if reflect.is_boolean(flag.type) { - tmp: b64 = true; - mem.copy(flag.data, &tmp, flag.type.size); - flag.parsed = true; - continue; - } else if value == "" { // must be in the next argument - if len(args) == 0 { - return .Arg_Error; - } - - value = args[0]; - args = args[1:]; - } - - #partial switch _ in flag.type.variant { - case Type_Info_Integer: - if v, ok := strconv.parse_int(value); ok { - mem.copy(flag.data, &v, flag.type.size); - } else { - return .Value_Parse_Error; - } - case Type_Info_String: - raw_string := cast(^mem.Raw_String)flag.data; - raw_string.data = raw_data(value); - raw_string.len = len(value); - case Type_Info_Float: - switch flag.type.size { - case 32: - if v, ok := strconv.parse_f32(value); ok { - mem.copy(flag.data, &v, flag.type.size); - } else { - return .Value_Parse_Error; - } - case 64: - if v, ok := strconv.parse_f64(value); ok { - mem.copy(flag.data, &v, flag.type.size); - } else { - return .Value_Parse_Error; - } - } - } - - flag.parsed = true; - } - - return .None; -} - -reflect_args_structure :: proc(ctx: ^Flag_Context, v: any) -> Flag_Error { - using runtime; - - if !reflect.is_struct(type_info_of(v.id)) { - return .No_Base_Struct; - } - - names := reflect.struct_field_names(v.id); - types := reflect.struct_field_types(v.id); - offsets := reflect.struct_field_offsets(v.id); - tags := reflect.struct_field_tags(v.id); - - for name, i in names { - flag: Flag; - - type := types[i]; - - if named_type, ok := type.variant.(Type_Info_Named); ok { - if union_type, ok := named_type.base.variant.(Type_Info_Union); ok && len(union_type.variants) == 1 { - flag.optional = true; - flag.offset = union_type.tag_offset + offsets[i]; - flag.tag_ptr = rawptr(flag.offset + uintptr(v.data)); - type = union_type.variants[0]; - } else { - return .Arg_Unsupported_Field_Type; - } - } - - #partial switch _ in type.variant { - case Type_Info_Integer, Type_Info_String, Type_Info_Boolean, Type_Info_Float: - flag.type = type; - flag.data = rawptr(uintptr(v.data) + uintptr(offsets[i])); - case: - return .Arg_Unsupported_Field_Type; - } - - flag_name: string; - - if value, ok := reflect.struct_tag_lookup(tags[i], "flag"); ok { - flag_name = cast(string)value; - } else { - return .Tag_Error; - } - - ctx.seen_flags[flag_name] = flag; - } - - return .None; -} - -parse :: proc(v: any, args: []string) -> Flag_Error { - - if v == nil { - return .None; - } - - ctx: Flag_Context; - - size := type_info_of(v.id).size; - - if res := reflect_args_structure(&ctx, v); res != .None { - return res; - } - - if res := parse_args(&ctx, args); res != .None { - return res; - } - - //validate that the required flags were actually set - for k, v in ctx.seen_flags { - if v.optional && v.parsed { - tag_value: i32 = 1; - mem.copy(v.tag_ptr, &tag_value, size - int(v.offset)); - } else if !v.parsed && !v.optional { - return .Arg_Non_Optional; - } - } - - return .None; -} - -usage :: proc(v: any) -> string { - return "failed"; -} |