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,46 @@
|
|
|
1
|
+
//
|
|
2
|
+
// HTTP.cc
|
|
3
|
+
// snowcrash
|
|
4
|
+
//
|
|
5
|
+
// Created by Zdenek Nemec on 7/11/13.
|
|
6
|
+
// Copyright (c) 2013 Apiary Inc. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
#include "HTTP.h"
|
|
10
|
+
|
|
11
|
+
using namespace snowcrash;
|
|
12
|
+
|
|
13
|
+
const std::string HTTPHeaderName::Accept = "Accept";
|
|
14
|
+
const std::string HTTPHeaderName::ContentLength = "Content-Length";
|
|
15
|
+
const std::string HTTPHeaderName::ContentType = "Content-Type";
|
|
16
|
+
const std::string HTTPHeaderName::TransferEncoding = "Transfer-Encoding";
|
|
17
|
+
|
|
18
|
+
const std::string HTTPMethodName::Head = "HEAD";
|
|
19
|
+
const std::string HTTPMethodName::Connect = "CONNECT";
|
|
20
|
+
|
|
21
|
+
StatusCodeTraits snowcrash::GetStatusCodeTrait(HTTPStatusCode code)
|
|
22
|
+
{
|
|
23
|
+
StatusCodeTraits traits;
|
|
24
|
+
traits.code = code;
|
|
25
|
+
|
|
26
|
+
// Following status codes MUST NOT contain response body
|
|
27
|
+
if (code == 204 || code == 304 || code/100 == 1) {
|
|
28
|
+
traits.allowBody = false;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return traits;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
HTTPMethodTraits snowcrash::GetMethodTrait(HTTPMethod method)
|
|
35
|
+
{
|
|
36
|
+
HTTPMethodTraits traits;
|
|
37
|
+
traits.method = method;
|
|
38
|
+
|
|
39
|
+
// Following HTTP methods MUST NOT contain response body
|
|
40
|
+
// FIXME: When refactoring traits don't forget that 'CONNECT' has no body only when 1xx-2xx
|
|
41
|
+
if (method == HTTPMethodName::Head || method == HTTPMethodName::Connect) {
|
|
42
|
+
traits.allowBody = false;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return traits;
|
|
46
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
//
|
|
2
|
+
// HTTP.h
|
|
3
|
+
// snowcrash
|
|
4
|
+
//
|
|
5
|
+
// Created by Zdenek Nemec on 7/11/13.
|
|
6
|
+
// Copyright (c) 2013 Apiary Inc. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
#ifndef SNOWCRASH_HTTP_H
|
|
10
|
+
#define SNOWCRASH_HTTP_H
|
|
11
|
+
|
|
12
|
+
#include <string>
|
|
13
|
+
#include "Blueprint.h"
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* \brief HTTP Methods
|
|
17
|
+
*
|
|
18
|
+
* Technical note: Using preprocessor macro instead of strict
|
|
19
|
+
* defined type due to C++98 string concatenation limitations.
|
|
20
|
+
* FIXME: To be improved with migration to C++11.
|
|
21
|
+
*/
|
|
22
|
+
#define HTTP_REQUEST_METHOD "(GET|POST|PUT|DELETE|OPTIONS|PATCH|PROPPATCH|LOCK|UNLOCK|COPY|MOVE|MKCOL|HEAD|LINK|UNLINK|CONNECT)"
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* \brief URI Template.
|
|
26
|
+
*
|
|
27
|
+
* See previous technical note (using macro).
|
|
28
|
+
*/
|
|
29
|
+
#define URI_TEMPLATE "(/.*)"
|
|
30
|
+
|
|
31
|
+
namespace snowcrash {
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Selected HTTP Header names.
|
|
35
|
+
*/
|
|
36
|
+
struct HTTPHeaderName {
|
|
37
|
+
static const std::string Accept;
|
|
38
|
+
static const std::string ContentLength;
|
|
39
|
+
static const std::string ContentType;
|
|
40
|
+
static const std::string TransferEncoding;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Selected HTTP Method names.
|
|
45
|
+
*/
|
|
46
|
+
struct HTTPMethodName {
|
|
47
|
+
static const std::string Head;
|
|
48
|
+
static const std::string Connect;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* A HTTP Status code.
|
|
53
|
+
*/
|
|
54
|
+
typedef unsigned int HTTPStatusCode;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Traits of a HTTP response.
|
|
58
|
+
*/
|
|
59
|
+
struct HTTPResponseTraits {
|
|
60
|
+
|
|
61
|
+
bool allowBody; /// < Response body is allowed.
|
|
62
|
+
|
|
63
|
+
HTTPResponseTraits() : allowBody(true) {}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Response traits for a HTTP method.
|
|
68
|
+
*
|
|
69
|
+
* HTTP request method related response prescription
|
|
70
|
+
* Ref: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
|
|
71
|
+
*/
|
|
72
|
+
struct HTTPMethodTraits : HTTPResponseTraits
|
|
73
|
+
{
|
|
74
|
+
HTTPMethod method;
|
|
75
|
+
HTTPMethodTraits() : method("") {}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Response traits for a HTTP status code.
|
|
80
|
+
*
|
|
81
|
+
* Status-related response prescription.
|
|
82
|
+
* Ref: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
|
|
83
|
+
*/
|
|
84
|
+
struct StatusCodeTraits : HTTPResponseTraits
|
|
85
|
+
{
|
|
86
|
+
HTTPStatusCode code;
|
|
87
|
+
StatusCodeTraits() : code(0) {}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* \brief Retrieve response traits for given HTTP method.
|
|
92
|
+
* \param method HTTP method to retrieve traits for.
|
|
93
|
+
* \return A %HTTPMethodTraits for given method.
|
|
94
|
+
*/
|
|
95
|
+
extern HTTPMethodTraits GetMethodTrait(HTTPMethod method);
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* \brief Retrieve response traits for given status code.
|
|
99
|
+
* \param code A HTTP status code to retrieve traits for.
|
|
100
|
+
* \return A %StatusCodeTraits for given code.
|
|
101
|
+
*/
|
|
102
|
+
extern StatusCodeTraits GetStatusCodeTrait(HTTPStatusCode code);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
#endif
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
//
|
|
2
|
+
// HeaderParser.h
|
|
3
|
+
// snowcrash
|
|
4
|
+
//
|
|
5
|
+
// Created by Zdenek Nemec on 5/22/13.
|
|
6
|
+
// Copyright (c) 2013 Apiary Inc. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
#ifndef SNOWCRASH_HEADERPARSER_H
|
|
10
|
+
#define SNOWCRASH_HEADERPARSER_H
|
|
11
|
+
|
|
12
|
+
#include <sstream>
|
|
13
|
+
#include "BlueprintParserCore.h"
|
|
14
|
+
#include "Blueprint.h"
|
|
15
|
+
#include "RegexMatch.h"
|
|
16
|
+
#include "StringUtility.h"
|
|
17
|
+
#include "ListBlockUtility.h"
|
|
18
|
+
|
|
19
|
+
namespace snowcrashconst {
|
|
20
|
+
|
|
21
|
+
/** Headers matching regex */
|
|
22
|
+
const char* const HeadersRegex = "^[[:blank:]]*[Hh]eaders?[[:blank:]]*$";
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
namespace snowcrash {
|
|
26
|
+
|
|
27
|
+
// Internal type alias for Collection of Headers
|
|
28
|
+
typedef Collection<Header>::type HeaderCollection;
|
|
29
|
+
|
|
30
|
+
// Query header signature a of given block
|
|
31
|
+
FORCEINLINE bool HasHeaderSignature(const BlockIterator& begin,
|
|
32
|
+
const BlockIterator& end) {
|
|
33
|
+
|
|
34
|
+
if (begin->type == ListBlockBeginType || begin->type == ListItemBlockBeginType) {
|
|
35
|
+
|
|
36
|
+
BlockIterator cur = ListItemNameBlock(begin, end);
|
|
37
|
+
if (cur == end)
|
|
38
|
+
return false;
|
|
39
|
+
|
|
40
|
+
if (cur->type != ParagraphBlockType &&
|
|
41
|
+
cur->type != ListItemBlockEndType)
|
|
42
|
+
return false;
|
|
43
|
+
|
|
44
|
+
std::string content = GetFirstLine(cur->content);
|
|
45
|
+
return RegexMatch(content, snowcrashconst::HeadersRegex);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Header iterator in its containment group
|
|
52
|
+
typedef Collection<Header>::const_iterator HeaderIterator;
|
|
53
|
+
|
|
54
|
+
// Finds a header in its containment group by its key (first)
|
|
55
|
+
FORCEINLINE HeaderIterator FindHeader(const HeaderCollection& headers,
|
|
56
|
+
const Header& header) {
|
|
57
|
+
|
|
58
|
+
return std::find_if(headers.begin(),
|
|
59
|
+
headers.end(),
|
|
60
|
+
std::bind2nd(MatchFirsts<Header>(), header));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Internal list items classifier, Headers Context */
|
|
64
|
+
template <>
|
|
65
|
+
FORCEINLINE SectionType ClassifyInternaListBlock<HeaderCollection>(const BlockIterator& begin,
|
|
66
|
+
const BlockIterator& end) {
|
|
67
|
+
return UndefinedSectionType;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Children List Block Classifier, HeaderCollection context. */
|
|
71
|
+
template <>
|
|
72
|
+
FORCEINLINE SectionType ClassifyChildrenListBlock<HeaderCollection>(const BlockIterator& begin,
|
|
73
|
+
const BlockIterator& end){
|
|
74
|
+
return UndefinedSectionType;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Block Classifier, Headers Context */
|
|
78
|
+
template <>
|
|
79
|
+
FORCEINLINE SectionType ClassifyBlock<HeaderCollection>(const BlockIterator& begin,
|
|
80
|
+
const BlockIterator& end,
|
|
81
|
+
const SectionType& context) {
|
|
82
|
+
|
|
83
|
+
if (context == UndefinedSectionType &&
|
|
84
|
+
HasHeaderSignature(begin, end)) {
|
|
85
|
+
return HeadersSectionType;
|
|
86
|
+
}
|
|
87
|
+
else if (context == HeadersSectionType) {
|
|
88
|
+
|
|
89
|
+
// SectionType closure
|
|
90
|
+
if (begin->type == ListItemBlockEndType ||
|
|
91
|
+
begin->type == ListBlockEndType)
|
|
92
|
+
return UndefinedSectionType;
|
|
93
|
+
|
|
94
|
+
// Adjacent list item
|
|
95
|
+
if (begin->type == ListItemBlockBeginType)
|
|
96
|
+
return UndefinedSectionType;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return (context == HeadersSectionType) ? context : UndefinedSectionType;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
//
|
|
103
|
+
// Headers SectionType Parser
|
|
104
|
+
//
|
|
105
|
+
template<>
|
|
106
|
+
struct SectionParser<HeaderCollection> {
|
|
107
|
+
|
|
108
|
+
static ParseSectionResult ParseSection(const BlueprintSection& section,
|
|
109
|
+
const BlockIterator& cur,
|
|
110
|
+
BlueprintParserCore& parser,
|
|
111
|
+
HeaderCollection& headers) {
|
|
112
|
+
|
|
113
|
+
ParseSectionResult result = std::make_pair(Result(), cur);
|
|
114
|
+
switch (section.type) {
|
|
115
|
+
case HeadersSectionType:
|
|
116
|
+
result = HandleHeadersSectionBlock(section, cur, parser, headers);
|
|
117
|
+
break;
|
|
118
|
+
|
|
119
|
+
case UndefinedSectionType:
|
|
120
|
+
result.second = CloseList(cur, section.bounds.second);
|
|
121
|
+
break;
|
|
122
|
+
|
|
123
|
+
default:
|
|
124
|
+
result.first.error = UnexpectedBlockError(section, cur, parser.sourceData);
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return result;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
static void Finalize(const SectionBounds& bounds,
|
|
132
|
+
BlueprintParserCore& parser,
|
|
133
|
+
HeaderCollection& headers,
|
|
134
|
+
Result& result) {}
|
|
135
|
+
|
|
136
|
+
static ParseSectionResult HandleHeadersSectionBlock(const BlueprintSection& section,
|
|
137
|
+
const BlockIterator& cur,
|
|
138
|
+
BlueprintParserCore& parser,
|
|
139
|
+
HeaderCollection& headers) {
|
|
140
|
+
|
|
141
|
+
SourceData data;
|
|
142
|
+
SourceDataBlock sourceMap;
|
|
143
|
+
ParseSectionResult result = ParseListPreformattedBlock<HeaderCollection>(section,
|
|
144
|
+
cur,
|
|
145
|
+
parser,
|
|
146
|
+
data,
|
|
147
|
+
sourceMap);
|
|
148
|
+
if (result.first.error.code != Error::OK ||
|
|
149
|
+
parser.sourceData.empty())
|
|
150
|
+
return result;
|
|
151
|
+
|
|
152
|
+
// Proces raw data
|
|
153
|
+
std::vector<std::string> lines = Split(data, '\n');
|
|
154
|
+
for (std::vector<std::string>::iterator line = lines.begin();
|
|
155
|
+
line != lines.end();
|
|
156
|
+
++line) {
|
|
157
|
+
|
|
158
|
+
Header header;
|
|
159
|
+
if (KeyValueFromLine(*line, header)) {
|
|
160
|
+
|
|
161
|
+
if (FindHeader(headers, header) != headers.end()) {
|
|
162
|
+
// WARN: duplicate header on this level
|
|
163
|
+
std::stringstream ss;
|
|
164
|
+
ss << "duplicate definition of '" << header.first << "' header";
|
|
165
|
+
|
|
166
|
+
result.first.warnings.push_back(Warning(ss.str(),
|
|
167
|
+
DuplicateWarning,
|
|
168
|
+
MapSourceDataBlock(sourceMap, parser.sourceData)));
|
|
169
|
+
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
headers.push_back(header);
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
// WARN: unable to parse header
|
|
176
|
+
result.first.warnings.push_back(Warning("unable to parse HTTP header, expected"
|
|
177
|
+
" '<header name> : <header value>', one header per line",
|
|
178
|
+
FormattingWarning,
|
|
179
|
+
MapSourceDataBlock(sourceMap, parser.sourceData)));
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return result;
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
typedef BlockParser<HeaderCollection, SectionParser<HeaderCollection> > HeadersParser;
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Generic HeaderSection parser handler
|
|
191
|
+
*/
|
|
192
|
+
template <class T>
|
|
193
|
+
ParseSectionResult HandleHeaders(const BlueprintSection& section,
|
|
194
|
+
const BlockIterator& cur,
|
|
195
|
+
BlueprintParserCore& parser,
|
|
196
|
+
T& t)
|
|
197
|
+
{
|
|
198
|
+
size_t headerCount = t.headers.size();
|
|
199
|
+
ParseSectionResult result = HeadersParser::Parse(cur,
|
|
200
|
+
section.bounds.second,
|
|
201
|
+
section,
|
|
202
|
+
parser,
|
|
203
|
+
t.headers);
|
|
204
|
+
if (result.first.error.code != Error::OK)
|
|
205
|
+
return result;
|
|
206
|
+
|
|
207
|
+
if (t.headers.size() == headerCount) {
|
|
208
|
+
BlockIterator nameBlock = ListItemNameBlock(cur, section.bounds.second);
|
|
209
|
+
SourceCharactersBlock sourceBlock = CharacterMapForBlock(nameBlock, cur, section.bounds, parser.sourceData);
|
|
210
|
+
result.first.warnings.push_back(Warning("no headers specified",
|
|
211
|
+
FormattingWarning,
|
|
212
|
+
sourceBlock));
|
|
213
|
+
}
|
|
214
|
+
return result;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
/** Helper for handling parsing of deprecated header sections */
|
|
219
|
+
template <typename T>
|
|
220
|
+
ParseSectionResult HandleDeprecatedHeaders(const BlueprintSection& section,
|
|
221
|
+
const BlockIterator& cur,
|
|
222
|
+
BlueprintParserCore& parser,
|
|
223
|
+
T& t) {
|
|
224
|
+
|
|
225
|
+
ParseSectionResult result = HandleHeaders<T>(section, cur, parser, t);
|
|
226
|
+
|
|
227
|
+
// WARN: Deprecated header sections
|
|
228
|
+
std::stringstream ss;
|
|
229
|
+
ss << "the 'headers' section at this level is deprecated and will be removed in a future, use respective payload header section(s) instead";
|
|
230
|
+
BlockIterator nameBlock = ListItemNameBlock(cur, section.bounds.second);
|
|
231
|
+
SourceCharactersBlock sourceBlock = CharacterMapForBlock(nameBlock, cur, section.bounds, parser.sourceData);
|
|
232
|
+
result.first.warnings.push_back(Warning(ss.str(),
|
|
233
|
+
DeprecatedWarning,
|
|
234
|
+
sourceBlock));
|
|
235
|
+
return result;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/** \brief Copy headers into example paylods headers. */
|
|
239
|
+
FORCEINLINE void InjectDeprecatedHeaders(const Collection<Header>::type& headers,
|
|
240
|
+
Collection<TransactionExample>::type& examples)
|
|
241
|
+
{
|
|
242
|
+
for (Collection<TransactionExample>::iterator exampleIt = examples.begin();
|
|
243
|
+
exampleIt != examples.end();
|
|
244
|
+
++exampleIt) {
|
|
245
|
+
|
|
246
|
+
// Requests
|
|
247
|
+
for (Collection<Request>::iterator reqIt = exampleIt->requests.begin();
|
|
248
|
+
reqIt != exampleIt->requests.end();
|
|
249
|
+
++reqIt) {
|
|
250
|
+
|
|
251
|
+
reqIt->headers.insert(reqIt->headers.begin(),
|
|
252
|
+
headers.begin(),
|
|
253
|
+
headers.end());
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Responses
|
|
257
|
+
for (Collection<Response>::iterator resIt = exampleIt->responses.begin();
|
|
258
|
+
resIt != exampleIt->responses.end();
|
|
259
|
+
++resIt) {
|
|
260
|
+
|
|
261
|
+
resIt->headers.insert(resIt->headers.begin(),
|
|
262
|
+
headers.begin(),
|
|
263
|
+
headers.end());
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Checks T's headers for occurence of R's headers, warns if a match is found.
|
|
269
|
+
template <class T, class R>
|
|
270
|
+
void CheckHeaderDuplicates(const T& left,
|
|
271
|
+
const R& right,
|
|
272
|
+
const SourceDataBlock& rightSourceMap,
|
|
273
|
+
const SourceData& sourceData,
|
|
274
|
+
Result& result) {
|
|
275
|
+
|
|
276
|
+
for (HeaderIterator it = right.headers.begin(); it != right.headers.end(); ++it) {
|
|
277
|
+
if (FindHeader(left.headers, *it) != left.headers.end()) {
|
|
278
|
+
// WARN: overshadowing header definition
|
|
279
|
+
std::stringstream ss;
|
|
280
|
+
ss << "overshadowing previous '" << it->first << "' header definition";
|
|
281
|
+
result.warnings.push_back(Warning(ss.str(),
|
|
282
|
+
RedefinitionWarning,
|
|
283
|
+
MapSourceDataBlock(rightSourceMap, sourceData)));
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
#endif
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
//
|
|
2
|
+
// ListBlockUtility.h
|
|
3
|
+
// snowcrash
|
|
4
|
+
//
|
|
5
|
+
// All the cool kids from ListUtility.h live here.
|
|
6
|
+
//
|
|
7
|
+
// Created by Zdenek Nemec on 11/11/13.
|
|
8
|
+
// Copyright (c) 2013 Apiary Inc. All rights reserved.
|
|
9
|
+
//
|
|
10
|
+
|
|
11
|
+
#ifndef SNOWCRASH_LISTBLOCKUTILITY_H
|
|
12
|
+
#define SNOWCRASH_LISTBLOCKUTILITY_H
|
|
13
|
+
|
|
14
|
+
#include "ListUtility.h"
|
|
15
|
+
|
|
16
|
+
namespace snowcrash {
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* \brief Return a first non-signature content block of a list(item).
|
|
20
|
+
* \param begin Begin of the block buffer to examine.
|
|
21
|
+
* \param end End of the block buffer.
|
|
22
|
+
* \return First non-signature content block or begin.
|
|
23
|
+
*
|
|
24
|
+
* Returns first block with the actual content of a list or list item.
|
|
25
|
+
*/
|
|
26
|
+
FORCEINLINE BlockIterator ContentBlock(const BlockIterator& begin,
|
|
27
|
+
const BlockIterator& end) {
|
|
28
|
+
|
|
29
|
+
BlockIterator cur = begin;
|
|
30
|
+
if (cur->type == ListBlockBeginType) {
|
|
31
|
+
if (++cur == end)
|
|
32
|
+
return end;
|
|
33
|
+
|
|
34
|
+
return cur;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (cur->type == ListItemBlockBeginType) {
|
|
38
|
+
if (++cur == end)
|
|
39
|
+
return end;
|
|
40
|
+
|
|
41
|
+
if (cur->type == ListItemBlockEndType)
|
|
42
|
+
return begin;
|
|
43
|
+
|
|
44
|
+
if (cur->type == ParagraphBlockType)
|
|
45
|
+
if (++cur == end)
|
|
46
|
+
return end;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return cur;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* \brief Skips first list item signature block.
|
|
54
|
+
*
|
|
55
|
+
* This function effectively returns the first content block of
|
|
56
|
+
* a list item that is not a signature block. If no such a block exists.
|
|
57
|
+
* a block following the list item is returned. If a list is provided it
|
|
58
|
+
* uses its first list item.
|
|
59
|
+
*/
|
|
60
|
+
FORCEINLINE BlockIterator SkipSignatureBlock(const BlockIterator& begin,
|
|
61
|
+
const BlockIterator& end) {
|
|
62
|
+
|
|
63
|
+
BlockIterator cur = begin;
|
|
64
|
+
|
|
65
|
+
// Skip to fist list item if appropriate
|
|
66
|
+
if (cur->type == ListBlockBeginType) {
|
|
67
|
+
cur = ContentBlock(cur, end);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Skip to first list item content
|
|
71
|
+
if (cur->type == ListItemBlockBeginType) {
|
|
72
|
+
BlockIterator firstContent = ContentBlock(cur, end);
|
|
73
|
+
if (cur != firstContent) {
|
|
74
|
+
cur = firstContent;
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
// No content, just move to the next block
|
|
78
|
+
++cur;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return cur;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Return name block of list item; that is either FirstContentBlock() or
|
|
86
|
+
// matching closing item block for inline items
|
|
87
|
+
FORCEINLINE BlockIterator ListItemNameBlock(const BlockIterator& begin,
|
|
88
|
+
const BlockIterator& end) {
|
|
89
|
+
|
|
90
|
+
BlockIterator cur = FirstContentBlock(begin, end);
|
|
91
|
+
if (cur == end ||
|
|
92
|
+
cur->type != ListBlockBeginType)
|
|
93
|
+
return cur;
|
|
94
|
+
|
|
95
|
+
// Inline list block
|
|
96
|
+
cur = SkipToClosingBlock(cur, end, ListBlockBeginType, ListBlockEndType);
|
|
97
|
+
if (cur != end)
|
|
98
|
+
return ++cur;
|
|
99
|
+
|
|
100
|
+
return cur;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* \brief Eats closing blocks of a list / list item block.
|
|
105
|
+
* \param begin Cursor to a list or list item closing block.
|
|
106
|
+
* \param end End of a block buffer.
|
|
107
|
+
* \return Block AFTER closed list / list item.
|
|
108
|
+
*
|
|
109
|
+
* Skips over subsequent ListItemBlockEndType and ListBlockEndType returning the fist
|
|
110
|
+
* other block after.
|
|
111
|
+
*/
|
|
112
|
+
FORCEINLINE BlockIterator CloseList(const BlockIterator& begin,
|
|
113
|
+
const BlockIterator& end) {
|
|
114
|
+
|
|
115
|
+
BlockIterator cur = begin;
|
|
116
|
+
if (cur != end &&
|
|
117
|
+
cur->type == ListItemBlockEndType) {
|
|
118
|
+
++cur; // eat list item end
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (cur != end &&
|
|
122
|
+
cur->type == ListBlockEndType) {
|
|
123
|
+
++cur; // eat list end
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return cur;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* \brief Skips COMPLETE consecutive (nested) closing elements of a list or a list item.
|
|
131
|
+
* \param begin The begin of a list or a list item.
|
|
132
|
+
* \param end End of markdown block buffer.
|
|
133
|
+
* \return An iterator pointing AFTER the last closing list / list item block.
|
|
134
|
+
*/
|
|
135
|
+
FORCEINLINE BlockIterator CloseNestedList(const BlockIterator& begin,
|
|
136
|
+
const BlockIterator& end) {
|
|
137
|
+
BlockIterator cur = begin;
|
|
138
|
+
while (cur != end &&
|
|
139
|
+
(cur->type == ListItemBlockEndType || cur->type == ListBlockEndType)) {
|
|
140
|
+
cur = CloseList(cur, end);
|
|
141
|
+
}
|
|
142
|
+
return cur;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* \brief Extract the first line of a list item content - its signature
|
|
147
|
+
* \param cur The begining of the list item to get its signature.
|
|
148
|
+
* \param end The begining of a block buffer.
|
|
149
|
+
* \param remainingContent Any additonal content after the first line of signature.
|
|
150
|
+
* \return First line of the list item signature.
|
|
151
|
+
*/
|
|
152
|
+
FORCEINLINE SourceData GetListItemSignature(const BlockIterator& cur,
|
|
153
|
+
const BlockIterator& end,
|
|
154
|
+
SourceData& remainingContent) {
|
|
155
|
+
|
|
156
|
+
BlockIterator sectionCur = ListItemNameBlock(cur, end);
|
|
157
|
+
if (sectionCur == end)
|
|
158
|
+
return SourceData();
|
|
159
|
+
|
|
160
|
+
ContentParts content = ExtractFirstLine(*sectionCur);
|
|
161
|
+
if (content.empty() ||
|
|
162
|
+
content.front().empty())
|
|
163
|
+
return SourceData();
|
|
164
|
+
|
|
165
|
+
if (content.size() == 2)
|
|
166
|
+
remainingContent = content[1];
|
|
167
|
+
|
|
168
|
+
return content[0];
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* \brief Check List Item signature for an addtional content and issue a warning.
|
|
173
|
+
* \param section Current section to be checked.
|
|
174
|
+
* \param cur The begining of the list item to check.
|
|
175
|
+
* \param bounds Bounds within the block buffer.
|
|
176
|
+
* \param sourceData Source data byte buffer.
|
|
177
|
+
* \param placeHint A string explaining the possible place of failure. Might be empty.
|
|
178
|
+
* \param expectedHint A string defining expected content. Might be empty.
|
|
179
|
+
* \param result Result to append the possible warning into.
|
|
180
|
+
* \return True if signagure contains no additional content, false otherwise.
|
|
181
|
+
*/
|
|
182
|
+
FORCEINLINE bool CheckSignatureAdditionalContent(const BlueprintSection& section,
|
|
183
|
+
const BlockIterator& cur,
|
|
184
|
+
const SourceData& sourceData,
|
|
185
|
+
const std::string& placeHint,
|
|
186
|
+
const std::string& expectedHint,
|
|
187
|
+
Result& result)
|
|
188
|
+
{
|
|
189
|
+
SourceData remainingContent;
|
|
190
|
+
SourceData signature = GetListItemSignature(cur, section.bounds.second, remainingContent);
|
|
191
|
+
|
|
192
|
+
if (!remainingContent.empty()) {
|
|
193
|
+
// WARN: Superfluous content in signature
|
|
194
|
+
|
|
195
|
+
std::stringstream ss;
|
|
196
|
+
ss << "ignoring additional content";
|
|
197
|
+
|
|
198
|
+
if (!placeHint.empty())
|
|
199
|
+
ss << " after " << placeHint;
|
|
200
|
+
|
|
201
|
+
if (!expectedHint.empty())
|
|
202
|
+
ss << ", expected " << expectedHint;
|
|
203
|
+
|
|
204
|
+
BlockIterator nameBlock = ListItemNameBlock(cur, section.bounds.second);
|
|
205
|
+
SourceCharactersBlock sourceBlock = CharacterMapForBlock(nameBlock, cur, section.bounds, sourceData);
|
|
206
|
+
result.warnings.push_back(Warning(ss.str(),
|
|
207
|
+
IgnoringWarning,
|
|
208
|
+
sourceBlock));
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return remainingContent.empty();
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* \brief Parses list (item) block as a preformatted code block.
|
|
216
|
+
* \param section Actual section being parsed.
|
|
217
|
+
* \param cur Cursor within the section boundaries.
|
|
218
|
+
* \param parser Parser instance.
|
|
219
|
+
* \param action An output data buffer.
|
|
220
|
+
* \param sourceMap An output source map buffer.
|
|
221
|
+
* \return A block parser section result, pointing AFTER the last block parsed.
|
|
222
|
+
*/
|
|
223
|
+
template <class T>
|
|
224
|
+
FORCEINLINE ParseSectionResult ParseListPreformattedBlock(const BlueprintSection& section,
|
|
225
|
+
const BlockIterator& cur,
|
|
226
|
+
BlueprintParserCore& parser,
|
|
227
|
+
SourceData& data,
|
|
228
|
+
SourceDataBlock& sourceMap) {
|
|
229
|
+
|
|
230
|
+
ParseSectionResult result = std::make_pair(Result(), cur);
|
|
231
|
+
BlockIterator sectionCur = cur;
|
|
232
|
+
|
|
233
|
+
if (sectionCur != section.bounds.first) {
|
|
234
|
+
// Parse subsequent blocks as standalone pre blocks.
|
|
235
|
+
return ParsePreformattedBlock<T>(section, sectionCur, parser, data, sourceMap);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Parse first block of list, throwing away its first line (signature)
|
|
239
|
+
SourceData content;
|
|
240
|
+
SourceData signature = GetListItemSignature(cur, section.bounds.second, content);
|
|
241
|
+
|
|
242
|
+
// Retrieve any extra lines after signature & warn
|
|
243
|
+
if (!content.empty()) {
|
|
244
|
+
|
|
245
|
+
data = content;
|
|
246
|
+
|
|
247
|
+
// WARN: not a preformatted code block
|
|
248
|
+
std::stringstream ss;
|
|
249
|
+
|
|
250
|
+
size_t level = CodeBlockIndentationLevel(section);
|
|
251
|
+
ss << SectionName(section.type) << " asset ";
|
|
252
|
+
ss << "is expected to be a pre-formatted code block, separate it by a newline and ";
|
|
253
|
+
ss << "indent every of its line by ";
|
|
254
|
+
ss << level * 4 << " spaces or " << level << " tabs";
|
|
255
|
+
|
|
256
|
+
BlockIterator nameBlock = ListItemNameBlock(sectionCur, section.bounds.second);
|
|
257
|
+
SourceCharactersBlock sourceBlock = CharacterMapForBlock(nameBlock, cur, section.bounds, parser.sourceData);
|
|
258
|
+
result.first.warnings.push_back(Warning(ss.str(),
|
|
259
|
+
IndentationWarning,
|
|
260
|
+
sourceBlock));
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
sectionCur = FirstContentBlock(cur, section.bounds.second);
|
|
264
|
+
sourceMap = sectionCur->sourceMap;
|
|
265
|
+
|
|
266
|
+
if (sectionCur != section.bounds.second)
|
|
267
|
+
result.second = ++sectionCur;
|
|
268
|
+
|
|
269
|
+
return result;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
#endif
|