const std = @import("std"); const os = std.os; const mem = std.mem; const assert = std.debug.assert; const stdout = std.io.getStdOut().writer(); fn extract_field(row: *[]u8, delim: u8) []u8 { var p: u64 = 0; while (p < row.len) { defer p += 1; if (row.*[p] == delim) { const result = row.*[0..p]; row.* = row.*[p + 1 ..]; return result; } } const result = row.*; row.* = row.*[row.len..]; return result; } pub fn main() !void { var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer arena.deinit(); const fd = try os.open("matricula.csv", os.O_RDONLY, 0); defer os.close(fd); try os.lseek_END(fd, 0); const length = try os.lseek_CUR_get(fd); const data = try os.mmap( null, length, os.PROT_READ, os.MAP_SHARED, fd, 0, ); defer os.munmap(data); var input_stream = data; var header = extract_field(&input_stream, '\n'); var column_count: u64 = 0; { var header_stream = header; while (header_stream.len > 0) { var field = extract_field(&header_stream, '|'); column_count += 1; } } var columns = try arena.allocator.alloc([]u8, column_count); { var header_stream = header; for (columns) |*column| { column.* = extract_field(&header_stream, '|'); } } var column_lengths = try arena.allocator.alloc(u64, column_count); { var i: u64 = 0; while (i < column_count) { defer i += 1; column_lengths[i] = 0; } } var row_count: u64 = 0; const data_range = input_stream; { while (input_stream.len > 0) { const row = extract_field(&input_stream, '\n'); row_count += 1; var row_stream = row; for (column_lengths) |*column_length| { const field = extract_field(&row_stream, '|'); column_length.* += field.len; } } } const output_fd = try os.open("matricula.transposed.csv", os.O_RDWR | os.O_CREAT | os.O_TRUNC, 0o644); defer os.close(output_fd); var output_length: u64 = 0; var column_offsets = try arena.allocator.alloc(u64, column_count); output_length += header.len; output_length += 1; { var i: u64 = 0; while (i < column_count) { defer i += 1; column_offsets[i] = output_length; output_length += column_lengths[i] + (row_count - 1); output_length += 1; } } if ((try os.pwrite(output_fd, &[_]u8{0}, output_length - 1)) != 1) { unreachable; } const output_data = try os.mmap( null, output_length, os.PROT_READ | os.PROT_WRITE, os.MAP_SHARED, output_fd, 0, ); defer os.munmap(output_data); mem.copy(u8, output_data[0..], header); output_data[header.len] = '\n'; var column_ranges = try arena.allocator.alloc([]u8, column_count); { var i: u64 = 0; while (i < column_count) { defer i += 1; column_ranges[i] = output_data[column_offsets[i]..(column_offsets[i] + column_lengths[i] + row_count)]; } } { input_stream = data_range; while (input_stream.len > 0) { const row = extract_field(&input_stream, '\n'); var row_stream = row; for (column_ranges) |*column_range| { const field = extract_field(&row_stream, '|'); mem.copy(u8, column_range.*, field); column_range.* = column_range.*[field.len..]; column_range.*[0] = '|'; column_range.* = column_range.*[1..]; } } } for (column_ranges) |*column_range, i| { assert(column_ranges[i].len == 0); output_data[column_offsets[i] + column_lengths[i] + (row_count - 1)] = '\n'; } }