Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit f67d553

Browse files
authoredAug 16, 2019
Merge pull request #132 from tgockel/issue/127/vla
Remove use of variable-length array in character conversion code.
2 parents bc8cb77 + 22fd567 commit f67d553

File tree

1 file changed

+48
-28
lines changed

1 file changed

+48
-28
lines changed
 

‎src/jsonv/char_convert.cpp

+48-28
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/** \file
2-
*
2+
*
33
* Copyright (c) 2012-2018 by Travis Gockel. All rights reserved.
44
*
55
* This program is free software: you can redistribute it and/or modify it under the terms of the Apache License
@@ -24,6 +24,26 @@
2424

2525
#include "detail/fixed_map.hpp"
2626

27+
#if __cplusplus >= 201703L || defined __has_include
28+
# if __has_include(<alloca.h>)
29+
# define JSONV_HAS_ALLOCA 1
30+
# include <alloca.h>
31+
# else
32+
# define JSONV_HAS_ALLOCA 0
33+
# endif
34+
#else
35+
# define JSONV_HAS_ALLOCA 0
36+
#endif
37+
38+
#if JSONV_HAS_ALLOCA
39+
# define JSONV_TEMP_BUFFER(type_, name_, elem_count_) \
40+
type_* name_ = reinterpret_cast<type_*>(::alloca(sizeof(type_) * (elem_count_)))
41+
#else
42+
# include <memory>
43+
# define JSONV_TEMP_BUFFER(type_, name_, elem_count_) \
44+
std::unique_ptr<type_[]> name_ = std::make_unique<type_[]>((elem_count_))
45+
#endif
46+
2747
namespace jsonv
2848
{
2949
namespace detail
@@ -51,7 +71,7 @@ decode_error::~decode_error() noexcept
5171
typedef detail::fixed_map<char, char, ESCAPES_LIST(TUPLE_PLUS_1_GEN)> converter_map;
5272

5373
/** These entries are sorted by the numeric value of the ASCII character (\c less_entry_cpp).
54-
*
74+
*
5575
* \note
5676
* The encode and decode map must be in a different order (even though they contain the same data) because the ASCII
5777
* representations of escape sequences are not in the same order as the characters they are escaping.
@@ -163,10 +183,10 @@ static bool utf8_extract_info(char c, unsigned& length, char& bitmask)
163183
static bool utf8_extract_code(const char* c, unsigned length, char bitmask, char32_t& num)
164184
{
165185
const char submask = '\x3f';
166-
186+
167187
num = char32_t(*c & bitmask);
168188
++c;
169-
189+
170190
for (unsigned i = 1; i < length; ++i, ++c)
171191
{
172192
if (char_bitmatch(*c, '\x80', '\x40'))
@@ -180,7 +200,7 @@ static bool utf8_extract_code(const char* c, unsigned length, char bitmask, char
180200
return false;
181201
}
182202
}
183-
203+
184204
return true;
185205
}
186206

@@ -211,7 +231,7 @@ static void utf16_create_surrogates(char32_t codepoint, uint16_t* high, uint16_t
211231
std::ostream& string_encode(std::ostream& stream, string_view source, bool ensure_ascii)
212232
{
213233
typedef string_view::size_type size_type;
214-
234+
215235
for (size_type idx = 0, source_size = source.size(); idx < source_size; /* incremented inline */)
216236
{
217237
const char& current = source[idx];
@@ -225,7 +245,7 @@ std::ostream& string_encode(std::ostream& stream, string_view source, bool ensur
225245
unsigned length;
226246
char bitmask;
227247
bool valid_utf8 = utf8_extract_info(current, length, bitmask);
228-
248+
229249
if (!needs_unicode_escaping(current))
230250
{
231251
stream << current;
@@ -243,7 +263,7 @@ std::ostream& string_encode(std::ostream& stream, string_view source, bool ensur
243263
length = 1;
244264
code = char32_t(current) & 0xff;
245265
}
246-
266+
247267
// if the input string is valid UTF-8, let it pass through
248268
if (valid_utf8 && !ensure_ascii)
249269
{
@@ -266,11 +286,11 @@ std::ostream& string_encode(std::ostream& stream, string_view source, bool ensur
266286
to_hex(stream, low);
267287
}
268288
}
269-
289+
270290
idx += length;
271291
}
272292
}
273-
293+
274294
return stream;
275295
}
276296

@@ -330,7 +350,7 @@ static uint16_t from_hex(const char* s, std::size_t idx_base)
330350
x = uint16_t(x + (from_hex_digit(*s, idx_base + idx) << (idx * 4)));
331351
++s;
332352
}
333-
353+
334354
return x;
335355
}
336356

