ziggy stuff happened

This commit is contained in:
Hamcha 2024-04-27 00:04:49 +02:00
parent 57824afd87
commit ff715db029
Signed by: hamcha
GPG Key ID: 1669C533B8CF6D89
2 changed files with 112 additions and 6 deletions

View File

@ -1,10 +1,25 @@
const std = @import("std");
const fs = std.fs;
const mem = std.mem;
const TrackInfo = @import("trackinfo.zig");
const TrackMap = std.StringHashMap(TrackInfo);
fn parse_musicdef(allocator: mem.Allocator, tracks: *TrackMap, file: []const u8) !void {
var lumps = mem.tokenizeSequence(u8, file, "Lump ");
while (lumps.next()) |lump| {
// Parse lump and add it to the tracklist
const info = try TrackInfo.parseLump(allocator, lump);
try tracks.put(try allocator.dupe(u8, info.id), info);
}
}
pub fn main() !void {
// Get allocator
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
defer _ = gpa.deinit();
// Get args
const args = try std.process.argsAlloc(allocator);
@ -19,12 +34,21 @@ pub fn main() !void {
const folder = args[1];
// Convert folder to absolute
const dir = try fs.cwd().openDir(folder, .{ .iterate = true });
const dir = try fs.cwd().openDir(folder, .{
.iterate = true,
});
// Prepare hashmap for storing song locations
var trackLocations = std.StringHashMap([]const u8).init(allocator);
defer trackLocations.deinit();
var trackInfos = TrackMap.init(allocator);
defer trackInfos.deinit();
var arenaAllocator = std.heap.ArenaAllocator.init(allocator);
defer arenaAllocator.deinit();
const keyAllocator = arenaAllocator.allocator();
// Iter through every file inside the directory (recursive)
var iter = try dir.walk(allocator);
defer iter.deinit();
@ -35,16 +59,28 @@ pub fn main() !void {
}
// Remove extension
const extIndex = std.mem.indexOf(u8, entry.basename, ".");
const extIndex = mem.indexOf(u8, entry.basename, ".");
const filename = if (extIndex) |index| entry.basename[0..index] else entry.basename;
// Check if it's a music definition file (and parse it if so)
if (std.mem.eql(u8, filename, "MUSICDEF")) {
//TODO
if (mem.eql(u8, filename, "MUSICDEF")) {
const filedata = try dir.readFileAlloc(allocator, entry.path, 1048576);
defer allocator.free(filedata);
try parse_musicdef(keyAllocator, &trackInfos, filedata);
} else {
// Save file to hashmap of resolved files
try trackLocations.put(filename, entry.path);
try trackLocations.put(try keyAllocator.dupe(u8, filename), entry.path);
}
std.debug.print("- {s}\n", .{filename});
}
// Print detected songs
var tracks = trackInfos.valueIterator();
while (tracks.next()) |trackInfo| {
std.debug.print("- [{s}] {?s} ({?s}, {?s})\n", .{
trackInfo.id,
trackInfo.title,
trackInfo.author,
trackInfo.source,
});
}
}

70
src/trackinfo.zig Normal file
View File

@ -0,0 +1,70 @@
const std = @import("std");
const mem = std.mem;
const Self = @This();
const InfoKey = enum {
Title,
Author,
Source,
OriginalComposers,
};
const source_original = "Dr. Robotnik's Ring Racers";
allocator: mem.Allocator,
id: []const u8,
title: ?[]const u8,
author: ?[]const u8,
source: ?[]const u8,
originalComposers: ?[]const u8,
is_original: bool,
pub fn parseLump(allocator: mem.Allocator, lump: []const u8) !Self {
// Get lines
var lines = mem.tokenize(u8, lump, "\n");
// Next line is the ID, we need that ASAP!
const id = mem.trim(u8, lines.next().?, " \r");
var info = Self{
.allocator = allocator,
.id = try allocator.dupe(u8, id),
.title = null,
.author = null,
.source = null,
.originalComposers = null,
.is_original = false,
};
// Read rest of lump and assign to fields in struct
while (lines.next()) |line| {
const sep = mem.indexOf(u8, line, "=");
if (sep) |sepIndex| {
const key = mem.trim(u8, line[0..sepIndex], " \r");
const val = mem.trim(u8, line[sepIndex + 1 ..], " \r");
const ownedVal = try allocator.dupe(u8, val);
const infoKey = std.meta.stringToEnum(InfoKey, key) orelse continue;
switch (infoKey) {
.Title => info.title = ownedVal,
.Author => info.author = ownedVal,
.Source => info.source = ownedVal,
.OriginalComposers => info.originalComposers = ownedVal,
}
}
}
// Check if it's an original work
if (info.source) |source| {
info.is_original = mem.eql(u8, source, source_original);
}
return info;
}
pub fn deinit(self: Self) void {
self.allocator.free(self.id);
if (self.title) |ptr| self.allocator.free(ptr);
if (self.author) |ptr| self.allocator.free(ptr);
if (self.source) |ptr| self.allocator.free(ptr);
if (self.title) |ptr| self.allocator.free(ptr);
if (self.originalComposers) |ptr| self.allocator.free(ptr);
}