| ... | ... | @@ -196,7 +196,12 @@ pub const Diagnostics = struct { |
| 196 | 196 | line_number: u64 = 1, |
| 197 | 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 | 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 | 206 | /// Starts at 1. |
| 202 | 207 | pub fn getLine(self: *const @This()) u64 { |
| ... | ... | @@ -204,11 +209,22 @@ pub const Diagnostics = struct { |
| 204 | 209 | } |
| 205 | 210 | /// Starts at 1. |
| 206 | 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 | 214 | /// Starts at 0. Measures the byte offset since the start of the input. |
| 210 | 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 | 260 | pub fn enableDiagnostics(self: *@This(), diagnostics: *Diagnostics) void { |
| 245 | 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 | 268 | pub const NextError = ReaderType.Error || Error || Allocator.Error; |
| 249 | 269 | pub const SkipError = NextError; |
| ... | ... | @@ -446,10 +466,20 @@ pub const Scanner = struct { |
| 446 | 466 | self.* = undefined; |
| 447 | 467 | } |
| 448 | 468 | |
| 469 | /// See also `saveDiagnostics()`. |
| 449 | 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 | 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 | 484 | /// Call this whenever you get `error.BufferUnderrun` from `next()`. |
| 455 | 485 | /// When there is no more input to provide, call `endInput()`. |