3using System.Globalization;
14 private readonly StringBuilder output =
new StringBuilder();
15 private char delimiterCharacter =
',';
16 private char indentCharacter =
'\t';
17 private int indentCharacterCount = 1;
18 private int keyFoldingDepth =
int.MaxValue;
19 private bool standardIndentation =
true;
20 private bool standardDelimiter =
true;
21 private bool keyFolding =
true;
22 private bool empty =
true;
23 private bool lastIsListItem =
false;
29 : this(new StringBuilder())
47 get => this.indentCharacter;
50 this.indentCharacter = value;
51 this.standardIndentation =
52 this.indentCharacter ==
'\t' &&
53 this.indentCharacterCount == 1;
62 get => this.indentCharacterCount;
67 throw new ArgumentException(
"Indent character count must be a positive integer.",
71 this.indentCharacterCount = value;
72 this.standardIndentation =
73 this.indentCharacter ==
'\t' &&
74 this.indentCharacterCount == 1;
91 public StringBuilder
Output => this.output;
96 public bool Empty => this.empty;
103 get => this.delimiterCharacter;
106 this.delimiterCharacter = value;
107 this.standardDelimiter = this.delimiterCharacter ==
',';
116 get => this.keyFolding;
119 this.keyFolding = value;
121 if (value && this.keyFoldingDepth <= 1)
122 this.keyFoldingDepth = 2;
132 get => this.keyFoldingDepth;
136 this.keyFolding =
false;
138 this.keyFoldingDepth = value;
150 if (this.standardIndentation)
154 Level *= this.indentCharacterCount;
157 this.output.Append(this.indentCharacter);
160 this.lastIsListItem =
false;
166 return this.output.ToString();
176 this.lastIsListItem =
false;
177 this.output.Append(Value);
187 this.lastIsListItem =
false;
188 this.output.Append(Value);
197 this.lastIsListItem =
false;
198 this.output.Append(this.delimiterCharacter);
206 this.output.Append(
'-');
207 this.lastIsListItem =
true;
216 this.lastIsListItem =
false;
217 this.output.Append(
'\n');
236 public string Encode(
string s,
bool InObject)
257 if (
double.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out
_))
258 return "\"" + s +
"\"";
263 if (s.StartsWith(
"[") ||
265 s.IndexOf(
this.delimiterCharacter) >= 0)
267 return "\"" + s +
"\"";
272 if (s.IndexOfAny(objectKeyCharacters) >= 0)
273 return "\"" + s +
"\"";
277 if (s.IndexOfAny(keyCharacters) >= 0)
278 return "\"" + s +
"\"";
285 private static readonly
char[] objectKeyCharacters =
new char[] {
':',
'-',
' ' };
286 private static readonly
char[] keyCharacters =
new char[] {
':',
'-' };
295 int?
Indent, Func<string, bool> MemberExists)
297 bool MultiRow =
Indent.HasValue;
303 if (!(Object is
null))
305 foreach (KeyValuePair<string, object> Member
in Object)
326 if (!First &&
Indent.Value > 0)
329 this.
Indent(Indent.Value);
341 int?
Indent, Func<string, bool> MemberExists)
343 bool MultiRow =
Indent.HasValue;
349 if (!(Object is
null))
351 foreach (KeyValuePair<string, IElement> Member
in Object)
370 if (!First &&
Indent.Value > 0)
373 this.
Indent(Indent.Value);
386 Func<string, bool> MemberExists)
388 bool AppendSpaces =
Indent.HasValue;
390 if (AppendSpaces && (
Indent.Value > 0 || (
Indent.Value == 0 && !
this.empty)))
392 if (this.lastIsListItem)
394 this.output.Append(
' ');
395 this.lastIsListItem =
false;
400 this.
Indent(Indent.Value);
419 if (this.keyFolding &&
421 this.Encode(Name,
true) == Name)
423 string OriginalName = Name;
424 object OriginalValue = Value;
428 while (Depth < this.keyFoldingDepth &&
429 Encoder.
CanFold(Value, out
string FoldedName, out
object FoldedValue) &&
430 this.Encode(FoldedName,
true) == FoldedName)
432 Name +=
"." + FoldedName;
441 if (Depth > 1 && MemberExists(Name))
443 this.keyFolding =
false;
459 this.keyFolding =
true;
462 else if (Depth == this.keyFoldingDepth)
464 this.keyFolding =
false;
480 this.keyFolding =
true;
Helps with common JSON-related tasks.
static void Indent(StringBuilder Output, int NrTabs)
Appends an indentation to a string builder using tab characters.
static string Encode(string s)
Encodes a string for inclusion in JSON.
static bool ContainsEscapeCharacters(string s)
If a string contains characters that need to be escaped to be encoded into JSON.
Helps with common TOON-related tasks.
static IToonEncoder GetEncoder(object Value)
Gets a TOON encoder for a given object, by looking up the best available encoder, based on the type o...
void AppendMember(string Name, object Value, int? Indent, Func< string, bool > MemberExists)
Appends a member of an object as TOON.
void Append(string Value)
Appends a string to the output.
int KeyFoldingDepth
Maximum depth for key folding. Default is int.MaxValue, meaning that all keys will be folded,...
string Encode(string s, bool InObject)
Encodes a string for inclusion in TOON.
void AppendLine()
Appends a new-line character to the output.
void AppendListItem()
Appends a list item character to the output (hyphen).
void AppendEncoded(string s, bool InObject)
Encodes a string, if necessary, and appends it to the output.
void AppendDelimiter()
Appends the delimiter character to the output.
bool KeyFolding
If key-folding is enabled (safe-mode). Default is true.
char IndentCharacter
Indentation character to use. Default is the TAB character.
int IndentCharacterCount
Indentation character to use. Default is the TAB character.
ToonOutput(StringBuilder Output)
TOON Output builder
StringBuilder Output
String builder where TOON output is appended.
bool Empty
If no output has been appended.
bool StandardIndentation
If the indentation is standard (one TAB character per step).
override string ToString()
void AppendAsObject(IEnumerable< KeyValuePair< string, IElement > > Object, int? Indent, Func< string, bool > MemberExists)
Appends an object as a TOON object.
void Append(char Value)
Appends a character to the output.
void Indent(int Level)
Appends an indentation to the output, according to the level specified.
ToonOutput()
TOON Output builder
void AppendAsObject(IEnumerable< KeyValuePair< string, object > > Object, int? Indent, Func< string, bool > MemberExists)
Appends an object as a TOON object.
char DelimiterCharacter
Delimiter character to use. Default is the comma character.
bool StandardDelimiter
If the standard delimiter is used.
Interface for encoding objects of certain types to TOON.
bool EncodesMultipleRows
If the encoder encodes values into multiple rows.
void Encode(object Object, int? Indent, ToonOutput Toon)
Encodes the Object to TOON.
bool EncodesAsVector(object Value)
If the encoder encodes a value as a vector.
bool EncodesAsObject(object Value)
If the encoder encodes a value as an object.
bool CanFold(object Object, out string FoldedName, out object FoldedValue)
Checks if an object can be folded to a shorter representation, and if so, returns the folded name and...
BracketsMode
How brackets should be handled when encoding vectors.