Created
March 7, 2021 12:35
-
-
Save pixelomer/bf11b3c852747863ed901817ceaf93d4 to your computer and use it in GitHub Desktop.
osu! beatmap metadata parser written in Objective-C
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <Foundation/Foundation.h> | |
NSDictionary *OSUParseBeatmap(NSURL *beatmapURL); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "OSUBeatmap.h" | |
static void OSUBeatmapProcessKeyValuePair(NSMutableDictionary *output, NSString *line, NSString *separator, NSString *outputKey) { | |
NSMutableDictionary *subDictionary = output[outputKey]; | |
if (!subDictionary) { | |
subDictionary = [NSMutableDictionary new]; | |
output[outputKey] = subDictionary; | |
} | |
NSMutableArray *components = [[line componentsSeparatedByString:separator] mutableCopy]; | |
NSString *key = components[0]; | |
[components removeObjectAtIndex:0]; | |
subDictionary[key] = [components componentsJoinedByString:separator]; | |
} | |
static void OSUBeatmapProcessLine(NSMutableDictionary *output, NSMutableString *section, NSString *line, NSUInteger lineIndex) { | |
@autoreleasepool { | |
if (lineIndex == 0) { | |
output[@"Version"] = line; | |
} | |
else if ([line length] == 0) { | |
// Empty line | |
} | |
else if ([line hasPrefix:@"//"]) { | |
// Comment line | |
} | |
else if ([line hasPrefix:@"["] && [line hasSuffix:@"]"]) { | |
NSString *newSection = [line substringWithRange:NSMakeRange(1, line.length-2)]; | |
[section setString:newSection]; | |
} | |
else if ([section isEqualToString:@"Metadata"]) { | |
OSUBeatmapProcessKeyValuePair(output, line, @":", @"Metadata"); | |
} | |
else if ([section isEqualToString:@"General"]) { | |
OSUBeatmapProcessKeyValuePair(output, line, @": ", @"General"); | |
} | |
else if ([section isEqualToString:@"Events"]) { | |
NSArray *components = [line componentsSeparatedByString:@","]; | |
if ((components.count >= 3) && ([components[0] isEqualToString:@"0"]) && ([components[1] isEqualToString:@"0"])) { | |
NSString *backgroundFilename = [components[2] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"\""]]; | |
output[@"BackgroundFilename"] = backgroundFilename; | |
} | |
} | |
} | |
} | |
NSDictionary *OSUParseBeatmap(NSURL *beatmapURL) { | |
NSInputStream *stream = [NSInputStream inputStreamWithURL:beatmapURL]; | |
if (!stream) { | |
return nil; | |
} | |
[stream open]; | |
NSUInteger lineIndex = 0; | |
NSMutableString *currentString = [NSMutableString new]; | |
NSMutableDictionary *output = [NSMutableDictionary new]; | |
NSMutableString *section = [NSMutableString new]; | |
NSMutableData *buffer = [NSMutableData dataWithCapacity:4096]; | |
while ([stream hasBytesAvailable]) { | |
NSInteger length = [stream read:[buffer mutableBytes] maxLength:4096]; | |
NSString *nextChunk = [[NSString alloc] initWithBytes:[buffer bytes] length:length encoding:NSUTF8StringEncoding]; | |
if (!nextChunk) { | |
[stream close]; | |
return nil; | |
} | |
[currentString appendString:nextChunk]; | |
NSRange lineRange; | |
NSString * const newline = @"\r\n"; | |
while ((lineRange = [currentString rangeOfString:newline]).location != NSNotFound) { | |
NSString *line = [currentString substringWithRange:NSMakeRange(0, lineRange.location)]; | |
[currentString deleteCharactersInRange:NSMakeRange(0, lineRange.location+newline.length)]; | |
OSUBeatmapProcessLine(output, section, line, lineIndex++); | |
} | |
} | |
if ([currentString length]) { | |
OSUBeatmapProcessLine(output, section, currentString, lineIndex++); | |
} | |
[stream close]; | |
return [[NSDictionary alloc] initWithDictionary:output copyItems:YES]; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment