redsnow 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +34 -0
- data/.gitmodules +3 -0
- data/.travis.yml +20 -0
- data/CHANGELOG.md +4 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +62 -0
- data/Rakefile +36 -0
- data/Vagrantfile +20 -0
- data/ext/snowcrash/Makefile +64 -0
- data/ext/snowcrash/Vagrantfile +20 -0
- data/ext/snowcrash/bin/snowcrash +0 -0
- data/ext/snowcrash/common.gypi +163 -0
- data/ext/snowcrash/config.gypi +10 -0
- data/ext/snowcrash/config.mk +5 -0
- data/ext/snowcrash/configure +213 -0
- data/ext/snowcrash/provisioning.sh +15 -0
- data/ext/snowcrash/snowcrash.gyp +141 -0
- data/ext/snowcrash/src/ActionParser.h +503 -0
- data/ext/snowcrash/src/AssetParser.h +215 -0
- data/ext/snowcrash/src/BlockUtility.h +186 -0
- data/ext/snowcrash/src/Blueprint.h +283 -0
- data/ext/snowcrash/src/BlueprintParser.h +347 -0
- data/ext/snowcrash/src/BlueprintParserCore.h +190 -0
- data/ext/snowcrash/src/BlueprintSection.h +140 -0
- data/ext/snowcrash/src/BlueprintUtility.h +126 -0
- data/ext/snowcrash/src/CBlueprint.cc +600 -0
- data/ext/snowcrash/src/CBlueprint.h +354 -0
- data/ext/snowcrash/src/CSourceAnnotation.cc +140 -0
- data/ext/snowcrash/src/CSourceAnnotation.h +106 -0
- data/ext/snowcrash/src/CodeBlockUtility.h +189 -0
- data/ext/snowcrash/src/DescriptionSectionUtility.h +156 -0
- data/ext/snowcrash/src/HTTP.cc +46 -0
- data/ext/snowcrash/src/HTTP.h +105 -0
- data/ext/snowcrash/src/HeaderParser.h +289 -0
- data/ext/snowcrash/src/ListBlockUtility.h +273 -0
- data/ext/snowcrash/src/ListUtility.h +95 -0
- data/ext/snowcrash/src/MarkdownBlock.cc +176 -0
- data/ext/snowcrash/src/MarkdownBlock.h +93 -0
- data/ext/snowcrash/src/MarkdownParser.cc +266 -0
- data/ext/snowcrash/src/MarkdownParser.h +88 -0
- data/ext/snowcrash/src/ParameterDefinitonParser.h +570 -0
- data/ext/snowcrash/src/ParametersParser.h +252 -0
- data/ext/snowcrash/src/Parser.cc +71 -0
- data/ext/snowcrash/src/Parser.h +29 -0
- data/ext/snowcrash/src/ParserCore.cc +120 -0
- data/ext/snowcrash/src/ParserCore.h +82 -0
- data/ext/snowcrash/src/PayloadParser.h +672 -0
- data/ext/snowcrash/src/Platform.h +54 -0
- data/ext/snowcrash/src/RegexMatch.h +32 -0
- data/ext/snowcrash/src/ResourceGroupParser.h +195 -0
- data/ext/snowcrash/src/ResourceParser.h +584 -0
- data/ext/snowcrash/src/SectionUtility.h +142 -0
- data/ext/snowcrash/src/Serialize.cc +52 -0
- data/ext/snowcrash/src/Serialize.h +69 -0
- data/ext/snowcrash/src/SerializeJSON.cc +601 -0
- data/ext/snowcrash/src/SerializeJSON.h +21 -0
- data/ext/snowcrash/src/SerializeYAML.cc +336 -0
- data/ext/snowcrash/src/SerializeYAML.h +21 -0
- data/ext/snowcrash/src/SourceAnnotation.h +177 -0
- data/ext/snowcrash/src/StringUtility.h +109 -0
- data/ext/snowcrash/src/SymbolTable.h +83 -0
- data/ext/snowcrash/src/UriTemplateParser.cc +195 -0
- data/ext/snowcrash/src/UriTemplateParser.h +243 -0
- data/ext/snowcrash/src/Version.h +39 -0
- data/ext/snowcrash/src/csnowcrash.cc +23 -0
- data/ext/snowcrash/src/csnowcrash.h +38 -0
- data/ext/snowcrash/src/posix/RegexMatch.cc +99 -0
- data/ext/snowcrash/src/snowcrash.cc +18 -0
- data/ext/snowcrash/src/snowcrash.h +41 -0
- data/ext/snowcrash/src/snowcrash/snowcrash.cc +170 -0
- data/ext/snowcrash/src/win/RegexMatch.cc +78 -0
- data/ext/snowcrash/sundown/CONTRIBUTING.md +10 -0
- data/ext/snowcrash/sundown/Makefile +83 -0
- data/ext/snowcrash/sundown/Makefile.win +33 -0
- data/ext/snowcrash/sundown/examples/smartypants.c +72 -0
- data/ext/snowcrash/sundown/examples/sundown.c +80 -0
- data/ext/snowcrash/sundown/html/houdini.h +37 -0
- data/ext/snowcrash/sundown/html/houdini_href_e.c +108 -0
- data/ext/snowcrash/sundown/html/houdini_html_e.c +84 -0
- data/ext/snowcrash/sundown/html/html.c +647 -0
- data/ext/snowcrash/sundown/html/html.h +77 -0
- data/ext/snowcrash/sundown/html/html_smartypants.c +389 -0
- data/ext/snowcrash/sundown/html_block_names.txt +25 -0
- data/ext/snowcrash/sundown/src/autolink.c +297 -0
- data/ext/snowcrash/sundown/src/autolink.h +51 -0
- data/ext/snowcrash/sundown/src/buffer.c +225 -0
- data/ext/snowcrash/sundown/src/buffer.h +96 -0
- data/ext/snowcrash/sundown/src/html_blocks.h +206 -0
- data/ext/snowcrash/sundown/src/markdown.c +2701 -0
- data/ext/snowcrash/sundown/src/markdown.h +147 -0
- data/ext/snowcrash/sundown/src/src_map.c +200 -0
- data/ext/snowcrash/sundown/src/src_map.h +58 -0
- data/ext/snowcrash/sundown/src/stack.c +81 -0
- data/ext/snowcrash/sundown/src/stack.h +29 -0
- data/ext/snowcrash/sundown/sundown.def +20 -0
- data/ext/snowcrash/tools/gyp/AUTHORS +11 -0
- data/ext/snowcrash/tools/gyp/DEPS +24 -0
- data/ext/snowcrash/tools/gyp/OWNERS +1 -0
- data/ext/snowcrash/tools/gyp/PRESUBMIT.py +120 -0
- data/ext/snowcrash/tools/gyp/buildbot/buildbot_run.py +190 -0
- data/ext/snowcrash/tools/gyp/codereview.settings +10 -0
- data/ext/snowcrash/tools/gyp/data/win/large-pdb-shim.cc +12 -0
- data/ext/snowcrash/tools/gyp/gyp +8 -0
- data/ext/snowcrash/tools/gyp/gyp.bat +5 -0
- data/ext/snowcrash/tools/gyp/gyp_main.py +18 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSNew.py +340 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSProject.py +208 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSSettings.py +1063 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSToolFile.py +58 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSUserFile.py +147 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSUtil.py +267 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSVersion.py +409 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/__init__.py +537 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/__init__.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/common.py +521 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/common.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/easy_xml.py +157 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/flock_tool.py +49 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/__init__.py +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/__init__.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/android.py +1069 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/cmake.py +1143 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/dump_dependency_json.py +81 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/eclipse.py +335 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/gypd.py +87 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/gypsh.py +56 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/make.py +2181 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/make.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/msvs.py +3335 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/ninja.py +2156 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/xcode.py +1224 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/xcode.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/input.py +2809 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/input.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/mac_tool.py +510 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/msvs_emulation.py +972 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/ninja_syntax.py +160 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/ordered_dict.py +289 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/win_tool.py +292 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/xcode_emulation.py +1440 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/xcode_emulation.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/xcodeproj_file.py +2889 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/xcodeproj_file.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/xml_fix.py +69 -0
- data/ext/snowcrash/tools/gyp/pylintrc +307 -0
- data/ext/snowcrash/tools/gyp/samples/samples +81 -0
- data/ext/snowcrash/tools/gyp/samples/samples.bat +5 -0
- data/ext/snowcrash/tools/gyp/setup.py +19 -0
- data/ext/snowcrash/tools/gyp/tools/Xcode/Specifications/gyp.pbfilespec +27 -0
- data/ext/snowcrash/tools/gyp/tools/Xcode/Specifications/gyp.xclangspec +226 -0
- data/ext/snowcrash/tools/gyp/tools/emacs/gyp.el +252 -0
- data/ext/snowcrash/tools/gyp/tools/graphviz.py +100 -0
- data/ext/snowcrash/tools/gyp/tools/pretty_gyp.py +155 -0
- data/ext/snowcrash/tools/gyp/tools/pretty_sln.py +168 -0
- data/ext/snowcrash/tools/gyp/tools/pretty_vcproj.py +329 -0
- data/ext/snowcrash/tools/homebrew/snowcrash.rb +11 -0
- data/ext/snowcrash/vcbuild.bat +184 -0
- data/lib/redsnow.rb +31 -0
- data/lib/redsnow/binding.rb +132 -0
- data/lib/redsnow/blueprint.rb +365 -0
- data/lib/redsnow/object.rb +18 -0
- data/lib/redsnow/parseresult.rb +107 -0
- data/lib/redsnow/version.rb +4 -0
- data/provisioning.sh +20 -0
- data/redsnow.gemspec +35 -0
- data/test/_helper.rb +15 -0
- data/test/fixtures/sample-api-ast.json +97 -0
- data/test/fixtures/sample-api.apib +20 -0
- data/test/redsnow_binding_test.rb +35 -0
- data/test/redsnow_parseresult_test.rb +50 -0
- data/test/redsnow_test.rb +285 -0
- metadata +358 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
//
|
|
2
|
+
// TrimString.h
|
|
3
|
+
// snowcrash
|
|
4
|
+
//
|
|
5
|
+
// Created by Zdenek Nemec on 5/11/13.
|
|
6
|
+
// Copyright (c) 2013 Apiary Inc. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
// Credits:
|
|
9
|
+
// http://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring
|
|
10
|
+
|
|
11
|
+
#ifndef SNOWCRAH_TRIMSTRING_H
|
|
12
|
+
#define SNOWCRAH_TRIMSTRING_H
|
|
13
|
+
|
|
14
|
+
#include <algorithm>
|
|
15
|
+
#include <functional>
|
|
16
|
+
#include <cctype>
|
|
17
|
+
#include <locale>
|
|
18
|
+
#include <string>
|
|
19
|
+
#include <sstream>
|
|
20
|
+
#include <vector>
|
|
21
|
+
|
|
22
|
+
namespace snowcrash {
|
|
23
|
+
|
|
24
|
+
// Check a character not to be an space of any kind
|
|
25
|
+
inline bool isSpace(const std::string::value_type i){
|
|
26
|
+
if(i == ' ' || i == '\t' || i == '\n' || i == '\v' || i == '\f' || i == '\r')
|
|
27
|
+
return true;
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Trim string from start
|
|
32
|
+
inline std::string& TrimStringStart(std::string &s) {
|
|
33
|
+
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(isSpace))));
|
|
34
|
+
return s;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Trim string from end
|
|
38
|
+
inline std::string& TrimStringEnd(std::string &s) {
|
|
39
|
+
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(isSpace))).base(), s.end());
|
|
40
|
+
return s;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Trim both ends of string
|
|
44
|
+
inline std::string& TrimString(std::string &s) {
|
|
45
|
+
return TrimStringStart(TrimStringEnd(s));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Retrieve first line of given string
|
|
49
|
+
inline std::string GetFirstLine(const std::string& s) {
|
|
50
|
+
std::string::size_type pos = s.find("\n");
|
|
51
|
+
if (pos == std::string::npos)
|
|
52
|
+
return s;
|
|
53
|
+
else
|
|
54
|
+
return s.substr(0, pos);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Split string by delim
|
|
58
|
+
inline std::vector<std::string>& Split(const std::string& s, char delim, std::vector<std::string>& elems) {
|
|
59
|
+
std::stringstream ss(s);
|
|
60
|
+
std::string item;
|
|
61
|
+
while (std::getline(ss, item, delim)) {
|
|
62
|
+
elems.push_back(item);
|
|
63
|
+
}
|
|
64
|
+
return elems;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Split string by delim
|
|
68
|
+
inline std::vector<std::string> Split(const std::string& s, char delim) {
|
|
69
|
+
std::vector<std::string> elems;
|
|
70
|
+
Split(s, delim, elems);
|
|
71
|
+
return elems;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Split string on the first occurrence of delim
|
|
75
|
+
inline std::vector<std::string> SplitOnFirst(const std::string& s, char delim) {
|
|
76
|
+
std::string::size_type pos = s.find(delim);
|
|
77
|
+
std::vector<std::string> elems;
|
|
78
|
+
if (pos == std::string::npos) {
|
|
79
|
+
elems.push_back(s);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
elems.push_back(s.substr(0, pos));
|
|
83
|
+
elems.push_back(s.substr(pos + 1, std::string::npos));
|
|
84
|
+
}
|
|
85
|
+
return elems;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* \brief Replace all occurrences of a string.
|
|
91
|
+
* \param s A string to search in.
|
|
92
|
+
* \param find A string to look for.
|
|
93
|
+
* \param replace A string to replace with.
|
|
94
|
+
* \return A copy of %s with all occurrences of %find replaced by %replace.
|
|
95
|
+
*/
|
|
96
|
+
inline std::string ReplaceString(const std::string& s,
|
|
97
|
+
const std::string& find,
|
|
98
|
+
const std::string& replace) {
|
|
99
|
+
size_t pos = 0;
|
|
100
|
+
std::string target(s);
|
|
101
|
+
while ((pos = target.find(find, pos)) != std::string::npos) {
|
|
102
|
+
target.replace(pos, find.length(), replace);
|
|
103
|
+
pos += replace.length();
|
|
104
|
+
}
|
|
105
|
+
return target;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
#endif
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
//
|
|
2
|
+
// SymbolTable.h
|
|
3
|
+
// snowcrash
|
|
4
|
+
//
|
|
5
|
+
// Created by Zdenek Nemec on 6/9/13.
|
|
6
|
+
// Copyright (c) 2013 Apiary Inc. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
#ifndef SNOWCRASH_SYMBOLTABLE_H
|
|
10
|
+
#define SNOWCRASH_SYMBOLTABLE_H
|
|
11
|
+
|
|
12
|
+
#include <string>
|
|
13
|
+
#include <map>
|
|
14
|
+
#include "RegexMatch.h"
|
|
15
|
+
|
|
16
|
+
#ifdef DEBUG
|
|
17
|
+
#include <iostream>
|
|
18
|
+
#include "Serialize.h"
|
|
19
|
+
#endif
|
|
20
|
+
|
|
21
|
+
#include "Blueprint.h"
|
|
22
|
+
#include "StringUtility.h"
|
|
23
|
+
|
|
24
|
+
// Symbol identifier regex
|
|
25
|
+
#define SYMBOL_IDENTIFIER "([^][()]+)"
|
|
26
|
+
|
|
27
|
+
namespace snowcrashconst {
|
|
28
|
+
|
|
29
|
+
/** Symbol reference matching regex */
|
|
30
|
+
const char* const SymbolReferenceRegex("^[[:blank:]]*\\[" SYMBOL_IDENTIFIER "]\\[][[:blank:]]*$");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
namespace snowcrash {
|
|
34
|
+
|
|
35
|
+
// Name of a symbol
|
|
36
|
+
typedef SourceData SymbolName;
|
|
37
|
+
|
|
38
|
+
// Resource Object Symbol
|
|
39
|
+
typedef std::pair<SymbolName, ResourceModel> ResourceModelSymbol;
|
|
40
|
+
|
|
41
|
+
// Resource Object Symbol Table
|
|
42
|
+
typedef std::map<SymbolName, ResourceModel> ResourceModelSymbolTable;
|
|
43
|
+
|
|
44
|
+
struct SymbolTable {
|
|
45
|
+
|
|
46
|
+
// Resource Object Symbol Table
|
|
47
|
+
ResourceModelSymbolTable resourceModels;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
// Checks whether given source data represents reference to a symbol returning true if so,
|
|
52
|
+
// false otherwise. If source data is represent reference referred symbol name is filled in.
|
|
53
|
+
FORCEINLINE bool GetSymbolReference(const SourceData& sourceData,
|
|
54
|
+
SymbolName& referredSymbol) {
|
|
55
|
+
|
|
56
|
+
CaptureGroups captureGroups;
|
|
57
|
+
if (RegexCapture(sourceData, snowcrashconst::SymbolReferenceRegex, captureGroups, 3)) {
|
|
58
|
+
referredSymbol = captureGroups[1];
|
|
59
|
+
TrimString(referredSymbol);
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
#ifdef DEBUG
|
|
66
|
+
// Prints markdown block recursively to stdout
|
|
67
|
+
FORCEINLINE void PrintSymbolTable(const SymbolTable& symbolTable) {
|
|
68
|
+
|
|
69
|
+
std::cout << "Resource Model Symbols:\n";
|
|
70
|
+
for (ResourceModelSymbolTable::const_iterator it = symbolTable.resourceModels.begin();
|
|
71
|
+
it != symbolTable.resourceModels.end();
|
|
72
|
+
++it) {
|
|
73
|
+
|
|
74
|
+
std::cout << "- " << it->first << " - body: '" << EscapeNewlines(it->second.body) << "'\n";
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
std::cout << std::endl;
|
|
78
|
+
}
|
|
79
|
+
#endif
|
|
80
|
+
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
#endif
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
//
|
|
2
|
+
// UriTemplateParser.cc
|
|
3
|
+
// snowcrash
|
|
4
|
+
//
|
|
5
|
+
// Created by Carl Griffiths on 24/02/14.
|
|
6
|
+
// Copyright (c) 2014 Apiary Inc. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
#include <iomanip>
|
|
9
|
+
#include "UriTemplateParser.h"
|
|
10
|
+
#include "RegexMatch.h"
|
|
11
|
+
|
|
12
|
+
using namespace snowcrash;
|
|
13
|
+
|
|
14
|
+
static bool HasMismatchedCurlyBrackets(const URITemplate& uriTemplate) {
|
|
15
|
+
int openCount = 0;
|
|
16
|
+
int closeCount = 0;
|
|
17
|
+
|
|
18
|
+
for (unsigned int i = 0; i < uriTemplate.length(); i++) {
|
|
19
|
+
if (uriTemplate[i] == '{') openCount++;
|
|
20
|
+
if (uriTemplate[i] == '}') closeCount++;
|
|
21
|
+
}
|
|
22
|
+
return openCount != closeCount;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
static bool HasNestedCurlyBrackets(const URITemplate& uriTemplate) {
|
|
26
|
+
char lastBracket = ' ';
|
|
27
|
+
bool result = false;
|
|
28
|
+
|
|
29
|
+
for (unsigned int i = 0; i < uriTemplate.length(); i++) {
|
|
30
|
+
if (uriTemplate[i] == '{') {
|
|
31
|
+
if (lastBracket == '{') {
|
|
32
|
+
result = true;
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
lastBracket = '{';
|
|
36
|
+
}
|
|
37
|
+
if (uriTemplate[i] == '}') {
|
|
38
|
+
if (lastBracket == '}') {
|
|
39
|
+
result = true;
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
lastBracket = '}';
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
static bool PathContainsSquareBrackets(const URITemplate& uriTemplate) {
|
|
49
|
+
return (uriTemplate.find('[') != std::string::npos || uriTemplate.find(']') != std::string::npos);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
static Expressions GetUriTemplateExpressions(const URITemplate& uriTemplate) {
|
|
53
|
+
Expressions expressions;
|
|
54
|
+
size_t expressionStartPos = 0;
|
|
55
|
+
size_t expressionEndPos = 0;
|
|
56
|
+
|
|
57
|
+
while (expressionStartPos != std::string::npos && expressionEndPos != std::string::npos && expressionStartPos < uriTemplate.length()) {
|
|
58
|
+
expressionStartPos = uriTemplate.find("{", expressionStartPos);
|
|
59
|
+
expressionEndPos = uriTemplate.find("}", expressionStartPos);
|
|
60
|
+
if (expressionStartPos != std::string::npos && expressionEndPos > expressionStartPos) {
|
|
61
|
+
expressions.push_back(uriTemplate.substr(expressionStartPos + 1, (expressionEndPos - expressionStartPos) - 1));
|
|
62
|
+
}
|
|
63
|
+
expressionStartPos++;
|
|
64
|
+
}
|
|
65
|
+
return expressions;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
static ClassifiedExpression ClassifyExpression(const Expression& expression) {
|
|
70
|
+
|
|
71
|
+
VariableExpression variableExpression(expression);
|
|
72
|
+
|
|
73
|
+
if (variableExpression.IsExpressionType()) {
|
|
74
|
+
return variableExpression;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
QueryStringExpression queryStringExpression(expression);
|
|
78
|
+
if (queryStringExpression.IsExpressionType()) {
|
|
79
|
+
return queryStringExpression;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
FragmentExpression fragmentExpression(expression);
|
|
83
|
+
if (fragmentExpression.IsExpressionType()) {
|
|
84
|
+
return fragmentExpression;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
ReservedExpansionExpression reservedExpansionExpression(expression);
|
|
88
|
+
if (reservedExpansionExpression.IsExpressionType()) {
|
|
89
|
+
return reservedExpansionExpression;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
LabelExpansionExpression labelExpansionExpression(expression);
|
|
93
|
+
if (labelExpansionExpression.IsExpressionType()) {
|
|
94
|
+
return labelExpansionExpression;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
PathSegmentExpansionExpression pathSegmentExpansionExpression(expression);
|
|
98
|
+
if (pathSegmentExpansionExpression.IsExpressionType()) {
|
|
99
|
+
return pathSegmentExpansionExpression;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
PathStyleParameterExpansionExpression pathStyleParameterExpansionExpression(expression);
|
|
103
|
+
if (pathStyleParameterExpansionExpression.IsExpressionType()) {
|
|
104
|
+
return pathSegmentExpansionExpression;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
FormStyleQueryContinuationExpression formStyleQueryContinuationExpression(expression);
|
|
108
|
+
if (formStyleQueryContinuationExpression.IsExpressionType()) {
|
|
109
|
+
return formStyleQueryContinuationExpression;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
UndefinedExpression undefinedExpression(expression);
|
|
113
|
+
|
|
114
|
+
return undefinedExpression;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
void URITemplateParser::parse(const URITemplate& uri, const SourceCharactersBlock& sourceBlock, ParsedURITemplate& result)
|
|
118
|
+
{
|
|
119
|
+
CaptureGroups groups;
|
|
120
|
+
Expressions expressions;
|
|
121
|
+
size_t gSize=5;
|
|
122
|
+
|
|
123
|
+
if (uri.empty()) return;
|
|
124
|
+
|
|
125
|
+
if (RegexCapture(uri, URI_REGEX, groups, gSize)) {
|
|
126
|
+
result.scheme = groups[1];
|
|
127
|
+
result.host = groups[3];
|
|
128
|
+
result.path = groups[4];
|
|
129
|
+
|
|
130
|
+
if (HasMismatchedCurlyBrackets(result.path)) {
|
|
131
|
+
result.result.warnings.push_back(Warning("The URI template contains mismatched expression brackets", URIWarning, sourceBlock));
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (HasNestedCurlyBrackets(result.path)) {
|
|
136
|
+
result.result.warnings.push_back(Warning("The URI template contains nested expression brackets", URIWarning, sourceBlock));
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (PathContainsSquareBrackets(result.path)) {
|
|
141
|
+
result.result.warnings.push_back(Warning("The URI template contains square brackets, please percent encode square brackets as %5B and %5D", URIWarning, sourceBlock));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
expressions = GetUriTemplateExpressions(result.path);
|
|
145
|
+
|
|
146
|
+
ExpressionIterator currentExpression = expressions.begin();
|
|
147
|
+
|
|
148
|
+
while (currentExpression != expressions.end()) {
|
|
149
|
+
|
|
150
|
+
ClassifiedExpression classifiedExpression = ClassifyExpression(*currentExpression);
|
|
151
|
+
|
|
152
|
+
if (classifiedExpression.IsSupportedExpressionType()) {
|
|
153
|
+
bool hasIllegalCharacters = false;
|
|
154
|
+
|
|
155
|
+
if (classifiedExpression.ContainsSpaces()) {
|
|
156
|
+
std::stringstream ss;
|
|
157
|
+
ss << "URI template expression \"" << classifiedExpression.innerExpression << "\" contains spaces. Allowed characters for expressions are A-Z a-z 0-9 _ and percent encoded characters";
|
|
158
|
+
result.result.warnings.push_back(Warning(ss.str(), URIWarning, sourceBlock));
|
|
159
|
+
hasIllegalCharacters = true;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (classifiedExpression.ContainsHyphens()) {
|
|
163
|
+
std::stringstream ss;
|
|
164
|
+
ss << "URI template expression \"" << classifiedExpression.innerExpression << "\" contains hyphens. Allowed characters for expressions are A-Z a-z 0-9 _ and percent encoded characters";
|
|
165
|
+
result.result.warnings.push_back(Warning(ss.str(), URIWarning, sourceBlock));
|
|
166
|
+
hasIllegalCharacters = true;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (classifiedExpression.ContainsAssignment()) {
|
|
170
|
+
std::stringstream ss;
|
|
171
|
+
ss << "URI template expression \"" << classifiedExpression.innerExpression << "\" contains assignment. Allowed characters for expressions are A-Z a-z 0-9 _ and percent encoded characters";
|
|
172
|
+
result.result.warnings.push_back(Warning(ss.str(), URIWarning, sourceBlock));
|
|
173
|
+
hasIllegalCharacters = true;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (!hasIllegalCharacters) {
|
|
177
|
+
if (classifiedExpression.IsInvalidExpressionName()) {
|
|
178
|
+
std::stringstream ss;
|
|
179
|
+
ss << "URI template expression \"" << classifiedExpression.innerExpression << "\" contains invalid characters. Allowed characters for expressions are A-Z a-z 0-9 _ and percent encoded characters";
|
|
180
|
+
result.result.warnings.push_back(Warning(ss.str(), URIWarning, sourceBlock));
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
else{
|
|
185
|
+
result.result.warnings.push_back(Warning(classifiedExpression.unsupportedWarningText, URIWarning, sourceBlock));
|
|
186
|
+
}
|
|
187
|
+
currentExpression++;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
else{
|
|
191
|
+
result.result.error = Error("Failed to parse URI Template", URIWarning);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
}
|
|
195
|
+
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
//
|
|
2
|
+
// UriTemplateTeParser.h
|
|
3
|
+
// snowcrash
|
|
4
|
+
//
|
|
5
|
+
// Created by Carl Griffiths 24/02/2014.
|
|
6
|
+
// Copyright (c) 2013 Apiary Inc. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
#ifndef SNOWCRASH_H
|
|
10
|
+
#define SNOWCRASH_H
|
|
11
|
+
|
|
12
|
+
#include <string>
|
|
13
|
+
#include "Blueprint.h"
|
|
14
|
+
#include "Parser.h"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
#define URI_REGEX "^(http|https|ftp|file)?(://)?([^/]*)?(.*)$"
|
|
19
|
+
#define URI_TEMPLATE_OPERATOR_REGEX "([+|#|.|/|;|?|&])"
|
|
20
|
+
#define URI_TEMPLATE_EXPRESSION_REGEX "^([?|#|+|&]?(([A-Z|a-z|0-9|_|,])*|(%[A-F|a-f|0-9]{2})*)*\\*?)$"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
namespace snowcrash {
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* \brief URI template parse result.
|
|
27
|
+
*/
|
|
28
|
+
struct ParsedURITemplate {
|
|
29
|
+
std::string scheme;
|
|
30
|
+
std::string host;
|
|
31
|
+
std::string path;
|
|
32
|
+
|
|
33
|
+
Result result;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* \brief URI template expression.
|
|
38
|
+
*/
|
|
39
|
+
typedef std::string Expression;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* \brief collection for expressions for a single URI template.
|
|
43
|
+
*/
|
|
44
|
+
typedef std::vector<Expression> Expressions;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* \brief iterator for collection of expressions.
|
|
48
|
+
*/
|
|
49
|
+
typedef std::vector<Expression>::const_iterator ExpressionIterator;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* \brief base class for URI template expression once classified.
|
|
53
|
+
*/
|
|
54
|
+
class ClassifiedExpression {
|
|
55
|
+
protected :
|
|
56
|
+
bool isSupported;
|
|
57
|
+
public :
|
|
58
|
+
ClassifiedExpression(const std::string& expression) {
|
|
59
|
+
isSupported = false;
|
|
60
|
+
unsupportedWarningText = "";
|
|
61
|
+
innerExpression = expression;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
std::string unsupportedWarningText;
|
|
65
|
+
|
|
66
|
+
snowcrash::Expression innerExpression;
|
|
67
|
+
|
|
68
|
+
virtual bool IsExpressionType() const {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
FORCEINLINE bool ContainsSpaces() {
|
|
73
|
+
return innerExpression.find(" ") != std::string::npos;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
FORCEINLINE bool ContainsAssignment() {
|
|
77
|
+
return innerExpression.find("=") != std::string::npos;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
FORCEINLINE bool ContainsHyphens() {
|
|
81
|
+
return innerExpression.find("-") != std::string::npos;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
FORCEINLINE bool IsInvalidExpressionName() {
|
|
85
|
+
std::string tmpExpression = innerExpression;
|
|
86
|
+
if (tmpExpression.find("..") != std::string::npos) return true;
|
|
87
|
+
|
|
88
|
+
size_t start_pos = 0;
|
|
89
|
+
while ((start_pos = tmpExpression.find(".", start_pos)) != std::string::npos) {
|
|
90
|
+
tmpExpression.replace(start_pos, 1, "_");
|
|
91
|
+
start_pos++;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return !RegexMatch(tmpExpression, URI_TEMPLATE_EXPRESSION_REGEX);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
FORCEINLINE bool IsSupportedExpressionType() {
|
|
98
|
+
return isSupported;
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* \brief level one basic variable expansion URI template expression.
|
|
104
|
+
*/
|
|
105
|
+
class VariableExpression : public ClassifiedExpression {
|
|
106
|
+
public :
|
|
107
|
+
VariableExpression(const std::string& expression):ClassifiedExpression(expression) {
|
|
108
|
+
isSupported = true;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
bool IsExpressionType() const {
|
|
112
|
+
return !RegexMatch(innerExpression.substr(0, 1), URI_TEMPLATE_OPERATOR_REGEX);
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* \brief level three query string expansion URI template expression.
|
|
118
|
+
*/
|
|
119
|
+
class QueryStringExpression : public ClassifiedExpression {
|
|
120
|
+
public :
|
|
121
|
+
QueryStringExpression(const std::string& expression):ClassifiedExpression(expression) {
|
|
122
|
+
isSupported = true;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
bool IsExpressionType() const {
|
|
126
|
+
return innerExpression.substr(0, 1) == "?";
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* \brief level two fragment expansion URI template expression.
|
|
132
|
+
*/
|
|
133
|
+
class FragmentExpression : public ClassifiedExpression {
|
|
134
|
+
public :
|
|
135
|
+
FragmentExpression(const std::string& expression):ClassifiedExpression(expression) {
|
|
136
|
+
isSupported = true;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
bool IsExpressionType() const {
|
|
140
|
+
return innerExpression.substr(0, 1) == "#";
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* \brief level two reserved expansion URI template expression.
|
|
146
|
+
*/
|
|
147
|
+
class ReservedExpansionExpression : public ClassifiedExpression {
|
|
148
|
+
public :
|
|
149
|
+
ReservedExpansionExpression(const std::string& expression):ClassifiedExpression(expression) {
|
|
150
|
+
isSupported = true;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
bool IsExpressionType() const {
|
|
154
|
+
return innerExpression.substr(0, 1) == "+";
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* \brief level three label expansion URI template expression.
|
|
160
|
+
*/
|
|
161
|
+
class LabelExpansionExpression : public ClassifiedExpression {
|
|
162
|
+
public :
|
|
163
|
+
LabelExpansionExpression(const std::string& expression):ClassifiedExpression(expression) {
|
|
164
|
+
unsupportedWarningText = "URI template label expansion is not supported";
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
bool IsExpressionType() const {
|
|
168
|
+
return innerExpression.substr(0, 1) == ".";
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* \brief level three path segment expansion URI template expression.
|
|
174
|
+
*/
|
|
175
|
+
class PathSegmentExpansionExpression : public ClassifiedExpression {
|
|
176
|
+
public :
|
|
177
|
+
PathSegmentExpansionExpression(const std::string& expression):ClassifiedExpression(expression) {
|
|
178
|
+
unsupportedWarningText = "URI template path segment expansion is not supported";
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
bool IsExpressionType() const {
|
|
182
|
+
return innerExpression.substr(0, 1) == "/";
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* \brief level three path style parameter expansion URI template expression.
|
|
188
|
+
*/
|
|
189
|
+
class PathStyleParameterExpansionExpression : public ClassifiedExpression {
|
|
190
|
+
public :
|
|
191
|
+
PathStyleParameterExpansionExpression(const std::string& expression):ClassifiedExpression(expression) {
|
|
192
|
+
unsupportedWarningText = "URI template path style parameter expansion is not supported";
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
bool IsExpressionType() const {
|
|
196
|
+
return innerExpression.substr(0, 1) == ";";
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* \brief level three form style query continuation expansion URI template expression.
|
|
202
|
+
*/
|
|
203
|
+
class FormStyleQueryContinuationExpression : public ClassifiedExpression {
|
|
204
|
+
public :
|
|
205
|
+
FormStyleQueryContinuationExpression(const std::string& expression):ClassifiedExpression(expression) {
|
|
206
|
+
isSupported = true;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
bool IsExpressionType() const {
|
|
210
|
+
return innerExpression.substr(0, 1) == "&";
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* \brief undefined URI template expression.
|
|
216
|
+
*/
|
|
217
|
+
class UndefinedExpression : public ClassifiedExpression{
|
|
218
|
+
public :
|
|
219
|
+
UndefinedExpression(const std::string& expression) :ClassifiedExpression(expression) {
|
|
220
|
+
unsupportedWarningText = "Unidentified expression";
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
bool IsExpressionType() const {
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* URI Template Parser Interface
|
|
230
|
+
* ------------------------------
|
|
231
|
+
*/
|
|
232
|
+
class URITemplateParser{
|
|
233
|
+
public :
|
|
234
|
+
/**
|
|
235
|
+
* \brief Parse the URI template into scheme, host and path and then parse for supported URI template expressions
|
|
236
|
+
*
|
|
237
|
+
* \param uri A uri to be parsed.
|
|
238
|
+
*/
|
|
239
|
+
static void parse(const URITemplate& uri, const SourceCharactersBlock& sourceBlock, ParsedURITemplate& result);
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
#endif
|