Add private shared class ArgumentVector
The parser is based on the FS shell's ArgVector.
This commit is contained in:
parent
fc4d98a2c0
commit
af350aa218
53
headers/private/shared/ArgumentVector.h
Normal file
53
headers/private/shared/ArgumentVector.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2007-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _ARGUMENT_VECTOR_H
|
||||
#define _ARGUMENT_VECTOR_H
|
||||
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
namespace BPrivate {
|
||||
|
||||
|
||||
class ArgumentVector {
|
||||
public:
|
||||
enum ParseError {
|
||||
NO_ERROR,
|
||||
NO_MEMORY,
|
||||
UNTERMINATED_QUOTED_STRING,
|
||||
TRAILING_BACKSPACE
|
||||
};
|
||||
|
||||
public:
|
||||
ArgumentVector();
|
||||
~ArgumentVector();
|
||||
|
||||
int32 ArgumentCount() const { return fCount; }
|
||||
const char* const* Arguments() const { return fArguments; }
|
||||
|
||||
char** DetachArguments();
|
||||
// Caller must free() -- it's all one big allocation at the
|
||||
// returned pointer.
|
||||
|
||||
ParseError Parse(const char* commandLine,
|
||||
const char** _errorLocation = NULL);
|
||||
|
||||
private:
|
||||
struct Parser;
|
||||
|
||||
private:
|
||||
char** fArguments;
|
||||
int32 fCount;
|
||||
};
|
||||
|
||||
|
||||
} // namespace BPrivate
|
||||
|
||||
|
||||
using BPrivate::ArgumentVector;
|
||||
|
||||
|
||||
#endif // _ARGUMENT_VECTOR_H
|
203
src/kits/shared/ArgumentVector.cpp
Normal file
203
src/kits/shared/ArgumentVector.cpp
Normal file
@ -0,0 +1,203 @@
|
||||
/*
|
||||
* Copyright 2007-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <ArgumentVector.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
struct ArgumentVector::Parser {
|
||||
ParseError Parse(const char* commandLine, const char*& _errorLocation)
|
||||
{
|
||||
// init temporary arg/argv storage
|
||||
fCurrentArg.clear();
|
||||
fCurrentArgStarted = false;
|
||||
fArgVector.clear();
|
||||
fTotalStringSize = 0;
|
||||
|
||||
for (; *commandLine; commandLine++) {
|
||||
char c = *commandLine;
|
||||
|
||||
// whitespace delimits args and is otherwise ignored
|
||||
if (isspace(c)) {
|
||||
_PushCurrentArg();
|
||||
continue;
|
||||
}
|
||||
|
||||
const char* errorBase = commandLine;
|
||||
|
||||
switch (c) {
|
||||
case '\'':
|
||||
// quoted string -- no quoting
|
||||
while (*++commandLine != '\'') {
|
||||
c = *commandLine;
|
||||
if (c == '\0') {
|
||||
_errorLocation = errorBase;
|
||||
return UNTERMINATED_QUOTED_STRING;
|
||||
}
|
||||
_PushCharacter(c);
|
||||
}
|
||||
break;
|
||||
|
||||
case '"':
|
||||
// quoted string -- some quoting
|
||||
while (*++commandLine != '"') {
|
||||
c = *commandLine;
|
||||
if (c == '\0') {
|
||||
_errorLocation = errorBase;
|
||||
return UNTERMINATED_QUOTED_STRING;
|
||||
}
|
||||
|
||||
if (c == '\\') {
|
||||
c = *++commandLine;
|
||||
if (c == '\0') {
|
||||
_errorLocation = errorBase;
|
||||
return UNTERMINATED_QUOTED_STRING;
|
||||
}
|
||||
|
||||
// only '\' and '"' can be quoted, otherwise the
|
||||
// the '\' is treated as a normal char
|
||||
if (c != '\\' && c != '"')
|
||||
_PushCharacter('\\');
|
||||
}
|
||||
|
||||
_PushCharacter(c);
|
||||
}
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
// quoted char
|
||||
c = *++commandLine;
|
||||
if (c == '\0') {
|
||||
_errorLocation = errorBase;
|
||||
return TRAILING_BACKSPACE;
|
||||
}
|
||||
_PushCharacter(c);
|
||||
break;
|
||||
|
||||
default:
|
||||
// normal char
|
||||
_PushCharacter(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// commit last arg
|
||||
_PushCurrentArg();
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
const std::vector<std::string>& ArgVector() const
|
||||
{
|
||||
return fArgVector;
|
||||
}
|
||||
|
||||
size_t TotalStringSize() const
|
||||
{
|
||||
return fTotalStringSize;
|
||||
}
|
||||
|
||||
private:
|
||||
void _PushCurrentArg()
|
||||
{
|
||||
if (fCurrentArgStarted) {
|
||||
fArgVector.push_back(fCurrentArg);
|
||||
fTotalStringSize += fCurrentArg.length() + 1;
|
||||
fCurrentArgStarted = false;
|
||||
}
|
||||
}
|
||||
|
||||
void _PushCharacter(char c)
|
||||
{
|
||||
if (!fCurrentArgStarted) {
|
||||
fCurrentArg = "";
|
||||
fCurrentArgStarted = true;
|
||||
}
|
||||
|
||||
fCurrentArg += c;
|
||||
}
|
||||
|
||||
private:
|
||||
// temporaries
|
||||
std::string fCurrentArg;
|
||||
bool fCurrentArgStarted;
|
||||
std::vector<std::string> fArgVector;
|
||||
size_t fTotalStringSize;
|
||||
};
|
||||
|
||||
|
||||
ArgumentVector::ArgumentVector()
|
||||
:
|
||||
fArguments(NULL),
|
||||
fCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ArgumentVector::~ArgumentVector()
|
||||
{
|
||||
free(fArguments);
|
||||
}
|
||||
|
||||
|
||||
char**
|
||||
ArgumentVector::DetachArguments()
|
||||
{
|
||||
char** arguments = fArguments;
|
||||
fArguments = NULL;
|
||||
fCount = 0;
|
||||
return arguments;
|
||||
}
|
||||
|
||||
|
||||
ArgumentVector::ParseError
|
||||
ArgumentVector::Parse(const char* commandLine, const char** _errorLocation)
|
||||
{
|
||||
free(DetachArguments());
|
||||
|
||||
ParseError error;
|
||||
const char* errorLocation = commandLine;
|
||||
|
||||
try {
|
||||
Parser parser;
|
||||
error = parser.Parse(commandLine, errorLocation);
|
||||
|
||||
if (error == NO_ERROR) {
|
||||
// Create a char* array and copy everything into a single
|
||||
// allocation.
|
||||
int count = parser.ArgVector().size();
|
||||
size_t arraySize = (count + 1) * sizeof(char*);
|
||||
fArguments = (char**)malloc(
|
||||
arraySize + parser.TotalStringSize());
|
||||
if (fArguments != 0) {
|
||||
char* argument = (char*)(fArguments + count + 1);
|
||||
for (int i = 0; i < count; i++) {
|
||||
fArguments[i] = argument;
|
||||
const std::string& sourceArgument = parser.ArgVector()[i];
|
||||
size_t argumentSize = sourceArgument.length() + 1;
|
||||
memcpy(argument, sourceArgument.c_str(), argumentSize);
|
||||
argument += argumentSize;
|
||||
}
|
||||
|
||||
fArguments[count] = NULL;
|
||||
fCount = count;
|
||||
} else
|
||||
error = NO_MEMORY;
|
||||
}
|
||||
} catch (...) {
|
||||
error = NO_MEMORY;
|
||||
}
|
||||
|
||||
if (error != NO_ERROR && _errorLocation != NULL)
|
||||
*_errorLocation = errorLocation;
|
||||
|
||||
return error;
|
||||
}
|
@ -15,6 +15,7 @@ UsePrivateHeaders kernel libroot ;
|
||||
StaticLibrary libshared.a :
|
||||
AboutMenuItem.cpp
|
||||
AboutWindow.cpp
|
||||
ArgumentVector.cpp
|
||||
CalendarView.cpp
|
||||
ColorQuantizer.cpp
|
||||
CommandPipe.cpp
|
||||
|
Loading…
x
Reference in New Issue
Block a user