/*
* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014
* Jonathan Schleifer <js@webkeks.org>
*
* All rights reserved.
*
* This file is part of ObjFW. It may be distributed under the terms of the
* Q Public License 1.0, which can be found in the file LICENSE.QPL included in
* the packaging of this file.
*
* Alternatively, it may be distributed under the terms of the GNU General
* Public License, either version 2 or 3, which can be found in the file
* LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
* file.
*/
#include "config.h"
#import "OFOptionsParser.h"
#import "OFApplication.h"
#import "OFArray.h"
#import "autorelease.h"
#import "macros.h"
@implementation OFOptionsParser
+ (instancetype)parserWithOptions: (OFString*)options
{
return [[[self alloc] initWithOptions: options] autorelease];
}
- init
{
OF_INVALID_INIT_METHOD
}
- initWithOptions: (OFString*)options
{
self = [super init];
@try {
_options = [self allocMemoryWithSize: sizeof(of_unichar_t)
count: [options length] + 1];
[options getCharacters: _options
inRange: of_range(0, [options length])];
_options[[options length]] = 0;
_arguments = [[OFApplication arguments] retain];
} @catch (id e) {
[self release];
@throw e;
}
return self;
}
- (void)dealloc
{
[_arguments release];
[_argument release];
[super dealloc];
}
- (of_unichar_t)nextOption
{
of_unichar_t *options;
OFString *argument;
if (_done || _index >= [_arguments count])
return '\0';
argument = [_arguments objectAtIndex: _index];
if (_subIndex == 0) {
if ([argument length] < 2 ||
[argument characterAtIndex: 0] != '-') {
_done = true;
return '\0';
}
if ([argument isEqual: @"--"]) {
_done = true;
_index++;
return '\0';
}
_subIndex = 1;
}
_lastOption = [argument characterAtIndex: _subIndex++];
if (_subIndex >= [argument length]) {
_index++;
_subIndex = 0;
}
for (options = _options; *options != 0; options++) {
if (_lastOption == *options) {
if (options[1] != ':') {
[_argument release];
_argument = nil;
return _lastOption;
}
if (_index >= [_arguments count])
return ':';
argument = [_arguments objectAtIndex: _index];
argument = [argument substringWithRange:
of_range(_subIndex, [argument length] - _subIndex)];
[_argument release];
_argument = [argument copy];
_index++;
_subIndex = 0;
return _lastOption;
}
}
return '?';
}
- (of_unichar_t)lastOption
{
return _lastOption;
}
- (OFString*)argument
{
return [[_argument copy] autorelease];
}
- (OFArray*)remainingArguments
{
return [_arguments objectsInRange:
of_range(_index, [_arguments count] - _index)];
}
@end