Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

transStringLiteralInitializer

Translate a string literal that is initializing an array. In general narrow string literals become "<string>".* or "<string>"[0..<size>].* if they need truncation. Wide string literals become an array of integers. zero-fillers pad out the array to the appropriate length, if necessary.

Translator.transStringLiteralInitializer
fn transStringLiteralInitializer(
    t: *Translator,
    expr: Node.Index,
    literal: Node.CharLiteral,
    array_type: ZigNode,
) TransError!ZigNode

File

lib/compiler/translate-c/Translator.zig:3643

Code

fn transStringLiteralInitializer(
    t: *Translator,
    expr: Node.Index,
    literal: Node.CharLiteral,
    array_type: ZigNode,
) TransError!ZigNode {
    assert(array_type.tag() == .array_type or array_type.tag() == .null_sentinel_array_type);

    const is_narrow = literal.kind == .ascii or literal.kind == .utf8;

    // The length of the string literal excluding the sentinel.
    const str_length = literal.qt.arrayLen(t.comp).? - 1;

    const payload = (array_type.castTag(.array_type) orelse array_type.castTag(.null_sentinel_array_type).?).data;
    const array_size = payload.len;
    const elem_type = payload.elem_type;

    if (array_size == 0) return ZigTag.empty_array.create(t.arena, array_type);

    const num_inits = @min(str_length, array_size);
    if (num_inits == 0) {
        return ZigTag.array_filler.create(t.arena, .{
            .type = elem_type,
            .filler = ZigTag.zero_literal.init(),
            .count = array_size,
        });
    }

    const init_node = if (is_narrow) blk: {
        // "string literal".* or string literal"[0..num_inits].*
        var str = try t.transNarrowStringLiteral(expr, literal);
        if (str_length != array_size) str = try ZigTag.string_slice.create(t.arena, .{ .string = str, .end = num_inits });
        break :blk try ZigTag.deref.create(t.arena, str);
    } else blk: {
        const size = literal.qt.childType(t.comp).sizeof(t.comp);

        const val = t.tree.value_map.get(expr).?;
        const bytes = t.comp.interner.get(val.ref()).bytes;

        const init_list = try t.arena.alloc(ZigNode, @intCast(num_inits));
        for (init_list, 0..) |*item, i| {
            const codepoint = switch (size) {
                2 => @as(*const u16, @ptrCast(@alignCast(bytes.ptr + i * 2))).*,
                4 => @as(*const u32, @ptrCast(@alignCast(bytes.ptr + i * 4))).*,
                else => unreachable,
            };
            item.* = try t.createCharLiteralNode(false, codepoint);
        }
        const init_args: ast.Payload.Array.ArrayTypeInfo = .{ .len = num_inits, .elem_type = elem_type };
        const init_array_type = if (array_type.tag() == .array_type)
            try ZigTag.array_type.create(t.arena, init_args)
        else
            try ZigTag.null_sentinel_array_type.create(t.arena, init_args);
        break :blk try ZigTag.array_init.create(t.arena, .{
            .cond = init_array_type,
            .cases = init_list,
        });
    };

    if (num_inits == array_size) return init_node;
    assert(array_size > str_length); // If array_size <= str_length, `num_inits == array_size` and we've already returned.

    const filler_node = try ZigTag.array_filler.create(t.arena, .{
        .type = elem_type,
        .filler = ZigTag.zero_literal.init(),
        .count = array_size - str_length,
    });
    return ZigTag.array_cat.create(t.arena, .{ .lhs = init_node, .rhs = filler_node });
}