Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions src/main/java/dev/toonformat/jtoon/decoder/ArrayDecoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
import java.util.List;
import java.util.regex.Matcher;

import static dev.toonformat.jtoon.util.Constants.BACKSLASH;
import static dev.toonformat.jtoon.util.Constants.COLON;
import static dev.toonformat.jtoon.util.Constants.DOUBLE_QUOTE;
import static dev.toonformat.jtoon.util.Constants.LIST_ITEM_PREFIX;
import static dev.toonformat.jtoon.util.Headers.ARRAY_HEADER_PATTERN;
import static dev.toonformat.jtoon.util.Headers.TABULAR_HEADER_PATTERN;

Expand Down Expand Up @@ -47,10 +51,10 @@ static Delimiter extractDelimiterFromHeader(String header, DecodeContext context
if (matcher.find()) {
String delimiter = matcher.group(3);
if (delimiter != null) {
if ("\t".equals(delimiter)) {
if (Delimiter.TAB.toString().equals(delimiter)) {
return Delimiter.TAB;
}
if ("|".equals(delimiter)) {
if (Delimiter.PIPE.toString().equals(delimiter)) {
return Delimiter.PIPE;
}
}
Expand Down Expand Up @@ -82,7 +86,7 @@ static List<Object> parseArrayWithDelimiter(String header, int depth, Delimiter
int headerEndIdx = arrayMatcher.end();
String afterHeader = header.substring(headerEndIdx).trim();

if (afterHeader.startsWith(":")) {
if (afterHeader.startsWith(COLON)) {
String inlineContent = afterHeader.substring(1).trim();

if (!inlineContent.isEmpty()) {
Expand All @@ -106,7 +110,7 @@ static List<Object> parseArrayWithDelimiter(String header, int depth, Delimiter
return Collections.emptyList();
}

if (nextContent.startsWith("- ")) {
if (nextContent.startsWith(LIST_ITEM_PREFIX)) {
context.currentLine--;
return parseListArray(depth, header, context);
} else {
Expand Down Expand Up @@ -195,11 +199,11 @@ static List<String> parseDelimitedValues(String input, Delimiter arrayDelimiter)
stringBuilder.append(currentChar);
escaped = false;
i++;
} else if (currentChar == '\\') {
} else if (currentChar == BACKSLASH) {
stringBuilder.append(currentChar);
escaped = true;
i++;
} else if (currentChar == '"') {
} else if (currentChar == DOUBLE_QUOTE) {
stringBuilder.append(currentChar);
inQuotes = !inQuotes;
i++;
Expand Down
13 changes: 9 additions & 4 deletions src/main/java/dev/toonformat/jtoon/decoder/DecodeHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
import java.util.List;
import java.util.Map;

import static dev.toonformat.jtoon.util.Constants.BACKSLASH;
import static dev.toonformat.jtoon.util.Constants.DOUBLE_QUOTE;
import static dev.toonformat.jtoon.util.Constants.SPACE;
import static dev.toonformat.jtoon.util.Constants.COLON;

/**
* Handles indentation, depth, conflicts, and validation for other decode classes.
*/
Expand Down Expand Up @@ -47,7 +52,7 @@ private static int computeLeadingSpaces(String line, DecodeContext context) {
int lengthOfLine = line.length();
while (i < lengthOfLine) {
char c = line.charAt(i);
if (c == ' ') {
if (c == SPACE.charAt(0)) {
leadingSpaces++;
} else if (c == Delimiter.TAB.getValue()) {
if (context.options.strict()) {
Expand Down Expand Up @@ -98,11 +103,11 @@ static int findUnquotedColon(String content) {

if (escaped) {
escaped = false;
} else if (c == '\\') {
} else if (c == BACKSLASH) {
escaped = true;
} else if (c == '"') {
} else if (c == DOUBLE_QUOTE) {
inQuotes = !inQuotes;
} else if (c == ':' && !inQuotes) {
} else if (c == COLON.charAt(0) && !inQuotes) {
return i;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.util.Map;
import java.util.regex.Matcher;

import static dev.toonformat.jtoon.util.Constants.DOT;
import static dev.toonformat.jtoon.util.Headers.KEYED_ARRAY_PATTERN;

/**
Expand Down Expand Up @@ -156,7 +157,7 @@ static boolean shouldExpandKey(String key, DecodeContext context) {
return false;
}
// Check if a key contains dots and is a valid identifier pattern
if (!key.contains(".")) {
if (!key.contains(DOT)) {
return false;
}
// Valid identifier: starts with a letter or underscore, followed by letters,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import java.util.Map;
import java.util.regex.Matcher;

import static dev.toonformat.jtoon.util.Constants.LIST_ITEM_MARKER;
import static dev.toonformat.jtoon.util.Constants.OPEN_BRACKET;
import static dev.toonformat.jtoon.util.Headers.KEYED_ARRAY_PATTERN;

/**
Expand All @@ -31,7 +33,7 @@ public static void processListArrayItem(String line, int lineDepth, int depth,
if (lineDepth == depth + 1) {
String content = line.substring((depth + 1) * context.options.indent());

if (content.startsWith("-")) {
if (content.startsWith(LIST_ITEM_MARKER)) {
result.add(parseListItem(content, depth, context));
} else {
context.currentLine++;
Expand Down Expand Up @@ -66,7 +68,7 @@ public static Object parseListItem(String content, int depth, DecodeContext cont
}

// Check for standalone array (e.g., "[2]: 1,2")
if (itemContent.startsWith("[")) {
if (itemContent.startsWith(OPEN_BRACKET)) {
// For nested arrays in list items, default to comma delimiter if not specified
Delimiter nestedArrayDelimiter = ArrayDecoder.extractDelimiterFromHeader(itemContent, context);
// parseArrayWithDelimiter handles currentLine increment internally
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

import dev.toonformat.jtoon.util.StringEscaper;

import static dev.toonformat.jtoon.util.Constants.DOT;
import static dev.toonformat.jtoon.util.Constants.NULL_LITERAL;
import static dev.toonformat.jtoon.util.Constants.TRUE_LITERAL;
import static dev.toonformat.jtoon.util.Constants.FALSE_LITERAL;

/**
* Handles parsing of primitive TOON values with type inference.
*
Expand Down Expand Up @@ -48,13 +53,13 @@ static Object parse(String value) {

// Check for null literal
switch (value) {
case "null" -> {
case NULL_LITERAL -> {
return null;
}
case "true" -> {
case TRUE_LITERAL -> {
return true;
}
case "false" -> {
case FALSE_LITERAL -> {
return false;
}
default -> {
Expand All @@ -78,7 +83,7 @@ static Object parse(String value) {
// Try parsing as number
try {
// Check if it contains exponent notation or decimal point
if (value.contains(".") || value.contains("e") || value.contains("E")) {
if (value.contains(DOT) || value.contains("e") || value.contains("E")) {
double parsed = Double.parseDouble(value);
// Handle negative zero - Java doesn't distinguish, but spec says it should be 0
if (parsed == 0.0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import java.util.Map;
import java.util.regex.Matcher;

import static dev.toonformat.jtoon.util.Constants.BACKSLASH;
import static dev.toonformat.jtoon.util.Constants.DOUBLE_QUOTE;
import static dev.toonformat.jtoon.util.Headers.TABULAR_HEADER_PATTERN;

/**
Expand Down Expand Up @@ -101,9 +103,9 @@ private static void validateKeysDelimiter(String keysStr, Delimiter expectedDeli
char c = keysStr.charAt(i);
if (escaped) {
escaped = false;
} else if (c == '\\') {
} else if (c == BACKSLASH) {
escaped = true;
} else if (c == '"') {
} else if (c == DOUBLE_QUOTE) {
inQuotes = !inQuotes;
} else if (!inQuotes) {
checkDelimiterMismatch(expectedChar, c);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import java.util.LinkedHashMap;
import java.util.regex.Matcher;

import static dev.toonformat.jtoon.util.Constants.NULL_LITERAL;
import static dev.toonformat.jtoon.util.Constants.OPEN_BRACKET;
import static dev.toonformat.jtoon.util.Headers.KEYED_ARRAY_PATTERN;

/**
Expand Down Expand Up @@ -52,7 +54,7 @@ public static Object decode(String toon, DecodeOptions options) {

// Special case: if input is exactly "null", return null
String trimmed = toon.trim();
if ("null".equals(trimmed)) {
if (NULL_LITERAL.equals(trimmed)) {
return null;
}

Expand All @@ -78,7 +80,7 @@ public static Object decode(String toon, DecodeOptions options) {
}

// Handle standalone arrays: [2]:
if (!line.isEmpty() && line.charAt(0) == '[') {
if (!line.isEmpty() && line.charAt(0) == OPEN_BRACKET.charAt(0)) {
return ArrayDecoder.parseArray(line, depth, context);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package dev.toonformat.jtoon.encoder;


import dev.toonformat.jtoon.EncodeOptions;
import tools.jackson.databind.JsonNode;
import tools.jackson.databind.node.ArrayNode;
Expand Down
12 changes: 7 additions & 5 deletions src/main/java/dev/toonformat/jtoon/encoder/Flatten.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import java.util.Set;
import java.util.regex.Pattern;

import static dev.toonformat.jtoon.util.Constants.DOT;

/**
* Recursively flattens a JSON object or array into a single-level object.
*/
Expand Down Expand Up @@ -75,7 +77,7 @@ public static FoldResult tryFoldKeyChain(String key,
}

// start chain from absolute key
String absKey = (pathPrefix == null) ? key : String.join(".", pathPrefix, key);
String absKey = (pathPrefix == null) ? key : String.join(DOT, pathPrefix, key);

// Collect segments of the single-key chain
final ChainResult chain = collectSingleKeyChain(absKey, value, remainingDepth);
Expand All @@ -97,7 +99,7 @@ public static FoldResult tryFoldKeyChain(String key,
}

// Build folded key
String foldedKey = String.join(".", chain.segments);
String foldedKey = String.join(DOT, chain.segments);

// Detect collisions with sibling keys
if (siblings.contains(foldedKey)) {
Expand All @@ -107,7 +109,7 @@ public static FoldResult tryFoldKeyChain(String key,
// Compute absolute dotted path
String absolutePath =
(pathPrefix != null && !pathPrefix.isEmpty())
? String.join(".", pathPrefix, foldedKey)
? String.join(DOT, pathPrefix, foldedKey)
: foldedKey;


Expand Down Expand Up @@ -138,8 +140,8 @@ public static FoldResult tryFoldKeyChain(String key,
*/
private static ChainResult collectSingleKeyChain(String startKey, JsonNode startValue, int maxDepth) {
// normalize absolute key to its local segment
String localStartKey = startKey.contains(".")
? startKey.substring(startKey.lastIndexOf('.') + 1)
String localStartKey = startKey.contains(DOT)
? startKey.substring(startKey.lastIndexOf(DOT.charAt(0)) + 1)
: startKey;

final List<String> segments = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@

import java.util.List;

import static dev.toonformat.jtoon.util.Constants.*;
import static dev.toonformat.jtoon.util.Constants.COLON;
import static dev.toonformat.jtoon.util.Constants.OPEN_BRACKET;
import static dev.toonformat.jtoon.util.Constants.COMMA;
import static dev.toonformat.jtoon.util.Constants.OPEN_BRACE;
import static dev.toonformat.jtoon.util.Constants.CLOSE_BRACE;
import static dev.toonformat.jtoon.util.Constants.CLOSE_BRACKET;
import static dev.toonformat.jtoon.util.Constants.HASHTAG;

/**
* Formats headers for arrays and tables in TOON format.
Expand Down Expand Up @@ -81,7 +87,7 @@ private static void appendArrayLength(
header.append(OPEN_BRACKET);

if (lengthMarker) {
header.append("#");
header.append(HASHTAG);
}

header.append(length);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import java.util.ArrayList;
import java.util.List;

import static dev.toonformat.jtoon.util.Constants.SPACE;

/**
* Line writer that accumulates indented lines for building the final output.
*/
Expand All @@ -16,7 +18,7 @@ public final class LineWriter {
* @param indentSize Number of spaces per indentation level
*/
public LineWriter(int indentSize) {
this.indentationString = " ".repeat(indentSize);
this.indentationString = SPACE.repeat(indentSize);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@
import java.util.List;
import java.util.Set;

import static dev.toonformat.jtoon.util.Constants.*;
import static dev.toonformat.jtoon.util.Constants.LIST_ITEM_MARKER;
import static dev.toonformat.jtoon.util.Constants.COLON;
import static dev.toonformat.jtoon.util.Constants.SPACE;
import static dev.toonformat.jtoon.util.Constants.LIST_ITEM_PREFIX;
import static dev.toonformat.jtoon.util.Constants.OPEN_BRACKET;
import static dev.toonformat.jtoon.util.Constants.CLOSE_BRACKET;

/**
* Handles encoding of objects as list items in non-uniform arrays.
Expand Down
13 changes: 7 additions & 6 deletions src/main/java/dev/toonformat/jtoon/encoder/ObjectEncoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.Set;
import java.util.stream.Collectors;

import static dev.toonformat.jtoon.util.Constants.DOT;
import static dev.toonformat.jtoon.util.Constants.COLON;
import static dev.toonformat.jtoon.util.Constants.SPACE;

Expand Down Expand Up @@ -44,7 +45,7 @@ public static void encodeObject(ObjectNode value, LineWriter writer, int depth,
if (depth == 0 && rootLiteralKeys != null) {
rootLiteralKeys.clear();
fields.stream()
.filter(e -> e.getKey().contains("."))
.filter(e -> e.getKey().contains(DOT))
.map(Map.Entry::getKey)
.forEach(rootLiteralKeys::add);
}
Expand Down Expand Up @@ -89,7 +90,7 @@ public static void encodeKeyValuePair(String key,
return;
}
String encodedKey = PrimitiveEncoder.encodeKey(key);
String currentPath = pathPrefix != null ? pathPrefix + "." + key : key;
String currentPath = pathPrefix != null ? pathPrefix + DOT + key : key;
int effectiveFlattenDepth = flattenDepth != null && flattenDepth > 0 ? flattenDepth : options.flattenDepth();
int remainingDepth = effectiveFlattenDepth - depth;

Expand Down Expand Up @@ -156,9 +157,9 @@ private static EncodeOptions flatten(String key, Flatten.FoldResult foldResult,

// Case 2: Partially folded with a tail object
if (remainder.isObject()) {
writer.push(depth, indentedLine(depth, encodedFoldedKey + ":", options.indent()));
writer.push(depth, indentedLine(depth, encodedFoldedKey + COLON, options.indent()));

String foldedPath = pathPrefix != null ? String.join(".", pathPrefix, foldedKey) : foldedKey;
String foldedPath = pathPrefix != null ? String.join(DOT, pathPrefix, foldedKey) : foldedKey;
int newRemainingDepth = remainingDepth - foldResult.segmentCount();

if (newRemainingDepth <= 0) {
Expand All @@ -182,7 +183,7 @@ private static void handleFullyFoldedLeaf(Flatten.FoldResult foldResult, LineWri
if (leaf.isValueNode()) {
writer.push(depth,
indentedLine(depth,
encodedFoldedKey + ": " +
encodedFoldedKey + COLON + SPACE +
PrimitiveEncoder.encodePrimitive(leaf, options.delimiter().toString()),
options.indent()));
return;
Expand All @@ -196,7 +197,7 @@ private static void handleFullyFoldedLeaf(Flatten.FoldResult foldResult, LineWri

// Object
if (leaf.isObject()) {
writer.push(depth, indentedLine(depth, encodedFoldedKey + ":", options.indent()));
writer.push(depth, indentedLine(depth, encodedFoldedKey + COLON, options.indent()));
if (!leaf.isEmpty()) {
encodeObject((ObjectNode) leaf, writer, depth + 1, options,
null, null, null, null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
import java.util.List;
import java.util.Objects;

import static dev.toonformat.jtoon.util.Constants.*;
import static dev.toonformat.jtoon.util.Constants.NULL_LITERAL;
import static dev.toonformat.jtoon.util.Constants.DOUBLE_QUOTE;

/**
* Encodes primitive values and object keys for TOON format.
Expand Down
Loading
Loading