summaryrefslogtreecommitdiff
path: root/src/dict.zig
blob: a38d18d3acd6d1d56fe15ae04d9d4e30cdfed909 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
const std = @import("std");
const c = @import("c");

const zpy = @import("root.zig");

pub const Dict = extern struct {
    const Self = @This();

    data: c.PyObject,

    pub const Key = union(enum) {
        string: [*c]const u8,
        object: *zpy.Object,
    };

    pub fn new() !*Self {
        return @ptrCast(c.PyDict_New() orelse return error.Exception);
    }

    pub fn clear(self: *Self) void {
        c.PyDict_Clear(self.object.ptr);
    }

    pub fn contains(self: *const Self, key: Key) bool {
        return switch (key) {
            .string => |str| c.PyDict_ContainsString(@ptrCast(self), str),
            .object => |obj| c.PyDict_Contains(@ptrCast(self), @ptrCast(obj)),
        } == 1;
    }

    pub fn copy(self: *const Self) *Self {
        return @ptrCast(c.PyDict_Copy(@ptrCast(self)));
    }

    pub fn set(self: *Self, key: Key, value: zpy.Object) !void {
        const ret = switch (key) {
            .string => |str| c.PyDict_SetItemString(self.object.ptr, str, value.ptr),
            .object => |obj| c.PyDict_SetItem(self.object.ptr, obj.ptr, value.ptr),
        };

        if (ret == -1) return error.Exception;
    }

    pub fn get(self: *const Self, key: Key) ?*zpy.Object {
        return @ptrCast(switch (key) {
            .string => |str| c.PyDict_GetItemString(@ptrCast(@constCast(self)), str),
            .object => |obj| c.PyDict_GetItem(@ptrCast(@constCast(self)), @ptrCast(obj)),
        });
    }

    pub fn delete(self: *Self, key: Key) !void {
        const ret = switch (key) {
            .string => |str| c.PyDict_DelItemString(@ptrCast(self), str),
            .object => |obj| c.PyDict_DelItem(@ptrCast(self), @ptrCast(obj)),
        };

        if (ret == -1) return error.Exception;
    }

    pub fn setDefault(self: *Self, key: *zpy.Object, default: *zpy.Object) *zpy.Object {
        return @ptrCast(c.PyDict_SetDefault(
            @ptrCast(self),
            @ptrCast(key),
            @ptrCast(default),
        ));
    }

    pub fn pop(self: *Self, key: Key) ?zpy.Object {
        var result: ?*c.PyObject = undefined;

        switch (key) {
            .string => |str| c.PyDict_PopString(@ptrCast(self), str, &result),
            .object => |obj| c.PyDict_Pop(@ptrCast(self), @ptrCast(obj), &result),
        }

        return result;
    }

    pub fn items(self: *const Self) zpy.List {
        return @ptrCast(c.PyDict_Items(@ptrCast(@constCast(self))));
    }

    pub fn keys(self: *const Self) zpy.List {
        return @ptrCast(c.PyDict_Keys(@ptrCast(@constCast(self))));
    }

    pub fn values(self: *const Self) zpy.List {
        return @ptrCast(c.PyDict_Values(@ptrCast(@constCast(self))));
    }

    pub fn size(self: *const Self) usize {
        return @intCast(c.PyDict_Size(@ptrCast(@constCast(self))));
    }

    pub const Iterator = struct {
        dict: *Dict,
        position: c.Py_ssize_t = 0,

        pub const Pair = struct {
            key: *zpy.Object,
            value: *zpy.Object,
        };

        pub fn next(self: *@This()) ?Pair {
            var pair: Pair = undefined;

            if (c.PyDict_Next(
                @ptrCast(self.dict),
                &self.position,
                @ptrCast(&pair.key),
                @ptrCast(&pair.value),
            ) == 1) {
                return pair;
            }

            return null;
        }
    };

    pub fn iterator(self: *Self) Iterator {
        return .{ .dict = self };
    }

    pub fn merge(self: *Self, other: *Self) !void {
        if (c.PyDict_Merge(
            @ptrCast(self),
            @ptrCast(other),
            0,
        ) == -1) {
            return error.Exception;
        }
    }

    pub fn update(self: *Self, other: *Self) !void {
        if (c.PyDict_Merge(
            @ptrCast(self),
            @ptrCast(other),
            1,
        ) == -1) {
            return error.Exception;
        }
    }
};