From 957767d865c63ac87ce2ebfb2d38e8b3e075aec8 Mon Sep 17 00:00:00 2001 From: reugenio Date: Thu, 18 Dec 2025 17:35:25 +0100 Subject: [PATCH] fix: validateIntRange/FloatRange soportan rangos negativos MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: "-100-100" se parseaba como ["", "100", "100"] con splitScalar Fix: Buscar el separador '-' que NO está al inicio del string Ejemplos que ahora funcionan: - "-100-100" → min=-100, max=100 - "-50-50" → min=-50, max=50 - "0-100" → min=0, max=100 (sin cambio) Test añadido para rangos negativos. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- src/zcatconfig.zig | 51 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/src/zcatconfig.zig b/src/zcatconfig.zig index 2d25821..a87f7b4 100644 --- a/src/zcatconfig.zig +++ b/src/zcatconfig.zig @@ -119,10 +119,18 @@ pub const ConfigVariable = struct { _ = self; const parsed = std.fmt.parseInt(i32, value, 10) catch return false; - // Parse "min-max" - var it = std.mem.splitScalar(u8, range, '-'); - const min_str = it.next() orelse return false; - const max_str = it.next() orelse return false; + // Parse "min-max" (soporta negativos, ej: "-100-100", "-50-50", "0-100") + // Buscar el '-' separador: es el primero que NO está al inicio + const separator_pos = blk: { + const start: usize = if (range.len > 0 and range[0] == '-') 1 else 0; + for (range[start..], start..) |c, i| { + if (c == '-') break :blk i; + } + return false; // No encontró separador + }; + + const min_str = range[0..separator_pos]; + const max_str = range[separator_pos + 1 ..]; const min = std.fmt.parseInt(i32, min_str, 10) catch return false; const max = std.fmt.parseInt(i32, max_str, 10) catch return false; @@ -134,10 +142,17 @@ pub const ConfigVariable = struct { _ = self; const parsed = std.fmt.parseFloat(f32, value) catch return false; - // Parse "min-max" - var it = std.mem.splitScalar(u8, range, '-'); - const min_str = it.next() orelse return false; - const max_str = it.next() orelse return false; + // Parse "min-max" (soporta negativos) + const separator_pos = blk: { + const start: usize = if (range.len > 0 and range[0] == '-') 1 else 0; + for (range[start..], start..) |c, i| { + if (c == '-') break :blk i; + } + return false; + }; + + const min_str = range[0..separator_pos]; + const max_str = range[separator_pos + 1 ..]; const min = std.fmt.parseFloat(f32, min_str) catch return false; const max = std.fmt.parseFloat(f32, max_str) catch return false; @@ -979,6 +994,26 @@ test "ConfigVariable validation - integer range" { try std.testing.expect(!int_var.validate("abc")); } +test "ConfigVariable validation - negative integer range" { + // Rango con mínimo negativo: "-100-100" + const neg_var = ConfigVariable{ + .name = "test_neg", + .config_key = "@test_neg", + .var_type = .integer, + .default = "0", + .auto_validate = "-100-100", + .description = "Test negative range", + }; + + try std.testing.expect(neg_var.validate("0")); + try std.testing.expect(neg_var.validate("-100")); + try std.testing.expect(neg_var.validate("100")); + try std.testing.expect(neg_var.validate("-50")); + try std.testing.expect(neg_var.validate("50")); + try std.testing.expect(!neg_var.validate("-101")); + try std.testing.expect(!neg_var.validate("101")); +} + test "ConfigVariable validation - enum" { const enum_var = ConfigVariable{ .name = "test_enum",