| ... | @@ -196,7 +196,12 @@ pub const Diagnostics = struct { | ... | @@ -196,7 +196,12 @@ pub const Diagnostics = struct { |
| 196 | line_number: u64 = 1, | 196 | line_number: u64 = 1, |
| 197 | line_start_cursor: usize = @as(usize, @bitCast(@as(isize, -1))), // Start just "before" the input buffer to get a 1-based column for line 1. | 197 | line_start_cursor: usize = @as(usize, @bitCast(@as(isize, -1))), // Start just "before" the input buffer to get a 1-based column for line 1. |
| 198 | total_bytes_before_current_input: u64 = 0, | 198 | total_bytes_before_current_input: u64 = 0, |
| 199 | cursor_pointer: *const usize = undefined, | 199 | /// While the source is operational, this is a pointer into it. |
| | 200 | /// If the source is destroyed, this becomes a literal value. |
| | 201 | cursor: union(enum) { |
| | 202 | pointer: *const usize, |
| | 203 | value: usize, |
| | 204 | } = undefined, |
| 200 | | 205 | |
| 201 | /// Starts at 1. | 206 | /// Starts at 1. |
| 202 | pub fn getLine(self: *const @This()) u64 { | 207 | pub fn getLine(self: *const @This()) u64 { |
| ... | @@ -204,11 +209,22 @@ pub const Diagnostics = struct { | ... | @@ -204,11 +209,22 @@ pub const Diagnostics = struct { |
| 204 | } | 209 | } |
| 205 | /// Starts at 1. | 210 | /// Starts at 1. |
| 206 | pub fn getColumn(self: *const @This()) u64 { | 211 | pub fn getColumn(self: *const @This()) u64 { |
| 207 | return self.cursor_pointer.* -% self.line_start_cursor; | 212 | return self.getCursor() -% self.line_start_cursor; |
| 208 | } | 213 | } |
| 209 | /// Starts at 0. Measures the byte offset since the start of the input. | 214 | /// Starts at 0. Measures the byte offset since the start of the input. |
| 210 | pub fn getByteOffset(self: *const @This()) u64 { | 215 | pub fn getByteOffset(self: *const @This()) u64 { |
| 211 | return self.total_bytes_before_current_input + self.cursor_pointer.*; | 216 | return self.total_bytes_before_current_input + self.getCursor(); |
| | 217 | } |
| | 218 | |
| | 219 | fn getCursor(self: *const @This()) usize { |
| | 220 | return switch (self.cursor) { |
| | 221 | .pointer => |p| p.*, |
| | 222 | .value => |v| v, |
| | 223 | }; |
| | 224 | } |
| | 225 | fn saveCursor(self: *@This()) void { |
| | 226 | const value = self.getCursor(); |
| | 227 | self.cursor = .{ .value = value }; |
| 212 | } | 228 | } |
| 213 | }; | 229 | }; |
| 214 | | 230 | |
| ... | @@ -244,6 +260,10 @@ pub fn Reader(comptime buffer_size: usize, comptime ReaderType: type) type { | ... | @@ -244,6 +260,10 @@ pub fn Reader(comptime buffer_size: usize, comptime ReaderType: type) type { |
| 244 | pub fn enableDiagnostics(self: *@This(), diagnostics: *Diagnostics) void { | 260 | pub fn enableDiagnostics(self: *@This(), diagnostics: *Diagnostics) void { |
| 245 | self.scanner.enableDiagnostics(diagnostics); | 261 | self.scanner.enableDiagnostics(diagnostics); |
| 246 | } | 262 | } |
| | 263 | /// Calls `std.json.Scanner.saveDiagnostics`. |
| | 264 | pub fn saveDiagnostics(self: *const @This()) void { |
| | 265 | self.scanner.saveDiagnostics(); |
| | 266 | } |
| 247 | | 267 | |
| 248 | pub const NextError = ReaderType.Error || Error || Allocator.Error; | 268 | pub const NextError = ReaderType.Error || Error || Allocator.Error; |
| 249 | pub const SkipError = NextError; | 269 | pub const SkipError = NextError; |
| ... | @@ -446,10 +466,20 @@ pub const Scanner = struct { | ... | @@ -446,10 +466,20 @@ pub const Scanner = struct { |
| 446 | self.* = undefined; | 466 | self.* = undefined; |
| 447 | } | 467 | } |
| 448 | | 468 | |
| | 469 | /// See also `saveDiagnostics()`. |
| 449 | pub fn enableDiagnostics(self: *@This(), diagnostics: *Diagnostics) void { | 470 | pub fn enableDiagnostics(self: *@This(), diagnostics: *Diagnostics) void { |
| 450 | diagnostics.cursor_pointer = &self.cursor; | 471 | diagnostics.cursor = .{ .pointer = &self.cursor }; |
| | 472 | std.log.warn("cursor(enableDiagnostics): {}", .{diagnostics.getCursor()}); |
| 451 | self.diagnostics = diagnostics; | 473 | self.diagnostics = diagnostics; |
| 452 | } | 474 | } |
| | 475 | /// Call this just before `deinit()` to make the diagnostics available after the `deinit()`. |
| | 476 | pub fn saveDiagnostics(self: *const @This()) void { |
| | 477 | if (self.diagnostics) |diag| { |
| | 478 | std.log.warn("cursor(deinit presave): {}", .{diag.getCursor()}); |
| | 479 | diag.saveCursor(); |
| | 480 | std.log.warn("cursor(deinit postsave): {}", .{diag.getCursor()}); |
| | 481 | } |
| | 482 | } |
| 453 | | 483 | |
| 454 | /// Call this whenever you get `error.BufferUnderrun` from `next()`. | 484 | /// Call this whenever you get `error.BufferUnderrun` from `next()`. |
| 455 | /// When there is no more input to provide, call `endInput()`. | 485 | /// When there is no more input to provide, call `endInput()`. |