diff --git a/.gitignore b/.gitignore index 25ab8d0..ee3c2c8 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ gradle gradlew gradle.bat build/ +hjson.iml +.idea diff --git a/assets/charset_result.hjson b/assets/charset_result.hjson new file mode 100644 index 0000000..d1573b6 --- /dev/null +++ b/assets/charset_result.hjson @@ -0,0 +1,5 @@ +{ + ql-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ + js-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ + ml-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ +} \ No newline at end of file diff --git a/assets/charset_result.json b/assets/charset_result.json new file mode 100644 index 0000000..6357d96 --- /dev/null +++ b/assets/charset_result.json @@ -0,0 +1,5 @@ +{ + "ql-ascii": "! \"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", + "js-ascii": "! \"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", + "ml-ascii": "! \"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" +} \ No newline at end of file diff --git a/assets/charset_test.hjson b/assets/charset_test.hjson new file mode 100644 index 0000000..7527b1e --- /dev/null +++ b/assets/charset_test.hjson @@ -0,0 +1,6 @@ +ql-ascii: ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ +js-ascii: "! \"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" +ml-ascii: + ''' + ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ + ''' diff --git a/assets/comments_test.hjson b/assets/comments_test.hjson index 2350080..7f1dfdc 100644 --- a/assets/comments_test.hjson +++ b/assets/comments_test.hjson @@ -1,3 +1,15 @@ +// test +# all +// comment +/* +styles +*/ +# with lf + + + +# ! + { # hjson style comment foo1: This is a string value. # part of the string diff --git a/assets/empty_result.hjson b/assets/empty_result.hjson new file mode 100644 index 0000000..a75b45b --- /dev/null +++ b/assets/empty_result.hjson @@ -0,0 +1,3 @@ +{ + "": empty +} \ No newline at end of file diff --git a/assets/empty_result.json b/assets/empty_result.json new file mode 100644 index 0000000..47f710f --- /dev/null +++ b/assets/empty_result.json @@ -0,0 +1,3 @@ +{ + "": "empty" +} \ No newline at end of file diff --git a/assets/empty_test.hjson b/assets/empty_test.hjson new file mode 100644 index 0000000..ac97a9d --- /dev/null +++ b/assets/empty_test.hjson @@ -0,0 +1,3 @@ +{ + "": empty +} diff --git a/assets/fail34_test.json b/assets/fail34_test.json new file mode 100644 index 0000000..9214364 --- /dev/null +++ b/assets/fail34_test.json @@ -0,0 +1,2 @@ +A quoteless string is OK, +but two must be contained in an array. diff --git a/assets/failStr1_test.hjson b/assets/failStr1_test.hjson new file mode 100644 index 0000000..91b930c --- /dev/null +++ b/assets/failStr1_test.hjson @@ -0,0 +1,4 @@ +{ + # invalid quoteless string + ql: ] +} diff --git a/assets/failStr2_test.hjson b/assets/failStr2_test.hjson new file mode 100644 index 0000000..5a8b28f --- /dev/null +++ b/assets/failStr2_test.hjson @@ -0,0 +1,4 @@ +{ + # invalid quoteless string + ql: } +} diff --git a/assets/failStr3_test.hjson b/assets/failStr3_test.hjson new file mode 100644 index 0000000..ec5d0ad --- /dev/null +++ b/assets/failStr3_test.hjson @@ -0,0 +1,4 @@ +{ + # invalid quoteless string + ql: { +} diff --git a/assets/failStr4_test.hjson b/assets/failStr4_test.hjson new file mode 100644 index 0000000..941f35b --- /dev/null +++ b/assets/failStr4_test.hjson @@ -0,0 +1,4 @@ +{ + # invalid quoteless string + ql: [ +} diff --git a/assets/failStr5_test.hjson b/assets/failStr5_test.hjson new file mode 100644 index 0000000..4093f7a --- /dev/null +++ b/assets/failStr5_test.hjson @@ -0,0 +1,4 @@ +{ + # invalid quoteless string + ql: : +} diff --git a/assets/failStr6_test.hjson b/assets/failStr6_test.hjson new file mode 100644 index 0000000..5223337 --- /dev/null +++ b/assets/failStr6_test.hjson @@ -0,0 +1,4 @@ +{ + # invalid quoteless string + ql: , +} diff --git a/assets/pass1_result.hjson b/assets/pass1_result.hjson index d6bdec7..2a3f4c9 100644 --- a/assets/pass1_result.hjson +++ b/assets/pass1_result.hjson @@ -17,7 +17,7 @@ real: -9876.54321 e: 1.23456789e-13 E: 1.23456789e+34 - "": 2.3456789012e+76 + -: 2.3456789012e+76 zero: 0 one: 1 space: " " diff --git a/assets/pass1_result.json b/assets/pass1_result.json index 7c2c188..69b354d 100644 --- a/assets/pass1_result.json +++ b/assets/pass1_result.json @@ -16,7 +16,7 @@ "real": -9876.54321, "e": 1.23456789e-13, "E": 1.23456789e+34, - "": 2.3456789012e+76, + "-": 2.3456789012e+76, "zero": 0, "one": 1, "space": " ", diff --git a/assets/pass1_test.json b/assets/pass1_test.json index 70e2685..61cfd90 100644 --- a/assets/pass1_test.json +++ b/assets/pass1_test.json @@ -12,7 +12,7 @@ "real": -9876.543210, "e": 0.123456789e-12, "E": 1.234567890E+34, - "": 23456789012E66, + "-": 23456789012E66, "zero": 0, "one": 1, "space": " ", diff --git a/assets/passSingle_result.hjson b/assets/passSingle_result.hjson index c9f0304..e580fce 100644 --- a/assets/passSingle_result.hjson +++ b/assets/passSingle_result.hjson @@ -1 +1 @@ -foo=bar \ No newline at end of file +allow quoteless strings \ No newline at end of file diff --git a/assets/passSingle_result.json b/assets/passSingle_result.json index cca243e..1829d36 100644 --- a/assets/passSingle_result.json +++ b/assets/passSingle_result.json @@ -1 +1 @@ -"foo=bar" \ No newline at end of file +"allow quoteless strings" \ No newline at end of file diff --git a/assets/passSingle_test.hjson b/assets/passSingle_test.hjson index c9f0304..e580fce 100644 --- a/assets/passSingle_test.hjson +++ b/assets/passSingle_test.hjson @@ -1 +1 @@ -foo=bar \ No newline at end of file +allow quoteless strings \ No newline at end of file diff --git a/assets/strings_result.hjson b/assets/strings_result.hjson index 47f75bf..579daaf 100644 --- a/assets/strings_result.hjson +++ b/assets/strings_result.hjson @@ -70,5 +70,4 @@ two: "2" minus: "-3" } - "": empty } \ No newline at end of file diff --git a/assets/strings_result.json b/assets/strings_result.json index 08afc7f..ecd59d2 100644 --- a/assets/strings_result.json +++ b/assets/strings_result.json @@ -49,6 +49,5 @@ "one": "1", "two": "2", "minus": "-3" - }, - "": "empty" + } } \ No newline at end of file diff --git a/assets/strings_test.hjson b/assets/strings_test.hjson index bf948f2..77cf721 100644 --- a/assets/strings_test.hjson +++ b/assets/strings_test.hjson @@ -75,6 +75,4 @@ two: "2" minus: "-3" } - - "": empty } diff --git a/assets/testlist.txt b/assets/testlist.txt new file mode 100644 index 0000000..c54b8e8 --- /dev/null +++ b/assets/testlist.txt @@ -0,0 +1,54 @@ +charset_test.hjson +comments_test.hjson +empty_test.hjson +fail10_test.json +fail11_test.json +fail12_test.json +fail13_test.json +fail14_test.json +fail15_test.json +fail16_test.json +fail17_test.json +fail19_test.json +fail20_test.json +fail21_test.json +fail22_test.json +fail23_test.json +fail24_test.json +fail26_test.json +fail28_test.json +fail29_test.json +fail2_test.json +fail30_test.json +fail31_test.json +fail32_test.json +fail33_test.json +fail34_test.json +fail5_test.json +fail6_test.json +fail7_test.json +fail8_test.json +failKey1_test.hjson +failKey2_test.hjson +failKey3_test.hjson +failObj1_test.hjson +failObj2_test.hjson +failObj3_test.hjson +failStr1_test.hjson +failStr2_test.hjson +failStr3_test.hjson +failStr4_test.hjson +failStr5_test.hjson +failStr6_test.hjson +kan_test.hjson +keys_test.hjson +oa_test.hjson +pass1_test.json +pass2_test.json +pass3_test.json +pass4_test.json +passSingle_test.hjson +root_test.hjson +stringify1_test.hjson +strings_test.hjson +trail_test.hjson \ No newline at end of file diff --git a/build.gradle b/build.gradle index 9726a8e..8438580 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ apply plugin: 'java' -version = '1.1.4' +version = '2.0.0' group = 'org.hjson' description = """Hjson, the Human JSON.""" @@ -28,11 +28,19 @@ task javadocJar(type: Jar, dependsOn: javadoc) { from 'build/docs/javadoc' } -task sourcesJar(type: Jar, dependsOn:classes) { +task sourcesJar(type: Jar, dependsOn: classes) { classifier = 'sources' from sourceSets.main.allSource } +jar { + manifest { + attributes( + 'Hjson-Version': version, + ) + } +} + artifacts { archives jar archives sourcesJar diff --git a/cli/bin/hjson b/cli/bin/hjson new file mode 100755 index 0000000..60eec2c --- /dev/null +++ b/cli/bin/hjson @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +SELF=`dirname $0` +java -jar $SELF/Hjson-cli.jar $* diff --git a/cli/bin/hjson.bat b/cli/bin/hjson.bat new file mode 100644 index 0000000..c30bb2f --- /dev/null +++ b/cli/bin/hjson.bat @@ -0,0 +1,2 @@ +@echo off +java -jar %~dp0\Hjson-cli.jar %* diff --git a/cli/build.gradle b/cli/build.gradle new file mode 100644 index 0000000..70d3845 --- /dev/null +++ b/cli/build.gradle @@ -0,0 +1,69 @@ +apply plugin: 'java' +apply plugin: 'maven' +apply plugin: 'application' + +version = '2.0.0' +group = 'org.hjson.cli' +description = """Hjson CLI""" + +sourceCompatibility = 1.8 +targetCompatibility = 1.8 + +sourceSets { + main { + java { + srcDir 'src' + } + } +} + +repositories { + flatDir { + dirs '../build/libs' + } + mavenCentral() +} + +dependencies { + compile 'org.hjson:hjson:'+version + compile 'commons-cli:commons-cli:1.3.1' +} + +mainClassName = 'org.hjson.cli.Main' + +jar { + baseName = 'Hjson' + manifest { + attributes( + 'Class-Path': configurations.compile.collect { it.getName() }.join(' '), + 'Main-Class': 'org.hjson.cli.Main', + 'Hjson-Version': version, + ) + } +} + +task distjar(type: Jar) { + manifest=jar.manifest + archiveName="Hjson-cli.jar" + //baseName="Hjson-dist" + from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } } + with jar + +} + +task dist(type: Copy, dependsOn: distjar) { + from('build/libs') { + include '*.jar' + } + from('bin') { + include '*' + } + into 'build/target' +} + +task zip(type:Zip, dependsOn: dist) { + from ('build/target') + include '*' + archiveName 'hjson.zip' + destinationDir file('build/zip') +} diff --git a/cli/src/org.hjson.cli/Main.java b/cli/src/org.hjson.cli/Main.java new file mode 100644 index 0000000..e1ab78f --- /dev/null +++ b/cli/src/org.hjson.cli/Main.java @@ -0,0 +1,76 @@ +package org.hjson.cli; + +import org.hjson.*; +import java.io.*; +import static java.lang.System.out; +import org.apache.commons.cli.*; +import java.util.jar.Manifest; +import java.util.jar.Attributes; +import java.util.List; +import java.net.URL; + +public class Main { + + public static String convertStreamToString(InputStream is) throws IOException { + Writer writer=new StringWriter(); + char[] buffer=new char[1024]; + try { + Reader reader=new BufferedReader(new InputStreamReader(is, "UTF-8")); + int n; + while ((n=reader.read(buffer))!=-1) writer.write(buffer, 0, n); + } finally { + is.close(); + } + return writer.toString(); + } + + + public static void main(String[] args) throws Exception { + + Options options=new Options(); + options.addOption(OptionBuilder.withLongOpt("help").withDescription("Show this screen.").create("h")); + options.addOption(OptionBuilder.withDescription("Output as formatted JSON.").create("j")); + options.addOption(OptionBuilder.withDescription("Output as JSON.").create("c")); + options.addOption(OptionBuilder.withLongOpt("version").withDescription("Show version.").create("v")); + + CommandLineParser parser=new DefaultParser(); + HelpFormatter formatter=new HelpFormatter(); + CommandLine cmd; + + try { + cmd=parser.parse(options, args); + if (cmd.hasOption("h")) { + formatter.printHelp("hjson [INPUT]", options); + return; + } else if (cmd.hasOption("v")) { + String className=JsonObject.class.getSimpleName()+".class"; + String classPath=JsonObject.class.getResource(className).toString(); + if (!classPath.startsWith("jar")) return; + String manifestPath=classPath.substring(0, classPath.lastIndexOf("!")+1)+"/META-INF/MANIFEST.MF"; + Attributes attr=new Manifest(new URL(manifestPath).openStream()).getMainAttributes(); + out.println("hjson v"+attr.getValue("Hjson-Version")); + return; + } + + List cargs=cmd.getArgList(); + Reader reader; + + if (cargs.size()>1) throw new org.apache.commons.cli.ParseException("input"); + + if (cargs.isEmpty()) reader=new InputStreamReader(System.in); + else reader=new FileReader(cargs.get(0)); + JsonValue value=JsonValue.readHjson(reader); + + if (cmd.hasOption("j")) out.println(value.toString(Stringify.FORMATTED)); + else if (cmd.hasOption("c")) out.println(value.toString(Stringify.PLAIN)); + else out.println(value.toString(Stringify.HJSON)); + + } catch (org.apache.commons.cli.ParseException e) { + out.println(e.getMessage()); + formatter.printHelp("hjson [INPUT]", options); + System.exit(1); + } + + + } +} diff --git a/gradle.properties b/gradle.properties index c02d643..0b789e0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ -VERSION_NAME=1.1.4 +VERSION_NAME=2.0.0 VERSION_CODE=0 GROUP=org.hjson diff --git a/history.md b/history.md index 3eaa83b..5f59c40 100644 --- a/history.md +++ b/history.md @@ -1,5 +1,8 @@ # hjson-java History +- v2.0.0 + - fix quoteless string starting with punctuator + - add cli - v1.1.4 - fix writer for comment tokens in keyname - v1.1.3 diff --git a/src/main/org/hjson/HjsonParser.java b/src/main/org/hjson/HjsonParser.java index 4c6ca9e..37643ec 100644 --- a/src/main/org/hjson/HjsonParser.java +++ b/src/main/org/hjson/HjsonParser.java @@ -112,6 +112,8 @@ private JsonValue readTfnns() throws IOException { // returns string, true, false, or null. StringBuilder value=new StringBuilder(); int first=current; + if (isPunctuatorChar(first)) + throw error("Found a punctuator character '" + (char)first + "' when excpecting a quoteless string (check your syntax)"); value.append((char)current); for (;;) { read(); @@ -472,6 +474,10 @@ private ParseException expected(String expected) { return error("Expected "+expected); } + private boolean isPunctuatorChar(int c) { + return c == '{' || c == '}' || c == '[' || c == ']' || c == ',' || c == ':'; + } + private ParseException error(String message) { int column=index-lineOffset; int offset=isEndOfText()?index:index-1; diff --git a/src/test/org/hjson/test/Main.java b/src/test/org/hjson/test/Main.java index 84f2109..f675051 100644 --- a/src/test/org/hjson/test/Main.java +++ b/src/test/org/hjson/test/Main.java @@ -6,54 +6,6 @@ public class Main { - private static String[] testNames={ - "comments_test.hjson", - "fail10_test.json", - "fail11_test.json", - "fail12_test.json", - "fail13_test.json", - "fail14_test.json", - "fail15_test.json", - "fail16_test.json", - "fail17_test.json", - "fail19_test.json", - "fail20_test.json", - "fail21_test.json", - "fail22_test.json", - "fail23_test.json", - "fail24_test.json", - "fail26_test.json", - "fail28_test.json", - "fail29_test.json", - "fail2_test.json", - "fail30_test.json", - "fail31_test.json", - "fail32_test.json", - "fail33_test.json", - "fail5_test.json", - "fail6_test.json", - "fail7_test.json", - "fail8_test.json", - "failKey1_test.hjson", - "failKey2_test.hjson", - "failKey3_test.hjson", - "failObj1_test.hjson", - "failObj2_test.hjson", - "failObj3_test.hjson", - "kan_test.hjson", - "keys_test.hjson", - "oa_test.hjson", - "pass1_test.json", - "pass2_test.json", - "pass3_test.json", - "pass4_test.json", - "passSingle_test.hjson", - "root_test.hjson", - "stringify1_test.hjson", - "strings_test.hjson", - "trail_test.hjson", - }; - public static String convertStreamToString(InputStream is) throws IOException { Writer writer=new StringWriter(); char[] buffer=new char[1024]; @@ -129,20 +81,28 @@ public static void main(String[] args) throws Exception { out.println("running tests..."); + String[] testNames=load("testlist.txt", false).split("\n"); + boolean allOK=true; + for (String file : testNames) { int extIdx=file.lastIndexOf('.'); String name=file.substring(0, extIdx); name=name.substring(0, name.length()-5); //if (filter!=null && !name.Contains(filter)) continue; - if (!test(name, file, false, false) - || !test(name, file, true, false) - || !test(name, file, false, true) - || !test(name, file, true, true)) { System.exit(1); return; } - out.println("- "+name+" OK"); + if (test(name, file, false, false) + && test(name, file, true, false) + && test(name, file, false, true) + && test(name, file, true, true)) { + out.println("- "+name+" OK"); + } + else { allOK=false; } } - out.println("ALL OK!"); + if (!allOK) { + out.println("FAILED!"); + System.exit(1); + } else { out.println("ALL OK!"); } } }