mirror of https://github.com/xfarrow/dircomp.git
code readability, importing JSON library
This commit is contained in:
parent
d872d3ba96
commit
0159a89394
|
@ -0,0 +1,119 @@
|
|||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* json - Parse and generate JSON (JavaScript Object Notation)
|
||||
*
|
||||
* This is a library for encoding and decoding JSON that strives to be
|
||||
* easy to learn, use, and incorporate into an application.
|
||||
*
|
||||
* JSON (JavaScript Object Notation) facilitates passing data among different
|
||||
* programming languages, particularly JavaScript. It looks like this:
|
||||
*
|
||||
* [
|
||||
* {
|
||||
* "id": 1,
|
||||
* "firstname": "John",
|
||||
* "lastname": "Smith",
|
||||
* "email": "john@example.com",
|
||||
* "likes_pizza": false
|
||||
* },
|
||||
* {
|
||||
* "id": 2,
|
||||
* "firstname": "Linda",
|
||||
* "lastname": "Jones",
|
||||
* "email": null,
|
||||
* "likes_pizza": true
|
||||
* }
|
||||
* ]
|
||||
*
|
||||
* Example:
|
||||
* #include <ccan/json/json.h>
|
||||
* #include <math.h>
|
||||
* #include <stdio.h>
|
||||
* #include <stdlib.h>
|
||||
*
|
||||
* static int find_number(JsonNode *object, const char *name, double *out)
|
||||
* {
|
||||
* JsonNode *node = json_find_member(object, name);
|
||||
* if (node && node->tag == JSON_NUMBER) {
|
||||
* *out = node->number_;
|
||||
* return 1;
|
||||
* }
|
||||
* return 0;
|
||||
* }
|
||||
*
|
||||
* static void solve_pythagorean(JsonNode *triple)
|
||||
* {
|
||||
* double a = 0, b = 0, c = 0;
|
||||
* int a_given, b_given, c_given;
|
||||
*
|
||||
* if (triple->tag != JSON_OBJECT) {
|
||||
* fprintf(stderr, "Error: Expected a JSON object.\n");
|
||||
* exit(EXIT_FAILURE);
|
||||
* }
|
||||
*
|
||||
* a_given = find_number(triple, "a", &a);
|
||||
* b_given = find_number(triple, "b", &b);
|
||||
* c_given = find_number(triple, "c", &c);
|
||||
*
|
||||
* if (a_given + b_given + c_given != 2) {
|
||||
* fprintf(stderr, "Error: I need two sides to compute the length of the third.\n");
|
||||
* exit(EXIT_FAILURE);
|
||||
* }
|
||||
*
|
||||
* if (a_given && b_given) {
|
||||
* c = sqrt(a*a + b*b);
|
||||
* json_append_member(triple, "c", json_mknumber(c));
|
||||
* } else if (a_given && c_given) {
|
||||
* b = sqrt(c*c - a*a);
|
||||
* json_append_member(triple, "b", json_mknumber(b));
|
||||
* } else if (b_given && c_given) {
|
||||
* a = sqrt(c*c - b*b);
|
||||
* json_append_member(triple, "a", json_mknumber(a));
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* int main(void)
|
||||
* {
|
||||
* JsonNode *triples = json_mkarray();
|
||||
*
|
||||
* json_append_element(triples, json_decode("{\"a\": 3, \"b\": 4}"));
|
||||
* json_append_element(triples, json_decode("{\"a\": 5, \"c\": 13}"));
|
||||
* json_append_element(triples, json_decode("{\"b\": 24, \"c\": 25}"));
|
||||
*
|
||||
* JsonNode *triple;
|
||||
* json_foreach(triple, triples)
|
||||
* solve_pythagorean(triple);
|
||||
*
|
||||
* char *tmp = json_stringify(triples, "\t");
|
||||
* puts(tmp);
|
||||
* free(tmp);
|
||||
*
|
||||
* json_delete(triples);
|
||||
* return 0;
|
||||
* }
|
||||
*
|
||||
* Author: Joey Adams
|
||||
* Version: 0.1
|
||||
* License: MIT
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
/* Expect exactly one argument */
|
||||
if (argc != 2)
|
||||
return 1;
|
||||
|
||||
if (strcmp(argv[1], "depends") == 0) {
|
||||
/* Nothing */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "libs") == 0) {
|
||||
printf("m\n"); /* Needed for sqrt() used in example code above. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
Copyright (C) 2011 Joseph A. Adams (joeyadams3.14159@gmail.com)
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CCAN_JSON_H
|
||||
#define CCAN_JSON_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
typedef enum {
|
||||
JSON_NULL,
|
||||
JSON_BOOL,
|
||||
JSON_STRING,
|
||||
JSON_NUMBER,
|
||||
JSON_ARRAY,
|
||||
JSON_OBJECT,
|
||||
} JsonTag;
|
||||
|
||||
typedef struct JsonNode JsonNode;
|
||||
|
||||
struct JsonNode
|
||||
{
|
||||
/* only if parent is an object or array (NULL otherwise) */
|
||||
JsonNode *parent;
|
||||
JsonNode *prev, *next;
|
||||
|
||||
/* only if parent is an object (NULL otherwise) */
|
||||
char *key; /* Must be valid UTF-8. */
|
||||
|
||||
JsonTag tag;
|
||||
union {
|
||||
/* JSON_BOOL */
|
||||
bool bool_;
|
||||
|
||||
/* JSON_STRING */
|
||||
char *string_; /* Must be valid UTF-8. */
|
||||
|
||||
/* JSON_NUMBER */
|
||||
double number_;
|
||||
|
||||
/* JSON_ARRAY */
|
||||
/* JSON_OBJECT */
|
||||
struct {
|
||||
JsonNode *head, *tail;
|
||||
} children;
|
||||
};
|
||||
};
|
||||
|
||||
/*** Encoding, decoding, and validation ***/
|
||||
|
||||
JsonNode *json_decode (const char *json);
|
||||
char *json_encode (const JsonNode *node);
|
||||
char *json_encode_string (const char *str);
|
||||
char *json_stringify (const JsonNode *node, const char *space);
|
||||
void json_delete (JsonNode *node);
|
||||
|
||||
bool json_validate (const char *json);
|
||||
|
||||
/*** Lookup and traversal ***/
|
||||
|
||||
JsonNode *json_find_element (JsonNode *array, int index);
|
||||
JsonNode *json_find_member (JsonNode *object, const char *key);
|
||||
|
||||
JsonNode *json_first_child (const JsonNode *node);
|
||||
|
||||
#define json_foreach(i, object_or_array) \
|
||||
for ((i) = json_first_child(object_or_array); \
|
||||
(i) != NULL; \
|
||||
(i) = (i)->next)
|
||||
|
||||
/*** Construction and manipulation ***/
|
||||
|
||||
JsonNode *json_mknull(void);
|
||||
JsonNode *json_mkbool(bool b);
|
||||
JsonNode *json_mkstring(const char *s);
|
||||
JsonNode *json_mknumber(double n);
|
||||
JsonNode *json_mkarray(void);
|
||||
JsonNode *json_mkobject(void);
|
||||
|
||||
void json_append_element(JsonNode *array, JsonNode *element);
|
||||
void json_prepend_element(JsonNode *array, JsonNode *element);
|
||||
void json_append_member(JsonNode *object, const char *key, JsonNode *value);
|
||||
void json_prepend_member(JsonNode *object, const char *key, JsonNode *value);
|
||||
|
||||
void json_remove_from_parent(JsonNode *node);
|
||||
|
||||
/*** Debugging ***/
|
||||
|
||||
/*
|
||||
* Look for structure and encoding problems in a JsonNode or its descendents.
|
||||
*
|
||||
* If a problem is detected, return false, writing a description of the problem
|
||||
* to errmsg (unless errmsg is NULL).
|
||||
*/
|
||||
bool json_check(const JsonNode *node, char errmsg[256]);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,18 @@
|
|||
#include <ccan/json/json.c>
|
||||
#include <ccan/tap/tap.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
static char *chomp(char *s)
|
||||
{
|
||||
char *e;
|
||||
|
||||
if (s == NULL || *s == 0)
|
||||
return s;
|
||||
|
||||
e = strchr(s, 0);
|
||||
if (e[-1] == '\n')
|
||||
*--e = 0;
|
||||
return s;
|
||||
}
|
|
@ -0,0 +1,191 @@
|
|||
/* Build a list of numbers with various appends and prepends, verify them by testing against their encoded value, do pointer consistency checks each time, do element lookups, and remove items as well. */
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define should_be(var, expected) should_be_(var, #var, expected)
|
||||
|
||||
static void should_be_(const JsonNode *node, const char *name, const char *expected)
|
||||
{
|
||||
char errmsg[256];
|
||||
char *encoded;
|
||||
|
||||
if (!json_check(node, errmsg)) {
|
||||
fail("Invariants check failed: %s", errmsg);
|
||||
return;
|
||||
}
|
||||
|
||||
encoded = json_encode(node);
|
||||
|
||||
if (strcmp(encoded, expected) == 0)
|
||||
pass("%s is %s", name, expected);
|
||||
else
|
||||
fail("%s should be %s, but is actually %s", name, expected, encoded);
|
||||
|
||||
free(encoded);
|
||||
}
|
||||
|
||||
static void test_string(void)
|
||||
{
|
||||
JsonNode *str;
|
||||
|
||||
str = json_mkstring("Hello\tworld!\n\001");
|
||||
should_be(str, "\"Hello\\tworld!\\n\\u0001\"");
|
||||
json_delete(str);
|
||||
|
||||
str = json_mkstring("\"\\\b\f\n\r\t");
|
||||
should_be(str, "\"\\\"\\\\\\b\\f\\n\\r\\t\"");
|
||||
json_delete(str);
|
||||
}
|
||||
|
||||
static void test_number(void)
|
||||
{
|
||||
JsonNode *num;
|
||||
|
||||
num = json_mknumber(5678901234.0);
|
||||
should_be(num, "5678901234");
|
||||
json_delete(num);
|
||||
|
||||
num = json_mknumber(-5678901234.0);
|
||||
should_be(num, "-5678901234");
|
||||
json_delete(num);
|
||||
|
||||
num = json_mknumber(0.0 / 0.0);
|
||||
should_be(num, "null");
|
||||
json_delete(num);
|
||||
}
|
||||
|
||||
static void test_array(void)
|
||||
{
|
||||
JsonNode *array;
|
||||
JsonNode *children[5 + 1];
|
||||
|
||||
array = json_mkarray();
|
||||
should_be(array, "[]");
|
||||
|
||||
children[1] = json_mknumber(1);
|
||||
children[2] = json_mknumber(2);
|
||||
children[3] = json_mknumber(3);
|
||||
children[4] = json_mknumber(4);
|
||||
children[5] = json_mknumber(5);
|
||||
|
||||
json_append_element(array, children[3]);
|
||||
should_be(array, "[3]");
|
||||
|
||||
json_remove_from_parent(children[3]);
|
||||
should_be(array, "[]");
|
||||
|
||||
json_prepend_element(array, children[3]);
|
||||
should_be(array, "[3]");
|
||||
|
||||
json_prepend_element(array, children[2]);
|
||||
should_be(array, "[2,3]");
|
||||
|
||||
json_append_element(array, children[4]);
|
||||
should_be(array, "[2,3,4]");
|
||||
|
||||
json_delete(children[3]);
|
||||
should_be(array, "[2,4]");
|
||||
|
||||
json_prepend_element(array, children[1]);
|
||||
should_be(array, "[1,2,4]");
|
||||
|
||||
json_delete(children[1]);
|
||||
should_be(array, "[2,4]");
|
||||
|
||||
json_delete(children[4]);
|
||||
should_be(array, "[2]");
|
||||
|
||||
ok1(json_find_element(array, 0) == children[2]);
|
||||
ok1(json_find_element(array, -1) == NULL);
|
||||
ok1(json_find_element(array, 1) == NULL);
|
||||
|
||||
json_append_element(array, children[5]);
|
||||
should_be(array, "[2,5]");
|
||||
|
||||
ok1(json_find_element(array, 0) == children[2]);
|
||||
ok1(json_find_element(array, 1) == children[5]);
|
||||
ok1(json_find_element(array, -1) == NULL);
|
||||
ok1(json_find_element(array, 2) == NULL);
|
||||
|
||||
json_delete(children[2]);
|
||||
json_delete(children[5]);
|
||||
should_be(array, "[]");
|
||||
|
||||
ok1(json_find_element(array, -1) == NULL);
|
||||
ok1(json_find_element(array, 0) == NULL);
|
||||
ok1(json_find_element(array, 1) == NULL);
|
||||
|
||||
json_delete(array);
|
||||
}
|
||||
|
||||
static void test_object(void)
|
||||
{
|
||||
JsonNode *object;
|
||||
JsonNode *children[5 + 1];
|
||||
|
||||
object = json_mkobject();
|
||||
should_be(object, "{}");
|
||||
|
||||
children[1] = json_mknumber(1);
|
||||
children[2] = json_mknumber(2);
|
||||
children[3] = json_mknumber(3);
|
||||
|
||||
ok1(json_find_member(object, "one") == NULL);
|
||||
ok1(json_find_member(object, "two") == NULL);
|
||||
ok1(json_find_member(object, "three") == NULL);
|
||||
|
||||
json_append_member(object, "one", children[1]);
|
||||
should_be(object, "{\"one\":1}");
|
||||
|
||||
ok1(json_find_member(object, "one") == children[1]);
|
||||
ok1(json_find_member(object, "two") == NULL);
|
||||
ok1(json_find_member(object, "three") == NULL);
|
||||
|
||||
json_prepend_member(object, "two", children[2]);
|
||||
should_be(object, "{\"two\":2,\"one\":1}");
|
||||
|
||||
ok1(json_find_member(object, "one") == children[1]);
|
||||
ok1(json_find_member(object, "two") == children[2]);
|
||||
ok1(json_find_member(object, "three") == NULL);
|
||||
|
||||
json_append_member(object, "three", children[3]);
|
||||
should_be(object, "{\"two\":2,\"one\":1,\"three\":3}");
|
||||
|
||||
ok1(json_find_member(object, "one") == children[1]);
|
||||
ok1(json_find_member(object, "two") == children[2]);
|
||||
ok1(json_find_member(object, "three") == children[3]);
|
||||
|
||||
json_delete(object);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
JsonNode *node;
|
||||
|
||||
(void) chomp;
|
||||
|
||||
plan_tests(49);
|
||||
|
||||
ok1(json_find_element(NULL, 0) == NULL);
|
||||
ok1(json_find_member(NULL, "") == NULL);
|
||||
ok1(json_first_child(NULL) == NULL);
|
||||
|
||||
node = json_mknull();
|
||||
should_be(node, "null");
|
||||
json_delete(node);
|
||||
|
||||
node = json_mkbool(false);
|
||||
should_be(node, "false");
|
||||
json_delete(node);
|
||||
|
||||
node = json_mkbool(true);
|
||||
should_be(node, "true");
|
||||
json_delete(node);
|
||||
|
||||
test_string();
|
||||
test_number();
|
||||
test_array();
|
||||
test_object();
|
||||
|
||||
return exit_status();
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
#include "common.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
const char *strings_file = "test/test-strings";
|
||||
const char *strings_reencoded_file = "test/test-strings-reencoded";
|
||||
FILE *f, *f2;
|
||||
char buffer[1024], buffer2[1024];
|
||||
|
||||
plan_tests(90);
|
||||
|
||||
f = fopen(strings_file, "rb");
|
||||
if (f == NULL) {
|
||||
diag("Could not open %s: %s", strings_file, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
f2 = fopen(strings_reencoded_file, "rb");
|
||||
if (f2 == NULL) {
|
||||
diag("Could not open %s: %s", strings_reencoded_file, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (fgets(buffer, sizeof(buffer), f)) {
|
||||
const char *s = chomp(buffer);
|
||||
bool valid;
|
||||
JsonNode *node;
|
||||
|
||||
if (expect_literal(&s, "valid ")) {
|
||||
valid = true;
|
||||
} else if (expect_literal(&s, "invalid ")) {
|
||||
valid = false;
|
||||
} else {
|
||||
fail("Invalid line in test-strings: %s", buffer);
|
||||
continue;
|
||||
}
|
||||
|
||||
node = json_decode(s);
|
||||
|
||||
if (valid) {
|
||||
char *reencoded;
|
||||
char errmsg[256];
|
||||
|
||||
if (node == NULL) {
|
||||
fail("%s is valid, but json_decode returned NULL", s);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!json_check(node, errmsg)) {
|
||||
fail("Corrupt tree produced by json_decode: %s", errmsg);
|
||||
continue;
|
||||
}
|
||||
|
||||
reencoded = json_encode(node);
|
||||
|
||||
if (!fgets(buffer2, sizeof(buffer2), f2)) {
|
||||
fail("test-strings-reencoded is missing this line: %s", reencoded);
|
||||
continue;
|
||||
}
|
||||
chomp(buffer2);
|
||||
|
||||
ok(strcmp(reencoded, buffer2) == 0, "re-encode %s -> %s", s, reencoded);
|
||||
|
||||
free(reencoded);
|
||||
json_delete(node);
|
||||
} else if (node != NULL) {
|
||||
fail("%s is invalid, but json_decode returned non-NULL", s);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (ferror(f) || fclose(f) != 0 || ferror(f2) || fclose(f2) != 0) {
|
||||
diag("I/O error reading test data.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return exit_status();
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
#include "common.h"
|
||||
|
||||
static char buf1[256], buf2[256];
|
||||
|
||||
/* Used for pass and fail messages */
|
||||
static char *quote_string(const char *str, char buf[256])
|
||||
{
|
||||
char *out = buf;
|
||||
|
||||
*out++ = '"';
|
||||
for (; *str != 0; str++) {
|
||||
if (out - buf > 256 - 5) {
|
||||
/* String is too long. End it with `...' */
|
||||
out = buf + 256 - 5;
|
||||
*out++ = '.';
|
||||
*out++ = '.';
|
||||
*out++ = '.';
|
||||
break;
|
||||
}
|
||||
switch (*str) {
|
||||
case '\t':
|
||||
*out++ = '\\';
|
||||
*out++ = 't';
|
||||
break;
|
||||
case '\n':
|
||||
*out++ = '\\';
|
||||
*out++ = 'n';
|
||||
break;
|
||||
case '"':
|
||||
*out++ = '\\';
|
||||
*out++ = '"';
|
||||
break;
|
||||
case '\\':
|
||||
*out++ = '\\';
|
||||
*out++ = '\\';
|
||||
break;
|
||||
default:
|
||||
*out++ = *str;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*out++ = '"';
|
||||
|
||||
*out = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void test_stringify(const char *input, const char *expected)
|
||||
{
|
||||
JsonNode *node = NULL;
|
||||
char *enc = NULL;
|
||||
char *strn = NULL;
|
||||
char *str = NULL;
|
||||
|
||||
node = json_decode(input);
|
||||
if (node == NULL) {
|
||||
fail("Failed to decode %s", input);
|
||||
goto end;
|
||||
}
|
||||
|
||||
enc = json_encode(node);
|
||||
if (strcmp(enc, input) != 0) {
|
||||
fail("%s re-encodes to %s. Either encode/decode is broken, or the input string needs to be normalized", input, enc);
|
||||
goto end;
|
||||
}
|
||||
|
||||
strn = json_stringify(node, NULL);
|
||||
if (strcmp(strn, enc) != 0) {
|
||||
fail("json_stringify with NULL space produced a different string than json_encode");
|
||||
goto end;
|
||||
}
|
||||
|
||||
str = json_stringify(node, "\t");
|
||||
if (strcmp(str, expected) != 0) {
|
||||
fail("Expected %s, but json_stringify produced %s",
|
||||
quote_string(expected, buf1), quote_string(str, buf2));
|
||||
goto end;
|
||||
}
|
||||
|
||||
pass("stringify %s", input);
|
||||
|
||||
end:
|
||||
json_delete(node);
|
||||
free(enc);
|
||||
free(strn);
|
||||
free(str);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
(void) chomp;
|
||||
|
||||
plan_tests(9);
|
||||
|
||||
test_stringify("[]", "[]");
|
||||
test_stringify("[1]", "[\n\t1\n]");
|
||||
test_stringify("[1,2,3]", "[\n\t1,\n\t2,\n\t3\n]");
|
||||
test_stringify("[[]]", "[\n\t[]\n]");
|
||||
test_stringify("[[1,2],[3,4]]", "[\n\t[\n\t\t1,\n\t\t2\n\t],\n\t[\n\t\t3,\n\t\t4\n\t]\n]");
|
||||
|
||||
test_stringify("{}", "{}");
|
||||
test_stringify("{\"one\":1}", "{\n\t\"one\": 1\n}");
|
||||
test_stringify("{\"one\":1,\"t*\":[2,3,10]}", "{\n\t\"one\": 1,\n\t\"t*\": [\n\t\t2,\n\t\t3,\n\t\t10\n\t]\n}");
|
||||
test_stringify("{\"a\":{\"1\":1,\"2\":2},\"b\":{\"3\":[null,false,true,\"\\f\"]}}",
|
||||
"{\n\t\"a\": {\n\t\t\"1\": 1,\n\t\t\"2\": 2\n\t},\n\t\"b\": {\n\t\t\"3\": [\n\t\t\tnull,\n\t\t\tfalse,\n\t\t\ttrue,\n\t\t\t\"\\f\"\n\t\t]\n\t}\n}");
|
||||
|
||||
return exit_status();
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
#include "common.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
const char *strings_file = "test/test-strings";
|
||||
FILE *f;
|
||||
char buffer[1024];
|
||||
|
||||
plan_tests(224);
|
||||
|
||||
f = fopen(strings_file, "rb");
|
||||
if (f == NULL) {
|
||||
diag("Could not open %s: %s", strings_file, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (fgets(buffer, sizeof(buffer), f)) {
|
||||
const char *s = chomp(buffer);
|
||||
bool valid;
|
||||
|
||||
if (expect_literal(&s, "valid ")) {
|
||||
valid = true;
|
||||
} else if (expect_literal(&s, "invalid ")) {
|
||||
valid = false;
|
||||
} else {
|
||||
fail("Invalid line in test-strings: %s", buffer);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(s, "\"1\\u2\"") == 0)
|
||||
puts("here");
|
||||
|
||||
if (json_validate(s) == valid) {
|
||||
pass("%s %s", valid ? "valid" : "invalid", s);
|
||||
} else {
|
||||
fail("%s is %s, but json_validate returned %s",
|
||||
s,
|
||||
valid ? "valid" : "invalid",
|
||||
valid ? "false" : "true");
|
||||
}
|
||||
}
|
||||
|
||||
if (ferror(f) || fclose(f) != 0) {
|
||||
diag("I/O error reading test strings.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return exit_status();
|
||||
}
|
|
@ -0,0 +1,224 @@
|
|||
invalid
|
||||
invalid
|
||||
invalid "
|
||||
invalid [,]
|
||||
invalid [)
|
||||
invalid []]
|
||||
invalid [}
|
||||
invalid {,}
|
||||
invalid {]
|
||||
invalid ["1":2]
|
||||
invalid [1,2,]
|
||||
invalid [1:2}
|
||||
invalid {"1":2,}
|
||||
invalid {1:2}
|
||||
invalid {"1":2, "2.5" : [3, 4, {}, {"5": ["6"], [7 ]}]}
|
||||
invalid {"1":2, "2.5" : [3, 4, {}, {"5": ["6"], [7]}]}
|
||||
invalid {"1":2, "2.5" : [3, 4, {}, {"5": ["6"], "7" :[8 ]}]
|
||||
invalid {"1":2, "2.5" : [3, 4, {}, {"5": ["6"], "7" :[8 ]}]]
|
||||
invalid {"1":2, "3":4
|
||||
invalid "1\u2"
|
||||
invalid [,2]
|
||||
invalid "3
|
||||
invalid "3" "4"
|
||||
invalid [3[4]
|
||||
invalid [3[4]]
|
||||
invalid [3, [4, [5], 6] 7, 8 9]
|
||||
invalid [3, [4, [5], 6] 7, 8, 9]
|
||||
invalid [3, [4, [5], 6], 7, 8 9]
|
||||
invalid {"hello":true, "bye":false, null}
|
||||
invalid {"hello":true, "bye":false, null:null}
|
||||
invalid "hi
|
||||
invalid "hi"""
|
||||
invalid {"hi": "bye"]
|
||||
invalid "\uD800\uD800"
|
||||
invalid "\uD800\uDBFF"
|
||||
invalid "\UD834\UDD1E"
|
||||
invalid "\uDB00"
|
||||
invalid "\uDB00\uDBFF"
|
||||
valid "\uFFFE"
|
||||
valid "\uFFFF"
|
||||
invalid .
|
||||
valid ""
|
||||
valid []
|
||||
valid {}
|
||||
invalid +.
|
||||
valid 0.5
|
||||
invalid 0.e1
|
||||
valid {"1":{}}
|
||||
valid {"1":2}
|
||||
valid {"1":2, "2.5" : [3, 4, {}, {"5": ["6"]}]}
|
||||
valid {"1":2, "2.5" : [3, 4, {}, {"5": ["6"], "7" :[8 ]}]}
|
||||
valid 1234
|
||||
valid -1234
|
||||
valid {"1":2, "3":4}
|
||||
invalid +1234
|
||||
invalid ++1234
|
||||
valid 123.456e142
|
||||
valid 123.456e-142
|
||||
valid 123.456e+142
|
||||
invalid 123.e-142
|
||||
valid "1\u2000"
|
||||
valid "1\u20001"
|
||||
valid 2
|
||||
invalid .246e-142
|
||||
invalid .2e-142
|
||||
valid 3
|
||||
invalid .3
|
||||
valid "3"
|
||||
valid [3]
|
||||
invalid +3.
|
||||
valid 3.2e+1
|
||||
valid [3, [4]]
|
||||
valid [3, [4, [5]]]
|
||||
valid [3, [4, [5], 6]]
|
||||
valid [3, [4, [5], 6], 7]
|
||||
valid [3, [4, [5], 6], 7, 8]
|
||||
valid [3, [4, [5], 6], 7, 8, 9]
|
||||
invalid +3.5
|
||||
invalid .3e
|
||||
invalid .3e1
|
||||
invalid .3e-1
|
||||
invalid .3e+1
|
||||
invalid 3.e1
|
||||
invalid 3.e+1
|
||||
valid 3e+1
|
||||
invalid .5
|
||||
invalid +.5
|
||||
invalid .5e+1
|
||||
valid [ 7]
|
||||
valid [7 ]
|
||||
valid [7]
|
||||
invalid .e-14234
|
||||
valid "hello"
|
||||
valid ["hello"]
|
||||
valid ["hello", "bye"]
|
||||
valid ["hello", "bye\n"]
|
||||
valid ["hello", "bye\n\r\t"]
|
||||
valid ["hello", "bye\n\r\t\b"]
|
||||
valid ["hello", "bye\n\r\t\b",true]
|
||||
valid ["hello", "bye\n\r\t\b",true , false]
|
||||
valid ["hello", "bye\n\r\t\b",true , false, null]
|
||||
invalid ["hello", "bye\n\r\t\v"]
|
||||
valid {"hello":true}
|
||||
valid {"hello":true, "bye":false}
|
||||
valid {"hello":true, "bye":false, "foo":["one","two","three"]}
|
||||
valid "hi"
|
||||
valid ["hi"]
|
||||
valid ["hi", "bye"]
|
||||
valid {"hi": "bye"}
|
||||
valid ["hi", "bye", 3]
|
||||
valid ["hi", "bye[", 3]
|
||||
valid "\u0007"
|
||||
valid "\u0008"
|
||||
valid "\u0009"
|
||||
valid "\u0010"
|
||||
valid "\u0020"
|
||||
valid "\u10000"
|
||||
valid "\u1234"
|
||||
valid "\u99999"
|
||||
valid "\ud800\udc00"
|
||||
valid "\uD800\uDC00"
|
||||
valid "\uD834\uDD1E"
|
||||
valid "\uDBFF\uDFFF"
|
||||
valid "\uFFFD"
|
||||
valid "\uFFFF"
|
||||
invalid hello
|
||||
valid [32, 1]
|
||||
invalid [32,
|
||||
valid "\uD800\uDC00"
|
||||
valid "\n"
|
||||
valid "hello"
|
||||
valid "hello\u0009world"
|
||||
valid "hello"
|
||||
valid "hello\n"
|
||||
valid "hello"
|
||||
valid 3
|
||||
invalid 3.
|
||||
invalid .3
|
||||
valid 0.3
|
||||
invalid 0.3e
|
||||
invalid 0.3e+
|
||||
valid 0.3e+5
|
||||
valid 0.3e-5
|
||||
valid 0.3e5
|
||||
valid "hello"
|
||||
invalid +3
|
||||
valid -3
|
||||
invalid -3.
|
||||
valid -3.1
|
||||
invalid .5
|
||||
invalid 5.
|
||||
invalid 5.e1
|
||||
valid 0.5
|
||||
invalid .3e1
|
||||
invalid .3e+1
|
||||
invalid .3e-1
|
||||
invalid .3e-1 .5
|
||||
invalid .3e-1.5
|
||||
invalid .3e+1.5
|
||||
invalid .3e+.
|
||||
invalid .3e+.5
|
||||
invalid .3e+1.5
|
||||
invalid 9.3e+1.5
|
||||
invalid 9.e+1.5
|
||||
invalid 9.e+
|
||||
invalid 9.e+1
|
||||
valid "\""
|
||||
valid "\"3.5"
|
||||
valid "\"."
|
||||
invalid "\".".
|
||||
valid "\"....."
|
||||
invalid "\"\"\"\"""
|
||||
invalid ["\"\"\"\"", .5]
|
||||
invalid [.5]
|
||||
valid ["\"\"\"\"", 0.5]
|
||||
invalid ["\"\"\"\"", .5]
|
||||
invalid ["\"\"\"\"",.5]
|
||||
invalid ["\"",.5]
|
||||
invalid ["\".5",.5]
|
||||
invalid ["\".5",".5\"".5]
|
||||
invalid ["\".5",".5\"", .5]
|
||||
invalid ["\".5",".5\"",.5]
|
||||
valid ["\".5",".5\"",0.5]
|
||||
invalid {"key":/*comment*/"value"}
|
||||
invalid {"key":/*comment"value"}
|
||||
invalid {"key":"value"}/*
|
||||
invalid {"key":"value"}/**/
|
||||
invalid {"key":"value"}/***/
|
||||
invalid {"key":"value"}/**//
|
||||
invalid {"key":"value"}/**///
|
||||
invalid {"key":"value"}/**///----
|
||||
invalid {"key":"value"}#
|
||||
invalid {"key":"value"}#{
|
||||
invalid {"key":"value"}#{}
|
||||
invalid {"key":"value"}#,
|
||||
invalid {"key":"value"/**/, "k2":"v2"}
|
||||
valid "\u0027"
|
||||
invalid "hello\'"
|
||||
invalid 'hello\''
|
||||
invalid 'hello'
|
||||
invalid 'hell\'o'
|
||||
invalid '\'hello'
|
||||
invalid '\'hello\''
|
||||
invalid \'hello\'
|
||||
invalid 'hello\'
|
||||
invalid ['hello\']
|
||||
invalid ['hello\'']
|
||||
invalid ['hello"']
|
||||
invalid ['hello\"']
|
||||
invalid ['hello"o']
|
||||
invalid ['"']
|
||||
invalid '"'
|
||||
invalid '"hello"'
|
||||
invalid '"hello'
|
||||
invalid '"hi"'
|
||||
valid [ 1 , 2 , 3 ]
|
||||
invalid nil
|
||||
invalid fals
|
||||
invalid falsify
|
||||
invalid falsetto
|
||||
invalid truism
|
||||
invalid {"key"
|
||||
invalid {"key","key2":value}
|
||||
invalid "\u0000"
|
|
@ -0,0 +1,90 @@
|
|||
""
|
||||
""
|
||||
""
|
||||
[]
|
||||
{}
|
||||
0.5
|
||||
{"1":{}}
|
||||
{"1":2}
|
||||
{"1":2,"2.5":[3,4,{},{"5":["6"]}]}
|
||||
{"1":2,"2.5":[3,4,{},{"5":["6"],"7":[8]}]}
|
||||
1234
|
||||
-1234
|
||||
{"1":2,"3":4}
|
||||
1.23456e+144
|
||||
1.23456e-140
|
||||
1.23456e+144
|
||||
"1 "
|
||||
"1 1"
|
||||
2
|
||||
3
|
||||
"3"
|
||||
[3]
|
||||
32
|
||||
[3,[4]]
|
||||
[3,[4,[5]]]
|
||||
[3,[4,[5],6]]
|
||||
[3,[4,[5],6],7]
|
||||
[3,[4,[5],6],7,8]
|
||||
[3,[4,[5],6],7,8,9]
|
||||
30
|
||||
[7]
|
||||
[7]
|
||||
[7]
|
||||
"hello"
|
||||
["hello"]
|
||||
["hello","bye"]
|
||||
["hello","bye\n"]
|
||||
["hello","bye\n\r\t"]
|
||||
["hello","bye\n\r\t\b"]
|
||||
["hello","bye\n\r\t\b",true]
|
||||
["hello","bye\n\r\t\b",true,false]
|
||||
["hello","bye\n\r\t\b",true,false,null]
|
||||
{"hello":true}
|
||||
{"hello":true,"bye":false}
|
||||
{"hello":true,"bye":false,"foo":["one","two","three"]}
|
||||
"hi"
|
||||
["hi"]
|
||||
["hi","bye"]
|
||||
{"hi":"bye"}
|
||||
["hi","bye",3]
|
||||
["hi","bye[",3]
|
||||
"\u0007"
|
||||
"\b"
|
||||
"\t"
|
||||
"\u0010"
|
||||
" "
|
||||
"က0"
|
||||
"ሴ"
|
||||
"香9"
|
||||
"𐀀"
|
||||
"𐀀"
|
||||
"𝄞"
|
||||
""
|
||||
"<22>"
|
||||
""
|
||||
[32,1]
|
||||
"𐀀"
|
||||
"\n"
|
||||
"hello"
|
||||
"hello\tworld"
|
||||
"hello"
|
||||
"hello\n"
|
||||
"hello"
|
||||
3
|
||||
0.3
|
||||
30000
|
||||
3e-06
|
||||
30000
|
||||
"hello"
|
||||
-3
|
||||
-3.1
|
||||
0.5
|
||||
"\""
|
||||
"\"3.5"
|
||||
"\"."
|
||||
"\"....."
|
||||
["\"\"\"\"",0.5]
|
||||
["\".5",".5\"",0.5]
|
||||
"'"
|
||||
[1,2,3]
|
17
dircomp.c
17
dircomp.c
|
@ -24,15 +24,19 @@ struct arguments{
|
|||
|
||||
struct arguments get_arguments(int, char**);
|
||||
void print_help(void);
|
||||
void print_files_in_directory(char*, struct arguments);
|
||||
void print_files_in_directory(struct arguments);
|
||||
|
||||
int main(int argc, char* argv[]){
|
||||
struct arguments arguments = get_arguments(argc, argv);
|
||||
|
||||
if(arguments.h == true)
|
||||
if(arguments.h == true){
|
||||
print_help();
|
||||
return 0;
|
||||
}
|
||||
|
||||
print_files_in_directory("/home/user", arguments);
|
||||
arguments.directory1 = "/home/user";
|
||||
arguments.directory2 = "/home/user";
|
||||
print_files_in_directory(arguments);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -56,7 +60,6 @@ struct arguments get_arguments(int argc, char** argv){
|
|||
break;
|
||||
case 'h':
|
||||
provided_arguments.h = true;
|
||||
print_help();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -76,11 +79,11 @@ void print_help(void){
|
|||
* References:
|
||||
* https://www.gnu.org/software/libc/manual/html_node/Directory-Entries.html
|
||||
*/
|
||||
void print_files_in_directory(char* directory, struct arguments arguments){
|
||||
printf("\nAnalyzing directory %s\n", directory);
|
||||
void print_files_in_directory(struct arguments arguments){ // testing only
|
||||
printf("\nAnalyzing directory %s\n", arguments.directory1);
|
||||
DIR *d;
|
||||
struct dirent *dir;
|
||||
d = opendir(directory);
|
||||
d = opendir(arguments.directory1);
|
||||
if (d) {
|
||||
while ((dir = readdir(d)) != NULL) {
|
||||
|
||||
|
|
Loading…
Reference in New Issue