Skip to content

Commit

Permalink
Simplify internal copy of std_data_json: remove support for strings o…
Browse files Browse the repository at this point in the history
…ther than `string`.

This avoids a linker error on 2.099.1.
  • Loading branch information
FeepingCreature committed Jun 27, 2022
1 parent e8b5e1a commit 7e38129
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 82 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Expand Up @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.4.8] - 2022-06-22
### Fixed
- Simplify internal copy of std_data_json: remove support for strings other than `string`.
This avoids a linker error on 2.099.1.

## [1.4.7] - 2022-03-25
### Fixed
- Encode null classes as JSON "null".
Expand Down
14 changes: 7 additions & 7 deletions src/funkwerk/stdx/data/json/generator.d
Expand Up @@ -67,7 +67,7 @@ string toJSON(GeneratorOptions options = GeneratorOptions.init, Input)(Input tok
return dst.data;
}
/// ditto
string toJSON(GeneratorOptions options = GeneratorOptions.init, String)(JSONToken!String token)
string toJSON(GeneratorOptions options = GeneratorOptions.init)(JSONToken token)
{
import std.array;
auto dst = appender!string();
Expand Down Expand Up @@ -116,7 +116,7 @@ string toJSON(GeneratorOptions options = GeneratorOptions.init, String)(JSONToke
auto tokens = lexJSON(`{"a": [], "b": [1, {}, null, true, false]}`);
assert(tokens.toJSON!(GeneratorOptions.compact)() == `{"a":[],"b":[1,{},null,true,false]}`);

JSONToken!string tok;
JSONToken tok;
tok.string = "Hello World";
assert(tok.toJSON() == `"Hello World"`);
}
Expand Down Expand Up @@ -164,7 +164,7 @@ void writeJSON(GeneratorOptions options = GeneratorOptions.init, Output, Input)(
}
}
/// ditto
void writeJSON(GeneratorOptions options = GeneratorOptions.init, String, Output)(in ref JSONToken!String token, ref Output output)
void writeJSON(GeneratorOptions options = GeneratorOptions.init, Output)(in ref JSONToken token, ref Output output)
if (isOutputRange!(Output, char))
{
final switch (token.kind) with (JSONTokenKind)
Expand Down Expand Up @@ -220,7 +220,7 @@ struct JSONOutputRange(R, GeneratorOptions options = GeneratorOptions.init)

/** Writes a single JSON primitive to the destination character range.
*/
void put(String)(JSONParserNode!String node)
void put(JSONParserNode node)
{
enum pretty_print = (options & GeneratorOptions.compact) == 0;

Expand Down Expand Up @@ -273,9 +273,9 @@ struct JSONOutputRange(R, GeneratorOptions options = GeneratorOptions.init)
}
}
/// ditto
void put(String)(JSONToken!String token)
void put(JSONToken token)
{
final switch (token.kind) with (JSONToken.Kind) {
final switch (token.kind) with (JSONTokenKind) {
case none: assert(false);
case error: m_output.put("_error_"); break;
case null_: put(null); break;
Expand All @@ -301,7 +301,7 @@ struct JSONOutputRange(R, GeneratorOptions options = GeneratorOptions.init)
/// ditto
void put(double value) { m_output.writeNumber!options(value); }
/// ditto
void put(String)(JSONString!String value)
void put(JSONString value)
{
auto s = value.anyValue;
if (s[0]) put(s[1]); // decoded string
Expand Down
84 changes: 39 additions & 45 deletions src/funkwerk/stdx/data/json/lexer.d
Expand Up @@ -62,12 +62,12 @@ import funkwerk.stdx.data.json.foundation;
* Instead, a token with kind $(D JSONToken.Kind.error) is generated as the
* last token in the range.
*/
JSONLexerRange!(Input, options, String) lexJSON
(LexOptions options = LexOptions.init, String = string, Input)
JSONLexerRange!(Input, options) lexJSON
(LexOptions options = LexOptions.init, Input)
(Input input, string filename = null)
if (isInputRange!Input && (isSomeChar!(ElementType!Input) || isIntegral!(ElementType!Input)))
{
return JSONLexerRange!(Input, options, String)(input, filename);
return JSONLexerRange!(Input, options)(input, filename);
}

///
Expand Down Expand Up @@ -204,7 +204,7 @@ unittest { // test built-in UTF validation
*
* See $(D lexJSON) for more information.
*/
struct JSONLexerRange(Input, LexOptions options = LexOptions.init, String = string)
struct JSONLexerRange(Input, LexOptions options = LexOptions.init)
if (isInputRange!Input && (isSomeChar!(ElementType!Input) || isIntegral!(ElementType!Input)))
{
import std.string : representation;
Expand All @@ -222,7 +222,7 @@ struct JSONLexerRange(Input, LexOptions options = LexOptions.init, String = stri
private
{
InternalInput _input;
JSONToken!String _front;
JSONToken _front;
Location _loc;
string _error;
}
Expand Down Expand Up @@ -259,7 +259,7 @@ struct JSONLexerRange(Input, LexOptions options = LexOptions.init, String = stri
/**
* Returns the current token in the stream.
*/
@property ref const(JSONToken!String) front()
@property ref const(JSONToken) front()
{
ensureFrontValid();
return _front;
Expand Down Expand Up @@ -398,7 +398,7 @@ struct JSONLexerRange(Input, LexOptions options = LexOptions.init, String = stri

private void parseString()
{
static if ((is(Input == string) || is(Input == immutable(ubyte)[])) && is(String == string)) // TODO: make this work for other kinds of "String"
static if ((is(Input == string) || is(Input == immutable(ubyte)[])))
{
InternalInput lit;
bool has_escapes = false;
Expand All @@ -412,7 +412,7 @@ struct JSONLexerRange(Input, LexOptions options = LexOptions.init, String = stri
return;
}
}
JSONString!String js;
JSONString js;
if (has_escapes) js.rawValue = litstr;
else js.value = litstr[1 .. $-1];
_front.string = js;
Expand All @@ -422,12 +422,12 @@ struct JSONLexerRange(Input, LexOptions options = LexOptions.init, String = stri
else
{
bool appender_init = false;
Appender!String dst;
String slice;
Appender!string dst;
string slice;

void initAppender()
@safe {
dst = appender!String();
dst = appender!string();
appender_init = true;
}

Expand Down Expand Up @@ -654,7 +654,7 @@ struct JSONLexerRange(Input, LexOptions options = LexOptions.init, String = stri
import std.exception;
import std.string : format, representation;

static JSONString!string parseStringHelper(R)(ref R input, ref Location loc)
static JSONString parseStringHelper(R)(ref R input, ref Location loc)
{
auto rng = JSONLexerRange!R(input);
rng.parseString();
Expand Down Expand Up @@ -844,7 +844,7 @@ struct JSONLexerRange(Input, LexOptions options = LexOptions.init, String = stri

@safe unittest
{
auto tokens = lexJSON!(LexOptions.init, char[])(`{"foo": "bar"}`);
auto tokens = lexJSON(`{"foo": "bar"}`);
assert(tokens.front.kind == JSONTokenKind.objectStart);
tokens.popFront();
assert(tokens.front.kind == JSONTokenKind.string);
Expand All @@ -862,19 +862,18 @@ struct JSONLexerRange(Input, LexOptions options = LexOptions.init, String = stri
/**
* A low-level JSON token as returned by $(D JSONLexer).
*/
@safe struct JSONToken(S)
@safe struct JSONToken
{
import std.algorithm : among;
import std.bigint : BigInt;

private alias Kind = JSONTokenKind; // compatibility alias
alias String = S;

private
{
union
{
JSONString!String _string;
JSONString _string;
bool _boolean;
JSONNumber _number;
}
Expand All @@ -895,9 +894,9 @@ struct JSONLexerRange(Input, LexOptions options = LexOptions.init, String = stri
// ditto
this(double value) @trusted { _kind = Kind.number; _number = value; }
// ditto
this(JSONString!String value) @trusted { _kind = Kind.string; _string = value; }
this(JSONString value) @trusted { _kind = Kind.string; _string = value; }
// ditto
this(String value) @trusted { _kind = Kind.string; _string = value; }
this(.string value) @trusted { _kind = Kind.string; _string = value; }

/** Constructs a token with a specific kind.
*
Expand All @@ -910,7 +909,7 @@ struct JSONLexerRange(Input, LexOptions options = LexOptions.init, String = stri
}


ref JSONToken opAssign(ref JSONToken other) nothrow @trusted @nogc
ref JSONToken opAssign(ref JSONToken other) nothrow @trusted @nogc return
{
_kind = other._kind;
switch (_kind) with (Kind) {
Expand Down Expand Up @@ -967,18 +966,18 @@ struct JSONLexerRange(Input, LexOptions options = LexOptions.init, String = stri
@property JSONNumber number(BigInt value) nothrow @nogc { return this.number = JSONNumber(value); }

/// Gets/sets the string value of the token.
@property const(JSONString!String) string() const pure nothrow @trusted @nogc
@property const(JSONString) string() const pure nothrow @trusted @nogc
in (_kind == Kind.string, "Token is not a string.")
{ return _kind == Kind.string ? _string : JSONString!String.init; }
{ return _kind == Kind.string ? _string : JSONString.init; }
/// ditto
@property JSONString!String string(JSONString!String value) pure nothrow @nogc
@property JSONString string(JSONString value) pure nothrow @nogc
{
_kind = Kind.string;
() @trusted { _string = value; } ();
return value;
}
/// ditto
@property JSONString!String string(String value) pure nothrow @nogc { return this.string = JSONString!String(value); }
@property JSONString string(.string value) pure nothrow @nogc { return this.string = JSONString(value); }

/**
* Enables equality comparisons.
Expand Down Expand Up @@ -1039,7 +1038,7 @@ struct JSONLexerRange(Input, LexOptions options = LexOptions.init, String = stri

@safe unittest
{
JSONToken!string tok;
JSONToken tok;

assert((tok.boolean = true) == true);
assert(tok.kind == JSONTokenKind.boolean);
Expand Down Expand Up @@ -1097,28 +1096,28 @@ enum JSONTokenKind
/**
* Represents a JSON string literal with lazy (un)escaping.
*/
@safe struct JSONString(String) {
@safe struct JSONString {
import std.typecons : Tuple, tuple;

private {
String _value;
String _rawValue;
string _value;
string _rawValue;
}

nothrow:

/**
* Constructs a JSONString from the given string value (unescaped).
*/
this(String value) pure nothrow @nogc
this(string value) pure nothrow @nogc
{
_value = value;
}

/**
* The decoded (unescaped) string value.
*/
@property String value()
@property string value()
{
if (!_value.length && _rawValue.length) {
auto res = unescapeStringLiteral(_rawValue, _value);
Expand All @@ -1127,18 +1126,18 @@ enum JSONTokenKind
return _value;
}
/// ditto
@property const(String) value() const
@property const(string) value() const
{
if (!_value.length && _rawValue.length) {
String unescaped;
string unescaped;
auto res = unescapeStringLiteral(_rawValue, unescaped);
assert(res, "Invalid raw string literal passed to JSONString: "~_rawValue);
return unescaped;
}
return _value;
}
/// ditto
@property String value(String val) nothrow @nogc
@property string value(string val) nothrow @nogc
{
_rawValue = null;
return _value = val;
Expand All @@ -1147,14 +1146,14 @@ enum JSONTokenKind
/**
* The raw (escaped) string literal, including the enclosing quotation marks.
*/
@property String rawValue()
@property string rawValue()
{
if (!_rawValue.length && _value.length)
_rawValue = escapeStringLiteral(_value);
return _rawValue;
}
/// ditto
@property String rawValue(String val) nothrow @nogc
@property string rawValue(string val) nothrow @nogc
{
import std.algorithm : canFind;
import std.string : representation;
Expand All @@ -1172,9 +1171,9 @@ enum JSONTokenKind
* set to `true` if the returned string is in decoded form. `false` is
* returned otherwise.
*/
@property Tuple!(const(String), bool) anyValue() const pure @nogc
@property Tuple!(const(string), bool) anyValue() const pure @nogc
{
alias T = Tuple!(const(String), bool); // work around "Cannot convert Tuple!(string, bool) to Tuple!(const(string), bool)" error when using tuple()
alias T = Tuple!(const(string), bool); // work around "Cannot convert Tuple!(string, bool) to Tuple!(const(string), bool)" error when using tuple()
return !_rawValue.length ? T(_value, true) : T(_rawValue, false);
}

Expand All @@ -1185,9 +1184,9 @@ enum JSONTokenKind
/// ditto
bool opEquals(in JSONString other) const nothrow { return this.value == other.value; }
/// ditto
bool opEquals(in String other) nothrow { return this.value == other; }
bool opEquals(in string other) nothrow { return this.value == other; }
/// ditto
bool opEquals(in String other) const nothrow { return this.value == other; }
bool opEquals(in string other) const nothrow { return this.value == other; }

/// Support relational comparisons
int opCmp(JSONString other) nothrow @trusted { import std.algorithm; return cmp(this.value, other.value); }
Expand All @@ -1197,12 +1196,12 @@ enum JSONTokenKind
}

@safe unittest {
JSONString!string s = "test";
JSONString s = "test";
assert(s == "test");
assert(s.value == "test");
assert(s.rawValue == `"test"`);

JSONString!string t;
JSONString t;
auto h = `"hello"`;
s.rawValue = h;
t = s; assert(s == t);
Expand All @@ -1220,11 +1219,6 @@ enum JSONTokenKind
t = s; assert(s == t);
assert(&s.rawValue[0] is &w[0]);
assert(&s.value[0] !is &h[1]);

JSONString!(char[]) u = "test".dup;
assert(u == "test");
assert(u.value == "test");
assert(u.rawValue == `"test"`);
}


Expand Down

0 comments on commit 7e38129

Please sign in to comment.