nicolas-arnaud
2 years ago
19 changed files with 1096 additions and 129 deletions
@ -0,0 +1,210 @@ |
|||||
|
#include "Token.hpp" |
||||
|
#include <cstdlib> |
||||
|
|
||||
|
class JSONParser { |
||||
|
std::fstream file; |
||||
|
JSONNode *root; |
||||
|
JSONNode *current; |
||||
|
Tokenizer tokenizer; |
||||
|
|
||||
|
public: |
||||
|
JSONParser(const string filename) : tokenizer(filename) {} |
||||
|
void parse() { |
||||
|
string key = ""; |
||||
|
while (tokenizer.hasMoreTokens()) { |
||||
|
Token *token; |
||||
|
JSONNode *parsed; |
||||
|
try { |
||||
|
token = tokenizer.getToken(); |
||||
|
switch (token->type) { |
||||
|
case CURLY_OPEN: { |
||||
|
parsed = parseObject(); |
||||
|
if (!root) { |
||||
|
root = parsed; |
||||
|
} |
||||
|
break; |
||||
|
} |
||||
|
case ARRAY_OPEN: { |
||||
|
parsed = parseList(); |
||||
|
if (!root) { |
||||
|
root = parsed; |
||||
|
} |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
case STRING: { |
||||
|
tokenizer.rollBackToken(); |
||||
|
parsed = parseString(); |
||||
|
break; |
||||
|
} |
||||
|
case NUMBER: { |
||||
|
tokenizer.rollBackToken(); |
||||
|
parsed = parseNumber(); |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
case BOOLEAN: { |
||||
|
tokenizer.rollBackToken(); |
||||
|
parsed = parseBoolean(); |
||||
|
break; |
||||
|
} |
||||
|
default: |
||||
|
break; |
||||
|
} |
||||
|
parsed->stringify(0); |
||||
|
} |
||||
|
catch (std::logic_error &e) { |
||||
|
break; |
||||
|
} |
||||
|
delete token; |
||||
|
} |
||||
|
// assert token not valid |
||||
|
} |
||||
|
|
||||
|
JSONNode *parseObject() { |
||||
|
//cout << "Parse Object\n"; |
||||
|
JSONNode *node = new JSONNode(); |
||||
|
JSONObject *keyObjectMap = new JSONObject(); |
||||
|
bool hasCompleted = false; |
||||
|
Token *token = tokenizer.getToken(); |
||||
|
while (!hasCompleted) { |
||||
|
if (tokenizer.hasMoreTokens()) { |
||||
|
string key = token->value; |
||||
|
tokenizer.getToken(); |
||||
|
token = tokenizer.getToken(); |
||||
|
switch (token->type) { |
||||
|
case STRING: { |
||||
|
tokenizer.rollBackToken(); |
||||
|
(*keyObjectMap)[key] = parseString(); |
||||
|
break; |
||||
|
} |
||||
|
case ARRAY_OPEN: { |
||||
|
(*keyObjectMap)[key] = parseList(); |
||||
|
break; |
||||
|
} |
||||
|
case NUMBER: { |
||||
|
tokenizer.rollBackToken(); |
||||
|
(*keyObjectMap)[key] = parseNumber(); |
||||
|
break; |
||||
|
} |
||||
|
case CURLY_OPEN: { |
||||
|
(*keyObjectMap)[key] = parseObject(); |
||||
|
break; |
||||
|
} |
||||
|
case BOOLEAN: { |
||||
|
tokenizer.rollBackToken(); |
||||
|
(*keyObjectMap)[key] = parseBoolean(); |
||||
|
break; |
||||
|
} |
||||
|
case NULL_TYPE: { |
||||
|
(*keyObjectMap)[key] = parseNull(); |
||||
|
break; |
||||
|
} |
||||
|
default: |
||||
|
break; |
||||
|
} |
||||
|
delete token; |
||||
|
token = tokenizer.getToken(); |
||||
|
if (token->type == CURLY_CLOSE) { |
||||
|
hasCompleted = true; |
||||
|
delete token; |
||||
|
break; |
||||
|
} |
||||
|
} else { |
||||
|
throw std::logic_error("No more tokens"); |
||||
|
} |
||||
|
} |
||||
|
node->setObject(keyObjectMap); |
||||
|
return node; |
||||
|
} |
||||
|
|
||||
|
JSONNode *parseList() { |
||||
|
//cout << "Parse List\n"; |
||||
|
JSONNode *node = new JSONNode(); |
||||
|
JSONList *list = new JSONList(); |
||||
|
bool hasCompleted = false; |
||||
|
Token *token = tokenizer.getToken(); |
||||
|
while (!hasCompleted) { |
||||
|
if (!tokenizer.hasMoreTokens()) { |
||||
|
throw std::logic_error("No more tokens"); |
||||
|
} else { |
||||
|
JSONNode *node; |
||||
|
switch (token->type) { |
||||
|
case ARRAY_OPEN: { |
||||
|
node = parseList(); |
||||
|
break; |
||||
|
} |
||||
|
case CURLY_OPEN: { |
||||
|
node = parseObject(); |
||||
|
break; |
||||
|
} |
||||
|
case STRING: { |
||||
|
tokenizer.rollBackToken(); |
||||
|
node = parseString(); |
||||
|
break; |
||||
|
} |
||||
|
case NUMBER: { |
||||
|
tokenizer.rollBackToken(); |
||||
|
node = parseNumber(); |
||||
|
break; |
||||
|
} |
||||
|
case BOOLEAN: { |
||||
|
tokenizer.rollBackToken(); |
||||
|
node = parseBoolean(); |
||||
|
break; |
||||
|
} |
||||
|
case NULL_TYPE: { |
||||
|
node = parseNull(); |
||||
|
break; |
||||
|
} |
||||
|
default: |
||||
|
break; |
||||
|
} |
||||
|
list->push_back(node); |
||||
|
delete token; |
||||
|
token = tokenizer.getToken(); |
||||
|
if (token->type == ARRAY_CLOSE) { |
||||
|
hasCompleted = true; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
delete token; |
||||
|
node->setList(list); |
||||
|
return node; |
||||
|
} |
||||
|
|
||||
|
JSONNode *parseString() { |
||||
|
//cout << "Parse string\n"; |
||||
|
JSONNode *node = new JSONNode(); |
||||
|
Token *token = tokenizer.getToken(); |
||||
|
string *sValue = new string(token->value); |
||||
|
delete token; |
||||
|
node->setString(sValue); |
||||
|
return node; |
||||
|
} |
||||
|
|
||||
|
JSONNode *parseNumber() { |
||||
|
//cout << "Parse number\n"; |
||||
|
JSONNode *node = new JSONNode(); |
||||
|
Token *token = tokenizer.getToken(); |
||||
|
string value = token->value; |
||||
|
delete token; |
||||
|
// cout << value << "\n"; |
||||
|
int nbr = std::atoi(value.c_str()); |
||||
|
node->setNumber(nbr); |
||||
|
return node; |
||||
|
} |
||||
|
JSONNode *parseBoolean() { |
||||
|
JSONNode *node = new JSONNode(); |
||||
|
Token *token = tokenizer.getToken(); |
||||
|
node->setBoolean(token->value == "True" ? true : false); |
||||
|
delete token; |
||||
|
return node; |
||||
|
} |
||||
|
|
||||
|
JSONNode *parseNull() { |
||||
|
JSONNode *node = new JSONNode(); |
||||
|
node->setNull(); |
||||
|
return node; |
||||
|
} |
||||
|
}; |
@ -0,0 +1,192 @@ |
|||||
|
--- |
||||
|
Language: Cpp |
||||
|
# BasedOnStyle: LLVM |
||||
|
AccessModifierOffset: -2 |
||||
|
AlignAfterOpenBracket: Align |
||||
|
AlignArrayOfStructures: None |
||||
|
AlignConsecutiveMacros: None |
||||
|
AlignConsecutiveAssignments: None |
||||
|
AlignConsecutiveBitFields: None |
||||
|
AlignConsecutiveDeclarations: None |
||||
|
AlignEscapedNewlines: Right |
||||
|
AlignOperands: Align |
||||
|
AlignTrailingComments: true |
||||
|
AllowAllArgumentsOnNextLine: true |
||||
|
AllowAllParametersOfDeclarationOnNextLine: true |
||||
|
AllowShortEnumsOnASingleLine: true |
||||
|
AllowShortBlocksOnASingleLine: Never |
||||
|
AllowShortCaseLabelsOnASingleLine: false |
||||
|
AllowShortFunctionsOnASingleLine: All |
||||
|
AllowShortLambdasOnASingleLine: All |
||||
|
AllowShortIfStatementsOnASingleLine: Never |
||||
|
AllowShortLoopsOnASingleLine: false |
||||
|
AlwaysBreakAfterDefinitionReturnType: None |
||||
|
AlwaysBreakAfterReturnType: None |
||||
|
AlwaysBreakBeforeMultilineStrings: false |
||||
|
AlwaysBreakTemplateDeclarations: MultiLine |
||||
|
AttributeMacros: |
||||
|
- __capability |
||||
|
BinPackArguments: true |
||||
|
BinPackParameters: true |
||||
|
BraceWrapping: |
||||
|
AfterCaseLabel: false |
||||
|
AfterClass: false |
||||
|
AfterControlStatement: Never |
||||
|
AfterEnum: false |
||||
|
AfterFunction: false |
||||
|
AfterNamespace: false |
||||
|
AfterObjCDeclaration: false |
||||
|
AfterStruct: false |
||||
|
AfterUnion: false |
||||
|
AfterExternBlock: false |
||||
|
BeforeCatch: false |
||||
|
BeforeElse: false |
||||
|
BeforeLambdaBody: false |
||||
|
BeforeWhile: false |
||||
|
IndentBraces: false |
||||
|
SplitEmptyFunction: true |
||||
|
SplitEmptyRecord: true |
||||
|
SplitEmptyNamespace: true |
||||
|
BreakBeforeBinaryOperators: None |
||||
|
BreakBeforeConceptDeclarations: true |
||||
|
BreakBeforeBraces: Attach |
||||
|
BreakBeforeInheritanceComma: false |
||||
|
BreakInheritanceList: BeforeColon |
||||
|
BreakBeforeTernaryOperators: true |
||||
|
BreakConstructorInitializersBeforeComma: false |
||||
|
BreakConstructorInitializers: BeforeColon |
||||
|
BreakAfterJavaFieldAnnotations: false |
||||
|
BreakStringLiterals: true |
||||
|
ColumnLimit: 80 |
||||
|
CommentPragmas: '^ IWYU pragma:' |
||||
|
QualifierAlignment: Leave |
||||
|
CompactNamespaces: false |
||||
|
ConstructorInitializerIndentWidth: 4 |
||||
|
ContinuationIndentWidth: 4 |
||||
|
Cpp11BracedListStyle: true |
||||
|
DeriveLineEnding: true |
||||
|
DerivePointerAlignment: false |
||||
|
DisableFormat: false |
||||
|
EmptyLineAfterAccessModifier: Never |
||||
|
EmptyLineBeforeAccessModifier: LogicalBlock |
||||
|
ExperimentalAutoDetectBinPacking: false |
||||
|
PackConstructorInitializers: BinPack |
||||
|
BasedOnStyle: '' |
||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: false |
||||
|
AllowAllConstructorInitializersOnNextLine: true |
||||
|
FixNamespaceComments: true |
||||
|
ForEachMacros: |
||||
|
- foreach |
||||
|
- Q_FOREACH |
||||
|
- BOOST_FOREACH |
||||
|
IfMacros: |
||||
|
- KJ_IF_MAYBE |
||||
|
IncludeBlocks: Preserve |
||||
|
IncludeCategories: |
||||
|
- Regex: '^"(llvm|llvm-c|clang|clang-c)/' |
||||
|
Priority: 2 |
||||
|
SortPriority: 0 |
||||
|
CaseSensitive: false |
||||
|
- Regex: '^(<|"(gtest|gmock|isl|json)/)' |
||||
|
Priority: 3 |
||||
|
SortPriority: 0 |
||||
|
CaseSensitive: false |
||||
|
- Regex: '.*' |
||||
|
Priority: 1 |
||||
|
SortPriority: 0 |
||||
|
CaseSensitive: false |
||||
|
IncludeIsMainRegex: '(Test)?$' |
||||
|
IncludeIsMainSourceRegex: '' |
||||
|
IndentAccessModifiers: false |
||||
|
IndentCaseLabels: false |
||||
|
IndentCaseBlocks: false |
||||
|
IndentGotoLabels: true |
||||
|
IndentPPDirectives: None |
||||
|
IndentExternBlock: AfterExternBlock |
||||
|
IndentRequires: false |
||||
|
IndentWidth: 4 |
||||
|
IndentWrappedFunctionNames: false |
||||
|
InsertTrailingCommas: None |
||||
|
JavaScriptQuotes: Leave |
||||
|
JavaScriptWrapImports: true |
||||
|
KeepEmptyLinesAtTheStartOfBlocks: true |
||||
|
LambdaBodyIndentation: Signature |
||||
|
MacroBlockBegin: '' |
||||
|
MacroBlockEnd: '' |
||||
|
MaxEmptyLinesToKeep: 1 |
||||
|
NamespaceIndentation: None |
||||
|
ObjCBinPackProtocolList: Auto |
||||
|
ObjCBlockIndentWidth: 2 |
||||
|
ObjCBreakBeforeNestedBlockParam: true |
||||
|
ObjCSpaceAfterProperty: false |
||||
|
ObjCSpaceBeforeProtocolList: true |
||||
|
PenaltyBreakAssignment: 2 |
||||
|
PenaltyBreakBeforeFirstCallParameter: 19 |
||||
|
PenaltyBreakComment: 300 |
||||
|
PenaltyBreakFirstLessLess: 120 |
||||
|
PenaltyBreakOpenParenthesis: 0 |
||||
|
PenaltyBreakString: 1000 |
||||
|
PenaltyBreakTemplateDeclaration: 10 |
||||
|
PenaltyExcessCharacter: 1000000 |
||||
|
PenaltyReturnTypeOnItsOwnLine: 60 |
||||
|
PenaltyIndentedWhitespace: 0 |
||||
|
PointerAlignment: Right |
||||
|
PPIndentWidth: -1 |
||||
|
ReferenceAlignment: Pointer |
||||
|
ReflowComments: true |
||||
|
RemoveBracesLLVM: false |
||||
|
SeparateDefinitionBlocks: Leave |
||||
|
ShortNamespaceLines: 1 |
||||
|
SortIncludes: CaseSensitive |
||||
|
SortJavaStaticImport: Before |
||||
|
SortUsingDeclarations: true |
||||
|
SpaceAfterCStyleCast: false |
||||
|
SpaceAfterLogicalNot: false |
||||
|
SpaceAfterTemplateKeyword: true |
||||
|
SpaceBeforeAssignmentOperators: true |
||||
|
SpaceBeforeCaseColon: false |
||||
|
SpaceBeforeCpp11BracedList: false |
||||
|
SpaceBeforeCtorInitializerColon: true |
||||
|
SpaceBeforeInheritanceColon: true |
||||
|
SpaceBeforeParens: ControlStatements |
||||
|
SpaceBeforeParensOptions: |
||||
|
AfterControlStatements: true |
||||
|
AfterForeachMacros: true |
||||
|
AfterFunctionDefinitionName: false |
||||
|
AfterFunctionDeclarationName: false |
||||
|
AfterIfMacros: true |
||||
|
AfterOverloadedOperator: false |
||||
|
BeforeNonEmptyParentheses: false |
||||
|
SpaceAroundPointerQualifiers: Default |
||||
|
SpaceBeforeRangeBasedForLoopColon: true |
||||
|
SpaceInEmptyBlock: false |
||||
|
SpaceInEmptyParentheses: false |
||||
|
SpacesBeforeTrailingComments: 1 |
||||
|
SpacesInAngles: Never |
||||
|
SpacesInConditionalStatement: false |
||||
|
SpacesInContainerLiterals: true |
||||
|
SpacesInCStyleCastParentheses: false |
||||
|
SpacesInLineCommentPrefix: |
||||
|
Minimum: 1 |
||||
|
Maximum: -1 |
||||
|
SpacesInParentheses: false |
||||
|
SpacesInSquareBrackets: false |
||||
|
SpaceBeforeSquareBrackets: false |
||||
|
BitFieldColonSpacing: Both |
||||
|
Standard: Latest |
||||
|
StatementAttributeLikeMacros: |
||||
|
- Q_EMIT |
||||
|
StatementMacros: |
||||
|
- Q_UNUSED |
||||
|
- QT_REQUIRE_VERSION |
||||
|
TabWidth: 4 |
||||
|
UseCRLF: false |
||||
|
UseTab: Never |
||||
|
WhitespaceSensitiveMacros: |
||||
|
- STRINGIZE |
||||
|
- PP_STRINGIZE |
||||
|
- BOOST_PP_STRINGIZE |
||||
|
- NS_SWIFT_NAME |
||||
|
- CF_SWIFT_NAME |
||||
|
... |
||||
|
|
@ -0,0 +1,32 @@ |
|||||
|
{ |
||||
|
"max_clients": 30, |
||||
|
"servers": |
||||
|
[ |
||||
|
{ |
||||
|
"listen": ["80", "[::]:80"], |
||||
|
"server_name": "localhost", |
||||
|
"return": "301 https://$host$uri" |
||||
|
|
||||
|
}, |
||||
|
{ |
||||
|
"listen": ["443", "[::]:443"], |
||||
|
"server_name": "localhost", |
||||
|
"root": "datas", |
||||
|
"locations": |
||||
|
{ |
||||
|
"/site": |
||||
|
{ |
||||
|
"root": "datas/website", |
||||
|
"index": ["index.html", "index.php"], |
||||
|
"try_files": "$uri /$uri =404" |
||||
|
}, |
||||
|
"/img": |
||||
|
{ |
||||
|
"index": ["datas/gallery.html"], |
||||
|
"autoindex": true |
||||
|
}, |
||||
|
"/": {"return": "404"} |
||||
|
} |
||||
|
} |
||||
|
] |
||||
|
} |
Binary file not shown.
@ -0,0 +1,131 @@ |
|||||
|
#include <iostream> |
||||
|
#include <map> |
||||
|
#include <sstream> |
||||
|
#include <string> |
||||
|
#include <vector> |
||||
|
|
||||
|
#define DEBUG 0 |
||||
|
|
||||
|
using std::cout; |
||||
|
using std::string; |
||||
|
|
||||
|
class JSONNode; |
||||
|
typedef std::map<string, JSONNode *> JSONObject; |
||||
|
typedef std::vector<JSONNode *> JSONList; |
||||
|
|
||||
|
class JSONNode { |
||||
|
public: |
||||
|
JSONObject obj() { |
||||
|
if (type == OBJECT) |
||||
|
return *values.object; |
||||
|
throw std::logic_error("Improper return"); |
||||
|
} |
||||
|
JSONList lst() { |
||||
|
if (type == LIST) |
||||
|
return *values.list; |
||||
|
throw std::logic_error("Improper return"); |
||||
|
} |
||||
|
string str() { |
||||
|
if (type == STRING) |
||||
|
return *values.str; |
||||
|
throw std::logic_error("Improper return"); |
||||
|
} |
||||
|
int nbr() { |
||||
|
if (type == NUMBER) |
||||
|
return values.nbr; |
||||
|
throw std::logic_error("Improper return"); |
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
enum Type { OBJECT, LIST, STRING, NUMBER, BOOLEAN, NULL_TYPE }; |
||||
|
union Values { |
||||
|
JSONObject *object; |
||||
|
JSONList *list; |
||||
|
string *str; |
||||
|
int nbr; |
||||
|
bool bValue; |
||||
|
} values; |
||||
|
Type type; |
||||
|
|
||||
|
void setObject(JSONObject *object) { |
||||
|
this->values.object = object; |
||||
|
type = OBJECT; |
||||
|
} |
||||
|
void setList(JSONList *list) { |
||||
|
this->values.list = list; |
||||
|
type = LIST; |
||||
|
} |
||||
|
void setString(string *str) { |
||||
|
this->values.str = str; |
||||
|
type = STRING; |
||||
|
} |
||||
|
void setNumber(int nbr) { |
||||
|
this->values.nbr = nbr; |
||||
|
type = NUMBER; |
||||
|
} |
||||
|
void setBoolean(bool v) { |
||||
|
this->values.bValue = v; |
||||
|
type = BOOLEAN; |
||||
|
} |
||||
|
void setNull() { type = NULL_TYPE; } |
||||
|
|
||||
|
string stringify(int indentationLevel) { |
||||
|
string spaceString = string(indentationLevel, ' '); |
||||
|
// sstreams
|
||||
|
std::stringstream output; |
||||
|
// cout < type << "\n";
|
||||
|
switch (type) { |
||||
|
case STRING: { |
||||
|
output << spaceString << *values.str; |
||||
|
break; |
||||
|
} |
||||
|
case NUMBER: { |
||||
|
output << spaceString << values.nbr; |
||||
|
break; |
||||
|
} |
||||
|
case BOOLEAN: { |
||||
|
output << spaceString << (values.bValue ? "true" : "false"); |
||||
|
break; |
||||
|
} |
||||
|
case NULL_TYPE: { |
||||
|
output << spaceString << "null"; |
||||
|
break; |
||||
|
} |
||||
|
case LIST: { |
||||
|
// cout << "[";
|
||||
|
output << spaceString << "[\n"; |
||||
|
unsigned int index = 0; |
||||
|
for (JSONList::iterator i = (*values.list).begin(); |
||||
|
i != (*values.list).end(); i++) { |
||||
|
output << (*i)->stringify(indentationLevel + 1); |
||||
|
if (index < (*values.list).size() - 1) { |
||||
|
output << ",\n"; |
||||
|
} |
||||
|
index++; |
||||
|
}; |
||||
|
output << "\n" << spaceString << "]\n"; |
||||
|
break; |
||||
|
} |
||||
|
case OBJECT: { |
||||
|
output << spaceString << "{\n"; |
||||
|
for (JSONObject::iterator i = (*values.object).begin(); |
||||
|
i != (*values.object).end(); i++) { |
||||
|
output << spaceString << " " |
||||
|
<< "\"" << i->first << "\"" |
||||
|
<< ": "; |
||||
|
output << i->second->stringify(indentationLevel + 1); |
||||
|
JSONObject::iterator next = i; |
||||
|
next++; |
||||
|
if ((next) != (*values.object).end()) { |
||||
|
output << ",\n"; |
||||
|
} |
||||
|
output << spaceString << "\n"; |
||||
|
} |
||||
|
output << spaceString << "}"; |
||||
|
return output.str(); |
||||
|
} |
||||
|
} |
||||
|
return output.str(); |
||||
|
} |
||||
|
friend class JSONParser; |
||||
|
}; |
@ -0,0 +1,213 @@ |
|||||
|
#include "Token.hpp" |
||||
|
#include <cstdlib> |
||||
|
|
||||
|
class JSONParser { |
||||
|
std::fstream file; |
||||
|
JSONNode *root; |
||||
|
JSONNode *current; |
||||
|
Tokenizer tokenizer; |
||||
|
|
||||
|
public: |
||||
|
JSONParser(const string filename) : tokenizer(filename) {} |
||||
|
JSONNode *parse() { |
||||
|
string key = ""; |
||||
|
JSONNode *parsed; |
||||
|
while (tokenizer.hasMoreTokens()) { |
||||
|
Token token; |
||||
|
try { |
||||
|
token = tokenizer.getToken(); |
||||
|
switch (token.type) { |
||||
|
case CURLY_OPEN: { |
||||
|
parsed = parseObject(); |
||||
|
break; |
||||
|
} |
||||
|
case ARRAY_OPEN: { |
||||
|
parsed = parseList(); |
||||
|
break; |
||||
|
} |
||||
|
case STRING: { |
||||
|
tokenizer.rollBackToken(); |
||||
|
parsed = parseString(); |
||||
|
break; |
||||
|
} |
||||
|
case NUMBER: { |
||||
|
tokenizer.rollBackToken(); |
||||
|
parsed = parseNumber(); |
||||
|
break; |
||||
|
} |
||||
|
case BOOLEAN: { |
||||
|
tokenizer.rollBackToken(); |
||||
|
parsed = parseBoolean(); |
||||
|
break; |
||||
|
} |
||||
|
default: |
||||
|
break; |
||||
|
} |
||||
|
} catch (std::logic_error &e) { |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
return parsed; |
||||
|
} |
||||
|
|
||||
|
JSONNode *parseObject() { |
||||
|
JSONNode *node = new JSONNode; |
||||
|
JSONObject *keyObjectMap = new JSONObject; |
||||
|
while (1) { |
||||
|
if (tokenizer.hasMoreTokens()) { |
||||
|
Token token = tokenizer.getToken(); |
||||
|
string key = token.value; |
||||
|
tokenizer.getToken(); |
||||
|
token = tokenizer.getToken(); |
||||
|
switch (token.type) { |
||||
|
case CURLY_OPEN: { |
||||
|
if (DEBUG) |
||||
|
cout << "=object=|" << key << "|===>>\n"; |
||||
|
(*keyObjectMap)[key] = parseObject(); |
||||
|
if (DEBUG) |
||||
|
cout << "<<===end object\n"; |
||||
|
break; |
||||
|
} |
||||
|
case ARRAY_OPEN: { |
||||
|
if (DEBUG) |
||||
|
cout << "-list-|" << key << "|--->>\n"; |
||||
|
(*keyObjectMap)[key] = parseList(); |
||||
|
if (DEBUG) |
||||
|
cout << "<<---end list\n"; |
||||
|
break; |
||||
|
} |
||||
|
case STRING: { |
||||
|
tokenizer.rollBackToken(); |
||||
|
(*keyObjectMap)[key] = parseString(); |
||||
|
if (DEBUG) |
||||
|
cout << key << "='" << (*keyObjectMap)[key]->str() |
||||
|
<< "'\n"; |
||||
|
break; |
||||
|
} |
||||
|
case NUMBER: { |
||||
|
tokenizer.rollBackToken(); |
||||
|
(*keyObjectMap)[key] = parseNumber(); |
||||
|
if (DEBUG) |
||||
|
cout << key << "=" << (*keyObjectMap)[key]->nbr() |
||||
|
<< "\n"; |
||||
|
break; |
||||
|
} |
||||
|
case BOOLEAN: { |
||||
|
tokenizer.rollBackToken(); |
||||
|
(*keyObjectMap)[key] = parseBoolean(); |
||||
|
if (DEBUG) |
||||
|
cout << key << "(BOOL)\n"; |
||||
|
break; |
||||
|
} |
||||
|
case NULL_TYPE: { |
||||
|
(*keyObjectMap)[key] = parseNull(); |
||||
|
break; |
||||
|
} |
||||
|
default: |
||||
|
break; |
||||
|
} |
||||
|
token = tokenizer.getToken(); |
||||
|
if (token.type == CURLY_CLOSE) |
||||
|
break; |
||||
|
|
||||
|
} else { |
||||
|
throw std::logic_error("No more tokens"); |
||||
|
} |
||||
|
} |
||||
|
node->setObject(keyObjectMap); |
||||
|
return node; |
||||
|
} |
||||
|
|
||||
|
JSONNode *parseList() { |
||||
|
JSONNode *node = new JSONNode(); |
||||
|
JSONList *list = new JSONList(); |
||||
|
bool hasCompleted = false; |
||||
|
while (!hasCompleted) { |
||||
|
if (!tokenizer.hasMoreTokens()) { |
||||
|
throw std::logic_error("No more tokens"); |
||||
|
} else { |
||||
|
Token token = tokenizer.getToken(); |
||||
|
JSONNode *subNode; |
||||
|
switch (token.type) { |
||||
|
case CURLY_OPEN: { |
||||
|
if (DEBUG) |
||||
|
cout << "=object===>>\n"; |
||||
|
subNode = parseObject(); |
||||
|
if (DEBUG) |
||||
|
cout << "<<===end object\n"; |
||||
|
break; |
||||
|
} |
||||
|
case ARRAY_OPEN: { |
||||
|
if (DEBUG) |
||||
|
cout << "-list--->>\n"; |
||||
|
subNode = parseList(); |
||||
|
if (DEBUG) |
||||
|
cout << "<<---end list\n"; |
||||
|
break; |
||||
|
} |
||||
|
case STRING: { |
||||
|
tokenizer.rollBackToken(); |
||||
|
subNode = parseString(); |
||||
|
if (DEBUG) |
||||
|
cout << "|'" << subNode->str() << "'"; |
||||
|
break; |
||||
|
} |
||||
|
case NUMBER: { |
||||
|
tokenizer.rollBackToken(); |
||||
|
subNode = parseNumber(); |
||||
|
if (DEBUG) |
||||
|
cout << "|" << subNode->nbr(); |
||||
|
break; |
||||
|
} |
||||
|
case BOOLEAN: { |
||||
|
tokenizer.rollBackToken(); |
||||
|
subNode = parseBoolean(); |
||||
|
break; |
||||
|
} |
||||
|
case NULL_TYPE: { |
||||
|
subNode = parseNull(); |
||||
|
break; |
||||
|
} |
||||
|
default: |
||||
|
break; |
||||
|
} |
||||
|
list->push_back(subNode); |
||||
|
token = tokenizer.getToken(); |
||||
|
if (token.type == ARRAY_CLOSE) { |
||||
|
hasCompleted = true; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
node->setList(list); |
||||
|
return node; |
||||
|
} |
||||
|
|
||||
|
JSONNode *parseString() { |
||||
|
JSONNode *node = new JSONNode(); |
||||
|
Token token = tokenizer.getToken(); |
||||
|
string *sValue = new string(token.value); |
||||
|
node->setString(sValue); |
||||
|
return node; |
||||
|
} |
||||
|
|
||||
|
JSONNode *parseNumber() { |
||||
|
JSONNode *node = new JSONNode(); |
||||
|
Token token = tokenizer.getToken(); |
||||
|
string value = token.value; |
||||
|
int nbr = std::atoi(value.c_str()); |
||||
|
node->setNumber(nbr); |
||||
|
return node; |
||||
|
} |
||||
|
JSONNode *parseBoolean() { |
||||
|
JSONNode *node = new JSONNode(); |
||||
|
Token token = tokenizer.getToken(); |
||||
|
node->setBoolean(token.value == "True" ? true : false); |
||||
|
return node; |
||||
|
} |
||||
|
|
||||
|
JSONNode *parseNull() { |
||||
|
JSONNode *node = new JSONNode(); |
||||
|
node->setNull(); |
||||
|
return node; |
||||
|
} |
||||
|
}; |
@ -0,0 +1,159 @@ |
|||||
|
#include "Nodes.hpp" |
||||
|
#include <fstream> |
||||
|
|
||||
|
enum TOKEN { |
||||
|
CURLY_OPEN, |
||||
|
CURLY_CLOSE, |
||||
|
COLON, |
||||
|
STRING, |
||||
|
NUMBER, |
||||
|
ARRAY_OPEN, |
||||
|
ARRAY_CLOSE, |
||||
|
COMMA, |
||||
|
BOOLEAN, |
||||
|
NULL_TYPE |
||||
|
}; |
||||
|
|
||||
|
typedef struct Token_s { |
||||
|
string value; |
||||
|
TOKEN type; |
||||
|
string toString() { |
||||
|
switch (type) { |
||||
|
case CURLY_OPEN: { |
||||
|
return "Curly open"; |
||||
|
} |
||||
|
case CURLY_CLOSE: { |
||||
|
return "Curly close"; |
||||
|
} |
||||
|
case COLON: { |
||||
|
return "COLON"; |
||||
|
} |
||||
|
case NUMBER: { |
||||
|
return "Number: " + value; |
||||
|
} |
||||
|
case STRING: { |
||||
|
return "String: " + value; |
||||
|
} |
||||
|
|
||||
|
case ARRAY_OPEN: { |
||||
|
return "Array open"; |
||||
|
} |
||||
|
case ARRAY_CLOSE: { |
||||
|
return "Array close"; |
||||
|
} |
||||
|
case COMMA: { |
||||
|
return "Comma"; |
||||
|
} |
||||
|
case BOOLEAN: { |
||||
|
return "Boolean: " + value; |
||||
|
} |
||||
|
|
||||
|
case NULL_TYPE: { |
||||
|
return "Null"; |
||||
|
} |
||||
|
default: |
||||
|
return "Other..."; |
||||
|
} |
||||
|
} |
||||
|
} Token; |
||||
|
|
||||
|
class Tokenizer { |
||||
|
std::fstream file; |
||||
|
size_t prevPos; |
||||
|
|
||||
|
public: |
||||
|
Tokenizer(string fileName) { |
||||
|
file.open(fileName.c_str(), std::ios::in); |
||||
|
if (!file.good()) |
||||
|
cout << "File open error" |
||||
|
<< "\n"; |
||||
|
}; |
||||
|
bool hasMoreTokens() { return !file.eof(); } |
||||
|
char getWithoutWhiteSpace() { |
||||
|
char c = ' '; |
||||
|
while ((c == ' ' || c == '\n') || c == '\t') { |
||||
|
file.get(c); // check
|
||||
|
|
||||
|
if ((c == ' ' || c == '\n') && !file.good()) { |
||||
|
// cout << file.eof() << " " << file.fail() << "\n";
|
||||
|
throw std::logic_error("Ran out of tokens"); |
||||
|
} else if (!file.good()) { |
||||
|
return c; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return c; |
||||
|
}; |
||||
|
void rollBackToken() { |
||||
|
if (file.eof()) |
||||
|
file.clear(); |
||||
|
file.seekg(prevPos); |
||||
|
}; |
||||
|
Token getToken() { |
||||
|
char c; |
||||
|
if (file.eof()) { |
||||
|
cout << "Exhaused tokens" |
||||
|
<< "\n"; |
||||
|
// throw std::exception("Exhausted tokens");
|
||||
|
} |
||||
|
prevPos = file.tellg(); |
||||
|
c = getWithoutWhiteSpace(); |
||||
|
|
||||
|
Token token; |
||||
|
token.type = NULL_TYPE; |
||||
|
if (c == '"') { |
||||
|
token.type = STRING; |
||||
|
token.value = ""; |
||||
|
file.get(c); |
||||
|
while (c != '"') { |
||||
|
token.value += c; |
||||
|
file.get(c); |
||||
|
} |
||||
|
} else if (c == '{') { |
||||
|
token.type = CURLY_OPEN; |
||||
|
} else if (c == '}') { |
||||
|
token.type = CURLY_CLOSE; |
||||
|
} else if (c == '-' || (c >= '0' && c <= '9')) { |
||||
|
// Check if string is numeric
|
||||
|
token.type = NUMBER; |
||||
|
token.value = ""; |
||||
|
token.value += c; |
||||
|
std::streampos prevCharPos = file.tellg(); |
||||
|
while ((c == '-') || (c >= '0' && c <= '9') || c == '.') { |
||||
|
prevCharPos = file.tellg(); |
||||
|
file.get(c); |
||||
|
|
||||
|
if (file.eof()) { |
||||
|
break; |
||||
|
} else { |
||||
|
if ((c == '-') || (c >= '0' && c <= '9') || (c == '.')) { |
||||
|
token.value += c; |
||||
|
} else { |
||||
|
file.seekg(prevCharPos); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} else if (c == 'f') { |
||||
|
token.type = BOOLEAN; |
||||
|
token.value = "False"; |
||||
|
file.seekg(4, std::ios_base::cur); |
||||
|
} else if (c == 't') { |
||||
|
token.type = BOOLEAN; |
||||
|
token.value = "True"; |
||||
|
file.seekg(3, std::ios_base::cur); |
||||
|
} else if (c == 'n') { |
||||
|
token.type = NULL_TYPE; |
||||
|
file.seekg(3, std::ios_base::cur); |
||||
|
} else if (c == '[') { |
||||
|
token.type = ARRAY_OPEN; |
||||
|
} else if (c == ']') { |
||||
|
token.type = ARRAY_CLOSE; |
||||
|
} else if (c == ':') { |
||||
|
token.type = COLON; |
||||
|
} else if (c == ',') { |
||||
|
token.type = COMMA; |
||||
|
} |
||||
|
// cout << token.type << " : " << token.value << "\n";
|
||||
|
return token; |
||||
|
}; |
||||
|
}; |
@ -1,3 +0,0 @@ |
|||||
#include "server.hpp" |
|
||||
|
|
||||
|
|
@ -1,37 +0,0 @@ |
|||||
#pragma once |
|
||||
|
|
||||
#include <arpa/inet.h> |
|
||||
#include <fcntl.h> |
|
||||
#include <netinet/in.h> |
|
||||
#include <sys/socket.h> |
|
||||
#include <sys/types.h> |
|
||||
#include <sys/time.h> //FD_SET, FD_ISSET, FD_ZERO macros |
|
||||
#include <unistd.h> |
|
||||
|
|
||||
#include <cerrno> |
|
||||
#include <cstring> |
|
||||
#include <fstream> |
|
||||
#include <iostream> |
|
||||
#include <string> |
|
||||
#include <vector> |
|
||||
|
|
||||
class Route { |
|
||||
std::string _location; |
|
||||
std::string _root; |
|
||||
std::string _index; |
|
||||
public: |
|
||||
Route(std::string location, std::string root, std::string index); |
|
||||
~Route(); |
|
||||
}; |
|
||||
|
|
||||
class Server { |
|
||||
unsigned int _port; |
|
||||
std::string _server_name; |
|
||||
std::vector<Route> _routes; |
|
||||
public: |
|
||||
Server(char *filename); |
|
||||
~Server(); |
|
||||
}; |
|
||||
|
|
||||
void *ft_memset(void *b, int c, size_t len); |
|
||||
|
|
Binary file not shown.
Binary file not shown.
@ -0,0 +1 @@ |
|||||
|
#include "webserv.hpp" |
@ -0,0 +1,49 @@ |
|||||
|
#pragma once |
||||
|
#include "conf_parser/Parser.hpp" |
||||
|
|
||||
|
#include <arpa/inet.h> |
||||
|
#include <fcntl.h> |
||||
|
#include <netinet/in.h> |
||||
|
#include <sys/socket.h> |
||||
|
#include <sys/time.h> //FD_SET, FD_ISSET, FD_ZERO macros |
||||
|
#include <sys/types.h> |
||||
|
#include <unistd.h> |
||||
|
|
||||
|
#include <cerrno> |
||||
|
#include <cstdio> |
||||
|
#include <cstdlib> |
||||
|
#include <cstring> |
||||
|
#include <fstream> |
||||
|
#include <iostream> |
||||
|
#include <sstream> |
||||
|
#include <string> |
||||
|
#include <vector> |
||||
|
|
||||
|
class Route { |
||||
|
std::vector<std::string> _location; |
||||
|
std::vector<std::string> _index; |
||||
|
std::string _root; |
||||
|
|
||||
|
public: |
||||
|
Route(std::string location, std::string root, std::string index); |
||||
|
~Route(); |
||||
|
}; |
||||
|
|
||||
|
class Server { |
||||
|
unsigned int _port; |
||||
|
std::string _server_name; |
||||
|
std::vector<Route> *_routes; |
||||
|
|
||||
|
public: |
||||
|
Server(std::string name, std::string root, std::string return, |
||||
|
JSONNode *listens, JSONNode *indexs, JSONNode *locations); |
||||
|
~Server(); |
||||
|
}; |
||||
|
|
||||
|
class Env { |
||||
|
public: |
||||
|
std::vector<Server> *servers; |
||||
|
int max_clients; |
||||
|
}; |
||||
|
|
||||
|
void *ft_memset(void *b, int c, size_t len); |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in new issue