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,10 @@
|
|
|
1
|
+
# Do not edit. Generated by the configure script.
|
|
2
|
+
{ 'target_defaults': { 'cflags': [],
|
|
3
|
+
'default_configuration': 'Release',
|
|
4
|
+
'defines': [],
|
|
5
|
+
'include_dirs': [],
|
|
6
|
+
'libraries': []},
|
|
7
|
+
'variables': { 'host_arch': 'x64',
|
|
8
|
+
'libsnowcrash_type': 'shared_library',
|
|
9
|
+
'python': '/usr/bin/python',
|
|
10
|
+
'target_arch': 'x64'}}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
#
|
|
3
|
+
# Attribution Notice
|
|
4
|
+
# ------------------
|
|
5
|
+
# This file uses parts of Node.js `configure`.
|
|
6
|
+
# Please refer to https://github.com/joyent/node.
|
|
7
|
+
#
|
|
8
|
+
import optparse
|
|
9
|
+
import os
|
|
10
|
+
import pprint
|
|
11
|
+
import re
|
|
12
|
+
import shlex
|
|
13
|
+
import subprocess
|
|
14
|
+
import sys
|
|
15
|
+
import platform
|
|
16
|
+
|
|
17
|
+
CC = os.environ.get('CC', 'cc')
|
|
18
|
+
|
|
19
|
+
root_dir = os.path.dirname(__file__)
|
|
20
|
+
build_dir = './build'
|
|
21
|
+
|
|
22
|
+
# Parse options
|
|
23
|
+
parser = optparse.OptionParser()
|
|
24
|
+
parser.add_option("--debug",
|
|
25
|
+
action="store_true",
|
|
26
|
+
dest="debug",
|
|
27
|
+
help="Also build the debug build.")
|
|
28
|
+
|
|
29
|
+
parser.add_option("--dest-cpu",
|
|
30
|
+
action="store",
|
|
31
|
+
dest="dest_cpu",
|
|
32
|
+
help="CPU architecture to build for. Valid values are: ia32, x64.")
|
|
33
|
+
|
|
34
|
+
parser.add_option("--shared",
|
|
35
|
+
action="store_true",
|
|
36
|
+
dest="shared",
|
|
37
|
+
help="Build and use shared libsnowcrash instead of static one.")
|
|
38
|
+
|
|
39
|
+
parser.add_option("--include-integration-tests",
|
|
40
|
+
action="store_true",
|
|
41
|
+
dest="include_integration_tests",
|
|
42
|
+
help="Configure for integration testing using Cucumber")
|
|
43
|
+
|
|
44
|
+
(options, args) = parser.parse_args()
|
|
45
|
+
|
|
46
|
+
def write(filename, data):
|
|
47
|
+
filename = os.path.join(root_dir, filename)
|
|
48
|
+
print "creating ", filename
|
|
49
|
+
f = open(filename, 'w+')
|
|
50
|
+
f.write(data)
|
|
51
|
+
|
|
52
|
+
def cc_macros():
|
|
53
|
+
"""Checks predefined macros using the CC command."""
|
|
54
|
+
|
|
55
|
+
try:
|
|
56
|
+
p = subprocess.Popen(shlex.split(CC) + ['-dM', '-E', '-'],
|
|
57
|
+
stdin=subprocess.PIPE,
|
|
58
|
+
stdout=subprocess.PIPE,
|
|
59
|
+
stderr=subprocess.PIPE)
|
|
60
|
+
except OSError:
|
|
61
|
+
print '''Configure error: No acceptable C compiler found!
|
|
62
|
+
|
|
63
|
+
Please make sure you have a C compiler installed on your system and/or
|
|
64
|
+
consider adjusting the CC environment variable if you installed
|
|
65
|
+
it in a non-standard prefix.
|
|
66
|
+
'''
|
|
67
|
+
sys.exit()
|
|
68
|
+
|
|
69
|
+
p.stdin.write('\n')
|
|
70
|
+
out = p.communicate()[0]
|
|
71
|
+
|
|
72
|
+
out = str(out).split('\n')
|
|
73
|
+
|
|
74
|
+
k = {}
|
|
75
|
+
for line in out:
|
|
76
|
+
lst = shlex.split(line)
|
|
77
|
+
if len(lst) > 2:
|
|
78
|
+
key = lst[1]
|
|
79
|
+
val = lst[2]
|
|
80
|
+
k[key] = val
|
|
81
|
+
return k
|
|
82
|
+
|
|
83
|
+
def host_arch_cc():
|
|
84
|
+
"""Host architecture check using the CC command."""
|
|
85
|
+
|
|
86
|
+
k = cc_macros()
|
|
87
|
+
|
|
88
|
+
matchup = {
|
|
89
|
+
'__x86_64__' : 'x64',
|
|
90
|
+
'__i386__' : 'ia32',
|
|
91
|
+
'__arm__' : 'arm',
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
rtn = 'ia32' # default
|
|
95
|
+
|
|
96
|
+
for i in matchup:
|
|
97
|
+
if i in k and k[i] != '0':
|
|
98
|
+
rtn = matchup[i]
|
|
99
|
+
break
|
|
100
|
+
|
|
101
|
+
return rtn
|
|
102
|
+
|
|
103
|
+
def host_arch_win():
|
|
104
|
+
"""Host architecture check using environ vars (better way to do this?)"""
|
|
105
|
+
|
|
106
|
+
arch = os.environ.get('PROCESSOR_ARCHITECTURE', 'x86')
|
|
107
|
+
|
|
108
|
+
matchup = {
|
|
109
|
+
'AMD64' : 'x64',
|
|
110
|
+
'x86' : 'ia32',
|
|
111
|
+
'arm' : 'arm',
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return matchup.get(arch, 'ia32')
|
|
115
|
+
|
|
116
|
+
def configure_snowcrash(o):
|
|
117
|
+
# Build configuration
|
|
118
|
+
o['default_configuration'] = 'Debug' if options.debug else 'Release'
|
|
119
|
+
|
|
120
|
+
# Architecture
|
|
121
|
+
host_arch = host_arch_win() if os.name == 'nt' else host_arch_cc()
|
|
122
|
+
target_arch = options.dest_cpu or host_arch
|
|
123
|
+
o['variables']['host_arch'] = host_arch
|
|
124
|
+
o['variables']['target_arch'] = target_arch
|
|
125
|
+
o['variables']['libsnowcrash_type'] = 'shared_library' if options.shared else 'static_library'
|
|
126
|
+
|
|
127
|
+
#
|
|
128
|
+
# Cucumber testing environment
|
|
129
|
+
#
|
|
130
|
+
# TODO: use bundle check
|
|
131
|
+
if options.include_integration_tests:
|
|
132
|
+
print "Installing dependencies for integration tests..."
|
|
133
|
+
try:
|
|
134
|
+
if sys.platform == 'win32':
|
|
135
|
+
subprocess.call(["bundle.bat", "install"])
|
|
136
|
+
else:
|
|
137
|
+
subprocess.call(["bundle", "install"])
|
|
138
|
+
except OSError as e:
|
|
139
|
+
if e.errno == os.errno.ENOENT:
|
|
140
|
+
raise RuntimeError(
|
|
141
|
+
"Integration test dependecies rely on Ruby Bundler "
|
|
142
|
+
"but it cannot be find in the system $PATH. "
|
|
143
|
+
"Please make sure to install Bundler or/and to "
|
|
144
|
+
"add it to the $PATH."
|
|
145
|
+
)
|
|
146
|
+
else:
|
|
147
|
+
raise
|
|
148
|
+
|
|
149
|
+
#
|
|
150
|
+
# config.gypi
|
|
151
|
+
#
|
|
152
|
+
output = {
|
|
153
|
+
'variables': { 'python': sys.executable },
|
|
154
|
+
'include_dirs': [],
|
|
155
|
+
'libraries': [],
|
|
156
|
+
'defines': [],
|
|
157
|
+
'cflags': [],
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
configure_snowcrash(output)
|
|
161
|
+
|
|
162
|
+
# variables should be a root level element,
|
|
163
|
+
# move everything else to target_defaults
|
|
164
|
+
variables = output['variables']
|
|
165
|
+
del output['variables']
|
|
166
|
+
output = {
|
|
167
|
+
'variables': variables,
|
|
168
|
+
'target_defaults': output
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
write('config.gypi', "# Do not edit. Generated by the configure script.\n" +
|
|
172
|
+
pprint.pformat(output, indent=2) + "\n")
|
|
173
|
+
|
|
174
|
+
#
|
|
175
|
+
# config.mk
|
|
176
|
+
#
|
|
177
|
+
config = {
|
|
178
|
+
'BUILDTYPE': 'Debug' if options.debug else 'Release',
|
|
179
|
+
'PYTHON': sys.executable,
|
|
180
|
+
'BUILD_DIR': build_dir,
|
|
181
|
+
'INTEGRATION_TESTS': '1' if options.include_integration_tests else ''
|
|
182
|
+
}
|
|
183
|
+
config = '\n'.join(map('='.join, config.iteritems())) + '\n'
|
|
184
|
+
|
|
185
|
+
write('config.mk',
|
|
186
|
+
'# Do not edit. Generated by the configure script.\n' + config)
|
|
187
|
+
|
|
188
|
+
#
|
|
189
|
+
# Gyp call
|
|
190
|
+
#
|
|
191
|
+
print "creating makefiles"
|
|
192
|
+
|
|
193
|
+
gyp_args = ['--generator-output', build_dir, '--depth', '.']
|
|
194
|
+
if sys.platform == 'win32':
|
|
195
|
+
# Windows
|
|
196
|
+
gyp_args.extend(['-f', 'msvs'])
|
|
197
|
+
else:
|
|
198
|
+
# Posix systems
|
|
199
|
+
gyp_args.extend(['-f', 'make'])
|
|
200
|
+
|
|
201
|
+
# Include common.gypi and config.gypi
|
|
202
|
+
if sys.platform == 'win32':
|
|
203
|
+
options_fn = os.path.join(root_dir, 'config.gypi')
|
|
204
|
+
else:
|
|
205
|
+
options_fn = os.path.join(os.path.abspath(root_dir), 'config.gypi')
|
|
206
|
+
|
|
207
|
+
if os.path.exists(options_fn):
|
|
208
|
+
gyp_args.extend(['-I', options_fn])
|
|
209
|
+
|
|
210
|
+
subprocess.call([sys.executable, 'tools/gyp/gyp_main.py'] + gyp_args)
|
|
211
|
+
|
|
212
|
+
# All done
|
|
213
|
+
print "All OK."
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# GCC 4.7
|
|
4
|
+
sudo apt-get update -y
|
|
5
|
+
sudo apt-get install -y python-software-properties
|
|
6
|
+
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
|
7
|
+
sudo apt-get update -y
|
|
8
|
+
sudo apt-get install -y gcc-4.7 g++-4.7 gdb build-essential git-core
|
|
9
|
+
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.6 60 --slave /usr/bin/g++ g++ /usr/bin/g++-4.6
|
|
10
|
+
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.7 70 --slave /usr/bin/g++ g++ /usr/bin/g++-4.7
|
|
11
|
+
|
|
12
|
+
#sudo update-alternatives --config gcc
|
|
13
|
+
|
|
14
|
+
# Ruby
|
|
15
|
+
gem install bundler
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
{
|
|
2
|
+
"includes": [
|
|
3
|
+
"common.gypi"
|
|
4
|
+
],
|
|
5
|
+
|
|
6
|
+
'targets' : [
|
|
7
|
+
{
|
|
8
|
+
'target_name': 'sundown',
|
|
9
|
+
'type': 'static_library',
|
|
10
|
+
'include_dirs': [
|
|
11
|
+
'sundown/src',
|
|
12
|
+
'sundown/html',
|
|
13
|
+
],
|
|
14
|
+
'sources': [
|
|
15
|
+
'sundown/src/autolink.c',
|
|
16
|
+
'sundown/src/buffer.c',
|
|
17
|
+
'sundown/html/houdini_href_e.c',
|
|
18
|
+
'sundown/html/houdini_html_e.c',
|
|
19
|
+
'sundown/html/html.c',
|
|
20
|
+
'sundown/html/html_smartypants.c',
|
|
21
|
+
'sundown/src/markdown.c',
|
|
22
|
+
'sundown/src/stack.c',
|
|
23
|
+
'sundown/src/src_map.c'
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
'target_name': 'libsnowcrash',
|
|
28
|
+
'type': '<(libsnowcrash_type)',
|
|
29
|
+
'include_dirs': [
|
|
30
|
+
'src',
|
|
31
|
+
'sundown/src',
|
|
32
|
+
'sundown/src/html'
|
|
33
|
+
],
|
|
34
|
+
'sources': [
|
|
35
|
+
'src/HTTP.cc',
|
|
36
|
+
'src/MarkdownBlock.cc',
|
|
37
|
+
'src/MarkdownParser.cc',
|
|
38
|
+
'src/Parser.cc',
|
|
39
|
+
'src/ParserCore.cc',
|
|
40
|
+
'src/RegexMatch.h',
|
|
41
|
+
'src/Serialize.cc',
|
|
42
|
+
'src/Serialize.h',
|
|
43
|
+
'src/SerializeJSON.cc',
|
|
44
|
+
'src/SerializeYAML.cc',
|
|
45
|
+
'src/UriTemplateParser.cc',
|
|
46
|
+
'src/snowcrash.cc',
|
|
47
|
+
'src/csnowcrash.cc',
|
|
48
|
+
'src/CBlueprint.cc',
|
|
49
|
+
'src/CSourceAnnotation.cc'
|
|
50
|
+
],
|
|
51
|
+
'conditions': [
|
|
52
|
+
[ 'OS=="win"',
|
|
53
|
+
{ 'sources': [ 'src/win/RegexMatch.cc' ] },
|
|
54
|
+
{ 'sources': [ 'src/posix/RegexMatch.cc' ] } # OS != Windows
|
|
55
|
+
]
|
|
56
|
+
],
|
|
57
|
+
'dependencies': [
|
|
58
|
+
'sundown'
|
|
59
|
+
]
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
'target_name': 'test-libsnowcrash',
|
|
63
|
+
'type': 'executable',
|
|
64
|
+
'include_dirs': [
|
|
65
|
+
'src',
|
|
66
|
+
'test',
|
|
67
|
+
'test/vendor/Catch/include',
|
|
68
|
+
'sundown/src',
|
|
69
|
+
'sundown/src/html'
|
|
70
|
+
],
|
|
71
|
+
'sources': [
|
|
72
|
+
'test/test-ActionParser.cc',
|
|
73
|
+
'test/test-AssetParser.cc',
|
|
74
|
+
'test/test-Blueprint.cc',
|
|
75
|
+
'test/test-BlueprintParser.cc',
|
|
76
|
+
'test/test-HeaderParser.cc',
|
|
77
|
+
'test/test-Indentation.cc',
|
|
78
|
+
'test/test-ListUtility.cc',
|
|
79
|
+
'test/test-MarkdownBlock.cc',
|
|
80
|
+
'test/test-MarkdownParser.cc',
|
|
81
|
+
'test/test-ParameterDefinitonParser.cc',
|
|
82
|
+
'test/test-ParametersParser.cc',
|
|
83
|
+
'test/test-Parser.cc',
|
|
84
|
+
'test/test-PayloadParser.cc',
|
|
85
|
+
'test/test-RegexMatch.cc',
|
|
86
|
+
'test/test-ResouceGroupParser.cc',
|
|
87
|
+
'test/test-ResourceParser.cc',
|
|
88
|
+
'test/test-SymbolIdentifier.cc',
|
|
89
|
+
'test/test-SymbolTable.cc',
|
|
90
|
+
'test/test-Warnings.cc',
|
|
91
|
+
'test/test-csnowcrash.cc',
|
|
92
|
+
'test/test-UriTemplateParser.cc',
|
|
93
|
+
'test/test-snowcrash.cc'
|
|
94
|
+
],
|
|
95
|
+
'dependencies': [
|
|
96
|
+
'libsnowcrash',
|
|
97
|
+
'sundown'
|
|
98
|
+
]
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
{
|
|
102
|
+
'target_name': 'snowcrash',
|
|
103
|
+
'type': 'executable',
|
|
104
|
+
'include_dirs': [
|
|
105
|
+
'src',
|
|
106
|
+
'src/snowcrash',
|
|
107
|
+
'cmdline'
|
|
108
|
+
],
|
|
109
|
+
'sources': [
|
|
110
|
+
'src/snowcrash/snowcrash.cc'
|
|
111
|
+
],
|
|
112
|
+
'dependencies': [
|
|
113
|
+
'libsnowcrash',
|
|
114
|
+
'sundown'
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
],
|
|
118
|
+
'conditions': [
|
|
119
|
+
['OS in "mac linux"', {
|
|
120
|
+
'targets': [
|
|
121
|
+
{
|
|
122
|
+
'target_name': 'perf-libsnowcrash',
|
|
123
|
+
'type': 'executable',
|
|
124
|
+
'include_dirs': [
|
|
125
|
+
'src',
|
|
126
|
+
'cmdline',
|
|
127
|
+
'test',
|
|
128
|
+
'test/performance',
|
|
129
|
+
],
|
|
130
|
+
'sources': [
|
|
131
|
+
'test/performance/perf-snowcrash.cc'
|
|
132
|
+
],
|
|
133
|
+
'dependencies': [
|
|
134
|
+
'libsnowcrash',
|
|
135
|
+
'sundown'
|
|
136
|
+
]
|
|
137
|
+
}
|
|
138
|
+
]
|
|
139
|
+
}]
|
|
140
|
+
]
|
|
141
|
+
}
|
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
//
|
|
2
|
+
// ActionParser.h
|
|
3
|
+
// snowcrash
|
|
4
|
+
//
|
|
5
|
+
// Created by Zdenek Nemec on 5/4/13.
|
|
6
|
+
// Copyright (c) 2013 Apiary Inc. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
#ifndef SNOWCRASH_ACTIONPARSER_H
|
|
10
|
+
#define SNOWCRASH_ACTIONPARSER_H
|
|
11
|
+
|
|
12
|
+
#include "BlueprintParserCore.h"
|
|
13
|
+
#include "Blueprint.h"
|
|
14
|
+
#include "RegexMatch.h"
|
|
15
|
+
#include "PayloadParser.h"
|
|
16
|
+
#include "HeaderParser.h"
|
|
17
|
+
#include "ParametersParser.h"
|
|
18
|
+
#include "HTTP.h"
|
|
19
|
+
#include "DescriptionSectionUtility.h"
|
|
20
|
+
|
|
21
|
+
namespace snowcrashconst {
|
|
22
|
+
|
|
23
|
+
/** Nameless action matching regex */
|
|
24
|
+
const char* const ActionHeaderRegex = "^[[:blank:]]*" HTTP_REQUEST_METHOD "[[:blank:]]*" URI_TEMPLATE "?$";
|
|
25
|
+
|
|
26
|
+
/** Named action matching regex */
|
|
27
|
+
const char* const NamedActionHeaderRegex = "^[[:blank:]]*" SYMBOL_IDENTIFIER "\\[" HTTP_REQUEST_METHOD "]$";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
namespace snowcrash {
|
|
31
|
+
|
|
32
|
+
// Method signature
|
|
33
|
+
enum ActionSignature {
|
|
34
|
+
UndefinedActionSignature,
|
|
35
|
+
NoActionSignature,
|
|
36
|
+
MethodActionSignature, // # GET
|
|
37
|
+
MethodURIActionSignature, // # GET /uri
|
|
38
|
+
NamedActionSignature // # My Method [GET]
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// Query method signature
|
|
42
|
+
FORCEINLINE ActionSignature GetActionSignature(const MarkdownBlock& block,
|
|
43
|
+
Name& name,
|
|
44
|
+
HTTPMethod& method) {
|
|
45
|
+
if (block.type != HeaderBlockType ||
|
|
46
|
+
block.content.empty())
|
|
47
|
+
return NoActionSignature;
|
|
48
|
+
|
|
49
|
+
CaptureGroups captureGroups;
|
|
50
|
+
if (RegexCapture(block.content, snowcrashconst::ActionHeaderRegex, captureGroups, 3)) {
|
|
51
|
+
// Nameless action
|
|
52
|
+
method = captureGroups[1];
|
|
53
|
+
URITemplate uri = captureGroups[2];
|
|
54
|
+
return (uri.empty()) ? MethodActionSignature : MethodURIActionSignature;
|
|
55
|
+
}
|
|
56
|
+
else if (RegexCapture(block.content, snowcrashconst::NamedActionHeaderRegex, captureGroups, 3)) {
|
|
57
|
+
// Named action
|
|
58
|
+
name = captureGroups[1];
|
|
59
|
+
TrimString(name);
|
|
60
|
+
method = captureGroups[2];
|
|
61
|
+
return NamedActionSignature;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return NoActionSignature;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Returns true if block has HTTP Method signature, false otherwise
|
|
68
|
+
FORCEINLINE bool HasActionSignature(const MarkdownBlock& block) {
|
|
69
|
+
|
|
70
|
+
if (block.type != HeaderBlockType ||
|
|
71
|
+
block.content.empty())
|
|
72
|
+
return false;
|
|
73
|
+
|
|
74
|
+
Name name;
|
|
75
|
+
HTTPMethod method;
|
|
76
|
+
return GetActionSignature(block, name, method) != NoActionSignature;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Finds an action inside resource
|
|
80
|
+
FORCEINLINE Collection<Action>::iterator FindAction(Resource& resource,
|
|
81
|
+
const Action& action) {
|
|
82
|
+
return std::find_if(resource.actions.begin(),
|
|
83
|
+
resource.actions.end(),
|
|
84
|
+
std::bind2nd(MatchAction<Action>(), action));
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
//
|
|
88
|
+
// Classifier of internal list items, Payload context
|
|
89
|
+
//
|
|
90
|
+
template <>
|
|
91
|
+
FORCEINLINE SectionType ClassifyInternaListBlock<Action>(const BlockIterator& begin,
|
|
92
|
+
const BlockIterator& end) {
|
|
93
|
+
if (HasHeaderSignature(begin, end))
|
|
94
|
+
return HeadersSectionType;
|
|
95
|
+
|
|
96
|
+
if (HasParametersSignature(begin, end))
|
|
97
|
+
return ParametersSectionType;
|
|
98
|
+
|
|
99
|
+
Name name;
|
|
100
|
+
SourceData mediaType;
|
|
101
|
+
PayloadSignature payload = GetPayloadSignature(begin, end, name, mediaType);
|
|
102
|
+
if (payload == RequestPayloadSignature)
|
|
103
|
+
return RequestSectionType;
|
|
104
|
+
else if (payload == ResponsePayloadSignature)
|
|
105
|
+
return ResponseSectionType;
|
|
106
|
+
else if (payload == ObjectPayloadSignature)
|
|
107
|
+
return ObjectSectionType;
|
|
108
|
+
else if (payload == ModelPayloadSignature)
|
|
109
|
+
return ModelSectionType;
|
|
110
|
+
|
|
111
|
+
return UndefinedSectionType;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** Children blocks classifier */
|
|
115
|
+
template <>
|
|
116
|
+
FORCEINLINE SectionType ClassifyChildrenListBlock<Action>(const BlockIterator& begin,
|
|
117
|
+
const BlockIterator& end) {
|
|
118
|
+
|
|
119
|
+
SectionType type = ClassifyInternaListBlock<Action>(begin, end);
|
|
120
|
+
if (type != UndefinedSectionType)
|
|
121
|
+
return type;
|
|
122
|
+
|
|
123
|
+
type = ClassifyChildrenListBlock<HeaderCollection>(begin, end);
|
|
124
|
+
if (type != UndefinedSectionType)
|
|
125
|
+
return type;
|
|
126
|
+
|
|
127
|
+
type = ClassifyChildrenListBlock<ParameterCollection>(begin, end);
|
|
128
|
+
if (type != UndefinedSectionType)
|
|
129
|
+
return type;
|
|
130
|
+
|
|
131
|
+
type = ClassifyChildrenListBlock<Payload>(begin, end);
|
|
132
|
+
if (type != UndefinedSectionType)
|
|
133
|
+
return type;
|
|
134
|
+
|
|
135
|
+
return UndefinedSectionType;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
//
|
|
139
|
+
// Block Classifier, Action Context
|
|
140
|
+
//
|
|
141
|
+
template <>
|
|
142
|
+
FORCEINLINE SectionType ClassifyBlock<Action>(const BlockIterator& begin,
|
|
143
|
+
const BlockIterator& end,
|
|
144
|
+
const SectionType& context) {
|
|
145
|
+
|
|
146
|
+
if (HasActionSignature(*begin))
|
|
147
|
+
return (context == UndefinedSectionType) ? ActionSectionType : UndefinedSectionType;
|
|
148
|
+
|
|
149
|
+
if (HasResourceSignature(*begin) ||
|
|
150
|
+
HasResourceGroupSignature(*begin))
|
|
151
|
+
return UndefinedSectionType;
|
|
152
|
+
|
|
153
|
+
SectionType listSection = ClassifyInternaListBlock<Action>(begin, end);
|
|
154
|
+
if (listSection != UndefinedSectionType)
|
|
155
|
+
return listSection;
|
|
156
|
+
|
|
157
|
+
// Unrecognized list item at this level
|
|
158
|
+
if (begin->type == ListItemBlockBeginType)
|
|
159
|
+
return ForeignSectionType;
|
|
160
|
+
|
|
161
|
+
return (context == ActionSectionType) ? ActionSectionType : UndefinedSectionType;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
//
|
|
165
|
+
// Action SectionType Parser
|
|
166
|
+
//
|
|
167
|
+
template<>
|
|
168
|
+
struct SectionParser<Action> {
|
|
169
|
+
|
|
170
|
+
static ParseSectionResult ParseSection(const BlueprintSection& section,
|
|
171
|
+
const BlockIterator& cur,
|
|
172
|
+
BlueprintParserCore& parser,
|
|
173
|
+
Action& action) {
|
|
174
|
+
|
|
175
|
+
ParseSectionResult result = std::make_pair(Result(), cur);
|
|
176
|
+
|
|
177
|
+
switch (section.type) {
|
|
178
|
+
case ActionSectionType:
|
|
179
|
+
result = HandleActionDescriptionBlock(section, cur, parser, action);
|
|
180
|
+
break;
|
|
181
|
+
|
|
182
|
+
case ParametersSectionType:
|
|
183
|
+
result = HandleParameters(section, cur, parser, action);
|
|
184
|
+
break;
|
|
185
|
+
|
|
186
|
+
case HeadersSectionType:
|
|
187
|
+
result = HandleDeprecatedHeaders(section, cur, parser, action);
|
|
188
|
+
break;
|
|
189
|
+
|
|
190
|
+
case RequestSectionType:
|
|
191
|
+
case ResponseSectionType:
|
|
192
|
+
result = HandlePayload(section, cur, parser, action);
|
|
193
|
+
break;
|
|
194
|
+
|
|
195
|
+
case ForeignSectionType:
|
|
196
|
+
result = HandleForeignSection<Action>(section, cur, parser.sourceData);
|
|
197
|
+
break;
|
|
198
|
+
|
|
199
|
+
case UndefinedSectionType:
|
|
200
|
+
result.second = CloseList(cur, section.bounds.second);
|
|
201
|
+
break;
|
|
202
|
+
|
|
203
|
+
case ModelSectionType:
|
|
204
|
+
case ObjectSectionType:
|
|
205
|
+
{
|
|
206
|
+
// ERR: Unexpected model definition
|
|
207
|
+
SourceCharactersBlock sourceBlock = CharacterMapForBlock(cur,
|
|
208
|
+
section.bounds.second,
|
|
209
|
+
section.bounds,
|
|
210
|
+
parser.sourceData);
|
|
211
|
+
result.first.error = Error("unexpected model definiton, a model can be only defined in the resource section",
|
|
212
|
+
SymbolError,
|
|
213
|
+
sourceBlock);
|
|
214
|
+
}
|
|
215
|
+
break;
|
|
216
|
+
|
|
217
|
+
default:
|
|
218
|
+
result.first.error = UnexpectedBlockError(section, cur, parser.sourceData);
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return result;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
static void Finalize(const SectionBounds& bounds,
|
|
226
|
+
BlueprintParserCore& parser,
|
|
227
|
+
Action& action,
|
|
228
|
+
Result& result)
|
|
229
|
+
{
|
|
230
|
+
// Consolidate deprecated headers into subsequent payloads
|
|
231
|
+
if (!action.headers.empty()) {
|
|
232
|
+
InjectDeprecatedHeaders(action.headers, action.examples);
|
|
233
|
+
action.headers.clear();
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Check whether transaction example request is followed by a response
|
|
237
|
+
if (action.examples.size() > 1 &&
|
|
238
|
+
!action.examples.back().requests.empty() &&
|
|
239
|
+
action.examples.back().responses.empty()) {
|
|
240
|
+
// WARN: No response for request
|
|
241
|
+
|
|
242
|
+
std::stringstream ss;
|
|
243
|
+
ss << "action is missing a response for ";
|
|
244
|
+
if (action.examples.back().requests.back().name.empty())
|
|
245
|
+
ss << "a request";
|
|
246
|
+
else
|
|
247
|
+
ss << "the '" << action.examples.back().requests.back().name << "' request";
|
|
248
|
+
|
|
249
|
+
SourceCharactersBlock sourceBlock = CharacterMapForBlock(bounds.first, bounds.first, bounds, parser.sourceData);
|
|
250
|
+
result.warnings.push_back(Warning(ss.str(),
|
|
251
|
+
EmptyDefinitionWarning,
|
|
252
|
+
sourceBlock));
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
static ParseSectionResult HandleActionDescriptionBlock(const BlueprintSection& section,
|
|
257
|
+
const BlockIterator& cur,
|
|
258
|
+
BlueprintParserCore& parser,
|
|
259
|
+
Action& action) {
|
|
260
|
+
|
|
261
|
+
ParseSectionResult result = std::make_pair(Result(), cur);
|
|
262
|
+
BlockIterator sectionCur(cur);
|
|
263
|
+
|
|
264
|
+
if (cur->type == HeaderBlockType &&
|
|
265
|
+
cur == section.bounds.first) {
|
|
266
|
+
|
|
267
|
+
GetActionSignature(*cur, action.name, action.method);
|
|
268
|
+
result.second = ++sectionCur;
|
|
269
|
+
return result;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
result = ParseDescriptionBlock<Action>(section,
|
|
273
|
+
sectionCur,
|
|
274
|
+
parser.sourceData,
|
|
275
|
+
action);
|
|
276
|
+
return result;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/** Parse Parameters section */
|
|
280
|
+
static ParseSectionResult HandleParameters(const BlueprintSection& section,
|
|
281
|
+
const BlockIterator& cur,
|
|
282
|
+
BlueprintParserCore& parser,
|
|
283
|
+
Action& action) {
|
|
284
|
+
ParameterCollection parameters;
|
|
285
|
+
ParseSectionResult result = ParametersParser::Parse(cur,
|
|
286
|
+
section.bounds.second,
|
|
287
|
+
section,
|
|
288
|
+
parser,
|
|
289
|
+
parameters);
|
|
290
|
+
if (result.first.error.code != Error::OK)
|
|
291
|
+
return result;
|
|
292
|
+
|
|
293
|
+
if (parameters.empty()) {
|
|
294
|
+
BlockIterator nameBlock = ListItemNameBlock(cur, section.bounds.second);
|
|
295
|
+
SourceCharactersBlock sourceBlock = CharacterMapForBlock(nameBlock, cur, section.bounds, parser.sourceData);
|
|
296
|
+
result.first.warnings.push_back(Warning(snowcrashconst::NoParametersMessage,
|
|
297
|
+
FormattingWarning,
|
|
298
|
+
sourceBlock));
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
action.parameters.insert(action.parameters.end(), parameters.begin(), parameters.end());
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
return result;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* \brief Parse action payload
|
|
309
|
+
* \param section Actual section being parsed.
|
|
310
|
+
* \param cur Cursor within the section boundaries.
|
|
311
|
+
* \param parser A parser's instance.
|
|
312
|
+
* \param action An output buffer to store parsed payload into.
|
|
313
|
+
* \return A block parser section result.
|
|
314
|
+
*/
|
|
315
|
+
static ParseSectionResult HandlePayload(const BlueprintSection& section,
|
|
316
|
+
const BlockIterator& cur,
|
|
317
|
+
BlueprintParserCore& parser,
|
|
318
|
+
Action& action)
|
|
319
|
+
{
|
|
320
|
+
Payload payload;
|
|
321
|
+
ParseSectionResult result = PayloadParser::Parse(cur,
|
|
322
|
+
section.bounds.second,
|
|
323
|
+
section,
|
|
324
|
+
parser,
|
|
325
|
+
payload);
|
|
326
|
+
if (result.first.error.code != Error::OK)
|
|
327
|
+
return result;
|
|
328
|
+
|
|
329
|
+
// Create transaction example if needed
|
|
330
|
+
if (action.examples.empty()) {
|
|
331
|
+
action.examples.push_back(TransactionExample());
|
|
332
|
+
}
|
|
333
|
+
else if (section.type == RequestSectionType) {
|
|
334
|
+
// Automatic request response pairing:
|
|
335
|
+
// If a request follows a response create a new transaction example
|
|
336
|
+
if (!action.examples.back().responses.empty()) {
|
|
337
|
+
action.examples.push_back(TransactionExample());
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
BlockIterator nameBlock = ListItemNameBlock(cur, section.bounds.second);
|
|
342
|
+
|
|
343
|
+
// Check for duplicate
|
|
344
|
+
if (IsPayloadDuplicate(section.type, payload, action.examples.back())) {
|
|
345
|
+
// WARN: duplicate payload
|
|
346
|
+
std::stringstream ss;
|
|
347
|
+
ss << SectionName(section.type) << " payload `" << payload.name << "`";
|
|
348
|
+
ss << " already defined for `" << action.method << "` method";
|
|
349
|
+
|
|
350
|
+
SourceCharactersBlock sourceBlock = CharacterMapForBlock(nameBlock, cur, section.bounds, parser.sourceData);
|
|
351
|
+
result.first.warnings.push_back(Warning(ss.str(),
|
|
352
|
+
DuplicateWarning,
|
|
353
|
+
sourceBlock));
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Check payload integrity
|
|
357
|
+
CheckPayload(section.type, payload, action.method, nameBlock->sourceMap, parser.sourceData, result.first);
|
|
358
|
+
|
|
359
|
+
// Inject parsed payload into the action
|
|
360
|
+
if (section.type == RequestSectionType) {
|
|
361
|
+
action.examples.back().requests.push_back(payload);
|
|
362
|
+
}
|
|
363
|
+
else if (section.type == ResponseSectionType) {
|
|
364
|
+
action.examples.back().responses.push_back(payload);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Check header duplicates
|
|
368
|
+
CheckHeaderDuplicates(action, payload, nameBlock->sourceMap, parser.sourceData, result.first);
|
|
369
|
+
|
|
370
|
+
return result;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* \brief Check & report payload validity.
|
|
376
|
+
* \param section A section of the payload.
|
|
377
|
+
* \param sourceMap Payload signature source map.
|
|
378
|
+
* \param payload The payload to be checked.
|
|
379
|
+
*/
|
|
380
|
+
static void CheckPayload(const SectionType& section,
|
|
381
|
+
const Payload& payload,
|
|
382
|
+
const HTTPMethod method,
|
|
383
|
+
const SourceDataBlock& sourceMap,
|
|
384
|
+
const SourceData& sourceData,
|
|
385
|
+
Result& result) {
|
|
386
|
+
|
|
387
|
+
bool warnEmptyBody = false;
|
|
388
|
+
|
|
389
|
+
std::string contentLength;
|
|
390
|
+
std::string transferEncoding;
|
|
391
|
+
|
|
392
|
+
for (Collection<Header>::const_iterator it = payload.headers.begin();
|
|
393
|
+
it != payload.headers.end();
|
|
394
|
+
++it) {
|
|
395
|
+
|
|
396
|
+
if (it->first == HTTPHeaderName::ContentLength) {
|
|
397
|
+
contentLength = it->second;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
if (it->first == HTTPHeaderName::TransferEncoding) {
|
|
401
|
+
transferEncoding = it->second;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
if (section == RequestSectionType) {
|
|
406
|
+
|
|
407
|
+
if (payload.body.empty()) {
|
|
408
|
+
|
|
409
|
+
// Warn when content-length or transfer-encoding is specified or both headers and body are empty
|
|
410
|
+
if (payload.headers.empty()) {
|
|
411
|
+
warnEmptyBody = true;
|
|
412
|
+
}
|
|
413
|
+
else {
|
|
414
|
+
warnEmptyBody = !contentLength.empty() ||
|
|
415
|
+
!transferEncoding.empty();
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
if (warnEmptyBody) {
|
|
419
|
+
// WARN: empty body
|
|
420
|
+
std::stringstream ss;
|
|
421
|
+
ss << "empty " << SectionName(section) << " " << SectionName(BodySectionType);
|
|
422
|
+
|
|
423
|
+
if (!contentLength.empty()) {
|
|
424
|
+
ss << ", expected " << SectionName(BodySectionType) << " for '" << contentLength << "' Content-Length";
|
|
425
|
+
}
|
|
426
|
+
else if (!transferEncoding.empty()) {
|
|
427
|
+
ss << ", expected " << SectionName(BodySectionType) << " for '" << transferEncoding << "' Transfer-Encoding";
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
result.warnings.push_back(Warning(ss.str(),
|
|
431
|
+
EmptyDefinitionWarning,
|
|
432
|
+
MapSourceDataBlock(sourceMap, sourceData)));
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
else if (section == ResponseSectionType) {
|
|
438
|
+
// Check status code
|
|
439
|
+
HTTPStatusCode code = 0;
|
|
440
|
+
|
|
441
|
+
if (!payload.name.empty()) {
|
|
442
|
+
std::stringstream(payload.name) >> code;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
StatusCodeTraits statusCodeTraits = GetStatusCodeTrait(code);
|
|
446
|
+
HTTPMethodTraits methodTraits = GetMethodTrait(method);
|
|
447
|
+
|
|
448
|
+
if ((!statusCodeTraits.allowBody || !methodTraits.allowBody) && !payload.body.empty()) {
|
|
449
|
+
// WARN: not empty body
|
|
450
|
+
|
|
451
|
+
if (!statusCodeTraits.allowBody) {
|
|
452
|
+
std::stringstream ss;
|
|
453
|
+
ss << "the " << code << " response MUST NOT include a " << SectionName(BodySectionType);
|
|
454
|
+
result.warnings.push_back(Warning(ss.str(),
|
|
455
|
+
EmptyDefinitionWarning,
|
|
456
|
+
MapSourceDataBlock(sourceMap, sourceData)));
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// WARN: Edge case for 2xx CONNECT
|
|
460
|
+
if (method == HTTPMethodName::Connect && code/100 == 2) {
|
|
461
|
+
std::stringstream ss;
|
|
462
|
+
ss << "the response for " << code << " " << method << " request MUST NOT include a " << SectionName(BodySectionType);
|
|
463
|
+
result.warnings.push_back(Warning(ss.str(),
|
|
464
|
+
EmptyDefinitionWarning,
|
|
465
|
+
MapSourceDataBlock(sourceMap, sourceData)));
|
|
466
|
+
|
|
467
|
+
}
|
|
468
|
+
else if (method != HTTPMethodName::Connect && !methodTraits.allowBody) {
|
|
469
|
+
std::stringstream ss;
|
|
470
|
+
ss << "the response for " << method << " request MUST NOT include a " << SectionName(BodySectionType);
|
|
471
|
+
result.warnings.push_back(Warning(ss.str(),
|
|
472
|
+
EmptyDefinitionWarning,
|
|
473
|
+
MapSourceDataBlock(sourceMap, sourceData)));
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Checks whether given section payload has duplicate within its transaction examples
|
|
483
|
+
* \return True when a duplicate is found, false otherwise.
|
|
484
|
+
*/
|
|
485
|
+
static bool IsPayloadDuplicate(const SectionType& section, const Payload& payload, TransactionExample& example) {
|
|
486
|
+
|
|
487
|
+
if (section == RequestSectionType) {
|
|
488
|
+
Collection<Request>::const_iterator duplicate = FindRequest(example, payload);
|
|
489
|
+
return duplicate != example.requests.end();
|
|
490
|
+
}
|
|
491
|
+
else if (section == ResponseSectionType) {
|
|
492
|
+
Collection<Response>::const_iterator duplicate = FindResponse(example, payload);
|
|
493
|
+
return duplicate != example.responses.end();
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
return false;
|
|
497
|
+
}
|
|
498
|
+
};
|
|
499
|
+
|
|
500
|
+
typedef BlockParser<Action, SectionParser<Action> > ActionParser;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
#endif
|