@@ -373,19 +393,19 @@ static void utf8_append_code(std::string& str, char32_t val)
373393
char c;
374394
std::size_t length;
375395
utf8_sequence_info(val, &length, &c);
376-
396+
377397
char buffer[8];
378398
char* bufferOut = buffer;
379399
*bufferOut++ = c;
380-
400+
381401
std::size_t shift = (length - 2) * 6;
382402
for (std::size_t idx = 1; idx < length; ++idx)
383403
{
384404
c = char('\x80' | ('\x3f' & (val >> shift)));
385405
*bufferOut++ = c;
386406
shift -= 6;
387407
}
388-
408+
389409
str.append(buffer, bufferOut);
390410
}
391411

@@ -418,12 +438,12 @@ template <parse_options::encoding encoding, bool require_printable>
418438
std::string string_decode(string_view source)
419439
{
420440
typedef std::string::size_type size_type;
421-
441+
422442
std::string output;
423443
const char* last_pushed_src = source.data();
424444
size_type utf8_sequence_start = 0;
425445
unsigned remaining_utf8_sequence = 0;
426-
446+
427447
for (size_type idx = 0; idx < source.size(); /* incremented inline */)
428448
{
429449
const char& current = source[idx];
@@ -432,7 +452,7 @@ std::string string_decode(string_view source)
432452
if (current == '\\')
433453
{
434454
output.append(last_pushed_src, source.data()+idx);
435-
455+
436456
const char& next = source[idx + 1];
437457
if (const char* replacement = find_decoding(next))
438458
{
@@ -444,11 +464,11 @@ std::string string_decode(string_view source)
444464
if (idx + 6 > source.size())
445465
throw decode_error(idx, "unterminated Unicode escape sequence (must have 4 hex characters)");
446466
uint16_t hexval = from_hex(&source[idx + 2], idx + 2);
447-
467+
448468
if (encoding == parse_options::encoding::cesu8 || hexval < 0xd800U || hexval > 0xdfffU)
449469
{
450470
utf8_append_code(output, hexval);
451-
471+
452472
idx += 6;
453473
}
454474
// numeric encoding is in U+d800 - U+dfff with UTF-8 output, so deal with surrogate pairing...
@@ -465,9 +485,9 @@ std::string string_decode(string_view source)
465485
char32_t codepoint;
466486
if (!utf16_combine_surrogates(hexval, hexlowval, &codepoint))
467487
throw decode_error(idx, std::string("unpaired high surrogate (") + surrogateString() + ")");
468-
488+
469489
utf8_append_code(output, codepoint);
470-
490+
471491
idx += 12;
472492
}
473493
}
@@ -477,10 +497,10 @@ std::string string_decode(string_view source)
477497
//output += '?'; Maybe better solution if we don't want to throw
478498
//++idx;
479499
}
480-
500+
481501
last_pushed_src = source.data() + idx;
482502
}
483-
else
503+
else
484504
{
485505
unsigned utf8_length;
486506
char utf8_bitmask;
@@ -495,7 +515,7 @@ std::string string_decode(string_view source)
495515
throw decode_error(idx, os.str());
496516
}
497517
);
498-
518+
499519
if (utf8_length > 1)
500520
{
501521
utf8_sequence_start = idx;
@@ -545,7 +565,7 @@ std::string string_decode(string_view source)
545565
}
546566
}
547567
}
548-
568+
549569
if (encoding != parse_options::encoding::cesu8 && remaining_utf8_sequence > 0)
550570
{
551571
std::ostringstream os;
@@ -558,7 +578,7 @@ std::string string_decode(string_view source)
558578
os << '\"';
559579
throw decode_error(utf8_sequence_start, os.str());
560580
}
561-
581+
562582
output.append(last_pushed_src, source.end());
563583
return output;
564584
}
@@ -580,7 +600,7 @@ string_decode_fn get_string_decoder(parse_options::encoding encoding)
580600
std::wstring convert_to_wide(string_view source)
581601
{
582602
// Step 1: Determine the codepoints from the source
583-
char32_t unicode_buff[source.size()];
603+
JSONV_TEMP_BUFFER(char32_t, unicode_buff, source.size());
584604
std::size_t unicode_idx = 0;
585605
std::size_t large_codes = 0;
586606

@@ -669,7 +689,7 @@ std::wstring convert_to_wide(string_view source)
669689
static std::string convert_to_narrow(const wchar_t* source_data, std::size_t source_size)
670690
{
671691
// Step 1: Extract codepoints from the source
672-
char32_t unicode_buff[source_size];
692+
JSONV_TEMP_BUFFER(char32_t, unicode_buff, source_size);
673693
std::size_t unicode_idx = 0;
674694
std::size_t out_chars = 0;
675695

0 commit comments

Comments
 (0)
Please sign in to comment.