Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielSchuette committed May 22, 2021
0 parents commit 795a9a5
Show file tree
Hide file tree
Showing 12 changed files with 1,616 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
tags
build/
bin/
189 changes: 189 additions & 0 deletions LICENSE.md

Large diffs are not rendered by default.

60 changes: 60 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
.DELETE_ON_ERROR:
.EXPORT_ALL_VARIABLES:
SRC_DIR = src
BUILD_DIR = build
BIN_DIR = bin
BIN = json_parse

# We specify globally applicable compiler options right here. They are exported
# to all recursively called Makefiles.
CC = gcc
CCFLAGS = -Wall -Werror -Wpedantic -Wextra -Wwrite-strings -Warray-bounds \
-Weffc++ -fno-exceptions --std=c++20 -O0
LDFLAGS = -lm -lstdc++

DEBUG = no
ifeq ($(DEBUG), yes)
CCFLAGS += -g -DNDEBUG
endif

.PHONY: all $(BIN) install test leak_test clean help

all: dirs $(BIN)

dirs: $(BUILD_DIR) $(BIN_DIR)

$(BUILD_DIR):
mkdir -p $(BUILD_DIR)

$(BIN_DIR):
mkdir -p $(BIN_DIR)

$(BIN):
ctags -R .
cd $(SRC_DIR) && $(MAKE)

install: all
cp $(BUILD_DIR)/$(BIN) $(BIN_DIR)

test: all
./$(BUILD_DIR)/$(BIN)

leak-test: all
valgrind -s --leak-check=full $(BUILD_DIR)/$(BIN)

# Since _all_ build artifacts are created in the build directory, we don't need
# to recursively call any subdirectory's Makefile for cleanup. We check whether
# the binary was installed in the base directory, because that might sometimes
# be useful.
clean:
rm -f tags
rm -rf $(BUILD_DIR)
[[ '$(BIN_DIR)' != '.' ]] && rm -rf $(BIN_DIR) || rm -f $(BIN)

help:
@printf "The following targets are available:\n"
@printf " all:\t\tBuild \`%s'.\n" $(BIN)
@printf " install:\tBuild and install \`%s' to \`%s'.\n" $(BIN) $(BIN_DIR)
@printf " test:\t\tBuild and execute \`%s'.\n" $(BIN)
@printf " clean:\t\tRemove all build artifacts.\n"
@printf "To enable debugging, supply the argument \`DEBUG=yes'.\n"
72 changes: 72 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Simple-JSON-Parser (SJP)
`SJP` is a minimal JSON parser that (almost) fully implements the JSON spec at
(https://www.json.org/json-en.html)[https://www.json.org/json-en.html]. It is
written in fairly clean C++ and the interface is designed to make data from a
JSON file easily accessible without a complicated API or any extra
dependencies. The following headers are used internally:

- `cassert`
- `cmath`
- `cstdarg`
- `cstdint`
- `cstdio`
- `cstdlib`
- `cstring`
- `algorithm`
- `unordered_map`
- `string`
- `queue`

The small logger I usually use depends on the following headers:

- `ctime`
- `unistd.h`

The logger interface is extremely minimal, too. If you're not on Linux and/or
want to use your own logger, just implement:

```c++
class YourLogger : public io::Logger {
public:
virtual void log(const char* fmt, ...) const override { /* ... */ }
virtual void warn(const char* fmt, ...) const override { /* ... */ }
[[noreturn]] virtual void log(const char* fmt, ...) const override
{ /* ... */ }
};
```
Then, replace `io.cc` with your mplementation file.
The `io.hh` header actually provides a `NullLogger` that doesn't do anything
and can be used if no logging should be done. Without a logger, you will only
know about parsing errors when you cannot access a specific property on your
JSON object.
We _do_ use `new`/`delete` for heap allocations and do not specify an interface
for using a custom allocator. Shouldn't be too hard to do, if that's a future
requirement. You can verify the fact that we don't leak any allocations with
`make leak-test` (requires `valgrind`).
# Usage Example
Take a look at `main.cc` for an example of how to use `SJP`. A
[Makefile](./src/Makefile) is provided (again, my setup with `gcc` as the
compiler). Run the following in the repository's base directory:
```bash
make test
```

# To-Do's
The only thing from the spec that we don't currently support are unicode code
points in string literals, i.e. right now `\uXXXX` is just ignored. For all my
purposes, I've never needed this.

There are a few things in the source that might need a fix. They're annotated
with `@TODO` and you can grep for them. Nothing big, though.

Lastly, we don't have a proper test suite right now. I've used this code as a
library quite a bit, but if you find a bug, I'll add regression tests ---
I promise!

# License
All code in this repository is licensed under the [GPLv3](./LICENSE.md).
27 changes: 27 additions & 0 deletions data/test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "John B. \"\tDoe\t\"!",
"format": {
"type": "rect",
"width": 1920,
"height": 1080,
"interlace": false,
"frame rate": 24,
"modes": [1, 2, 3, 4, 5, true],
"hex stuff": ["\u0182", "\u00e6", "\u3164", "\u3165", "\u00d8"],
"array of objects": [
{
"abc": true,
"def": false
},
{
"abc": false,
"def": true
}
]
},
"data": {
"deeply": {
"nested": [-0.124, 4230.0, 3.1415, 0, 1, 2, 3, 4]
}
}
}
29 changes: 29 additions & 0 deletions src/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
.DELETE_ON_ERROR:
.EXPORT_ALL_VARIABLES:
SRCS = $(wildcard *.cc)
OBJS = $(SRCS:.cc=.o)
DEPS = $(SRCS:.cc=.d)

# Since we create all build artifacts in a dedicated build directory, we must
# reconstruct an absolute path for every object file and the resulting binary.
# Also, for them to work, dependency files must be in the same directory as the
# related object file.
BUILD_DIR_PATH = ../$(BUILD_DIR)
BIN_PATH = $(BUILD_DIR_PATH)/$(BIN)
OBJS_PATH = $(addprefix $(BUILD_DIR_PATH)/,$(OBJS))
DEPS_PATH = $(addprefix $(BUILD_DIR_PATH)/,$(DEPS))

.PHONY: all

all: $(BIN_PATH)

# The resulting binary is created in the build directory. The main Makefile can
# then go and place it wherever it might seem appropriate.
$(BIN_PATH): $(OBJS_PATH)
$(CC) $(LDFLAGS) -o $@ $^

# We create all object files directly in the build directory.
$(OBJS_PATH): $(BUILD_DIR_PATH)/%.o: %.cc
$(CC) $(CCFLAGS) -MMD -MP -c -o $@ $<

-include $(DEPS_PATH)
27 changes: 27 additions & 0 deletions src/common.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/* Includes common to all parts of the project.
*
* Simple-JSON-Parser (SJP) Copyright (C) 2021 Daniel Schuette
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _COMMON_HH_
#define _COMMON_HH_

#include <cassert>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#endif /* _COMMON_HH_ */
Loading

0 comments on commit 795a9a5

Please sign in to comment.