summaryrefslogtreecommitdiff
path: root/sqlite.zig
diff options
context:
space:
mode:
authorGravatar Vincent Rischmann2020-12-21 02:35:40 +0100
committerGravatar Vincent Rischmann2020-12-21 02:35:40 +0100
commit9221d3056be82bb18d601df790aebfae30d850a7 (patch)
tree1c4cf1c71bd34ad172fcbd43d06036bf0ad2f94f /sqlite.zig
parentadd the readPointer method (diff)
downloadzig-sqlite-9221d3056be82bb18d601df790aebfae30d850a7.tar.gz
zig-sqlite-9221d3056be82bb18d601df790aebfae30d850a7.tar.xz
zig-sqlite-9221d3056be82bb18d601df790aebfae30d850a7.zip
implement reading of sentineled slices
Diffstat (limited to 'sqlite.zig')
-rw-r--r--sqlite.zig75
1 files changed, 50 insertions, 25 deletions
diff --git a/sqlite.zig b/sqlite.zig
index 10695ba..dedd480 100644
--- a/sqlite.zig
+++ b/sqlite.zig
@@ -232,6 +232,10 @@ pub fn Iterator(comptime Type: type) type {
232 debug.assert(columns == 1); 232 debug.assert(columns == 1);
233 return try self.readArray(Type, 0); 233 return try self.readArray(Type, 0);
234 }, 234 },
235 .Pointer => {
236 debug.assert(columns == 1);
237 return try self.readPointer(Type, 0, options);
238 },
235 .Struct => { 239 .Struct => {
236 std.debug.assert(columns == TypeInfo.Struct.fields.len); 240 std.debug.assert(columns == TypeInfo.Struct.fields.len);
237 return try self.readStruct(options); 241 return try self.readStruct(options);
@@ -300,6 +304,25 @@ pub fn Iterator(comptime Type: type) type {
300 Text, 304 Text,
301 }; 305 };
302 306
307 // dupeWithSentinel is like dupe/dupeZ but allows for any sentinel value.
308 fn dupeWithSentinel(comptime SliceType: type, allocator: *mem.Allocator, data: []const u8) !SliceType {
309 const type_info = @typeInfo(SliceType);
310 switch (type_info) {
311 .Pointer => |ptr_info| {
312 if (ptr_info.sentinel) |sentinel| {
313 const slice = try allocator.alloc(u8, data.len + 1);
314 mem.copy(u8, slice, data);
315 slice[data.len] = sentinel;
316
317 return slice[0..data.len :sentinel];
318 } else {
319 return try allocator.dupe(u8, data);
320 }
321 },
322 else => @compileError("cannot dupe type " ++ @typeName(SliceType)),
323 }
324 }
325
303 // readBytes reads a sqlite BLOB or TEXT column. 326 // readBytes reads a sqlite BLOB or TEXT column.
304 // 327 //
305 // The mode controls which sqlite function is used to retrieve the data: 328 // The mode controls which sqlite function is used to retrieve the data:
@@ -312,46 +335,47 @@ pub fn Iterator(comptime Type: type) type {
312 // The options must contain an `allocator` field which will be used to create a copy of the data. 335 // The options must contain an `allocator` field which will be used to create a copy of the data.
313 fn readBytes(self: *Self, comptime BytesType: type, _i: usize, comptime mode: ReadBytesMode, options: anytype) !BytesType { 336 fn readBytes(self: *Self, comptime BytesType: type, _i: usize, comptime mode: ReadBytesMode, options: anytype) !BytesType {
314 const i = @intCast(c_int, _i); 337 const i = @intCast(c_int, _i);
338 const type_info = @typeInfo(BytesType);
315 339
316 var ret: BytesType = switch (BytesType) { 340 var ret: BytesType = switch (BytesType) {
317 Text, Blob => .{ .data = "" }, 341 Text, Blob => .{ .data = "" },
318 else => "", // TODO(vincent): I think with a []u8 this will crash if the caller attempts to modify it... 342 else => try dupeWithSentinel(BytesType, options.allocator, ""),
319 }; 343 };
320 344
321 switch (mode) { 345 switch (mode) {
322 .Blob => { 346 .Blob => {
323 const data = c.sqlite3_column_blob(self.stmt, i); 347 const data = c.sqlite3_column_blob(self.stmt, i);
324 if (data == null) return ret; 348 if (data == null) {
349 return switch (BytesType) {
350 Text, Blob => .{ .data = try options.allocator.dupe(u8, "") },
351 else => try dupeWithSentinel(BytesType, options.allocator, ""),
352 };
353 }
325 354
326 const size = @intCast(usize, c.sqlite3_column_bytes(self.stmt, i)); 355 const size = @intCast(usize, c.sqlite3_column_bytes(self.stmt, i));
327 const ptr = @ptrCast([*c]const u8, data)[0..size]; 356 const ptr = @ptrCast([*c]const u8, data)[0..size];
328 357
329 return switch (BytesType) { 358 if (BytesType == Blob) {
330 []const u8, []u8 => try options.allocator.dupe(u8, ptr), 359 return Blob{ .data = try options.allocator.dupe(u8, ptr) };
331 Blob => blk: { 360 }
332 var tmp: Blob = undefined; 361 return try dupeWithSentinel(BytesType, options.allocator, ptr);
333 tmp.data = try options.allocator.dupe(u8, ptr);
334 break :blk tmp;
335 },
336 else => @compileError("cannot read blob into type " ++ @typeName(BytesType)),
337 };
338 }, 362 },
339 .Text => { 363 .Text => {
340 const data = c.sqlite3_column_text(self.stmt, i); 364 const data = c.sqlite3_column_text(self.stmt, i);
341 if (data == null) return ret; 365 if (data == null) {
366 return switch (BytesType) {
367 Text, Blob => .{ .data = try options.allocator.dupe(u8, "") },
368 else => try dupeWithSentinel(BytesType, options.allocator, ""),
369 };
370 }
342 371
343 const size = @intCast(usize, c.sqlite3_column_bytes(self.stmt, i)); 372 const size = @intCast(usize, c.sqlite3_column_bytes(self.stmt, i));
344 const ptr = @ptrCast([*c]const u8, data)[0..size]; 373 const ptr = @ptrCast([*c]const u8, data)[0..size];
345 374
346 return switch (BytesType) { 375 if (BytesType == Text) {
347 []const u8, []u8 => try options.allocator.dupe(u8, ptr), 376 return Text{ .data = try options.allocator.dupe(u8, ptr) };
348 Text => blk: { 377 }
349 var tmp: Text = undefined; 378 return try dupeWithSentinel(BytesType, options.allocator, ptr);
350 tmp.data = try options.allocator.dupe(u8, ptr);
351 break :blk tmp;
352 },
353 else => @compileError("cannot read text into type " ++ @typeName(BytesType)),
354 };
355 }, 379 },
356 } 380 }
357 } 381 }
@@ -926,16 +950,17 @@ test "sqlite: read a single text value" {
926 try db.init(testing.allocator, .{ .mode = dbMode() }); 950 try db.init(testing.allocator, .{ .mode = dbMode() });
927 try addTestData(&db); 951 try addTestData(&db);
928 952
929 // TODO(vincent): implement the following
930 // [:0]const u8
931 // [:0]u8
932
933 const types = &[_]type{ 953 const types = &[_]type{
934 // Slices 954 // Slices
935 []const u8, 955 []const u8,
936 []u8, 956 []u8,
957 [:0]const u8,
958 [:0]u8,
959 [:0xAD]const u8,
960 [:0xAD]u8,
937 // Array 961 // Array
938 [8:0]u8, 962 [8:0]u8,
963 [8:0xAD]u8,
939 // Specific text or blob 964 // Specific text or blob
940 Text, 965 Text,
941 Blob, 966 Blob,