Implement offset and limit features - #20
Conversation
📝 WalkthroughWalkthroughChanges widen ChangesOffset and limit handling
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Caller
participant CSVReader
participant skip_records
participant Stream
Caller->>CSVReader: csv_reader_init_standalone(config)
CSVReader->>CSVReader: records_returned = 0
CSVReader->>skip_records: skip_records(reader, config->offset)
loop offset count
skip_records->>Stream: read full record
skip_records->>CSVReader: line_number++
end
skip_records-->>CSVReader: offset applied
Caller->>CSVReader: csv_reader_next_record()
CSVReader->>CSVReader: check records_returned vs limit
CSVReader->>Stream: read record
CSVReader->>CSVReader: records_returned++
CSVReader-->>Caller: return CSVRecord
Caller->>CSVReader: csv_reader_rewind()
CSVReader->>CSVReader: records_returned = 0, recompute line_number
CSVReader->>skip_records: skip_records(reader, config->offset)
skip_records-->>CSVReader: offset re-applied
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
csv_reader.c (1)
125-132: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider reusing
skip_recordsincsv_reader_seek.
csv_reader_seek's advance loop (elsewhere in this file) duplicates the samearena_reset+read_full_record+line_number++pattern now encapsulated inskip_records. Callingskip_records(reader, position)there (adjusting for itsif (!line) break;vs seek'sreturn 0on failure) would remove the duplication.♻️ Sketch
int csv_reader_seek(CSVReader *reader, long position) { if (!reader || !reader->file || position < 0) { return 0; } csv_reader_rewind(reader); - for (long i = 0; i < position; i++) { - arena_reset(reader->temp_arena); - char *line = read_full_record(reader->file, reader->temp_arena); - if (!line) { - return 0; - } - reader->line_number++; - } + long before = reader->line_number; + skip_records(reader, (int)position); + if (reader->line_number - before < position) { + return 0; + } return 1; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@csv_reader.c` around lines 125 - 132, The seek advance logic duplicates the same record-skipping pattern already encapsulated in skip_records; update csv_reader_seek to reuse skip_records instead of reimplementing arena_reset, read_full_record, and line_number updates. Keep csv_reader_seek’s failure behavior aligned with its current return-0 semantics by checking whether the requested position was fully skipped and propagating failure if read_full_record stops early.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@csv_reader.c`:
- Around line 125-132: The reader navigation paths are not honoring
skipEmptyLines consistently, so empty lines still advance record position in
csv_reader_init_*, csv_reader_rewind, csv_reader_seek, skip_records, and
csv_reader_next_record. Update the record-skipping and iteration logic in these
routines to detect and ignore blank lines when skipEmptyLines is enabled,
matching the behavior already used by csv_reader_get_record_count, so offsets
and seeks land on the correct data row.
---
Nitpick comments:
In `@csv_reader.c`:
- Around line 125-132: The seek advance logic duplicates the same
record-skipping pattern already encapsulated in skip_records; update
csv_reader_seek to reuse skip_records instead of reimplementing arena_reset,
read_full_record, and line_number updates. Keep csv_reader_seek’s failure
behavior aligned with its current return-0 semantics by checking whether the
requested position was fully skipped and propagating failure if read_full_record
stops early.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: c1a5fb44-26a6-40bb-90dd-89900c24a1ee
📒 Files selected for processing (4)
csv_config.hcsv_reader.ccsv_reader.htests/test_csv_reader.c
| static void skip_records(CSVReader *reader, int count) { | ||
| for (int i = 0; i < count; i++) { | ||
| arena_reset(reader->temp_arena); | ||
| char *line = read_full_record(reader->file, reader->temp_arena); | ||
| if (!line) break; | ||
| reader->line_number++; | ||
| } | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Inspect how skipEmptyLines is actually implemented relative to raw line reads
rg -nP -C5 '\bskipEmptyLines\b' --type=c
rg -nP -C8 'read_full_record\s*\(' --type=c
rg -nP -C8 'csv_parse_line_inplace\s*\(' --type=cRepository: csvtoolkit/FastCSV-C
Length of output: 158
🏁 Script executed:
git ls-filesRepository: csvtoolkit/FastCSV-C
Length of output: 602
🏁 Script executed:
ast-grep outline csv_reader.c --view expanded
ast-grep outline csv_parser.c --view expanded
ast-grep outline tests/test_csv_reader.c --view expanded
rg -n "empty|skip|limit|offset|record" csv_reader.c csv_parser.c csv_config.c tests/test_csv_reader.cRepository: csvtoolkit/FastCSV-C
Length of output: 25378
🏁 Script executed:
sed -n '1,220p' csv_reader.c
printf '\n----\n'
sed -n '220,360p' csv_reader.c
printf '\n----\n'
sed -n '1,220p' csv_config.c
printf '\n----\n'
sed -n '330,390p' tests/test_csv_reader.c
printf '\n----\n'
sed -n '470,650p' tests/test_csv_reader.cRepository: csvtoolkit/FastCSV-C
Length of output: 22351
🏁 Script executed:
sed -n '1,260p' csv_parser.c
printf '\n----\n'
sed -n '1,220p' csv_reader.h
printf '\n----\n'
sed -n '1,220p' csv_config.h
printf '\n----\n'
sed -n '1,220p' README.mdRepository: csvtoolkit/FastCSV-C
Length of output: 19190
🏁 Script executed:
sed -n '260,340p' csv_parser.c
printf '\n----\n'
python3 - <<'PY'
from pathlib import Path
text = Path('csv_parser.c').read_text()
# print the exact blank-line handling branch if present
for needle in ['record_len == 0', 'line comment', 'EOF']:
pass
PYRepository: csvtoolkit/FastCSV-C
Length of output: 1111
Make skipEmptyLines consistent in reader navigation csv_reader_get_record_count skips blank lines, but csv_reader_init_*, csv_reader_rewind, csv_reader_seek, skip_records, and csv_reader_next_record still count them as records. With skipEmptyLines enabled, offset/seek can land on the wrong data row in files that contain empty lines.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@csv_reader.c` around lines 125 - 132, The reader navigation paths are not
honoring skipEmptyLines consistently, so empty lines still advance record
position in csv_reader_init_*, csv_reader_rewind, csv_reader_seek, skip_records,
and csv_reader_next_record. Update the record-skipping and iteration logic in
these routines to detect and ignore blank lines when skipEmptyLines is enabled,
matching the behavior already used by csv_reader_get_record_count, so offsets
and seeks land on the correct data row.
This pr implements offset and limit features in csv_reader:
records_returnedvariableskip_recordsfunction which is run on init and on rewind / seekcsv_reader_next_recordnow returns NULL iflimit > 0andrecords_returned >= limitSummary by CodeRabbit
New Features
Bug Fixes