redsnow 0.2.1 → 0.3.0
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 +4 -4
- data/CHANGELOG.md +2 -0
- data/ext/snowcrash/bin/snowcrash +0 -0
- data/ext/snowcrash/snowcrash.xcworkspace/contents.xcworkspacedata +10 -0
- data/ext/snowcrash/src/ActionParser.h +35 -33
- data/ext/snowcrash/src/AssetParser.h +17 -17
- data/ext/snowcrash/src/Blueprint.h +101 -66
- data/ext/snowcrash/src/BlueprintParser.h +219 -10
- data/ext/snowcrash/src/BlueprintSourcemap.h +1 -1
- data/ext/snowcrash/src/BlueprintUtility.h +14 -14
- data/ext/snowcrash/src/CBlueprint.cc +29 -10
- data/ext/snowcrash/src/CBlueprint.h +19 -3
- data/ext/snowcrash/src/CBlueprintSourcemap.cc +20 -10
- data/ext/snowcrash/src/CBlueprintSourcemap.h +12 -3
- data/ext/snowcrash/src/CodeBlockUtility.h +25 -25
- data/ext/snowcrash/src/HTTP.cc +3 -0
- data/ext/snowcrash/src/HTTP.h +9 -6
- data/ext/snowcrash/src/HeadersParser.h +34 -14
- data/ext/snowcrash/src/ParameterParser.h +21 -21
- data/ext/snowcrash/src/ParametersParser.h +6 -5
- data/ext/snowcrash/src/PayloadParser.h +174 -129
- data/ext/snowcrash/src/RegexMatch.h +3 -3
- data/ext/snowcrash/src/ResourceGroupParser.h +5 -4
- data/ext/snowcrash/src/ResourceParser.h +30 -26
- data/ext/snowcrash/src/Section.cc +6 -6
- data/ext/snowcrash/src/Section.h +2 -2
- data/ext/snowcrash/src/SectionParser.h +41 -41
- data/ext/snowcrash/src/SectionParserData.h +10 -10
- data/ext/snowcrash/src/SectionProcessor.h +70 -30
- data/ext/snowcrash/src/Serialize.h +3 -3
- data/ext/snowcrash/src/SerializeJSON.cc +124 -96
- data/ext/snowcrash/src/SerializeJSON.h +1 -1
- data/ext/snowcrash/src/SerializeYAML.cc +71 -53
- data/ext/snowcrash/src/SerializeYAML.h +1 -1
- data/ext/snowcrash/src/Signature.cc +2 -2
- data/ext/snowcrash/src/Signature.h +1 -1
- data/ext/snowcrash/src/SourceAnnotation.h +23 -23
- data/ext/snowcrash/src/StringUtility.h +71 -9
- data/ext/snowcrash/src/SymbolTable.h +17 -17
- data/ext/snowcrash/src/UriTemplateParser.cc +5 -5
- data/ext/snowcrash/src/UriTemplateParser.h +9 -9
- data/ext/snowcrash/src/ValuesParser.h +2 -2
- data/ext/snowcrash/src/Version.h +1 -1
- data/ext/snowcrash/src/csnowcrash.cc +10 -8
- data/ext/snowcrash/src/snowcrash.cc +9 -9
- data/ext/snowcrash/src/snowcrash.h +6 -8
- data/ext/snowcrash/src/snowcrash/snowcrash.cc +14 -14
- data/ext/snowcrash/src/win/RegexMatch.cc +7 -7
- data/ext/snowcrash/tools/gyp/pylib/gyp/__init__.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/common.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/__init__.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/make.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/xcode.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/input.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/xcode_emulation.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/xcodeproj_file.pyc +0 -0
- data/ext/snowcrash/tools/homebrew/snowcrash.rb +1 -1
- data/lib/redsnow/binding.rb +8 -2
- data/lib/redsnow/blueprint.rb +4 -3
- data/lib/redsnow/sourcemap.rb +6 -4
- data/lib/redsnow/version.rb +1 -1
- metadata +4 -17
@@ -272,16 +272,6 @@ SC_API const sc_source_map_t* sc_sm_payload_name(const sc_sm_payload_t* handle)
|
|
272
272
|
return AS_CTYPE(sc_source_map_t, &p->name.sourceMap);
|
273
273
|
}
|
274
274
|
|
275
|
-
/** TODO: Need to change this to use the "Reference" data structure */
|
276
|
-
SC_API const sc_source_map_t* sc_sm_payload_symbol(const sc_sm_payload_t* handle)
|
277
|
-
{
|
278
|
-
const snowcrash::SourceMap<snowcrash::Payload>* p = AS_CTYPE(snowcrash::SourceMap<snowcrash::Payload>, handle);
|
279
|
-
if (!p)
|
280
|
-
return NULL;
|
281
|
-
|
282
|
-
return AS_CTYPE(sc_source_map_t, &p->symbol.sourceMap);
|
283
|
-
}
|
284
|
-
|
285
275
|
SC_API const sc_source_map_t* sc_sm_payload_description(const sc_sm_payload_t* handle)
|
286
276
|
{
|
287
277
|
const snowcrash::SourceMap<snowcrash::Payload>* p = AS_CTYPE(snowcrash::SourceMap<snowcrash::Payload>, handle);
|
@@ -311,6 +301,26 @@ SC_API const sc_source_map_t* sc_sm_payload_schema(const sc_sm_payload_t* handle
|
|
311
301
|
|
312
302
|
/*----------------------------------------------------------------------*/
|
313
303
|
|
304
|
+
SC_API const sc_sm_reference_t* sc_sm_reference_handle(const sc_sm_payload_t* handle)
|
305
|
+
{
|
306
|
+
const snowcrash::SourceMap<snowcrash::Payload>* p = AS_CTYPE(snowcrash::SourceMap<snowcrash::Payload>, handle);
|
307
|
+
if(!p)
|
308
|
+
return NULL;
|
309
|
+
|
310
|
+
return AS_CTYPE(sc_sm_reference_t, &p->reference);
|
311
|
+
}
|
312
|
+
|
313
|
+
SC_API const sc_source_map_t* sc_sm_reference(const sc_sm_reference_t* handle)
|
314
|
+
{
|
315
|
+
const snowcrash::SourceMap<snowcrash::Reference>* p = AS_CTYPE(snowcrash::SourceMap<snowcrash::Reference>, handle);
|
316
|
+
if (!p)
|
317
|
+
return NULL;
|
318
|
+
|
319
|
+
return AS_CTYPE(sc_source_map_t, &p->sourceMap);
|
320
|
+
}
|
321
|
+
|
322
|
+
/*----------------------------------------------------------------------*/
|
323
|
+
|
314
324
|
SC_API const sc_sm_parameter_collection_t* sc_sm_parameter_collection_handle_payload(const sc_sm_payload_t* handle)
|
315
325
|
{
|
316
326
|
const snowcrash::SourceMap<snowcrash::Payload>* p = AS_CTYPE(snowcrash::SourceMap<snowcrash::Payload>, handle);
|
@@ -53,6 +53,10 @@ extern "C" {
|
|
53
53
|
struct sc_sm_resource_model_s;
|
54
54
|
typedef struct sc_sm_resource_model_s sc_sm_resource_model_t;
|
55
55
|
|
56
|
+
/** Class Reference source map wrapper */
|
57
|
+
struct sc_sm_reference_s;
|
58
|
+
typedef struct sc_sm_reference_s sc_sm_reference_t;
|
59
|
+
|
56
60
|
/** Array Payload Collection source map wrapper */
|
57
61
|
struct sc_sm_payload_collection_s;
|
58
62
|
typedef struct sc_sm_payload_collection_s sc_sm_payload_collection_t;
|
@@ -205,9 +209,6 @@ extern "C" {
|
|
205
209
|
/** \returns Payload name source map */
|
206
210
|
SC_API const sc_source_map_t* sc_sm_payload_name(const sc_sm_payload_t* handle);
|
207
211
|
|
208
|
-
/** \returns Payload symbol name source map */
|
209
|
-
SC_API const sc_source_map_t* sc_sm_payload_symbol(const sc_sm_payload_t* handle);
|
210
|
-
|
211
212
|
/** \returns Payload description source map */
|
212
213
|
SC_API const sc_source_map_t* sc_sm_payload_description(const sc_sm_payload_t* handle);
|
213
214
|
|
@@ -219,6 +220,14 @@ extern "C" {
|
|
219
220
|
|
220
221
|
/*----------------------------------------------------------------------*/
|
221
222
|
|
223
|
+
/** \returns Reference source map handle */
|
224
|
+
SC_API const sc_sm_reference_t* sc_sm_reference_handle(const sc_sm_payload_t* handle);
|
225
|
+
|
226
|
+
/** \returns Reference identifier source map */
|
227
|
+
SC_API const sc_source_map_t* sc_sm_reference(const sc_sm_reference_t* handle);
|
228
|
+
|
229
|
+
/*----------------------------------------------------------------------*/
|
230
|
+
|
222
231
|
/** \returns Parameter Collection source map array handle from Payload source map */
|
223
232
|
SC_API const sc_sm_parameter_collection_t* sc_sm_parameter_collection_handle_payload(const sc_sm_payload_t* handle);
|
224
233
|
|
@@ -14,9 +14,9 @@
|
|
14
14
|
#include "StringUtility.h"
|
15
15
|
|
16
16
|
namespace snowcrash {
|
17
|
-
|
17
|
+
|
18
18
|
struct CodeBlockUtility {
|
19
|
-
|
19
|
+
|
20
20
|
/**
|
21
21
|
* \brief Expected indentation level of a code block.
|
22
22
|
*
|
@@ -30,21 +30,21 @@ namespace snowcrash {
|
|
30
30
|
type == ResourceGroupSectionType ||
|
31
31
|
type == ResourceSectionType ||
|
32
32
|
type == ActionSectionType) {
|
33
|
-
|
33
|
+
|
34
34
|
return 1;
|
35
35
|
}
|
36
36
|
else if (type == RequestBodySectionType ||
|
37
37
|
type == ResponseBodySectionType ||
|
38
38
|
type == ModelBodySectionType) {
|
39
|
-
|
39
|
+
|
40
40
|
return 2;
|
41
41
|
}
|
42
42
|
else {
|
43
|
-
|
43
|
+
|
44
44
|
return 3;
|
45
45
|
}
|
46
46
|
}
|
47
|
-
|
47
|
+
|
48
48
|
/**
|
49
49
|
* \brief Retrieve the textual content of a Markdown node as if it was a code block.
|
50
50
|
* \param pd Parser status
|
@@ -57,14 +57,14 @@ namespace snowcrash {
|
|
57
57
|
mdp::ByteBuffer& content) {
|
58
58
|
|
59
59
|
checkPossibleReference(node, pd, report);
|
60
|
-
|
60
|
+
|
61
61
|
if (node->type == mdp::CodeMarkdownNodeType) {
|
62
62
|
content += node->text;
|
63
63
|
|
64
64
|
checkExcessiveIndentation(node, pd, report);
|
65
65
|
return;
|
66
66
|
}
|
67
|
-
|
67
|
+
|
68
68
|
// Other blocks, process & warn
|
69
69
|
content += mdp::MapBytesRangeSet(node->sourceMap, pd.sourceData);
|
70
70
|
|
@@ -79,25 +79,25 @@ namespace snowcrash {
|
|
79
79
|
|
80
80
|
ss << " is expected to be a pre-formatted code block, every of its line indented by exactly ";
|
81
81
|
ss << level * 4 << " spaces or " << level << " tabs";
|
82
|
-
|
82
|
+
|
83
83
|
mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
|
84
84
|
report.warnings.push_back(Warning(ss.str(),
|
85
85
|
IndentationWarning,
|
86
86
|
sourceMap));
|
87
87
|
}
|
88
|
-
|
88
|
+
|
89
89
|
/** \brief Retrieve the textual content of a signature markdown */
|
90
90
|
static void signatureContentAsCodeBlock(const MarkdownNodeIterator& node,
|
91
91
|
const SectionParserData& pd,
|
92
92
|
Report& report,
|
93
93
|
mdp::ByteBuffer& content) {
|
94
|
-
|
94
|
+
|
95
95
|
mdp::ByteBuffer remainingContent;
|
96
96
|
GetFirstLine(node->text, remainingContent);
|
97
|
-
|
97
|
+
|
98
98
|
if (remainingContent.empty())
|
99
99
|
return;
|
100
|
-
|
100
|
+
|
101
101
|
content += remainingContent;
|
102
102
|
content += "\n";
|
103
103
|
|
@@ -114,13 +114,13 @@ namespace snowcrash {
|
|
114
114
|
ss << " is expected to be a pre-formatted code block, separate it by a newline and ";
|
115
115
|
ss << "indent every of its line by ";
|
116
116
|
ss << level * 4 << " spaces or " << level << " tabs";
|
117
|
-
|
117
|
+
|
118
118
|
mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
|
119
119
|
report.warnings.push_back(Warning(ss.str(),
|
120
120
|
IndentationWarning,
|
121
121
|
sourceMap));
|
122
122
|
}
|
123
|
-
|
123
|
+
|
124
124
|
/**
|
125
125
|
* \brief Check for potential excessive indentation of a list section
|
126
126
|
* \return True if code block contains a recognized list section, false otherwise.
|
@@ -128,7 +128,7 @@ namespace snowcrash {
|
|
128
128
|
static bool checkExcessiveIndentation(const MarkdownNodeIterator& node,
|
129
129
|
const SectionParserData& pd,
|
130
130
|
Report& report) {
|
131
|
-
|
131
|
+
|
132
132
|
// Check for possible superfluous indentation of a recognized list items.
|
133
133
|
mdp::ByteBuffer r;
|
134
134
|
mdp::ByteBuffer line = GetFirstLine(node->text, r);
|
@@ -138,11 +138,11 @@ namespace snowcrash {
|
|
138
138
|
if (line.empty() ||
|
139
139
|
(line[0] != '-' && line[0] != '+' && line[0] != '*'))
|
140
140
|
return false;
|
141
|
-
|
141
|
+
|
142
142
|
// Skip leading Markdown list item mark
|
143
143
|
std::string signature = line.substr(1, std::string::npos);
|
144
144
|
TrimStringStart(signature);
|
145
|
-
|
145
|
+
|
146
146
|
SectionType type = RecognizeCodeBlockFirstLine(signature);
|
147
147
|
|
148
148
|
if (type != UndefinedSectionType) {
|
@@ -172,7 +172,7 @@ namespace snowcrash {
|
|
172
172
|
IndentationWarning,
|
173
173
|
sourceMap));
|
174
174
|
}
|
175
|
-
|
175
|
+
|
176
176
|
return false;
|
177
177
|
}
|
178
178
|
|
@@ -184,15 +184,15 @@ namespace snowcrash {
|
|
184
184
|
*/
|
185
185
|
static bool keyValueFromLine(const mdp::ByteBuffer& line,
|
186
186
|
KeyValuePair& keyValuePair) {
|
187
|
-
|
187
|
+
|
188
188
|
std::vector<std::string> rawMetadata = SplitOnFirst(line, ':');
|
189
189
|
if (rawMetadata.size() != 2)
|
190
190
|
return false;
|
191
|
-
|
191
|
+
|
192
192
|
keyValuePair = std::make_pair(rawMetadata[0], rawMetadata[1]);
|
193
193
|
TrimString(keyValuePair.first);
|
194
194
|
TrimString(keyValuePair.second);
|
195
|
-
|
195
|
+
|
196
196
|
return (!keyValuePair.first.empty() && !keyValuePair.second.empty());
|
197
197
|
}
|
198
198
|
|
@@ -218,14 +218,14 @@ namespace snowcrash {
|
|
218
218
|
|
219
219
|
TwoNewLines(asset);
|
220
220
|
out += asset;
|
221
|
-
|
221
|
+
|
222
222
|
size_t level = CodeBlockUtility::codeBlockIndentationLevel(sectionType);
|
223
223
|
|
224
224
|
if (node->type == mdp::CodeMarkdownNodeType)
|
225
225
|
level--; // Deduct one level for a code block
|
226
226
|
|
227
227
|
checkPossibleReference(node, pd, report);
|
228
|
-
|
228
|
+
|
229
229
|
if (level) {
|
230
230
|
// WARN: Dangling asset
|
231
231
|
std::stringstream ss;
|
@@ -250,7 +250,7 @@ namespace snowcrash {
|
|
250
250
|
Report& report) {
|
251
251
|
|
252
252
|
mdp::ByteBuffer source = node->text;
|
253
|
-
|
253
|
+
Identifier symbol;
|
254
254
|
|
255
255
|
TrimString(source);
|
256
256
|
|
data/ext/snowcrash/src/HTTP.cc
CHANGED
@@ -15,6 +15,9 @@ const std::string HTTPHeaderName::ContentLength = "Content-Length";
|
|
15
15
|
const std::string HTTPHeaderName::ContentType = "Content-Type";
|
16
16
|
const std::string HTTPHeaderName::TransferEncoding = "Transfer-Encoding";
|
17
17
|
|
18
|
+
const std::string HTTPHeaderName::SetCookie = "Set-Cookie";
|
19
|
+
const std::string HTTPHeaderName::Link = "Link";
|
20
|
+
|
18
21
|
const std::string HTTPMethodName::Head = "HEAD";
|
19
22
|
const std::string HTTPMethodName::Connect = "CONNECT";
|
20
23
|
|
data/ext/snowcrash/src/HTTP.h
CHANGED
@@ -13,7 +13,7 @@
|
|
13
13
|
#include "Blueprint.h"
|
14
14
|
|
15
15
|
/**
|
16
|
-
* \brief HTTP Methods
|
16
|
+
* \brief HTTP Methods
|
17
17
|
*
|
18
18
|
* Technical note: Using preprocessor macro instead of strict
|
19
19
|
* defined type due to C++98 string concatenation limitations.
|
@@ -21,7 +21,7 @@
|
|
21
21
|
*/
|
22
22
|
#define HTTP_REQUEST_METHOD "(GET|POST|PUT|DELETE|OPTIONS|PATCH|PROPPATCH|LOCK|UNLOCK|COPY|MOVE|MKCOL|HEAD|LINK|UNLINK|CONNECT)"
|
23
23
|
|
24
|
-
/**
|
24
|
+
/**
|
25
25
|
* \brief URI Template.
|
26
26
|
*
|
27
27
|
* See previous technical note (using macro).
|
@@ -29,7 +29,7 @@
|
|
29
29
|
#define URI_TEMPLATE "(/.*)"
|
30
30
|
|
31
31
|
namespace snowcrash {
|
32
|
-
|
32
|
+
|
33
33
|
/**
|
34
34
|
* Selected HTTP Header names.
|
35
35
|
*/
|
@@ -38,6 +38,9 @@ namespace snowcrash {
|
|
38
38
|
static const std::string ContentLength;
|
39
39
|
static const std::string ContentType;
|
40
40
|
static const std::string TransferEncoding;
|
41
|
+
|
42
|
+
static const std::string SetCookie;
|
43
|
+
static const std::string Link;
|
41
44
|
};
|
42
45
|
|
43
46
|
/**
|
@@ -57,9 +60,9 @@ namespace snowcrash {
|
|
57
60
|
* Traits of a HTTP response.
|
58
61
|
*/
|
59
62
|
struct HTTPResponseTraits {
|
60
|
-
|
63
|
+
|
61
64
|
bool allowBody; /// < Response body is allowed.
|
62
|
-
|
65
|
+
|
63
66
|
HTTPResponseTraits() : allowBody(true) {}
|
64
67
|
};
|
65
68
|
|
@@ -86,7 +89,7 @@ namespace snowcrash {
|
|
86
89
|
HTTPStatusCode code;
|
87
90
|
StatusCodeTraits() : code(0) {}
|
88
91
|
};
|
89
|
-
|
92
|
+
|
90
93
|
/**
|
91
94
|
* \brief Retrieve response traits for given HTTP method.
|
92
95
|
* \param method HTTP method to retrieve traits for.
|
@@ -22,18 +22,18 @@ namespace snowcrash {
|
|
22
22
|
|
23
23
|
/** Header Iterator in its containment group */
|
24
24
|
typedef Collection<Header>::const_iterator HeaderIterator;
|
25
|
-
|
25
|
+
|
26
26
|
/**
|
27
27
|
* Headers Section Processor
|
28
28
|
*/
|
29
29
|
template<>
|
30
30
|
struct SectionProcessor<Headers> : public SectionProcessorBase<Headers> {
|
31
|
-
|
31
|
+
|
32
32
|
static MarkdownNodeIterator processSignature(const MarkdownNodeIterator& node,
|
33
33
|
const MarkdownNodes& siblings,
|
34
34
|
SectionParserData& pd,
|
35
35
|
SectionLayout& layout,
|
36
|
-
|
36
|
+
const ParseResultRef<Headers>& out) {
|
37
37
|
|
38
38
|
mdp::ByteBuffer content;
|
39
39
|
CodeBlockUtility::signatureContentAsCodeBlock(node, pd, out.report, content);
|
@@ -42,11 +42,11 @@ namespace snowcrash {
|
|
42
42
|
|
43
43
|
return ++MarkdownNodeIterator(node);
|
44
44
|
}
|
45
|
-
|
45
|
+
|
46
46
|
static MarkdownNodeIterator processDescription(const MarkdownNodeIterator& node,
|
47
47
|
const MarkdownNodes& siblings,
|
48
48
|
SectionParserData& pd,
|
49
|
-
|
49
|
+
const ParseResultRef<Headers>& out) {
|
50
50
|
|
51
51
|
return node;
|
52
52
|
}
|
@@ -54,7 +54,7 @@ namespace snowcrash {
|
|
54
54
|
static MarkdownNodeIterator processContent(const MarkdownNodeIterator& node,
|
55
55
|
const MarkdownNodes& siblings,
|
56
56
|
SectionParserData& pd,
|
57
|
-
|
57
|
+
const ParseResultRef<Headers>& out) {
|
58
58
|
|
59
59
|
mdp::ByteBuffer content;
|
60
60
|
CodeBlockUtility::contentAsCodeBlock(node, pd, out.report, content);
|
@@ -63,18 +63,18 @@ namespace snowcrash {
|
|
63
63
|
|
64
64
|
return ++MarkdownNodeIterator(node);
|
65
65
|
}
|
66
|
-
|
66
|
+
|
67
67
|
static bool isDescriptionNode(const MarkdownNodeIterator& node,
|
68
68
|
SectionType sectionType) {
|
69
69
|
return false;
|
70
70
|
}
|
71
|
-
|
71
|
+
|
72
72
|
static bool isContentNode(const MarkdownNodeIterator& node,
|
73
73
|
SectionType sectionType) {
|
74
74
|
|
75
75
|
return (SectionKeywordSignature(node) == UndefinedSectionType);
|
76
76
|
}
|
77
|
-
|
77
|
+
|
78
78
|
static SectionType sectionType(const MarkdownNodeIterator& node) {
|
79
79
|
|
80
80
|
if (node->type == mdp::ListItemMarkdownNodeType
|
@@ -83,7 +83,7 @@ namespace snowcrash {
|
|
83
83
|
mdp::ByteBuffer subject = node->children().front().text;
|
84
84
|
mdp::ByteBuffer signature;
|
85
85
|
mdp::ByteBuffer remainingContent;
|
86
|
-
|
86
|
+
|
87
87
|
signature = GetFirstLine(subject, remainingContent);
|
88
88
|
TrimString(signature);
|
89
89
|
|
@@ -96,7 +96,7 @@ namespace snowcrash {
|
|
96
96
|
|
97
97
|
static void finalize(const MarkdownNodeIterator& node,
|
98
98
|
SectionParserData& pd,
|
99
|
-
|
99
|
+
const ParseResultRef<Headers>& out) {
|
100
100
|
|
101
101
|
if (out.node.empty()) {
|
102
102
|
|
@@ -112,7 +112,7 @@ namespace snowcrash {
|
|
112
112
|
static void headersFromContent(const MarkdownNodeIterator& node,
|
113
113
|
const mdp::ByteBuffer& content,
|
114
114
|
SectionParserData& pd,
|
115
|
-
|
115
|
+
const ParseResultRef<Headers>& out) {
|
116
116
|
|
117
117
|
std::vector<std::string> lines = Split(content, '\n');
|
118
118
|
|
@@ -127,7 +127,7 @@ namespace snowcrash {
|
|
127
127
|
Header header;
|
128
128
|
|
129
129
|
if (CodeBlockUtility::keyValueFromLine(*line, header)) {
|
130
|
-
if (findHeader(out.node, header) != out.node.end()) {
|
130
|
+
if (findHeader(out.node, header) != out.node.end() && !isAllowedMultipleDefinition(header)) {
|
131
131
|
// WARN: duplicate header on this level
|
132
132
|
std::stringstream ss;
|
133
133
|
|
@@ -228,7 +228,27 @@ namespace snowcrash {
|
|
228
228
|
|
229
229
|
return std::find_if(headers.begin(),
|
230
230
|
headers.end(),
|
231
|
-
std::bind2nd(MatchFirsts<Header>(), header));
|
231
|
+
std::bind2nd(MatchFirsts<Header, IEqual<typename Header::first_type> >(), header));
|
232
|
+
}
|
233
|
+
|
234
|
+
typedef std::vector<std::string> HeadersKeyCollection;
|
235
|
+
/** Get collection of allowed keywords - workarround due to C++98 restriction - static initialization of vector */
|
236
|
+
static const HeadersKeyCollection& getAllowedMultipleDefinitions() {
|
237
|
+
static std::string keys[] = {
|
238
|
+
HTTPHeaderName::SetCookie,
|
239
|
+
HTTPHeaderName::Link,
|
240
|
+
};
|
241
|
+
|
242
|
+
static const HeadersKeyCollection allowedMultipleDefinitions(keys, keys + (sizeof(keys)/sizeof(keys[0])));
|
243
|
+
return allowedMultipleDefinitions;
|
244
|
+
}
|
245
|
+
|
246
|
+
/** Check if Header name has allowed multiple definitions */
|
247
|
+
static bool isAllowedMultipleDefinition(const Header& header) {
|
248
|
+
const HeadersKeyCollection& keys = getAllowedMultipleDefinitions();
|
249
|
+
return std::find_if(keys.begin(),
|
250
|
+
keys.end(),
|
251
|
+
std::bind1st(MatchFirstWith<Header, std::string, IEqual<std::string> >(), header)) != keys.end();
|
232
252
|
}
|
233
253
|
};
|
234
254
|
|