работающее сохранение
This commit is contained in:
@@ -23,6 +23,23 @@ pub fn deinit(self: *Document, allocator: std.mem.Allocator) void {
|
|||||||
self.objects.deinit(allocator);
|
self.objects.deinit(allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clone(self: *const Document, allocator: std.mem.Allocator) !Document {
|
||||||
|
var objects_list = std.ArrayList(Object).empty;
|
||||||
|
errdefer {
|
||||||
|
for (objects_list.items) |*obj| obj.deinit(allocator);
|
||||||
|
objects_list.deinit(allocator);
|
||||||
|
}
|
||||||
|
var next_id = self.next_object_id;
|
||||||
|
for (self.objects.items) |obj| {
|
||||||
|
try objects_list.append(allocator, try obj.clone(allocator, &next_id));
|
||||||
|
}
|
||||||
|
return .{
|
||||||
|
.size = self.size,
|
||||||
|
.objects = objects_list,
|
||||||
|
.next_object_id = next_id,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn addObject(self: *Document, allocator: std.mem.Allocator, template: Object) !void {
|
pub fn addObject(self: *Document, allocator: std.mem.Allocator, template: Object) !void {
|
||||||
const obj = try template.clone(allocator, &self.next_object_id);
|
const obj = try template.clone(allocator, &self.next_object_id);
|
||||||
try self.objects.append(allocator, obj);
|
try self.objects.append(allocator, obj);
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
const Document = @import("../models/Document.zig");
|
|
||||||
|
|
||||||
pub fn saveToFile(doc: *const Document, path: []const u8) !void {
|
|
||||||
var file = try std.fs.cwd().createFile(path, .{ .truncate = true });
|
|
||||||
defer file.close();
|
|
||||||
|
|
||||||
var buffer: [4096]u8 = undefined;
|
|
||||||
var writer = file.writer(&buffer);
|
|
||||||
|
|
||||||
try std.json.Stringify.value(
|
|
||||||
doc,
|
|
||||||
.{ .whitespace = .indent_2 },
|
|
||||||
&writer.interface,
|
|
||||||
);
|
|
||||||
|
|
||||||
try writer.interface.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn loadFromFile(allocator: std.mem.Allocator, path: []const u8) !Document {
|
|
||||||
var file = try std.fs.cwd().openFile(path, .{});
|
|
||||||
defer file.close();
|
|
||||||
|
|
||||||
const data = try file.readToEndAlloc(allocator, std.math.maxInt(usize));
|
|
||||||
defer allocator.free(data);
|
|
||||||
|
|
||||||
const parsed = try std.json.parseFromSlice(Document, allocator, data, .{ .parse_numbers = true });
|
|
||||||
|
|
||||||
return parsed.value;
|
|
||||||
}
|
|
||||||
33
src/persistence/json_io.zig
Normal file
33
src/persistence/json_io.zig
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const Document = @import("../models/Document.zig");
|
||||||
|
|
||||||
|
/// Сохраняет значение произвольного типа T в JSON-файл.
|
||||||
|
pub fn saveToFile(comptime T: type, value: *const T, path: []const u8) !void {
|
||||||
|
var file = try std.fs.cwd().createFile(path, .{ .truncate = true });
|
||||||
|
defer file.close();
|
||||||
|
|
||||||
|
var buffer: [4096]u8 = undefined;
|
||||||
|
var writer = file.writer(&buffer);
|
||||||
|
|
||||||
|
try std.json.Stringify.value(value, .{ .whitespace = .indent_2 }, &writer.interface);
|
||||||
|
|
||||||
|
try writer.interface.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Загружает значение типа T из JSON-файла.
|
||||||
|
/// Для Document после разбора делается клон через allocator, т.к. парсер выделяет память
|
||||||
|
/// из арены — при закрытии документа её нельзя освобождать нашим аллокатором.
|
||||||
|
pub fn loadFromFile(comptime T: type, allocator: std.mem.Allocator, path: []const u8) !T {
|
||||||
|
var file = try std.fs.cwd().openFile(path, .{});
|
||||||
|
defer file.close();
|
||||||
|
|
||||||
|
const data = try file.readToEndAlloc(allocator, std.math.maxInt(usize));
|
||||||
|
defer allocator.free(data);
|
||||||
|
|
||||||
|
var parsed = try std.json.parseFromSlice(T, allocator, data, .{ .ignore_unknown_fields = true });
|
||||||
|
if (T == Document) {
|
||||||
|
defer parsed.deinit();
|
||||||
|
return try parsed.value.clone(allocator);
|
||||||
|
}
|
||||||
|
return parsed.value;
|
||||||
|
}
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const dvui = @import("dvui");
|
const dvui = @import("dvui");
|
||||||
const WindowContext = @import("../WindowContext.zig");
|
const WindowContext = @import("../WindowContext.zig");
|
||||||
const document_json = @import("../persistence/document_json.zig");
|
const Document = @import("../models/Document.zig");
|
||||||
|
const json_io = @import("../persistence/json_io.zig");
|
||||||
|
|
||||||
pub fn menuBar(ctx: *WindowContext) void {
|
pub fn menuBar(ctx: *WindowContext) void {
|
||||||
var m = dvui.menu(@src(), .horizontal, .{ .background = true, .expand = .horizontal });
|
var m = dvui.menu(@src(), .horizontal, .{ .background = true, .expand = .horizontal });
|
||||||
@@ -35,7 +36,7 @@ fn openDocumentDialog(ctx: *WindowContext) void {
|
|||||||
defer ctx.allocator.free(path_z);
|
defer ctx.allocator.free(path_z);
|
||||||
|
|
||||||
const path = path_z[0..path_z.len];
|
const path = path_z[0..path_z.len];
|
||||||
const doc = document_json.loadFromFile(ctx.allocator, path) catch |err| {
|
const doc = json_io.loadFromFile(Document, ctx.allocator, path) catch |err| {
|
||||||
std.debug.print("Open file error: {}\n", .{err});
|
std.debug.print("Open file error: {}\n", .{err});
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
@@ -58,7 +59,7 @@ fn saveAsDialog(ctx: *WindowContext) void {
|
|||||||
defer ctx.allocator.free(path_z);
|
defer ctx.allocator.free(path_z);
|
||||||
|
|
||||||
const path_raw = path_z[0..path_z.len];
|
const path_raw = path_z[0..path_z.len];
|
||||||
document_json.saveToFile(&open_doc.document, path_raw) catch |err| {
|
json_io.saveToFile(Document, &open_doc.document, path_raw) catch |err| {
|
||||||
std.debug.print("Save file error: {}\n", .{err});
|
std.debug.print("Save file error: {}\n", .{err});
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user