ctgPi icon

CSV transpose

ctgPi | PRO | 04/17/21 01:10:44 PM UTC (Edited) | 0 ⭐ | 219 👁️ | Never ⏰ | []
text |

4.1 KB

|

None

|

0 👍

/

0 👎

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';
    }
}
 

Comments