├── .editorconfig ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── debian ├── changelog ├── compat ├── control ├── copyright ├── ljudge.install ├── rules └── source │ └── format ├── etc └── ljudge │ ├── 3.py │ ├── run.cmd_list │ ├── run.mirrorfs │ └── version.cmd_list │ ├── _default │ ├── check.lrun_args │ ├── check.mirrorfs │ ├── compile.exe_name │ ├── compile.lrun_args │ ├── compile.mirrorfs │ ├── run.cmd_list │ ├── run.lrun_args │ └── run.mirrorfs │ ├── asm │ ├── check.mirrorfs │ ├── compile.cmd_list │ ├── compile.mirrorfs │ ├── run.mirrorfs │ └── version.cmd_list │ ├── awk │ ├── run.cmd_list │ ├── run.mirrorfs │ └── version.cmd_list │ ├── c │ ├── compile.cmd_list │ └── version.cmd_list │ ├── cj │ ├── compile.cmd_list │ ├── compile.mirrorfs │ ├── run.env │ ├── run.mirrorfs │ └── version.cmd_list │ ├── cl │ ├── run.cmd_list │ ├── run.mirrorfs │ └── version.cmd_list │ ├── clang.c │ ├── compile.cmd_list │ └── version.cmd_list │ ├── clang.cpp │ ├── compile.cmd_list │ └── version.cmd_list │ ├── cpp │ ├── compile.cmd_list │ └── version.cmd_list │ ├── cs │ ├── __tmp__a.csproj │ ├── compile.cmd_list │ ├── compile.env │ ├── compile.exe_name │ ├── compile.file_add │ ├── compile.mirrorfs │ ├── compile.src_name │ ├── run.cmd_list │ ├── run.env │ ├── run.lrun_args │ ├── run.mirrorfs │ └── version.cmd_list │ ├── d │ ├── compile.cmd_list │ ├── compile.mirrorfs │ └── version.cmd_list │ ├── f95 │ ├── compile.cmd_list │ └── version.cmd_list │ ├── fs │ ├── __tmp__a.fsproj │ ├── compile.cmd_list │ ├── compile.env │ ├── compile.exe_name │ ├── compile.file_add │ ├── compile.mirrorfs │ ├── compile.src_name │ ├── run.cmd_list │ ├── run.env │ ├── run.lrun_args │ ├── run.mirrorfs │ └── version.cmd_list │ ├── gcc.go │ ├── compile.cmd_list │ └── version.cmd_list │ ├── go │ ├── compile.cmd_list │ ├── compile.exe_name │ ├── compile.mirrorfs │ ├── compile.src_name │ └── version.cmd_list │ ├── hs │ ├── compile.cmd_list │ ├── compile.mirrorfs │ └── version.cmd_list │ ├── java │ ├── compile.cmd_list │ ├── compile.env │ ├── compile.exe_name │ ├── compile.mirrorfs │ ├── compile.src_name │ ├── run.cmd_list │ ├── run.env │ ├── run.lrun_args │ ├── run.mirrorfs │ └── version.cmd_list │ ├── jit.lua │ ├── run.cmd_list │ ├── run.mirrorfs │ └── version.cmd_list │ ├── js │ ├── run.cmd_list │ ├── run.mirrorfs │ └── version.cmd_list │ ├── kt │ ├── compile.cmd_list │ ├── compile.env │ ├── compile.exe_name │ ├── compile.mirrorfs │ ├── compile.src_name │ ├── run.cmd_list │ ├── run.env │ ├── run.lrun_args │ ├── run.mirrorfs │ └── version.cmd_list │ ├── lua │ ├── run.cmd_list │ ├── run.mirrorfs │ └── version.cmd_list │ ├── m │ ├── compile.cmd_list │ ├── run.mirrorfs │ └── version.cmd_list │ ├── ml │ ├── compile.cmd_list │ ├── compile.mirrorfs │ ├── run.mirrorfs │ └── version.cmd_list │ ├── modern.c │ ├── compile.cmd_list │ └── version.cmd_list │ ├── octave │ ├── run.cmd_list │ ├── run.mirrorfs │ └── version.cmd_list │ ├── pas │ ├── compile.cmd_list │ ├── compile.exe_name │ ├── compile.mirrorfs │ ├── compile.src_name │ └── version.cmd_list │ ├── php │ ├── run.cmd_list │ ├── run.mirrorfs │ └── version.cmd_list │ ├── pl │ ├── run.cmd_list │ ├── run.mirrorfs │ └── version.cmd_list │ ├── py │ ├── run.cmd_list │ ├── run.mirrorfs │ └── version.cmd_list │ ├── pypy.3.py │ ├── run.cmd_list │ ├── run.mirrorfs │ └── version.cmd_list │ ├── r │ ├── run.cmd_list │ ├── run.env │ ├── run.lrun_args │ ├── run.mirrorfs │ └── version.cmd_list │ ├── rb │ ├── run.cmd_list │ ├── run.mirrorfs │ └── version.cmd_list │ ├── rkt │ ├── compile.cmd_list │ ├── compile.exe_name │ ├── compile.mirrorfs │ ├── compile.src_name │ ├── run.cmd_list │ ├── run.mirrorfs │ ├── version.cmd_list │ └── version.name │ ├── rs │ ├── compile.cmd_list │ ├── compile.mirrorfs │ └── version.cmd_list │ ├── scala │ ├── compile.cmd_list │ ├── compile.env │ ├── compile.exe_name │ ├── compile.mirrorfs │ ├── compile.src_name │ ├── run.cmd_list │ ├── run.env │ ├── run.lrun_args │ ├── run.mirrorfs │ └── version.cmd_list │ ├── sh │ ├── run.cmd_list │ ├── run.lrun_args │ ├── run.mirrorfs │ └── version.cmd_list │ ├── swift │ ├── compile.cmd_list │ └── version.cmd_list │ ├── txt │ ├── run.cmd_list │ ├── run.mirrorfs │ └── version.cmd_list │ ├── vala │ ├── compile.cmd_list │ └── version.cmd_list │ └── vb │ ├── __tmp__a.vbproj │ ├── compile.cmd_list │ ├── compile.env │ ├── compile.exe_name │ ├── compile.file_add │ ├── compile.mirrorfs │ ├── compile.src_name │ ├── run.cmd_list │ ├── run.env │ ├── run.lrun_args │ ├── run.mirrorfs │ └── version.cmd_list ├── examples ├── a-plus-b │ ├── 1.in │ ├── 1.out │ ├── 2.in │ ├── 2.out │ ├── a.3.py │ ├── a.asm │ ├── a.awk │ ├── a.c │ ├── a.cj │ ├── a.cl │ ├── a.clang.c │ ├── a.clang.cpp │ ├── a.cpp │ ├── a.cs │ ├── a.d │ ├── a.f95 │ ├── a.fs │ ├── a.gcc.go │ ├── a.gcj.java │ ├── a.go │ ├── a.hs │ ├── a.java │ ├── a.jit.lua │ ├── a.js │ ├── a.kt │ ├── a.lua │ ├── a.m │ ├── a.ml │ ├── a.modern.c │ ├── a.octave │ ├── a.pas │ ├── a.php │ ├── a.pl │ ├── a.py │ ├── a.pypy.3.py │ ├── a.r │ ├── a.rb │ ├── a.rkt │ ├── a.rs │ ├── a.scala │ ├── a.sh │ ├── a.swift │ ├── a.txt │ ├── a.vala │ ├── a.vb │ ├── legacy_checker.c │ ├── run.sh │ └── wa.c ├── interactor │ ├── 19 │ ├── 20 │ ├── 21 │ ├── 01 │ ├── 01.out │ ├── 19.out │ ├── 20.out │ ├── 21.out │ ├── ac.cpp │ ├── check.cpp │ ├── interactor.cpp │ ├── ml.cpp │ ├── pe.cpp │ ├── run.sh │ ├── too-many-iter.cpp │ └── wa.cpp └── stack │ ├── 1.in │ ├── 1.out │ ├── 2.in │ ├── 2.out │ ├── large_stack.c │ └── run.sh ├── schema └── response.json └── src ├── Makefile ├── deps ├── fs │ ├── fs.c │ ├── fs.h │ └── package.json ├── log.h │ ├── log.h │ └── package.json ├── picojson │ ├── .gitignore │ ├── .travis.yml │ ├── Changes │ ├── LICENSE │ ├── Makefile │ ├── README.mkdn │ ├── examples │ │ ├── github-issues.cc │ │ ├── iostream.cc │ │ └── streaming.cc │ └── picojson.h ├── sha1 │ ├── package.json │ ├── sha1.c │ └── sha1.h └── tinyformat │ ├── README.rst │ └── tinyformat.h ├── fs.cc ├── fs.hpp ├── ljudge.cc ├── sha1.cc ├── sha1.hpp ├── term.cc └── term.hpp /.editorconfig: -------------------------------------------------------------------------------- 1 | # This file is for unifying the coding style for different editors and IDEs 2 | # editorconfig.org 3 | 4 | root = true 5 | 6 | [!src/deps/**/*] 7 | indent_size = 2 8 | indent_style = space 9 | charset = utf-8 10 | end_of_line = lf 11 | insert_final_newline = true 12 | trim_trailing_whitespace = true 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | /src/ljudge 3 | node_modules 4 | *.log 5 | .idea -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | LJUDGE 2 | ====== 3 | 4 | Copyright (C) 2014 Jun Wu 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | 24 | 25 | 3RD-PARTIES 26 | =========== 27 | 28 | fs.c (src/deps/fs) 29 | ------------------ 30 | 31 | The MIT License (MIT) 32 | 33 | Copyright (c) 2013 Joseph Werle 34 | 35 | Permission is hereby granted, free of charge, to any person obtaining a copy of 36 | this software and associated documentation files (the "Software"), to deal in 37 | the Software without restriction, including without limitation the rights to 38 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 39 | the Software, and to permit persons to whom the Software is furnished to do so, 40 | subject to the following conditions: 41 | 42 | The above copyright notice and this permission notice shall be included in all 43 | copies or substantial portions of the Software. 44 | 45 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 46 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 47 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 48 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 49 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 50 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 51 | 52 | 53 | log.h (src/deps/log.h) 54 | ---------------------- 55 | 56 | Copyright 2013 Thorsten Lorenz. 57 | All rights reserved. 58 | 59 | Permission is hereby granted, free of charge, to any person 60 | obtaining a copy of this software and associated documentation 61 | files (the "Software"), to deal in the Software without 62 | restriction, including without limitation the rights to use, 63 | copy, modify, merge, publish, distribute, sublicense, and/or sell 64 | copies of the Software, and to permit persons to whom the 65 | Software is furnished to do so, subject to the following 66 | conditions: 67 | 68 | The above copyright notice and this permission notice shall be 69 | included in all copies or substantial portions of the Software. 70 | 71 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 72 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 73 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 74 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 75 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 76 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 77 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 78 | OTHER DEALINGS IN THE SOFTWARE. 79 | 80 | 81 | picojson (src/deps/picojson) 82 | ---------------------------- 83 | 84 | Copyright 2009-2010 Cybozu Labs, Inc. 85 | Copyright 2011-2014 Kazuho Oku 86 | All rights reserved. 87 | 88 | Redistribution and use in source and binary forms, with or without 89 | modification, are permitted provided that the following conditions are met: 90 | 91 | 1. Redistributions of source code must retain the above copyright notice, 92 | this list of conditions and the following disclaimer. 93 | 94 | 2. Redistributions in binary form must reproduce the above copyright notice, 95 | this list of conditions and the following disclaimer in the documentation 96 | and/or other materials provided with the distribution. 97 | 98 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 99 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 100 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 101 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 102 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 103 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 104 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 105 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 106 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 107 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 108 | POSSIBILITY OF SUCH DAMAGE. 109 | 110 | 111 | sha1 (src/deps/sha1) 112 | -------------------- 113 | 114 | (Public domain) 115 | 116 | 117 | tinyformat (src/deps/tinyformat) 118 | -------------------------------- 119 | 120 | Copyright (C) 2011, Chris Foster [chris42f (at) gmail (d0t) com] 121 | 122 | Boost Software License - Version 1.0 123 | 124 | Permission is hereby granted, free of charge, to any person or organization 125 | obtaining a copy of the software and accompanying documentation covered by 126 | this license (the "Software") to use, reproduce, display, distribute, 127 | execute, and transmit the Software, and to prepare derivative works of the 128 | Software, and to permit third-parties to whom the Software is furnished to 129 | do so, all subject to the following: 130 | 131 | The copyright notices in the Software and this entire statement, including 132 | the above license grant, this restriction and the following disclaimer, 133 | must be included in all copies of the Software, in whole or in part, and 134 | all derivative works of the Software, unless such copies or derivative 135 | works are solely in the form of machine-executable object code generated by 136 | a source language processor. 137 | 138 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 139 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 140 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 141 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 142 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 143 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 144 | DEALINGS IN THE SOFTWARE. 145 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | make -C src 3 | 4 | install: 5 | make -C src install 6 | 7 | clean: 8 | make -C src clean 9 | 10 | deb: 11 | debuild -i -us -uc -b 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ljudge 2 | ====== 3 | 4 | ljudge is a command line tool to compile, run, check its output and generate a JSON report. It is designed to be the backend tool for an online judge system. 5 | 6 | Dependencies 7 | ------------ 8 | * [lrun](https://github.com/quark-zju/lrun), used for sandboxing the untrusted program 9 | 10 | lrun provides amd64 .deb packages. You can install (and setup) them using: 11 | 12 | ```bash 13 | wget https://github.com/quark-zju/lrun/releases/download/v1.1.3/lrun_1.1.3_amd64.deb 14 | # for Debian 7, you may need to add wheezy-backports apt source first 15 | sudo apt-get install libseccomp2 16 | sudo dpkg -i lrun_1.1.3_amd64.deb 17 | 18 | # following steps are required to pass ljudge --check 19 | sudo gpasswd -a $USER lrun 20 | ``` 21 | 22 | Installation 23 | ------------ 24 | 1. Typically, `make && sudo install` 25 | 2. Copy configuration files at `etc/ljudge` to `/etc/ljudge` or `~/.cache/ljudge` 26 | 3. Run `ljudge --check`. It will examine the environment and tell you how to fix problems it finds. Repeat this step until ljudge complains nothing 27 | 4. (Optionally) Install compilers (take Debian for example): 28 | 29 | ```bash 30 | sudo apt-get install build-essential clisp fpc gawk gccgo gcj-jdk ghc git golang lua5.2 mono-mcs ocaml openjdk-7-jdk perl php5-cli python2.7 python3 racket rake ruby1.9.3 valac 31 | # nodejs 32 | sudo apt-get install rlwrap 33 | wget https://deb.nodesource.com/node/pool/main/n/nodejs/nodejs_0.10.33-2nodesource1~wheezy1_amd64.deb 34 | sudo dpkg -i nodejs_0.10.33-2nodesource1~wheezy1_amd64.deb 35 | ``` 36 | 37 | 5. (Optionally) Run `ljudge --compiler-versions` to check installed compilers 38 | 6. (Optionally) Run tests to verify things actually work: `cd examples/a-plus-b; ./run.sh` 39 | 40 | Example 41 | ------- 42 | 43 | ```bash 44 | % echo 'a;b;main(){scanf("%d%d",&a,&b);printf("%d",a+b);exit(0);}' > a.c 45 | % echo '1 2' > 1.in 46 | % echo '3' > 1.out 47 | % echo '111111111111111111111111 1' > 2.in 48 | % echo '111111111111111111111112' > 2.out 49 | % ljudge --max-cpu-time 1.0 --max-memory 32m --user-code a.c --testcase --input 1.in --output 1.out --testcase --input 2.in --output 2.out 50 | { 51 | "compilation": { 52 | "log": "a.c:1:1: warning: data definition has no type or storage (...)", 53 | "success": true 54 | }, 55 | "testcases": [ 56 | { 57 | "memory": 1220608, 58 | "result": "ACCEPTED", 59 | "time": 0.002 60 | }, 61 | { 62 | "memory": 1527808, 63 | "result": "WRONG_ANSWER", 64 | "time": 0.002 65 | } 66 | ] 67 | } 68 | ``` 69 | 70 | FAQ 71 | --- 72 | **Q: What are the available options?** 73 | 74 | A: Run `ljudge --help`. 75 | 76 | **Q: What is the schema of the output JSON?** 77 | 78 | A: Run `ljudge --json-schema` or check `schema/response.json`. You can verify the output JSON with [validator tools](http://json-schema.org/implementations.html#validator-list). 79 | 80 | **Q: Does ljudge take advantage of multiple cores?** 81 | 82 | A: Yes. ljudge runs testcases in parallel, with thread number = cpu core number by default. You can control it with `--threads n`. For example, `--threads 1` makes ljudge to run testcases sequentially. 83 | 84 | **Q: What is the "checker"?** 85 | 86 | A: The checker is used to compare the output of the user program and the standard output. It will return one of ACCEPTED, WRONG\_ANSWER, PRESENTATION\_ERROR. The default checker works in these steps, given both outputs: 87 | 88 | 1. Ignores the ending `\n` of the last non-empty line of both output files. 89 | 2. If they are identical, return ACCEPTED. 90 | 3. Remove all blank characters from both outputs. 91 | 4. If they are identical now, return PRESENTATION\_ERROR. 92 | 5. Return WRONG\_ANSWER. 93 | 94 | **Q: What is the minimal supported version of Java?** 95 | 96 | A: 7. Java 6 requires the `execve` syscall, which is disabled. Try to set default Java to 7. For Debian, run `update-alternatives --config java`. Alternative you can enable `execve` syscall. 97 | 98 | **Q: What if I want to write a custom checker?** 99 | 100 | A: Just write one and pass it to ljudge using `--checker-code`. Your checker's stdin is the standard input and it can open these files: 101 | 102 | * `"input"`: the reference input passed as `--testcase --input` 103 | * `"output"`: the reference output passed as `--testcase --output` 104 | * `"user_output"` (or `argv[1]`): the output of the user program 105 | * `"user_code"`: the source code provided using `--user-code` 106 | 107 | The checker's stdout will be captured. It should return 0 for ACCEPTED, 1 for WRONG\_ANSWER and 2 for PRESENTATION\_ERROR. 108 | To be compatible with some old checkers, -1 (or 255) means WRONG\_ANSWER too. 109 | 110 | Notes 111 | ----- 112 | Tested in: 113 | 114 | * Debian 7 115 | * Ubuntu 14.04/16.04 116 | * Arch Linux 2014.11 117 | 118 | Some environment variables can change ljudge behavior (for debugging purpose). Therefore the environment variables must be trusted. You can also `export NDEBUG=1` before building ljudge to remove all debug related features. 119 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | ljudge (0.6.1) unstable; urgency=low 2 | 3 | * Update default config. 4 | * Install default config to /etc. 5 | 6 | -- Jun Wu Tue, 12 May 2015 16:02:00 +0800 7 | 8 | ljudge (0.6.0) unstable; urgency=low 9 | 10 | * Replace filterefs with lrun-mirrorfs. 11 | * Update configs to use lrun fopen-filter. 12 | * Fix a segfault issue. 13 | 14 | -- Jun Wu Sun, 11 Jan 2015 10:42:00 +0800 15 | 16 | ljudge (0.5.0) unstable; urgency=low 17 | 18 | * Support check output using SHA1. 19 | * More accurate memory accounting. 20 | * Ship with vbnc, gcj configs. 21 | 22 | -- Jun Wu Tue, 25 Nov 2014 14:35:00 +0800 23 | 24 | ljudge (0.4.1) unstable; urgency=low 25 | 26 | * Fix cgroup checking. 27 | 28 | -- Jun Wu Sun, 12 Nov 2014 20:05:00 +0800 29 | 30 | ljudge (0.4.0) unstable; urgency=low 31 | 32 | * Fix some threading issues. 33 | * Remove some debugging code. 34 | 35 | -- Jun Wu Sun, 10 Nov 2014 21:40:00 +0800 36 | 37 | ljudge (0.3.0) unstable; urgency=low 38 | 39 | * Initial debian package release. 40 | 41 | -- Jun Wu Sun, 09 Nov 2014 15:40:00 +0800 42 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 8 -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: ljudge 2 | Section: utils 3 | Priority: optional 4 | Maintainer: Jun Wu 5 | Standards-Version: 3.9.3 6 | Build-Depends: debhelper (>= 8) 7 | Homepage: https://github.com/quark-zju/ljudge 8 | 9 | Package: ljudge 10 | Architecture: any 11 | Depends: ${shlibs:Depends}, ${misc:Depends}, lrun (>= 1.1.4) 12 | Description: Backend tool for an online judge system 13 | ljudge is a command line tool to compile, run, check its output 14 | and generate a JSON report. 15 | . 16 | It is designed to be the backend tool for an online judge system. 17 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: ljudge 3 | Source: https://github.com/quark-zju/ljudge 4 | 5 | Files: * 6 | Copyright: 2014 Jun Wu 7 | License: MIT 8 | 9 | License: MIT 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | . 17 | The above copyright notice and this permission notice shall be included in 18 | all copies or substantial portions of the Software. 19 | . 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | THE SOFTWARE. 27 | -------------------------------------------------------------------------------- /debian/ljudge.install: -------------------------------------------------------------------------------- 1 | etc/ljudge/* etc/ljudge 2 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | DEB_BUILD_HARDENING=1 4 | DPKG_EXPORT_BUILDFLAGS=1 5 | include /usr/share/dpkg/buildflags.mk 6 | 7 | %: 8 | dh ${@} 9 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (native) 2 | -------------------------------------------------------------------------------- /etc/ljudge/3.py/run.cmd_list: -------------------------------------------------------------------------------- 1 | python3 2 | $src 3 | -------------------------------------------------------------------------------- /etc/ljudge/3.py/run.mirrorfs: -------------------------------------------------------------------------------- 1 | ../py/run.mirrorfs -------------------------------------------------------------------------------- /etc/ljudge/3.py/version.cmd_list: -------------------------------------------------------------------------------- 1 | python3 2 | --version 3 | -------------------------------------------------------------------------------- /etc/ljudge/_default/check.lrun_args: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pintia/ljudge/a2bbb388421fdb05b2fb6a2e71642be394457a64/etc/ljudge/_default/check.lrun_args -------------------------------------------------------------------------------- /etc/ljudge/_default/check.mirrorfs: -------------------------------------------------------------------------------- 1 | compile.mirrorfs -------------------------------------------------------------------------------- /etc/ljudge/_default/compile.exe_name: -------------------------------------------------------------------------------- 1 | a.out 2 | -------------------------------------------------------------------------------- /etc/ljudge/_default/compile.lrun_args: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pintia/ljudge/a2bbb388421fdb05b2fb6a2e71642be394457a64/etc/ljudge/_default/compile.lrun_args -------------------------------------------------------------------------------- /etc/ljudge/_default/compile.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev/ 2 | mkdir /proc/ 3 | mkdir /tmp/ 4 | mirror /bin/ 5 | mirror /usr/ 6 | mirror /lib/ 7 | mirror /lib64/ 8 | mirror /var/lib/ 9 | mirror /etc/ld.so.cache 10 | mirror /etc/alternatives/ 11 | -------------------------------------------------------------------------------- /etc/ljudge/_default/run.cmd_list: -------------------------------------------------------------------------------- 1 | ./$exe 2 | -------------------------------------------------------------------------------- /etc/ljudge/_default/run.lrun_args: -------------------------------------------------------------------------------- 1 | # ptrace is dangerous. see http://www.kernelhub.org/?p=2&msg=72053 2 | --syscalls 3 | !execve,flock,ptrace,sync,fdatasync,fsync,msync,sync_file_range,syncfs,unshare,setns,clone[a&268435456==268435456],query_module,syslog,sysfs 4 | --hostname 5 | ljudge 6 | -------------------------------------------------------------------------------- /etc/ljudge/_default/run.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev 2 | mkdir /tmp 3 | mirror /lib/ 4 | mirror /lib64/ 5 | mirror /usr/lib*/ 6 | mirror /etc/ld.so.cache 7 | -------------------------------------------------------------------------------- /etc/ljudge/asm/check.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev 2 | mkdir /tmp 3 | mirror /lib/ 4 | mirror /lib32/ 5 | mirror /usr/lib*/ 6 | mirror /etc/ld.so.cache 7 | -------------------------------------------------------------------------------- /etc/ljudge/asm/compile.cmd_list: -------------------------------------------------------------------------------- 1 | nasm.sh 2 | $src 3 | $exe 4 | -------------------------------------------------------------------------------- /etc/ljudge/asm/compile.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev/ 2 | mkdir /proc/ 3 | mkdir /tmp/ 4 | mirror /bin/ 5 | mirror /usr/ 6 | mirror /lib/ 7 | mirror /lib32/ 8 | mirror /lib64/ 9 | mirror /var/lib/ 10 | mirror /etc/ld.so.cache 11 | mirror /etc/alternatives/ 12 | -------------------------------------------------------------------------------- /etc/ljudge/asm/run.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev 2 | mkdir /tmp 3 | mirror /lib/ 4 | mirror /lib32/ 5 | mirror /usr/lib*/ 6 | mirror /etc/ld.so.cache 7 | -------------------------------------------------------------------------------- /etc/ljudge/asm/version.cmd_list: -------------------------------------------------------------------------------- 1 | nasm 2 | -version 3 | -------------------------------------------------------------------------------- /etc/ljudge/awk/run.cmd_list: -------------------------------------------------------------------------------- 1 | awk 2 | -f 3 | $src 4 | -------------------------------------------------------------------------------- /etc/ljudge/awk/run.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev 2 | mkdir /tmp 3 | mirror /lib/ 4 | mirror /lib64/ 5 | mirror /usr/lib*/ 6 | mirror /etc/ld.so.cache 7 | mirror /etc/alternatives/ 8 | mirror /usr/bin/{gawk,awk} 9 | -------------------------------------------------------------------------------- /etc/ljudge/awk/version.cmd_list: -------------------------------------------------------------------------------- 1 | awk 2 | --version 3 | -------------------------------------------------------------------------------- /etc/ljudge/c/compile.cmd_list: -------------------------------------------------------------------------------- 1 | gcc 2 | -DONLINE_JUDGE 3 | # http://codeforces.com/blog/entry/11450#comment-164021 4 | -fno-tree-ch 5 | -O2 6 | -Wall 7 | -std=c99 8 | -pipe 9 | $src 10 | -lm 11 | -o 12 | $exe 13 | -------------------------------------------------------------------------------- /etc/ljudge/c/version.cmd_list: -------------------------------------------------------------------------------- 1 | gcc 2 | --version 3 | -------------------------------------------------------------------------------- /etc/ljudge/cj/compile.cmd_list: -------------------------------------------------------------------------------- 1 | cjc 2 | --cfg 3 | ENV=ONLINE_JUDGE 4 | -O2 5 | -Won 6 | all 7 | --error-count-limit 8 | 10 9 | $src 10 | -o 11 | $exe 12 | -------------------------------------------------------------------------------- /etc/ljudge/cj/compile.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev/ 2 | mkdir /proc/ 3 | mkdir /tmp/ 4 | mirror /bin/ 5 | mirror /usr/ 6 | mirror /lib/ 7 | mirror /lib64/ 8 | mirror /var/lib/ 9 | mirror /etc/ld.so.cache 10 | mirror /etc/alternatives/ 11 | mirror /opt/cangjie/ 12 | -------------------------------------------------------------------------------- /etc/ljudge/cj/run.env: -------------------------------------------------------------------------------- 1 | LD_LIBRARY_PATH=/opt/cangjie/runtime/lib/linux_x86_64_llvm 2 | -------------------------------------------------------------------------------- /etc/ljudge/cj/run.mirrorfs: -------------------------------------------------------------------------------- 1 | compile.mirrorfs -------------------------------------------------------------------------------- /etc/ljudge/cj/version.cmd_list: -------------------------------------------------------------------------------- 1 | cjc 2 | --version 3 | -------------------------------------------------------------------------------- /etc/ljudge/cl/run.cmd_list: -------------------------------------------------------------------------------- 1 | sbcl 2 | --script 3 | $src 4 | -------------------------------------------------------------------------------- /etc/ljudge/cl/run.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev 2 | mkdir /tmp 3 | mirror /lib/ 4 | mirror /lib64/ 5 | mirror /usr/lib*/ 6 | mirror /etc/ld.so.cache 7 | mirror /usr/bin/sbcl 8 | -------------------------------------------------------------------------------- /etc/ljudge/cl/version.cmd_list: -------------------------------------------------------------------------------- 1 | sbcl 2 | --version 3 | -------------------------------------------------------------------------------- /etc/ljudge/clang.c/compile.cmd_list: -------------------------------------------------------------------------------- 1 | clang 2 | -DONLINE_JUDGE 3 | -O2 4 | -Wall 5 | -std=c99 6 | -pipe 7 | $src 8 | -lm 9 | -o 10 | $exe 11 | -------------------------------------------------------------------------------- /etc/ljudge/clang.c/version.cmd_list: -------------------------------------------------------------------------------- 1 | clang 2 | --version 3 | -------------------------------------------------------------------------------- /etc/ljudge/clang.cpp/compile.cmd_list: -------------------------------------------------------------------------------- 1 | clang++ 2 | -DONLINE_JUDGE 3 | -O2 4 | -Wall 5 | -std=c++20 6 | -pipe 7 | $src 8 | -lm 9 | -o 10 | $exe 11 | -------------------------------------------------------------------------------- /etc/ljudge/clang.cpp/version.cmd_list: -------------------------------------------------------------------------------- 1 | clang++ 2 | --version 3 | -------------------------------------------------------------------------------- /etc/ljudge/cpp/compile.cmd_list: -------------------------------------------------------------------------------- 1 | g++ 2 | -DONLINE_JUDGE 3 | # http://codeforces.com/blog/entry/11450#comment-164021 4 | -fno-tree-ch 5 | -O2 6 | -Wall 7 | -std=gnu++20 8 | -pipe 9 | $src 10 | -lm 11 | -o 12 | $exe 13 | -------------------------------------------------------------------------------- /etc/ljudge/cpp/version.cmd_list: -------------------------------------------------------------------------------- 1 | g++ 2 | --version 3 | -------------------------------------------------------------------------------- /etc/ljudge/cs/__tmp__a.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | net6.0 5 | a.out 6 | 7 | 8 | -------------------------------------------------------------------------------- /etc/ljudge/cs/compile.cmd_list: -------------------------------------------------------------------------------- 1 | dotnet 2 | build 3 | -------------------------------------------------------------------------------- /etc/ljudge/cs/compile.env: -------------------------------------------------------------------------------- 1 | DOTNET_CLI_TELEMETRY_OPTOUT=1 2 | COMPlus_EnableDiagnostics=0 3 | -------------------------------------------------------------------------------- /etc/ljudge/cs/compile.exe_name: -------------------------------------------------------------------------------- 1 | bin/Debug/net6.0/a.out 2 | -------------------------------------------------------------------------------- /etc/ljudge/cs/compile.file_add: -------------------------------------------------------------------------------- 1 | __tmp__a.csproj 2 | -------------------------------------------------------------------------------- /etc/ljudge/cs/compile.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev/ 2 | mkdir /proc/ 3 | mkdir /tmp/ 4 | mirror /bin/ 5 | mirror /usr/ 6 | mirror /lib/ 7 | mirror /lib64/ 8 | mirror /var/lib/ 9 | mirror /etc/ld.so.cache 10 | # required by dotnet 11 | touch /etc/passwd 12 | -------------------------------------------------------------------------------- /etc/ljudge/cs/compile.src_name: -------------------------------------------------------------------------------- 1 | a.cs 2 | -------------------------------------------------------------------------------- /etc/ljudge/cs/run.cmd_list: -------------------------------------------------------------------------------- 1 | $exe 2 | -------------------------------------------------------------------------------- /etc/ljudge/cs/run.env: -------------------------------------------------------------------------------- 1 | compile.env -------------------------------------------------------------------------------- /etc/ljudge/cs/run.lrun_args: -------------------------------------------------------------------------------- 1 | --syscalls 2 | !execve,flock,ptrace,sync,fdatasync,fsync,msync,sync_file_range,syncfs,unshare,setns,clone[a&268435456==268435456],query_module,syslog,sysfs 3 | --hostname 4 | ljudge 5 | -------------------------------------------------------------------------------- /etc/ljudge/cs/run.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev 2 | mkdir /proc 3 | mkdir /tmp 4 | mirror /lib/ 5 | mirror /lib64/ 6 | mirror /var/lib/ 7 | mirror /usr/lib*/ 8 | mirror /etc/ld.so.cache 9 | mirror /usr/share/dotnet/ 10 | -------------------------------------------------------------------------------- /etc/ljudge/cs/version.cmd_list: -------------------------------------------------------------------------------- 1 | dotnet 2 | --version 3 | -------------------------------------------------------------------------------- /etc/ljudge/d/compile.cmd_list: -------------------------------------------------------------------------------- 1 | dmd 2 | -O 3 | $src 4 | -of$exe 5 | -------------------------------------------------------------------------------- /etc/ljudge/d/compile.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev/ 2 | mkdir /proc/ 3 | mkdir /tmp/ 4 | mirror /bin/ 5 | mirror /usr/ 6 | mirror /lib/ 7 | mirror /lib64/ 8 | mirror /var/lib/ 9 | mirror /etc/ld.so.cache 10 | mirror /etc/alternatives/ 11 | # dlang 12 | mirror /etc/dmd.conf 13 | -------------------------------------------------------------------------------- /etc/ljudge/d/version.cmd_list: -------------------------------------------------------------------------------- 1 | dmd 2 | --help 3 | -------------------------------------------------------------------------------- /etc/ljudge/f95/compile.cmd_list: -------------------------------------------------------------------------------- 1 | gfortran 2 | $src 3 | -------------------------------------------------------------------------------- /etc/ljudge/f95/version.cmd_list: -------------------------------------------------------------------------------- 1 | gfortran 2 | --version 3 | -------------------------------------------------------------------------------- /etc/ljudge/fs/__tmp__a.fsproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | net6.0 5 | a.out 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /etc/ljudge/fs/compile.cmd_list: -------------------------------------------------------------------------------- 1 | ../cs/compile.cmd_list -------------------------------------------------------------------------------- /etc/ljudge/fs/compile.env: -------------------------------------------------------------------------------- 1 | ../cs/compile.env -------------------------------------------------------------------------------- /etc/ljudge/fs/compile.exe_name: -------------------------------------------------------------------------------- 1 | ../cs/compile.exe_name -------------------------------------------------------------------------------- /etc/ljudge/fs/compile.file_add: -------------------------------------------------------------------------------- 1 | __tmp__a.fsproj 2 | -------------------------------------------------------------------------------- /etc/ljudge/fs/compile.mirrorfs: -------------------------------------------------------------------------------- 1 | ../cs/compile.mirrorfs -------------------------------------------------------------------------------- /etc/ljudge/fs/compile.src_name: -------------------------------------------------------------------------------- 1 | a.fs 2 | -------------------------------------------------------------------------------- /etc/ljudge/fs/run.cmd_list: -------------------------------------------------------------------------------- 1 | ../cs/run.cmd_list -------------------------------------------------------------------------------- /etc/ljudge/fs/run.env: -------------------------------------------------------------------------------- 1 | ../cs/run.env -------------------------------------------------------------------------------- /etc/ljudge/fs/run.lrun_args: -------------------------------------------------------------------------------- 1 | ../cs/run.lrun_args -------------------------------------------------------------------------------- /etc/ljudge/fs/run.mirrorfs: -------------------------------------------------------------------------------- 1 | ../cs/run.mirrorfs -------------------------------------------------------------------------------- /etc/ljudge/fs/version.cmd_list: -------------------------------------------------------------------------------- 1 | ../cs/version.cmd_list -------------------------------------------------------------------------------- /etc/ljudge/gcc.go/compile.cmd_list: -------------------------------------------------------------------------------- 1 | gccgo 2 | # -g is needed for Ubuntu 14.04. see https://bugs.launchpad.net/ubuntu/+source/gcc-4.9/+bug/1318027 3 | # You can remove -g if you are using Debian 7 4 | -g 5 | -Wall 6 | -pipe 7 | $src 8 | -o 9 | $exe 10 | -------------------------------------------------------------------------------- /etc/ljudge/gcc.go/version.cmd_list: -------------------------------------------------------------------------------- 1 | gccgo 2 | --version 3 | -------------------------------------------------------------------------------- /etc/ljudge/go/compile.cmd_list: -------------------------------------------------------------------------------- 1 | go 2 | build 3 | $src -------------------------------------------------------------------------------- /etc/ljudge/go/compile.exe_name: -------------------------------------------------------------------------------- 1 | a -------------------------------------------------------------------------------- /etc/ljudge/go/compile.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev/ 2 | mkdir /proc/ 3 | mkdir /tmp/ 4 | mirror /bin/ 5 | mirror /usr/ 6 | mirror /lib/ 7 | mirror /lib64/ 8 | mirror /var/lib/ 9 | mirror /etc/ld.so.cache 10 | mirror /etc/alternatives/ 11 | # golang 12 | mirror /etc/golang/ 13 | -------------------------------------------------------------------------------- /etc/ljudge/go/compile.src_name: -------------------------------------------------------------------------------- 1 | a.go -------------------------------------------------------------------------------- /etc/ljudge/go/version.cmd_list: -------------------------------------------------------------------------------- 1 | go 2 | version -------------------------------------------------------------------------------- /etc/ljudge/hs/compile.cmd_list: -------------------------------------------------------------------------------- 1 | ghc 2 | -v0 3 | -O2 4 | --make 5 | -threaded 6 | $src 7 | -o 8 | $exe 9 | -------------------------------------------------------------------------------- /etc/ljudge/hs/compile.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev/ 2 | mkdir /proc/ 3 | mkdir /tmp/ 4 | mirror /bin/ 5 | mirror /usr/ 6 | mirror /lib/ 7 | mirror /lib64/ 8 | mirror /var/lib/ 9 | mirror /etc/ld.so.cache 10 | mirror /etc/alternatives/ 11 | # ghc 12 | mirror /opt/ghc/ 13 | -------------------------------------------------------------------------------- /etc/ljudge/hs/version.cmd_list: -------------------------------------------------------------------------------- 1 | ghc 2 | --version 3 | -------------------------------------------------------------------------------- /etc/ljudge/java/compile.cmd_list: -------------------------------------------------------------------------------- 1 | javac 2 | -encoding 3 | UTF8 4 | $src 5 | -------------------------------------------------------------------------------- /etc/ljudge/java/compile.env: -------------------------------------------------------------------------------- 1 | JAVA_HOME 2 | -------------------------------------------------------------------------------- /etc/ljudge/java/compile.exe_name: -------------------------------------------------------------------------------- 1 | Main.class 2 | -------------------------------------------------------------------------------- /etc/ljudge/java/compile.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev/ 2 | mkdir /proc/ 3 | mkdir /tmp/ 4 | mirror /bin/ 5 | mirror /usr/ 6 | mirror /lib/ 7 | mirror /lib64/ 8 | mirror /var/lib/ 9 | mirror /etc/ld.so.cache 10 | mirror /etc/alternatives/ 11 | # java 12 | mirror /etc/java*/ 13 | -------------------------------------------------------------------------------- /etc/ljudge/java/compile.src_name: -------------------------------------------------------------------------------- 1 | Main.java 2 | -------------------------------------------------------------------------------- /etc/ljudge/java/run.cmd_list: -------------------------------------------------------------------------------- 1 | java 2 | -Dfile.encoding=UTF-8 3 | -XX:+UseSerialGC 4 | Main 5 | -------------------------------------------------------------------------------- /etc/ljudge/java/run.env: -------------------------------------------------------------------------------- 1 | ./compile.env -------------------------------------------------------------------------------- /etc/ljudge/java/run.lrun_args: -------------------------------------------------------------------------------- 1 | --syscalls 2 | !execve,flock,ptrace,sync,fdatasync,fsync,msync,sync_file_range,syncfs,unshare,setns,clone[a&268435456==268435456],query_module,syslog,sysfs 3 | --fopen-filter 4 | f:/tmp/Main.class 5 | R 6 | --fopen-filter 7 | m:/proc:.*/(meminfo|maps)$ 8 | a 9 | --fopen-filter 10 | m:/proc: 11 | d 12 | --hostname 13 | ljudge 14 | -------------------------------------------------------------------------------- /etc/ljudge/java/run.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev 2 | mkdir /tmp 3 | # java needs /proc/self/exe to know its path 4 | mkdir /proc 5 | mirror /lib/ 6 | mirror /lib64/ 7 | mirror /usr/lib*/ 8 | mirror /etc/ld.so.cache 9 | mirror /etc/alternatives/ 10 | mirror /etc/java*/ 11 | mirror /usr/bin/java 12 | -------------------------------------------------------------------------------- /etc/ljudge/java/version.cmd_list: -------------------------------------------------------------------------------- 1 | javac 2 | -version 3 | -------------------------------------------------------------------------------- /etc/ljudge/jit.lua/run.cmd_list: -------------------------------------------------------------------------------- 1 | luajit 2 | $src 3 | -------------------------------------------------------------------------------- /etc/ljudge/jit.lua/run.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev 2 | mkdir /tmp 3 | mirror /lib/ 4 | mirror /lib64/ 5 | mirror /usr/lib*/ 6 | mirror /etc/ld.so.cache 7 | mirror /etc/alternatives/ 8 | mirror /usr/bin/luajit* 9 | -------------------------------------------------------------------------------- /etc/ljudge/jit.lua/version.cmd_list: -------------------------------------------------------------------------------- 1 | luajit 2 | -v 3 | -------------------------------------------------------------------------------- /etc/ljudge/js/run.cmd_list: -------------------------------------------------------------------------------- 1 | node 2 | $src 3 | -------------------------------------------------------------------------------- /etc/ljudge/js/run.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev 2 | mkdir /tmp 3 | mirror /lib/ 4 | mirror /lib64/ 5 | mirror /usr/lib*/ 6 | mirror /etc/ld.so.cache 7 | mirror /etc/alternatives/ 8 | mirror /usr/bin/node{,js} 9 | -------------------------------------------------------------------------------- /etc/ljudge/js/version.cmd_list: -------------------------------------------------------------------------------- 1 | node 2 | --version 3 | -------------------------------------------------------------------------------- /etc/ljudge/kt/compile.cmd_list: -------------------------------------------------------------------------------- 1 | kotlinc 2 | $src 3 | -------------------------------------------------------------------------------- /etc/ljudge/kt/compile.env: -------------------------------------------------------------------------------- 1 | JAVA_HOME 2 | CLASSPATH=.:/usr/lib/kotlin/lib/* 3 | -------------------------------------------------------------------------------- /etc/ljudge/kt/compile.exe_name: -------------------------------------------------------------------------------- 1 | MainKt.class 2 | -------------------------------------------------------------------------------- /etc/ljudge/kt/compile.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev/ 2 | mkdir /proc/ 3 | mkdir /tmp/ 4 | mirror /bin/ 5 | mirror /usr/ 6 | mirror /lib/ 7 | mirror /lib64/ 8 | mirror /var/lib/ 9 | mirror /etc/ld.so.cache 10 | mirror /etc/alternatives/ 11 | # java 12 | mirror /etc/java*/ 13 | -------------------------------------------------------------------------------- /etc/ljudge/kt/compile.src_name: -------------------------------------------------------------------------------- 1 | Main.kt 2 | -------------------------------------------------------------------------------- /etc/ljudge/kt/run.cmd_list: -------------------------------------------------------------------------------- 1 | java 2 | -Dfile.encoding=UTF-8 3 | -XX:+UseSerialGC 4 | MainKt 5 | -------------------------------------------------------------------------------- /etc/ljudge/kt/run.env: -------------------------------------------------------------------------------- 1 | compile.env -------------------------------------------------------------------------------- /etc/ljudge/kt/run.lrun_args: -------------------------------------------------------------------------------- 1 | --syscalls 2 | !execve,flock,ptrace,sync,fdatasync,fsync,msync,sync_file_range,syncfs,unshare,setns,clone[a&268435456==268435456],query_module,syslog,sysfs 3 | --fopen-filter 4 | f:/tmp/MainKt.class 5 | R 6 | --fopen-filter 7 | m:/proc:.*/(meminfo|maps)$ 8 | a 9 | --fopen-filter 10 | m:/proc: 11 | d 12 | --hostname 13 | ljudge 14 | -------------------------------------------------------------------------------- /etc/ljudge/kt/run.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev 2 | mkdir /tmp 3 | # java needs /proc/self/exe to know its path 4 | mkdir /proc 5 | mirror /lib/ 6 | mirror /lib64/ 7 | mirror /usr/lib*/ 8 | mirror /etc/ld.so.cache 9 | mirror /etc/alternatives/ 10 | mirror /etc/java*/ 11 | mirror /usr/bin/java 12 | -------------------------------------------------------------------------------- /etc/ljudge/kt/version.cmd_list: -------------------------------------------------------------------------------- 1 | kotlinc 2 | -version 3 | -------------------------------------------------------------------------------- /etc/ljudge/lua/run.cmd_list: -------------------------------------------------------------------------------- 1 | lua 2 | $src 3 | -------------------------------------------------------------------------------- /etc/ljudge/lua/run.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev 2 | mkdir /tmp 3 | mirror /lib/ 4 | mirror /lib64/ 5 | mirror /usr/lib*/ 6 | mirror /etc/ld.so.cache 7 | mirror /etc/alternatives/ 8 | mirror /usr/bin/lua{,[0-9]*} 9 | -------------------------------------------------------------------------------- /etc/ljudge/lua/version.cmd_list: -------------------------------------------------------------------------------- 1 | lua 2 | -v 3 | -------------------------------------------------------------------------------- /etc/ljudge/m/compile.cmd_list: -------------------------------------------------------------------------------- 1 | clang 2 | $src 3 | -MMD 4 | -MP 5 | -DGNUSTEP 6 | -DGNUSTEP_BASE_LIBRARY=1 7 | -DGNU_GUI_LIBRARY=1 8 | -DGNU_RUNTIME=1 9 | -fno-strict-aliasing 10 | -fexceptions 11 | -fobjc-exceptions 12 | -D_NATIVE_OBJC_EXCEPTIONS 13 | -pthread 14 | -fPIC 15 | -Wall 16 | -DGSWARN 17 | -DGSDIAGNOSE 18 | -Wno-import 19 | -g 20 | -O2 21 | -fgnu-runtime 22 | -fconstant-string-class=NSConstantString 23 | -fexec-charset=UTF-8 24 | -I. 25 | -I/home/judger/GNUstep/Library/Headers 26 | -I/usr/local/include/GNUstep 27 | -I/usr/include/GNUstep 28 | -rdynamic 29 | -shared-libgcc 30 | -lgnustep-base 31 | -lobjc 32 | -lm 33 | -o 34 | $exe 35 | -------------------------------------------------------------------------------- /etc/ljudge/m/run.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev 2 | mkdir /tmp 3 | mirror /lib/ 4 | mirror /lib64/ 5 | mirror /usr/lib*/ 6 | mirror /etc/ld.so.cache 7 | # gnustep need proc 8 | mkdir /proc 9 | mirror /etc/passwd 10 | mirror /etc/group 11 | mirror /etc/subuid 12 | mirror /etc/subgid 13 | -------------------------------------------------------------------------------- /etc/ljudge/m/version.cmd_list: -------------------------------------------------------------------------------- 1 | clang 2 | --version 3 | -------------------------------------------------------------------------------- /etc/ljudge/ml/compile.cmd_list: -------------------------------------------------------------------------------- 1 | ocamlc 2 | -unsafe 3 | $src 4 | -o 5 | $exe 6 | -------------------------------------------------------------------------------- /etc/ljudge/ml/compile.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev/ 2 | mkdir /proc/ 3 | mkdir /tmp/ 4 | mirror /bin/ 5 | mirror /usr/ 6 | mirror /lib/ 7 | mirror /lib64/ 8 | mirror /var/lib/ 9 | mirror /etc/ld.so.cache 10 | mirror /etc/alternatives/ 11 | # ocaml 12 | mirror /opt/opam/ 13 | -------------------------------------------------------------------------------- /etc/ljudge/ml/run.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev 2 | mkdir /tmp 3 | mirror /lib/ 4 | mirror /lib64/ 5 | mirror /usr/lib*/ 6 | mirror /etc/ld.so.cache 7 | mirror /opt/opam/ 8 | mirror /usr/bin/ocamlrun 9 | -------------------------------------------------------------------------------- /etc/ljudge/ml/version.cmd_list: -------------------------------------------------------------------------------- 1 | ocamlc 2 | -v 3 | -------------------------------------------------------------------------------- /etc/ljudge/modern.c/compile.cmd_list: -------------------------------------------------------------------------------- 1 | gcc 2 | -DONLINE_JUDGE 3 | -pedantic-errors 4 | -fno-tree-ch 5 | -O2 6 | -Wall 7 | -std=gnu11 8 | -pipe 9 | $src 10 | -lm 11 | -o 12 | $exe 13 | -------------------------------------------------------------------------------- /etc/ljudge/modern.c/version.cmd_list: -------------------------------------------------------------------------------- 1 | ../c/version.cmd_list -------------------------------------------------------------------------------- /etc/ljudge/octave/run.cmd_list: -------------------------------------------------------------------------------- 1 | octave-cli 2 | --no-gui 3 | --no-history 4 | --no-init-file 5 | --no-init-path 6 | --no-line-editing 7 | --no-site-file 8 | --no-window-system 9 | --norc 10 | $src 11 | -------------------------------------------------------------------------------- /etc/ljudge/octave/run.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev 2 | mkdir /tmp 3 | mirror /lib/ 4 | mirror /lib64/ 5 | mirror /usr/lib*/ 6 | mirror /etc/ld.so.cache 7 | 8 | mirror /etc/alternatives/ 9 | mirror /usr/bin/octave* 10 | -------------------------------------------------------------------------------- /etc/ljudge/octave/version.cmd_list: -------------------------------------------------------------------------------- 1 | octave 2 | --version 3 | -------------------------------------------------------------------------------- /etc/ljudge/pas/compile.cmd_list: -------------------------------------------------------------------------------- 1 | fpc 2 | -dONLINE_JUDGE 3 | -O2 4 | $src 5 | -------------------------------------------------------------------------------- /etc/ljudge/pas/compile.exe_name: -------------------------------------------------------------------------------- 1 | a 2 | -------------------------------------------------------------------------------- /etc/ljudge/pas/compile.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev/ 2 | mkdir /proc/ 3 | mkdir /tmp/ 4 | mirror /bin/ 5 | mirror /usr/ 6 | mirror /lib/ 7 | mirror /lib64/ 8 | mirror /var/lib/ 9 | mirror /etc/ld.so.cache 10 | mirror /etc/alternatives/ 11 | # free pascal 12 | mirror /etc/fpc*.cfg 13 | -------------------------------------------------------------------------------- /etc/ljudge/pas/compile.src_name: -------------------------------------------------------------------------------- 1 | a.pas 2 | -------------------------------------------------------------------------------- /etc/ljudge/pas/version.cmd_list: -------------------------------------------------------------------------------- 1 | fpc 2 | -iV 3 | -------------------------------------------------------------------------------- /etc/ljudge/php/run.cmd_list: -------------------------------------------------------------------------------- 1 | php 2 | $src 3 | -------------------------------------------------------------------------------- /etc/ljudge/php/run.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev 2 | mkdir /tmp 3 | mirror /lib/ 4 | mirror /lib64/ 5 | mirror /usr/lib*/ 6 | mirror /etc/ld.so.cache 7 | mirror /etc/alternatives/ 8 | mirror /usr/bin/php{,[0-9]*} 9 | -------------------------------------------------------------------------------- /etc/ljudge/php/version.cmd_list: -------------------------------------------------------------------------------- 1 | php 2 | --version 3 | -------------------------------------------------------------------------------- /etc/ljudge/pl/run.cmd_list: -------------------------------------------------------------------------------- 1 | perl 2 | $src 3 | -------------------------------------------------------------------------------- /etc/ljudge/pl/run.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev 2 | mkdir /tmp 3 | mirror /lib/ 4 | mirror /lib64/ 5 | mirror /usr/lib*/ 6 | mirror /etc/ld.so.cache 7 | mirror /etc/alternatives/ 8 | mirror /usr/bin/perl{,[0-9]*} 9 | -------------------------------------------------------------------------------- /etc/ljudge/pl/version.cmd_list: -------------------------------------------------------------------------------- 1 | perl 2 | --version 3 | -------------------------------------------------------------------------------- /etc/ljudge/py/run.cmd_list: -------------------------------------------------------------------------------- 1 | python2 2 | $src 3 | -------------------------------------------------------------------------------- /etc/ljudge/py/run.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev 2 | mkdir /tmp 3 | mirror /lib/ 4 | mirror /lib64/ 5 | mirror /usr/lib*/ 6 | mirror /usr/local/lib/python2.7/dist-packages/ 7 | mirror /usr/local/lib/python3.10/dist-packages/ 8 | mirror /etc/ld.so.cache 9 | mirror /etc/alternatives/ 10 | # required by python 11 | touch /etc/passwd 12 | mirror /usr/bin/python{,2*,3*} 13 | -------------------------------------------------------------------------------- /etc/ljudge/py/version.cmd_list: -------------------------------------------------------------------------------- 1 | python2 2 | --version 3 | -------------------------------------------------------------------------------- /etc/ljudge/pypy.3.py/run.cmd_list: -------------------------------------------------------------------------------- 1 | pypy3 2 | $src 3 | -------------------------------------------------------------------------------- /etc/ljudge/pypy.3.py/run.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev 2 | mkdir /tmp 3 | mirror /lib/ 4 | mirror /lib64/ 5 | mirror /usr/lib*/ 6 | mirror /usr/local/lib/pypy3.7/dist-packages/ 7 | mirror /etc/ld.so.cache 8 | mirror /etc/alternatives/ 9 | # required by python 10 | touch /etc/passwd 11 | mirror /usr/bin/pypy{,2*,3*} 12 | # required by pypy 13 | mirror /proc/cpuinfo 14 | -------------------------------------------------------------------------------- /etc/ljudge/pypy.3.py/version.cmd_list: -------------------------------------------------------------------------------- 1 | pypy3 2 | --version 3 | -------------------------------------------------------------------------------- /etc/ljudge/r/run.cmd_list: -------------------------------------------------------------------------------- 1 | R 2 | --slave 3 | --vanilla 4 | -f 5 | $src 6 | -------------------------------------------------------------------------------- /etc/ljudge/r/run.env: -------------------------------------------------------------------------------- 1 | R_HOME=/usr/lib/R 2 | -------------------------------------------------------------------------------- /etc/ljudge/r/run.lrun_args: -------------------------------------------------------------------------------- 1 | # ptrace is dangerous. see http://www.kernelhub.org/?p=2&msg=72053 2 | --syscalls 3 | !execve,flock,ptrace,sync,fdatasync,fsync,msync,sync_file_range,syncfs,unshare,setns,clone[a&268435456==268435456],query_module,syslog,sysfs 4 | --hostname 5 | ljudge 6 | --tmpfs 7 | /tmpfs 8 | 5242880 9 | --env 10 | TMPDIR 11 | /tmpfs 12 | -------------------------------------------------------------------------------- /etc/ljudge/r/run.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev 2 | mkdir /tmp 3 | mkdir /tmpfs 4 | mirror /lib/ 5 | mirror /lib64/ 6 | mirror /usr/lib*/ 7 | mirror /etc/ld.so.cache 8 | 9 | mirror /etc/R/ 10 | mirror /etc/alternatives/ 11 | mirror /usr/bin/R 12 | -------------------------------------------------------------------------------- /etc/ljudge/r/version.cmd_list: -------------------------------------------------------------------------------- 1 | Rscript 2 | --version 3 | -------------------------------------------------------------------------------- /etc/ljudge/rb/run.cmd_list: -------------------------------------------------------------------------------- 1 | ruby 2 | $src 3 | -------------------------------------------------------------------------------- /etc/ljudge/rb/run.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev 2 | mkdir /tmp 3 | mirror /lib/ 4 | mirror /lib64/ 5 | mirror /usr/lib*/ 6 | mirror /etc/ld.so.cache 7 | mirror /etc/alternatives/ 8 | mirror /usr/bin/ruby* 9 | -------------------------------------------------------------------------------- /etc/ljudge/rb/version.cmd_list: -------------------------------------------------------------------------------- 1 | ruby 2 | --version 3 | -------------------------------------------------------------------------------- /etc/ljudge/rkt/compile.cmd_list: -------------------------------------------------------------------------------- 1 | raco 2 | make 3 | $src 4 | -------------------------------------------------------------------------------- /etc/ljudge/rkt/compile.exe_name: -------------------------------------------------------------------------------- 1 | compiled/a_rkt.zo 2 | -------------------------------------------------------------------------------- /etc/ljudge/rkt/compile.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev/ 2 | mkdir /proc/ 3 | mkdir /tmp/ 4 | mirror /bin/ 5 | mirror /usr/ 6 | mirror /lib/ 7 | mirror /lib64/ 8 | mirror /var/lib/ 9 | mirror /etc/ld.so.cache 10 | mirror /etc/alternatives/ 11 | # racket 12 | mirror /etc/racket/ 13 | -------------------------------------------------------------------------------- /etc/ljudge/rkt/compile.src_name: -------------------------------------------------------------------------------- 1 | a.rkt 2 | -------------------------------------------------------------------------------- /etc/ljudge/rkt/run.cmd_list: -------------------------------------------------------------------------------- 1 | racket 2 | $src 3 | -------------------------------------------------------------------------------- /etc/ljudge/rkt/run.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev 2 | mkdir /tmp 3 | mirror /lib/ 4 | mirror /lib64/ 5 | mirror /usr/lib*/ 6 | mirror /etc/ld.so.cache 7 | mirror /usr/bin/racket 8 | # Racket collections 9 | mirror /usr/share/racket/ 10 | -------------------------------------------------------------------------------- /etc/ljudge/rkt/version.cmd_list: -------------------------------------------------------------------------------- 1 | racket 2 | --version 3 | -------------------------------------------------------------------------------- /etc/ljudge/rkt/version.name: -------------------------------------------------------------------------------- 1 | racket 2 | -------------------------------------------------------------------------------- /etc/ljudge/rs/compile.cmd_list: -------------------------------------------------------------------------------- 1 | rustc 2 | --edition=2018 3 | -O 4 | --cfg 5 | ONLINE_JUDGE 6 | $src 7 | -o 8 | $exe 9 | -------------------------------------------------------------------------------- /etc/ljudge/rs/compile.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev/ 2 | mkdir /proc/ 3 | mkdir /tmp/ 4 | mirror /bin/ 5 | mirror /usr/ 6 | mirror /lib/ 7 | mirror /lib64/ 8 | mirror /var/lib/ 9 | mirror /etc/ld.so.cache 10 | mirror /etc/alternatives/ 11 | # rust 12 | mirror /opt/rust/ 13 | -------------------------------------------------------------------------------- /etc/ljudge/rs/version.cmd_list: -------------------------------------------------------------------------------- 1 | rustc 2 | --version 3 | -------------------------------------------------------------------------------- /etc/ljudge/scala/compile.cmd_list: -------------------------------------------------------------------------------- 1 | scalac 2 | $src 3 | -------------------------------------------------------------------------------- /etc/ljudge/scala/compile.env: -------------------------------------------------------------------------------- 1 | JAVA_HOME 2 | CLASSPATH=.:/usr/lib/scala/lib/* 3 | -------------------------------------------------------------------------------- /etc/ljudge/scala/compile.exe_name: -------------------------------------------------------------------------------- 1 | Main.class 2 | -------------------------------------------------------------------------------- /etc/ljudge/scala/compile.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev/ 2 | mkdir /proc/ 3 | mkdir /tmp/ 4 | mirror /bin/ 5 | mirror /usr/ 6 | mirror /lib/ 7 | mirror /lib64/ 8 | mirror /var/lib/ 9 | mirror /etc/ld.so.cache 10 | mirror /etc/alternatives/ 11 | # java 12 | mirror /etc/java*/ 13 | -------------------------------------------------------------------------------- /etc/ljudge/scala/compile.src_name: -------------------------------------------------------------------------------- 1 | Main.scala 2 | -------------------------------------------------------------------------------- /etc/ljudge/scala/run.cmd_list: -------------------------------------------------------------------------------- 1 | java 2 | -Dfile.encoding=UTF-8 3 | -XX:+UseSerialGC 4 | Main 5 | -------------------------------------------------------------------------------- /etc/ljudge/scala/run.env: -------------------------------------------------------------------------------- 1 | compile.env -------------------------------------------------------------------------------- /etc/ljudge/scala/run.lrun_args: -------------------------------------------------------------------------------- 1 | --syscalls 2 | !execve,flock,ptrace,sync,fdatasync,fsync,msync,sync_file_range,syncfs,unshare,setns,clone[a&268435456==268435456],query_module,syslog,sysfs 3 | --fopen-filter 4 | f:/tmp/Main.class 5 | R 6 | --fopen-filter 7 | m:/proc:.*/(meminfo|maps)$ 8 | a 9 | --fopen-filter 10 | m:/proc: 11 | d 12 | --hostname 13 | ljudge 14 | -------------------------------------------------------------------------------- /etc/ljudge/scala/run.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev 2 | mkdir /tmp 3 | # java needs /proc/self/exe to know its path 4 | mkdir /proc 5 | mirror /lib/ 6 | mirror /lib64/ 7 | mirror /usr/lib*/ 8 | mirror /etc/ld.so.cache 9 | mirror /etc/alternatives/ 10 | mirror /etc/java*/ 11 | mirror /usr/bin/java 12 | -------------------------------------------------------------------------------- /etc/ljudge/scala/version.cmd_list: -------------------------------------------------------------------------------- 1 | scalac 2 | -version 3 | -------------------------------------------------------------------------------- /etc/ljudge/sh/run.cmd_list: -------------------------------------------------------------------------------- 1 | bash 2 | $src 3 | -------------------------------------------------------------------------------- /etc/ljudge/sh/run.lrun_args: -------------------------------------------------------------------------------- 1 | --syscalls 2 | !flock,ptrace,sync,fdatasync,fsync,msync,sync_file_range,syncfs,unshare,setns,clone[a&268435456==268435456],query_module,syslog,sysfs 3 | --hostname 4 | ljudge 5 | -------------------------------------------------------------------------------- /etc/ljudge/sh/run.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev 2 | mkdir /tmp 3 | mirror /lib/ 4 | mirror /lib64/ 5 | mirror /usr/lib*/ 6 | mirror /etc/ld.so.cache 7 | mirror /{usr/,}bin/{awk,gawk,bash,bc,cat,cut,dc,echo,expr,factor,false,fmt,fold,grep,head,join,printf,sed,seq,shuf,sort,split,tac,tail,test,true,tsort,uniq,wc} 8 | -------------------------------------------------------------------------------- /etc/ljudge/sh/version.cmd_list: -------------------------------------------------------------------------------- 1 | bash 2 | --version 3 | -------------------------------------------------------------------------------- /etc/ljudge/swift/compile.cmd_list: -------------------------------------------------------------------------------- 1 | swiftc 2 | $src 3 | -O 4 | -o 5 | $exe 6 | -------------------------------------------------------------------------------- /etc/ljudge/swift/version.cmd_list: -------------------------------------------------------------------------------- 1 | swiftc 2 | -version 3 | -------------------------------------------------------------------------------- /etc/ljudge/txt/run.cmd_list: -------------------------------------------------------------------------------- 1 | cat 2 | $src 3 | -------------------------------------------------------------------------------- /etc/ljudge/txt/run.mirrorfs: -------------------------------------------------------------------------------- 1 | mkdir /dev 2 | mkdir /tmp 3 | mirror /lib/ 4 | mirror /lib64/ 5 | mirror /usr/lib*/ 6 | mirror /etc/ld.so.cache 7 | mirror /{usr/,}bin/cat 8 | -------------------------------------------------------------------------------- /etc/ljudge/txt/version.cmd_list: -------------------------------------------------------------------------------- 1 | # do not expose GNU coreutils version 2 | echo 3 | 1.0 4 | -------------------------------------------------------------------------------- /etc/ljudge/vala/compile.cmd_list: -------------------------------------------------------------------------------- 1 | valac 2 | -D 3 | ONLINE_JUDGE 4 | --thread 5 | $src 6 | -o 7 | $exe 8 | -------------------------------------------------------------------------------- /etc/ljudge/vala/version.cmd_list: -------------------------------------------------------------------------------- 1 | valac 2 | --version 3 | -------------------------------------------------------------------------------- /etc/ljudge/vb/__tmp__a.vbproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | net6.0 5 | a.out 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /etc/ljudge/vb/compile.cmd_list: -------------------------------------------------------------------------------- 1 | ../cs/compile.cmd_list -------------------------------------------------------------------------------- /etc/ljudge/vb/compile.env: -------------------------------------------------------------------------------- 1 | ../cs/compile.env -------------------------------------------------------------------------------- /etc/ljudge/vb/compile.exe_name: -------------------------------------------------------------------------------- 1 | ../cs/compile.exe_name -------------------------------------------------------------------------------- /etc/ljudge/vb/compile.file_add: -------------------------------------------------------------------------------- 1 | __tmp__a.vbproj 2 | -------------------------------------------------------------------------------- /etc/ljudge/vb/compile.mirrorfs: -------------------------------------------------------------------------------- 1 | ../cs/compile.mirrorfs -------------------------------------------------------------------------------- /etc/ljudge/vb/compile.src_name: -------------------------------------------------------------------------------- 1 | a.vb 2 | -------------------------------------------------------------------------------- /etc/ljudge/vb/run.cmd_list: -------------------------------------------------------------------------------- 1 | ../cs/run.cmd_list -------------------------------------------------------------------------------- /etc/ljudge/vb/run.env: -------------------------------------------------------------------------------- 1 | ../cs/run.env -------------------------------------------------------------------------------- /etc/ljudge/vb/run.lrun_args: -------------------------------------------------------------------------------- 1 | ../cs/run.lrun_args -------------------------------------------------------------------------------- /etc/ljudge/vb/run.mirrorfs: -------------------------------------------------------------------------------- 1 | ../cs/run.mirrorfs -------------------------------------------------------------------------------- /etc/ljudge/vb/version.cmd_list: -------------------------------------------------------------------------------- 1 | ../cs/version.cmd_list -------------------------------------------------------------------------------- /examples/a-plus-b/1.in: -------------------------------------------------------------------------------- 1 | 1 2 2 | -------------------------------------------------------------------------------- /examples/a-plus-b/1.out: -------------------------------------------------------------------------------- 1 | 3 2 | -------------------------------------------------------------------------------- /examples/a-plus-b/2.in: -------------------------------------------------------------------------------- 1 | 1 -2 2 | 3 4 3 | -------------------------------------------------------------------------------- /examples/a-plus-b/2.out: -------------------------------------------------------------------------------- 1 | -1 2 | 7 3 | -------------------------------------------------------------------------------- /examples/a-plus-b/a.3.py: -------------------------------------------------------------------------------- 1 | a.py -------------------------------------------------------------------------------- /examples/a-plus-b/a.asm: -------------------------------------------------------------------------------- 1 | ; add1.asm 2 | SECTION .data 3 | formatin: db "%d", 0 4 | formatout: db "%d", 10, 0 ; newline, nul terminator 5 | integer1: times 4 db 0 ; 32-bits integer = 4 bytes 6 | integer2: times 4 db 0 ; 7 | SECTION .text 8 | global main 9 | extern scanf 10 | extern printf 11 | 12 | main: 13 | 14 | push ebx ; save registers 15 | push ecx 16 | 17 | add esp, 4 ; remove parameters 18 | push integer1 ; address of integer1 (second parameter) 19 | push formatin ; arguments are right to left (first parameter) 20 | call scanf 21 | 22 | add esp, 4 ; remove parameters 23 | push integer2 ; address of integer2 24 | push formatin ; arguments are right to left 25 | call scanf 26 | 27 | add esp, 8 ; remove parameters 28 | 29 | mov ebx, dword [integer1] 30 | mov ecx, dword [integer2] 31 | add ebx, ecx ; add the values ; the addition 32 | push ebx 33 | push formatout 34 | call printf ; call printf to display the sum 35 | add esp, 8 ; remove parameters 36 | pop ecx 37 | pop ebx ; restore registers in reverse order 38 | mov eax, 0 ; no error 39 | ret 40 | -------------------------------------------------------------------------------- /examples/a-plus-b/a.awk: -------------------------------------------------------------------------------- 1 | {print $1 + $2} 2 | -------------------------------------------------------------------------------- /examples/a-plus-b/a.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char const *argv[]) { 4 | int a, b; 5 | while(scanf("%d %d",&a, &b) != EOF) 6 | printf("%d\n", a + b); 7 | 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /examples/a-plus-b/a.cj: -------------------------------------------------------------------------------- 1 | import std.core.* 2 | import std.console.* 3 | import std.collection.* 4 | import std.convert.* 5 | 6 | main(): Int64 { 7 | while (let Some(line) <- Console.stdIn.readln()) { 8 | let nums = map(Int.parse)(line.split(" ")) 9 | let sum = reduce({a: Int64, b: Int64 => a + b})(nums) 10 | if (let Some(r) <- sum) { 11 | Console.stdOut.writeln(r) 12 | } 13 | } 14 | return 0 15 | } 16 | -------------------------------------------------------------------------------- /examples/a-plus-b/a.cl: -------------------------------------------------------------------------------- 1 | (loop for n = (read t nil nil) 2 | while n 3 | do (format t "~d~C" (+ n (read)) #\linefeed)) 4 | -------------------------------------------------------------------------------- /examples/a-plus-b/a.clang.c: -------------------------------------------------------------------------------- 1 | a.c -------------------------------------------------------------------------------- /examples/a-plus-b/a.clang.cpp: -------------------------------------------------------------------------------- 1 | a.cpp -------------------------------------------------------------------------------- /examples/a-plus-b/a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main(int argc, char const *argv[]) { 6 | int a, b; 7 | while (cin >> a >> b) 8 | cout << a+b << endl; 9 | 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /examples/a-plus-b/a.cs: -------------------------------------------------------------------------------- 1 | public class Program { 2 | public static void Main() { 3 | string line; 4 | while ((line = System.Console.ReadLine ()) != null) { 5 | string[] tokens = line.Split(); 6 | System.Console.WriteLine(int.Parse(tokens[0]) + int.Parse(tokens[1])); 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/a-plus-b/a.d: -------------------------------------------------------------------------------- 1 | import std.stdio; 2 | 3 | void main() { 4 | int a, b; 5 | while (readf(" %s %s", &a, &b)) { 6 | writeln(a + b); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /examples/a-plus-b/a.f95: -------------------------------------------------------------------------------- 1 | program a 2 | integer :: i, j, stat 3 | do 4 | read(*,*,iostat=stat) i, j 5 | if (stat /= 0) exit 6 | write(*, '(I0)') i+j 7 | end do 8 | end program a 9 | -------------------------------------------------------------------------------- /examples/a-plus-b/a.fs: -------------------------------------------------------------------------------- 1 | open System 2 | 3 | while true do 4 | let line = Console.In.ReadLine() 5 | match line with 6 | | null -> exit 0 7 | | _ -> let a = line.Split [|' '|] |> Seq.sumBy int 8 | printfn "%d" a 9 | 10 | -------------------------------------------------------------------------------- /examples/a-plus-b/a.gcc.go: -------------------------------------------------------------------------------- 1 | a.go -------------------------------------------------------------------------------- /examples/a-plus-b/a.gcj.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | 3 | public class Main { 4 | public static void main(String[] args) { 5 | Scanner in = new Scanner(System.in); 6 | try { 7 | while (in.hasNextInt()) { 8 | int a = in.nextInt(); 9 | int b = in.nextInt(); 10 | System.out.println(a + b); 11 | } 12 | } catch (NullPointerException ex) { 13 | // gcj Scanner has a bug that throws NPE 14 | ; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/a-plus-b/a.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var a, b int 7 | for { 8 | n, _ := fmt.Scanf("%d %d", &a, &b) 9 | if (n != 2) { break } 10 | fmt.Println(a + b) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /examples/a-plus-b/a.hs: -------------------------------------------------------------------------------- 1 | main = interact $ unlines . map (show . sum . map read . words) . lines 2 | -------------------------------------------------------------------------------- /examples/a-plus-b/a.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | 3 | public class Main { 4 | public static void main(String[] args) { 5 | Scanner in = new Scanner(System.in); 6 | while (in.hasNextInt()) { 7 | int a = in.nextInt(); 8 | int b = in.nextInt(); 9 | System.out.println(a + b); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /examples/a-plus-b/a.jit.lua: -------------------------------------------------------------------------------- 1 | a.lua -------------------------------------------------------------------------------- /examples/a-plus-b/a.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var buf = ''; 3 | 4 | process.stdin.on('readable', function() { 5 | var chunk = process.stdin.read(); 6 | if (chunk) buf += chunk.toString(); 7 | }); 8 | 9 | process.stdin.on('end', function() { 10 | buf.split('\n').forEach(function(line) { 11 | var tokens = line.split(' ').map(function(x) { return parseInt(x); }); 12 | if (tokens.length != 2) return; 13 | console.log(tokens.reduce(function(a, b) { return a + b; })); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /examples/a-plus-b/a.kt: -------------------------------------------------------------------------------- 1 | import java.util.Scanner 2 | 3 | fun main(args: Array) { 4 | val input = Scanner(System.`in`) 5 | while (input.hasNextInt()) { 6 | val a = input.nextInt() 7 | val b = input.nextInt() 8 | println(a + b) 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/a-plus-b/a.lua: -------------------------------------------------------------------------------- 1 | for a, b in io.read('*a'):gmatch('([%d-]+) ([%d-]+)') do 2 | print(tonumber(a) + tonumber(b)) 3 | end 4 | -------------------------------------------------------------------------------- /examples/a-plus-b/a.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | int main (int argc, const char * argv[]) 4 | { 5 | int a, b; 6 | while(scanf("%d %d", &a, &b) != EOF) { 7 | printf("%d\n", a + b); 8 | } 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /examples/a-plus-b/a.ml: -------------------------------------------------------------------------------- 1 | try 2 | while true do 3 | Scanf.scanf " %d %d" (fun a b -> Printf.printf "%d\n" (a + b)) 4 | done; 5 | None 6 | with 7 | End_of_file -> None 8 | ;; 9 | -------------------------------------------------------------------------------- /examples/a-plus-b/a.modern.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char const *argv[]) { 4 | int a, b; 5 | while(scanf("%d %d",&a, &b) != EOF) 6 | printf("%d\n", a + b); 7 | 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /examples/a-plus-b/a.octave: -------------------------------------------------------------------------------- 1 | while (true) 2 | a = scanf("%d", [1, 2]); 3 | if (! feof(stdin()) ) 4 | printf("%d\n", sum(a)); 5 | else 6 | break 7 | endif 8 | endwhile 9 | -------------------------------------------------------------------------------- /examples/a-plus-b/a.pas: -------------------------------------------------------------------------------- 1 | var 2 | a, b: integer; 3 | begin 4 | while not eof(input) do begin 5 | readln(a, b); 6 | writeln(a + b); 7 | end; 8 | end. 9 | -------------------------------------------------------------------------------- /examples/a-plus-b/a.php: -------------------------------------------------------------------------------- 1 | i.toInt }.sum) 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/a-plus-b/a.sh: -------------------------------------------------------------------------------- 1 | while read i; do 2 | echo $((${i/ /+})) 3 | done 4 | -------------------------------------------------------------------------------- /examples/a-plus-b/a.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | while let line = readLine() { 3 | let words: [String] = line.components(separatedBy: NSCharacterSet.whitespaces) 4 | let inputs: [Int] = words.map { Int($0)! } 5 | print(inputs[0] + inputs[1]) 6 | } 7 | -------------------------------------------------------------------------------- /examples/a-plus-b/a.txt: -------------------------------------------------------------------------------- 1 | 3 2 | -------------------------------------------------------------------------------- /examples/a-plus-b/a.vala: -------------------------------------------------------------------------------- 1 | public static int main(string[] args) { 2 | int a = 0, b = 0; 3 | while (stdin.scanf("%d%d", &a, &b) == 2) { 4 | stdout.printf("%d\n", a + b); 5 | } 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /examples/a-plus-b/a.vb: -------------------------------------------------------------------------------- 1 | Module Program 2 | 3 | Sub Main() 4 | Do 5 | Dim line As String = Console.ReadLine() 6 | If line Is Nothing Then Exit Do 7 | Dim a() As String = line.Split(" "c) 8 | Console.WriteLine(CInt(a(0)) + CInt(a(1))) 9 | Loop 10 | End Sub 11 | 12 | End Module 13 | -------------------------------------------------------------------------------- /examples/a-plus-b/legacy_checker.c: -------------------------------------------------------------------------------- 1 | // only compare int streams, ignoring empty spaces and line breaks 2 | #include 3 | 4 | const int ZOJ_WA_CODE = -1; 5 | const int AC_CODE = 0; 6 | int main() { 7 | FILE *fstd, *fuser; 8 | fstd = fopen("output", "r"); 9 | fuser = fopen("user_output", "r"); 10 | 11 | int std_answer, user_answer; 12 | while (fscanf(fstd, "%d", &std_answer) == 1) { 13 | fscanf(fuser, "%d", &user_answer); 14 | if (std_answer != user_answer) { 15 | return ZOJ_WA_CODE; 16 | } 17 | } 18 | return AC_CODE; 19 | } 20 | -------------------------------------------------------------------------------- /examples/a-plus-b/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | LIST="$@" 4 | [ -z "$LIST" ] && LIST=`ls a* | sed 's#a\.##'` 5 | 6 | echo1() { 7 | # echo in 1 line 8 | echo "$@" | tr -d "\n" 9 | } 10 | 11 | DEBUG_LOG=.debug.$$.log 12 | ERROR_LOG=error.log 13 | 14 | for i in $LIST; do 15 | src=a.$i 16 | [ -e $src ] || continue 17 | echo -n $src': ' 18 | 19 | export SEGFAULT_USE_ALTSTACK=1 20 | export SEGFAULT_OUTPUT_NAME=segfault.$i.$$.log 21 | RESULT=`ljudge --debug --keep-stdout --keep-stderr --user-code $src --testcase --input 1.in --output 1.out --testcase --input 2.in --output-sha1 7b80e651613b8ee99d6f2a578062673a7e40bb65,6b979d97a529a16aced6c9cc59375fa4fe3962e7 2> $DEBUG_LOG | cat` 22 | EXITCODE=$? 23 | if [ "$EXITCODE" != 0 ] || [ -z "$RESULT" ] || (echo1 "$RESULT" | grep -qi ERROR) || (echo1 "$RESULT" | grep -qv ACCEPT); then 24 | # Log error 25 | echo `date` 'Error running' $i 'test (exit code ' $EXITCODE ')' >> $ERROR_LOG 26 | echo1 "$RESULT" >> $ERROR_LOG 27 | cat $DEBUG_LOG >> $ERROR_LOG 28 | echo >> $ERROR_LOG 29 | # notify user 30 | echo1 'ERROR' "$RESULT" 31 | echo 32 | echo 'To re-run: ljudge -u '$src' -i 1.in -o 1.out -i 2.in -o 2.out --debug' 33 | echo 34 | else 35 | echo OKAY 36 | fi 37 | done 2>/dev/null 38 | 39 | # Test the legacy checker with the wrong user code. AC on first case and WA on second case. 40 | echo -n 'Test legacy checker: ' 41 | src=wa.c 42 | RESULT=`ljudge --debug --keep-stdout --keep-stderr --user-code $src --testcase --input 1.in --output 1.out --testcase --input 2.in --output 2.out --checker-code legacy_checker.c 2> $DEBUG_LOG | cat` 43 | EXITCODE=$? 44 | if [ "$EXITCODE" != 0 ] || [ -z "$RESULT" ] || (echo1 "$RESULT" | grep -qi ERROR) || (echo1 "$RESULT" | grep -qv ACCEPT) || (echo1 "$RESULT" | grep -qv WRONG_ANSWER); then 45 | # Log error 46 | echo `date` 'Error running' $i 'test (exit code ' $EXITCODE ')' >> $ERROR_LOG 47 | echo1 "$RESULT" >> $ERROR_LOG 48 | cat $DEBUG_LOG >> $ERROR_LOG 49 | echo >> $ERROR_LOG 50 | # notify user 51 | echo1 'ERROR' "$RESULT" 52 | echo 53 | echo 'To re-run: ljudge -u '$src' -i 1.in -o 1.out -i 2.in -o 2.out -c legacy_checker.c' 54 | echo 55 | else 56 | echo OKAY 57 | fi 58 | 59 | 60 | [ -e $DEBUG_LOG ] && unlink $DEBUG_LOG 61 | -------------------------------------------------------------------------------- /examples/a-plus-b/wa.c: -------------------------------------------------------------------------------- 1 | // AC on test case 1 and WA on test case 2. 2 | #include 3 | main() { printf("3\n"); return 0;} 4 | -------------------------------------------------------------------------------- /examples/interactor/01: -------------------------------------------------------------------------------- 1 | 12 20 2 | -------------------------------------------------------------------------------- /examples/interactor/01.out: -------------------------------------------------------------------------------- 1 | 4 2 | -------------------------------------------------------------------------------- /examples/interactor/19: -------------------------------------------------------------------------------- 1 | 1 1000000 2 | -------------------------------------------------------------------------------- /examples/interactor/19.out: -------------------------------------------------------------------------------- 1 | 19 2 | -------------------------------------------------------------------------------- /examples/interactor/20: -------------------------------------------------------------------------------- 1 | 1000000 1000000 2 | -------------------------------------------------------------------------------- /examples/interactor/20.out: -------------------------------------------------------------------------------- 1 | 20 2 | -------------------------------------------------------------------------------- /examples/interactor/21: -------------------------------------------------------------------------------- 1 | 1 1 2 | -------------------------------------------------------------------------------- /examples/interactor/21.out: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /examples/interactor/ac.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define forn(i, n) for(int i=0;i 29 | 30 | template inline X abs(const X& a) { return a < 0? -a: a; } 31 | template inline X sqr(const X& a) { return a * a; } 32 | 33 | typedef long long li; 34 | typedef long double ld; 35 | 36 | using namespace std; 37 | 38 | const int INF = 1000*1000*1000; 39 | const ld EPS = 1e-9; 40 | const ld PI = acos(-1.0); 41 | 42 | int n; 43 | int lf, rg; 44 | 45 | bool read() 46 | { 47 | cin >> n; 48 | return true; 49 | } 50 | 51 | void solve() 52 | { 53 | lf = 1, rg = n; 54 | while(lf != rg) 55 | { 56 | int mid = (lf + rg + 1) / 2; 57 | cout << mid << endl; 58 | fflush(stdout); 59 | string s; 60 | cin >> s; 61 | if(s == "<") 62 | rg = mid - 1; 63 | else 64 | lf = mid; 65 | } 66 | 67 | cout << "! " << lf << endl; 68 | } 69 | 70 | int main () 71 | { 72 | srand(time(NULL)); 73 | cerr << setprecision(10) << fixed; 74 | assert(read()); 75 | solve(); 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /examples/interactor/check.cpp: -------------------------------------------------------------------------------- 1 | #include "testlib.h" 2 | 3 | int main(int argc, char * argv[]) { 4 | registerTestlibCmd(argc, argv); 5 | 6 | int oufq = ouf.readInt(); 7 | int ansq = ans.readInt(); 8 | 9 | if (ansq > 25) 10 | quitf(_fail, "Limit is %d, but main solution have made %d queries", 25, ansq); 11 | 12 | if (oufq > 25) 13 | quitf(_wa, "Limit is %d, but solution have made %d queries", 25, oufq); 14 | 15 | int n = inf.readInt(); 16 | int m = inf.readInt(); 17 | quitf(_ok, "Number %d is guessed successfully (range [1..%d]) with %d queries", n, m, oufq); 18 | } 19 | -------------------------------------------------------------------------------- /examples/interactor/interactor.cpp: -------------------------------------------------------------------------------- 1 | #include "testlib.h" 2 | #include 3 | 4 | using namespace std; 5 | 6 | void upd(int& lf, int& rg, int x, int y) { 7 | if(x > y) 8 | return; 9 | lf = max(lf, x); 10 | rg = min(rg, y); 11 | } 12 | 13 | void send(string x) { 14 | cout << x << endl; 15 | fflush(stdout); 16 | } 17 | 18 | const int INF = 1000'000'000; 19 | 20 | int main(int argc, char* argv[]) { 21 | registerInteraction(argc, argv); 22 | int x = inf.readInt(); 23 | int n = inf.readInt(); 24 | cout << n << endl << flush; 25 | int lf = 1, rg = n; 26 | 27 | int queries = 0; 28 | while (true) 29 | { 30 | bool is_answer = false; 31 | string cur = ouf.readToken("!|[1-9][0-9]{0,8}"); 32 | int last; 33 | if (cur != "!") { 34 | InStream tmp(ouf, cur); 35 | last = tmp.readInt(-INF, INF); 36 | queries++; 37 | } else { 38 | is_answer = true; 39 | last = ouf.readInt(-INF, INF); 40 | } 41 | 42 | if (last < 1 || last > n) 43 | quitf(_pe, "number %d from stdin is out of range [%d, %d]", last, 1, n); 44 | 45 | if (is_answer) { 46 | if(last == x && lf == rg) { 47 | tout << queries << endl; 48 | quitf(_ok, "number is guessed."); 49 | } else if(last == x && lf != rg) 50 | quitf(_wa, "number is but it was made in a random way"); 51 | else 52 | quitf(_wa, "guessed number is incorrect"); 53 | } 54 | 55 | if(x < last) { 56 | send("<"); 57 | upd(lf, rg, 1, last - 1); 58 | } else { 59 | send(">="); 60 | upd(lf, rg, last, n); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /examples/interactor/ml.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define forn(i, n) for(int i=0;i 29 | 30 | template inline X abs(const X& a) { return a < 0? -a: a; } 31 | template inline X sqr(const X& a) { return a * a; } 32 | 33 | typedef long long li; 34 | typedef long double ld; 35 | 36 | using namespace std; 37 | 38 | const int INF = 1000*1000*1000; 39 | const ld EPS = 1e-9; 40 | const ld PI = acos(-1.0); 41 | 42 | int n; 43 | int lf, rg; 44 | 45 | bool read() 46 | { 47 | cin >> n; 48 | return true; 49 | } 50 | 51 | void solve() 52 | { 53 | lf = 1, rg = n; 54 | vectorwas; 55 | int it = 0; 56 | while(lf != rg) 57 | { 58 | it++; 59 | int mid = (lf + rg + 1) / 2; 60 | if(it > 5) 61 | for(int i = 0; i < 10000000; i++) 62 | was.pb(rand()); 63 | cout << mid << endl; 64 | fflush(stdout); 65 | string s; 66 | cin >> s; 67 | if(s == "<") 68 | rg = mid - 1; 69 | else 70 | lf = mid; 71 | } 72 | 73 | cout << "! " << lf << endl; 74 | } 75 | 76 | int main () 77 | { 78 | srand(time(NULL)); 79 | cerr << setprecision(10) << fixed; 80 | assert(read()); 81 | solve(); 82 | return 0; 83 | } 84 | -------------------------------------------------------------------------------- /examples/interactor/pe.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define forn(i, n) for(int i=0;i 29 | 30 | template inline X abs(const X& a) { return a < 0? -a: a; } 31 | template inline X sqr(const X& a) { return a * a; } 32 | 33 | typedef long long li; 34 | typedef long double ld; 35 | 36 | using namespace std; 37 | 38 | const int INF = 1000*1000*1000; 39 | const ld EPS = 1e-9; 40 | const ld PI = acos(-1.0); 41 | 42 | int n; 43 | int lf, rg; 44 | 45 | bool read() 46 | { 47 | cin >> n; 48 | return true; 49 | } 50 | 51 | void solve() 52 | { 53 | lf = 1, rg = n; 54 | int it = 0; 55 | while(lf != rg) 56 | { 57 | it++; 58 | int mid = (lf + rg + 1) / 2; 59 | cout << mid << endl; 60 | fflush(stdout); 61 | string s; 62 | cin >> s; 63 | if(s == "<") 64 | rg = mid - 1; 65 | else 66 | lf = mid; 67 | } 68 | if(it> 15) 69 | cout << "!!"; 70 | cout << "! " << lf << endl; 71 | } 72 | 73 | int main () 74 | { 75 | srand(time(NULL)); 76 | cerr << setprecision(10) << fixed; 77 | assert(read()); 78 | solve(); 79 | return 0; 80 | } 81 | -------------------------------------------------------------------------------- /examples/interactor/run.sh: -------------------------------------------------------------------------------- 1 | ljudge -u ac.cpp -a interactor.cpp -i 01 -o 01.out -i 19 -o 19.out -i 20 -o 20.out -i 21 -o 21.out --debug # no checker 2 | ljudge -u ac.cpp -a interactor.cpp -c check.cpp -i 01 -o 01.out -i 19 -o 19.out -i 20 -o 20.out -i 21 -o 21.out --debug # with checker 3 | ljudge -u wa.cpp -a interactor.cpp -c check.cpp -i 01 -o 01.out -i 19 -o 19.out -i 20 -o 20.out -i 21 -o 21.out --debug # wa 4 | ljudge -u pe.cpp -a interactor.cpp -c check.cpp -i 01 -o 01.out -i 19 -o 19.out -i 20 -o 20.out -i 21 -o 21.out --debug # pe? 5 | ljudge -u too-many-iter.cpp -a interactor.cpp -c check.cpp -i 01 -o 01.out -i 19 -o 19.out -i 20 -o 20.out -i 21 -o 21.out --debug # TLE 6 | ljudge --max-cpu-time 10 --max-real-time 10 --max-interactor-cpu-time 10 --max-interactor-real-time 10 -u too-many-iter.cpp -a interactor.cpp -c check.cpp -i 01 -o 01.out -i 19 -o 19.out -i 20 -o 20.out -i 21 -o 21.out --debug # wa 7 | -------------------------------------------------------------------------------- /examples/interactor/too-many-iter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define forn(i, n) for(int i=0;i 29 | 30 | template inline X abs(const X& a) { return a < 0? -a: a; } 31 | template inline X sqr(const X& a) { return a * a; } 32 | 33 | typedef long long li; 34 | typedef long double ld; 35 | 36 | using namespace std; 37 | 38 | const int INF = 1000*1000*1000; 39 | const ld EPS = 1e-9; 40 | const ld PI = acos(-1.0); 41 | 42 | int n; 43 | int lf, rg; 44 | 45 | bool read() 46 | { 47 | cin >> n; 48 | return true; 49 | } 50 | 51 | void solve() 52 | { 53 | lf = 1, rg = n; 54 | while(lf != rg) 55 | { 56 | int mid = (lf + rg + 1) / 2; 57 | cout << mid << endl; 58 | fflush(stdout); 59 | string s; 60 | cin >> s; 61 | if(s == "<") 62 | rg--; 63 | else 64 | lf = mid; 65 | } 66 | 67 | cout << "! " << lf << endl; 68 | } 69 | 70 | int main () 71 | { 72 | srand(time(NULL)); 73 | cerr << setprecision(10) << fixed; 74 | assert(read()); 75 | solve(); 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /examples/interactor/wa.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define forn(i, n) for(int i=0;i 29 | 30 | template inline X abs(const X& a) { return a < 0? -a: a; } 31 | template inline X sqr(const X& a) { return a * a; } 32 | 33 | typedef long long li; 34 | typedef long double ld; 35 | 36 | using namespace std; 37 | 38 | const int INF = 1000*1000*1000; 39 | const ld EPS = 1e-9; 40 | const ld PI = acos(-1.0); 41 | 42 | int n; 43 | int lf, rg; 44 | 45 | bool read() 46 | { 47 | cin >> n; 48 | return true; 49 | } 50 | 51 | void solve() 52 | { 53 | lf = 1, rg = n; 54 | while(rg - lf > 1) 55 | { 56 | int mid = (lf + rg + 1) / 2; 57 | cout << mid << endl; 58 | fflush(stdout); 59 | string s; 60 | cin >> s; 61 | if(s == "<") 62 | rg = mid - 1; 63 | else 64 | lf = mid; 65 | } 66 | int ans = lf; 67 | if(rand() % 2) 68 | ans = rg; 69 | cout << "! " << ans << endl; 70 | } 71 | 72 | int main () 73 | { 74 | srand(time(NULL)); 75 | cerr << setprecision(10) << fixed; 76 | assert(read()); 77 | solve(); 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /examples/stack/1.in: -------------------------------------------------------------------------------- 1 | 1 2 2 | -------------------------------------------------------------------------------- /examples/stack/1.out: -------------------------------------------------------------------------------- 1 | 3 2 | -------------------------------------------------------------------------------- /examples/stack/2.in: -------------------------------------------------------------------------------- 1 | 1 -2 2 | 3 4 3 | -------------------------------------------------------------------------------- /examples/stack/2.out: -------------------------------------------------------------------------------- 1 | -1 2 | 7 3 | -------------------------------------------------------------------------------- /examples/stack/large_stack.c: -------------------------------------------------------------------------------- 1 | #include 2 | int dfs(int x, int MAX) { 3 | if (x == MAX) return 1; 4 | int tmp[10] = {}; 5 | for (int i = 0; i < 10; ++i) { 6 | tmp[i] = x - i; 7 | } 8 | int res = dfs(x+1, MAX), tot = 0; 9 | for (int i = 0; i < 10; ++i) { 10 | tot += i * tmp[i] * res; 11 | } 12 | return tot; 13 | } 14 | int main() { 15 | int a, b; 16 | while(scanf("%d %d",&a, &b) != EOF) { 17 | printf("%d\n", dfs(0, 1000000)); 18 | } 19 | return 0; 20 | } -------------------------------------------------------------------------------- /examples/stack/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo1() { 4 | # echo in 1 line 5 | echo "$@" | tr -d "\n" 6 | } 7 | 8 | DEBUG_LOG=.debug.$$.log 9 | ERROR_LOG=error.log 10 | 11 | # Test configuring stack size 12 | src=large_stack.c 13 | # Use default stack size (8M) will cause SEGMENTATION_FAULT 14 | echo -n 'Test limitation of stack size: ' 15 | RESULT=`ljudge --debug --keep-stdout --keep-stderr --user-code $src --testcase --input 1.in --output 1.out --testcase --input 2.in --output 2.out 2> $DEBUG_LOG | cat` 16 | EXITCODE=$? 17 | if [ "$EXITCODE" != 0 ] || [ -z "$RESULT" ] || (echo1 "$RESULT" | grep -qi ERROR) || (echo1 "$RESULT" | grep -qv SEGMENTATION_FAULT); then 18 | # Log error 19 | echo `date` 'Error running' $i 'test (exit code ' $EXITCODE ')' >> $ERROR_LOG 20 | echo1 "$RESULT" >> $ERROR_LOG 21 | cat $DEBUG_LOG >> $ERROR_LOG 22 | echo >> $ERROR_LOG 23 | # notify user 24 | echo1 'ERROR' "$RESULT" 25 | echo 26 | echo 'To re-run: ljudge -u '$src' -i 1.in -o 1.out -i 2.in -o 2.out' 27 | echo 28 | else 29 | echo OKAY 30 | fi 31 | # Use larger stack size to eliminate SEGMENTATION_FAULT 32 | echo -n 'Test larger stack size: ' 33 | RESULT=`ljudge --debug --keep-stdout --keep-stderr --user-code $src --max-stack 128M --testcase --input 1.in --output 1.out --testcase --input 2.in --output 2.out 2> $DEBUG_LOG | cat` 34 | EXITCODE=$? 35 | if [ "$EXITCODE" != 0 ] || [ -z "$RESULT" ] || (echo1 "$RESULT" | grep -qi ERROR) || (echo1 "$RESULT" | grep -q SEGMENTATION_FAULT); then 36 | # Log error 37 | echo `date` 'Error running' $i 'test (exit code ' $EXITCODE ')' >> $ERROR_LOG 38 | echo1 "$RESULT" >> $ERROR_LOG 39 | cat $DEBUG_LOG >> $ERROR_LOG 40 | echo >> $ERROR_LOG 41 | # notify user 42 | echo1 'ERROR' "$RESULT" 43 | echo 44 | echo 'To re-run: ljudge -u '$src' -i 1.in -o 1.out -i 2.in -o 2.out --max-stack 128M' 45 | echo 46 | else 47 | echo OKAY 48 | fi 49 | 50 | [ -e $DEBUG_LOG ] && unlink $DEBUG_LOG 51 | -------------------------------------------------------------------------------- /schema/response.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "type": "object", 4 | "definitions": { 5 | "compilationResult": { 6 | "type": "object", 7 | "description": "The compilation result of the source code", 8 | "properties": { 9 | "log": { 10 | "type": "string", 11 | "description": "Compiler log, including warnings and errors. Show this to end-users" 12 | }, 13 | "success": { 14 | "type": "boolean", 15 | "description": "Whether compilation has succeeded" 16 | }, 17 | "error": { 18 | "type": "string", 19 | "description": "Internal error message. Should not be visible to end-users. Present only when an internal error (ex. required compiler is not installed) happens" 20 | } 21 | }, 22 | "additionalProperties": false, 23 | "required": ["log", "success"] 24 | }, 25 | "testcaseResult": { 26 | "type": "object", 27 | "properties": { 28 | "result": { 29 | "type": "string", 30 | "enum": [ 31 | "ACCEPTED", 32 | "PRESENTATION_ERROR", 33 | "WRONG_ANSWER", 34 | "NON_ZERO_EXIT_CODE", 35 | "MEMORY_LIMIT_EXCEEDED", 36 | "TIME_LIMIT_EXCEEDED", 37 | "OUTPUT_LIMIT_EXCEEDED", 38 | "FLOAT_POINT_EXCEPTION", 39 | "SEGMENTATION_FAULT", 40 | "RUNTIME_ERROR", 41 | "INTERNAL_ERROR", 42 | "SKIPPED" 43 | ], 44 | "description": "Judge response for the test case" 45 | }, 46 | "exceed": { 47 | "type": "string", 48 | "enum": [ 49 | "CPU_TIME", 50 | "REAL_TIME", 51 | "MEMORY", 52 | "OUTPUT" 53 | ], 54 | "description": "The limit that the program exceeded. Present only when the program has exceeded one limit" 55 | }, 56 | "time": { 57 | "type": "number", 58 | "description": "CPU time used by the program, in seconds. Present only when \"exceed\" is missing, and \"result\" is not \"SKIPPED\" or \"INTERNAL_ERROR\"" 59 | }, 60 | "memory": { 61 | "type": "number", 62 | "description": "Peak memory used by the program, in bytes. Present only when \"exceed\" is missing, and \"result\" is not \"SKIPPED\" or \"INTERNAL_ERROR\"" 63 | }, 64 | "exitcode": { 65 | "type": "number", 66 | "description": "Exit code of the program. Present only when the program exits normally, and \"result\" is not \"SKIPPED\" or \"INTERNAL_ERROR\"" 67 | }, 68 | "termsig": { 69 | "type": "number", 70 | "description": "Signal number that terminates the program. Present only when the program has not exceeded any limit and has exited abnormally (is signaled)" 71 | }, 72 | "error": { 73 | "type": "string", 74 | "description": "Internal error message. Present only when \"result\" is \"INTERNAL_ERROR\". Should not be visible to end-users" 75 | }, 76 | "stdout": { 77 | "type": "string", 78 | "description": "stdout output of the program. Present only when the command line option \"--keep-stdout\" is set" 79 | }, 80 | "stderr": { 81 | "type": "string", 82 | "description": "stderr output of the program. Present only when the command line option \"--keep-stderr\" is set" 83 | }, 84 | "checkerOutput": { 85 | "type": "string", 86 | "description": "Custom checker output (stdout). Present only when custom checker is used and it writes something to stdout" 87 | } 88 | }, 89 | "additionalProperties": false, 90 | "required": ["result"] 91 | } 92 | }, 93 | "properties": { 94 | "compilation": { 95 | "$ref": "#/definitions/compilationResult", 96 | "description": "Compilation result of the user code" 97 | }, 98 | "checkerCompilation": { 99 | "$ref": "#/definitions/compilationResult", 100 | "description": "Compilation result of the custom checker code. Present only when the command line option \"--checker-code\" is provided" 101 | }, 102 | "testcases": { 103 | "type": "array", 104 | "description": "Test case results. Present only when compilation has successed", 105 | "items": {"$ref": "#/definitions/testcaseResult"} 106 | } 107 | }, 108 | "additionalProperties": false, 109 | "required": ["compilation"] 110 | } 111 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | CXX?=g++ 2 | CXXFLAGS?=-Wall -Os -g 3 | 4 | ifneq ($(NDEBUG),) 5 | CXXFLAGS += -DNDEBUG 6 | endif 7 | 8 | ifeq ($(DESTDIR),) 9 | PREFIX?=/usr/local 10 | else 11 | PREFIX?=/usr 12 | endif 13 | 14 | .SUFFIXES: 15 | 16 | .PHONY: all clean install cog 17 | 18 | all: ljudge 19 | 20 | ljudge: ljudge.o sha1.o fs.o term.o 21 | $(CXX) -o $@ $(LDFLAGS) -fopenmp $^ -pthread -ldl 22 | 23 | %.o: %.cc 24 | $(CXX) -pthread -std=c++11 -fopenmp -c -o $@ $(CXXFLAGS) $< 25 | 26 | clean: 27 | -rm -f *.o **/*.o ljudge 28 | 29 | install: ljudge 30 | install -D -m0755 -oroot -groot -s $< $(DESTDIR)$(PREFIX)/bin/ljudge 31 | ifneq ($(DESTDIR),) 32 | mkdir -p $(DESTDIR)/etc/ 33 | cp -a ../etc/ljudge $(DESTDIR)/etc/ 34 | endif 35 | 36 | cog: ljudge.cc 37 | cog.py -r $^ 38 | -------------------------------------------------------------------------------- /src/deps/fs/fs.c: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * fs.c 4 | * 5 | * copyright 2013 - joseph werle 6 | */ 7 | 8 | #define _POSIX_C_SOURCE 200809L 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include "fs.h" 19 | 20 | void 21 | fs_error (const char *prefix) { 22 | char fmt[256]; 23 | sprintf(fmt, "fs: %s: error", prefix); 24 | perror(fmt); 25 | } 26 | 27 | 28 | FILE * 29 | fs_open (const char *path, const char *flags) { 30 | return fopen(path, flags); 31 | } 32 | 33 | 34 | int 35 | fs_close (FILE *file) { 36 | return fclose(file); 37 | } 38 | 39 | 40 | int 41 | fs_rename (const char *from, const char *to) { 42 | return rename(from, to); 43 | } 44 | 45 | 46 | fs_stats * 47 | fs_stat (const char *path) { 48 | fs_stats *stats = (fs_stats*)malloc(sizeof(fs_stats)); 49 | int e = stat(path, stats); 50 | if (-1 == e) { 51 | free(stats); 52 | return NULL; 53 | } 54 | return stats; 55 | } 56 | 57 | 58 | fs_stats * 59 | fs_fstat (FILE *file) { 60 | if (NULL == file) return NULL; 61 | fs_stats *stats = (fs_stats*)malloc(sizeof(fs_stats)); 62 | int fd = fileno(file); 63 | int e = fstat(fd, stats); 64 | if (-1 == e) { 65 | free(stats); 66 | return NULL; 67 | } 68 | return stats; 69 | } 70 | 71 | 72 | fs_stats * 73 | fs_lstat (const char *path) { 74 | fs_stats *stats = (fs_stats*)malloc(sizeof(fs_stats)); 75 | #ifdef _WIN32 76 | int e = stat(path, stats); 77 | #else 78 | int e = lstat(path, stats); 79 | #endif 80 | if (-1 == e) { 81 | free(stats); 82 | return NULL; 83 | } 84 | return stats; 85 | } 86 | 87 | 88 | int 89 | fs_ftruncate (FILE *file, int len) { 90 | int fd = fileno(file); 91 | return ftruncate(fd, (off_t) len); 92 | } 93 | 94 | 95 | int 96 | fs_truncate (const char *path, int len) { 97 | #ifdef _WIN32 98 | int ret = -1; 99 | int fd = open(path, O_RDWR | O_CREAT, S_IREAD | S_IWRITE); 100 | if (fd != -1) { 101 | ret = ftruncate(fd, (off_t) len); 102 | close(fd); 103 | } 104 | return ret; 105 | #else 106 | return truncate(path, (off_t) len); 107 | #endif 108 | } 109 | 110 | 111 | int 112 | fs_chown (const char *path, int uid, int gid) { 113 | #ifdef _WIN32 114 | errno = ENOSYS; 115 | return -1; 116 | #else 117 | return chown(path, (uid_t) uid, (gid_t) gid); 118 | #endif 119 | } 120 | 121 | 122 | int 123 | fs_fchown (FILE *file, int uid, int gid) { 124 | #ifdef _WIN32 125 | errno = ENOSYS; 126 | return -1; 127 | #else 128 | int fd = fileno(file); 129 | return fchown(fd, (uid_t) uid, (gid_t) gid); 130 | #endif 131 | } 132 | 133 | 134 | int 135 | fs_lchown (const char *path, int uid, int gid) { 136 | #ifdef _WIN32 137 | errno = ENOSYS; 138 | return -1; 139 | #else 140 | return lchown(path, (uid_t) uid, (gid_t) gid); 141 | #endif 142 | } 143 | 144 | 145 | size_t 146 | fs_size (const char *path) { 147 | size_t size; 148 | FILE *file = fs_open(path, FS_OPEN_READ); 149 | if (NULL == file) return -1; 150 | fseek(file, 0, SEEK_END); 151 | size = ftell(file); 152 | fs_close(file); 153 | return size; 154 | } 155 | 156 | 157 | size_t 158 | fs_fsize (FILE *file) { 159 | // store current position 160 | unsigned long pos = ftell(file); 161 | rewind(file); 162 | fseek(file, 0, SEEK_END); 163 | size_t size = ftell(file); 164 | fseek(file, pos, SEEK_SET); 165 | return size; 166 | } 167 | 168 | 169 | char * 170 | fs_read (const char *path) { 171 | FILE *file = fs_open(path, FS_OPEN_READ); 172 | if (NULL == file) return NULL; 173 | char *data = fs_fread(file); 174 | fclose(file); 175 | return data; 176 | } 177 | 178 | 179 | char * 180 | fs_nread (const char *path, int len) { 181 | FILE *file = fs_open(path, FS_OPEN_READ); 182 | if (NULL == file) return NULL; 183 | char *buffer = fs_fnread(file, len); 184 | fs_close(file); 185 | return buffer; 186 | } 187 | 188 | 189 | char * 190 | fs_fread (FILE *file) { 191 | size_t fsize = fs_fsize(file); 192 | return fs_fnread(file, fsize); 193 | } 194 | 195 | 196 | char * 197 | fs_fnread (FILE *file, int len) { 198 | char *buffer = (char*)malloc(sizeof(char) * (len + 1)); 199 | size_t n = fread(buffer, 1, len, file); 200 | buffer[n] = buffer[len] = '\0'; 201 | return buffer; 202 | } 203 | 204 | 205 | int 206 | fs_write (const char *path, const char *buffer) { 207 | return fs_nwrite(path, buffer, strlen(buffer)); 208 | } 209 | 210 | 211 | int 212 | fs_nwrite (const char *path, const char *buffer, int len) { 213 | FILE *file = fs_open(path, FS_OPEN_WRITE); 214 | if (NULL == file) return -1; 215 | int result = fs_fnwrite(file, buffer, len); 216 | fclose(file); 217 | return result; 218 | } 219 | 220 | 221 | int 222 | fs_fwrite (FILE *file, const char *buffer) { 223 | return fs_fnwrite(file, buffer, strlen(buffer)); 224 | } 225 | 226 | 227 | int 228 | fs_fnwrite (FILE *file, const char *buffer, int len) { 229 | return (int) fwrite(buffer, 1, len, file); 230 | } 231 | 232 | 233 | int 234 | fs_mkdir (const char *path, int mode) { 235 | #ifdef _WIN32 236 | return mkdir(path); 237 | #else 238 | return mkdir(path, (mode_t) mode); 239 | #endif 240 | } 241 | 242 | 243 | int 244 | fs_rmdir (const char *path) { 245 | return rmdir(path); 246 | } 247 | 248 | 249 | int 250 | fs_exists (const char *path) { 251 | struct stat b; 252 | return stat(path, &b); 253 | } 254 | -------------------------------------------------------------------------------- /src/deps/fs/fs.h: -------------------------------------------------------------------------------- 1 | #ifndef FS_H 2 | #define FS_H 1 3 | 4 | 5 | /** 6 | * fs.h 7 | * 8 | * copyright 2013 - joseph werle 9 | */ 10 | 11 | 12 | #include 13 | #include 14 | 15 | #ifdef _WIN32 16 | #define FS_OPEN_READ "rb" 17 | #define FS_OPEN_WRITE "wb" 18 | #define FS_OPEN_READWRITE "rwb" 19 | #else 20 | #define FS_OPEN_READ "r" 21 | #define FS_OPEN_WRITE "w" 22 | #define FS_OPEN_READWRITE "rw" 23 | #endif 24 | 25 | typedef struct stat fs_stats; 26 | 27 | 28 | 29 | /** 30 | * Prints the last error to stderr 31 | */ 32 | 33 | void 34 | fs_error (const char *prefix); 35 | 36 | 37 | /** 38 | * Opens a file with given flags 39 | * and returns a file descriptor 40 | */ 41 | 42 | FILE * 43 | fs_open (const char *path, const char *flags); 44 | 45 | 46 | /** 47 | * Closes a given file descriptor 48 | */ 49 | 50 | int 51 | fs_close (FILE *file); 52 | 53 | 54 | /** 55 | * Moves a path to a new destination 56 | */ 57 | 58 | int 59 | fs_rename (const char *from, const char *to); 60 | 61 | 62 | /** 63 | * Stats a given path and returns 64 | * a `struct stat` 65 | */ 66 | 67 | fs_stats * 68 | fs_stat (const char *path); 69 | 70 | 71 | /** 72 | * Stats a given file descriptor 73 | */ 74 | 75 | fs_stats * 76 | fs_fstat (FILE *file); 77 | 78 | 79 | /** 80 | * Stats a given link path 81 | */ 82 | 83 | fs_stats * 84 | fs_lstat (const char *path); 85 | 86 | 87 | /** 88 | * Truncates a file to a specified 89 | * length from a given file descriptor 90 | */ 91 | 92 | int 93 | fs_ftruncate (FILE *file, int len); 94 | 95 | 96 | /** 97 | * Truncates a file to a specified 98 | * len from a given file path 99 | */ 100 | 101 | int 102 | fs_truncate (const char *path, int len); 103 | 104 | 105 | /** 106 | * Changes ownership of a given 107 | * file path to a given owner 108 | * and group 109 | */ 110 | 111 | int 112 | fs_chown (const char *path, int uid, int gid); 113 | 114 | 115 | /** 116 | * Change ownership of a given 117 | * file descriptor to a given owner 118 | * and group 119 | */ 120 | 121 | int 122 | fs_fchown (FILE *file, int uid, int gid); 123 | 124 | 125 | /** 126 | * Returns the size of a file from 127 | * a given file path 128 | */ 129 | 130 | size_t 131 | fs_size (const char *path); 132 | 133 | 134 | /** 135 | * Returns the size of a file 136 | * from a given file descriptor 137 | */ 138 | 139 | size_t 140 | fs_fsize (FILE *file); 141 | 142 | 143 | /** 144 | * Change ownership of a given 145 | * link path to a given owner 146 | * and group 147 | */ 148 | 149 | int 150 | fs_lchown (const char *path, int uid, int gid); 151 | 152 | 153 | /** 154 | * Reads a file by a given file 155 | * path 156 | */ 157 | 158 | char * 159 | fs_read (const char *path); 160 | 161 | 162 | /** 163 | * Reads a file by a given 164 | * file path by a given `n` 165 | * number of bytes 166 | */ 167 | 168 | char * 169 | fs_nread (const char *path, int len); 170 | 171 | 172 | /** 173 | * Reads a file by a given 174 | * file descriptor 175 | */ 176 | 177 | char * 178 | fs_fread (FILE *file); 179 | 180 | 181 | /** 182 | * Reads a file by a given 183 | * file descriptor by a given 184 | * `n` number of bytes 185 | */ 186 | 187 | char * 188 | fs_fnread (FILE *file, int len); 189 | 190 | 191 | /** 192 | * Writes a buffer 193 | * to a given file path 194 | */ 195 | 196 | int 197 | fs_write (const char *path, const char *buffer); 198 | 199 | 200 | /** 201 | * Writes `n` bytes of a buffer to a given 202 | * file path 203 | */ 204 | 205 | int 206 | fs_nwrite (const char *path, const char *buffer, int len); 207 | 208 | 209 | /** 210 | * Writes a buffer to a given 211 | * file stream 212 | */ 213 | 214 | int 215 | fs_fwrite (FILE *file, const char *buffer); 216 | 217 | 218 | /** 219 | * Writes `n` bytes of a buffer 220 | * to a given file stream 221 | */ 222 | 223 | int 224 | fs_fnwrite (FILE *file, const char *buffer, int len); 225 | 226 | 227 | /** 228 | * Makes a directory and returns 0 229 | * on success or -1 on failure 230 | */ 231 | 232 | int 233 | fs_mkdir (const char *path, int mode); 234 | 235 | 236 | /** 237 | * Removes a directory and returns 238 | * 0 on success and -1 on failure 239 | */ 240 | 241 | int 242 | fs_rmdir (const char *path); 243 | 244 | /** 245 | * Check if the given `path` exists 246 | */ 247 | 248 | int 249 | fs_exists (const char *path); 250 | 251 | 252 | #endif 253 | -------------------------------------------------------------------------------- /src/deps/fs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fs", 3 | "version": "0.1.1", 4 | "description": "File system API much like Node's fs module", 5 | "repo": "jwerle/fs.c", 6 | "src": ["fs.h", "fs.c"], 7 | "scripts": { 8 | "test": "make test" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git@github.com:jwerle/fs.c.git" 13 | }, 14 | "keywords": [ 15 | "fs" 16 | ], 17 | "author": "Joseph Werle", 18 | "license": "MIT", 19 | "bugs": { 20 | "url": "https://github.com/jwerle/fs.c/issues" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/deps/log.h/log.h: -------------------------------------------------------------------------------- 1 | #ifndef __LOG_h__ 2 | #define __LOG_h__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) 9 | 10 | extern int debug_level; 11 | #ifdef _OPENMP 12 | # define LOG_H_PREFIX_FORMAT "%3d " 13 | # define LOG_H_PREFIX_VALUE omp_get_thread_num() 14 | #else 15 | # define LOG_H_PREFIX_FORMAT "%s" 16 | # define LOG_H_PREFIX_VALUE "" 17 | #endif 18 | 19 | #ifdef NDEBUG 20 | /* compile with all debug messages removed */ 21 | #define log_debug(M, ...) 22 | #else 23 | #define log_debug(M, ...) if (debug_level > 5) fprintf(stderr, LOG_H_PREFIX_FORMAT "\33[34mDEBUG\33[39m " M " \33[90m at %s (%s:%d) \33[39m\n", LOG_H_PREFIX_VALUE, ##__VA_ARGS__, __func__, __FILE__, __LINE__) 24 | #endif 25 | 26 | /* safe readable version of errno */ 27 | #define clean_errno() (errno == 0 ? "None" : strerror(errno)) 28 | 29 | #define log_error(M, ...) fprintf(stderr, LOG_H_PREFIX_FORMAT "\33[31mERR\33[39m " M " \33[90m at %s (%s:%d) \33[94merrno: %s\33[39m\n", LOG_H_PREFIX_VALUE, ##__VA_ARGS__, __func__, __FILE__, __LINE__, clean_errno()) 30 | 31 | #define log_warn(M, ...) if (debug_level >= 0) fprintf(stderr, LOG_H_PREFIX_FORMAT "\33[91mWARN\33[39m " M " \33[90m at %s (%s:%d) \33[94merrno: %s\33[39m\n", LOG_H_PREFIX_VALUE, ##__VA_ARGS__, __func__, __FILE__, __LINE__, clean_errno()) 32 | 33 | #define log_info(M, ...) if (debug_level > 4) fprintf(stderr, LOG_H_PREFIX_FORMAT "\33[32mINFO\33[39m " M " \33[90m at %s (%s:%d) \33[39m\n", LOG_H_PREFIX_VALUE, ##__VA_ARGS__, __func__, __FILENAME__, __LINE__) 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/deps/log.h/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "log.h", 3 | "main": "log.h", 4 | "version": "0.1.3", 5 | "description": "Minimal yet colorful logging lib.", 6 | "repository": { 7 | "type": "git", 8 | "url": "git://github.com/thlorenz/log.h.git" 9 | }, 10 | "src": [ 11 | "log.h" 12 | ], 13 | "homepage": "https://github.com/thlorenz/log.h", 14 | "keywords": [ 15 | "log", 16 | "debug", 17 | "print", 18 | "diagnostics" 19 | ], 20 | "author": { 21 | "name": "Thorsten Lorenz", 22 | "email": "thlorenz@gmx.de", 23 | "url": "http://thlorenz.com" 24 | }, 25 | "license": { 26 | "type": "MIT", 27 | "url": "https://github.com/thlorenz/log.h/blob/master/LICENSE" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/deps/picojson/.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | a.out 3 | -------------------------------------------------------------------------------- /src/deps/picojson/.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | 3 | compiler: 4 | - clang 5 | - gcc 6 | 7 | script: 8 | - make test 9 | -------------------------------------------------------------------------------- /src/deps/picojson/Changes: -------------------------------------------------------------------------------- 1 | Revision history for picojson 2 | 3 | 1.1.1 2014-06-25 10:35:00+0900 4 | - tweaks to suppress compiler errors / warning (#38 #39) 5 | - clarify the licenses of the files in exmaple/ (#42) 6 | 7 | 1.1 2014-06-16 12:57:00+0900 8 | - added experimental support for int64 type (#34) 9 | - by default, throw std::runtime_error instead of using assert for runtime errors (#33) 10 | - refine compatibility regarding the use of isinf/isnan (#29, #36) 11 | - remove `.get()` (#35) 12 | 13 | 1.0 2014-06-05 12:54:00+0900 14 | - initial release with a version number 15 | -------------------------------------------------------------------------------- /src/deps/picojson/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2009-2010 Cybozu Labs, Inc. 2 | Copyright 2011-2014 Kazuho Oku 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /src/deps/picojson/Makefile: -------------------------------------------------------------------------------- 1 | test: 2 | $(MAKE) test-core 3 | $(MAKE) test-core TEST_OPTS=-DPICOJSON_USE_INT64 4 | 5 | test-core: 6 | $(CXX) -o test-core -Wall $(TEST_OPTS) -DTEST_PICOJSON -x c++ - < picojson.h && ./test-core 7 | 8 | .PHONY: test test-core 9 | -------------------------------------------------------------------------------- /src/deps/picojson/README.mkdn: -------------------------------------------------------------------------------- 1 | # PicoJSON - a C++ JSON parser / serializer 2 | 3 | Copyright © 2009-2010 Cybozu Labs, Inc. 4 | Copyright © 2011-2014 Kazuho Oku 5 | 6 | Licensed under [2-clause BSD license](http://opensource.org/licenses/BSD-2-Clause) 7 | 8 | ## Version 9 | 10 | 1.1.2-dev [![Build Status](https://travis-ci.org/kazuho/picojson.svg?branch=master)](https://travis-ci.org/kazuho/picojson) 11 | 12 | ## Introduction 13 | 14 | PicoJSON is a tiny JSON parser / serializer for C++ with following properties: 15 | 16 | - header-file only 17 | - no external dependencies (only uses standard C++ libraries) 18 | - STL-frendly (arrays are represented by using std::vector, objects are std::map) 19 | - provides both pull interface and streaming (event-based) interface 20 | 21 | ## Reading JSON using the pull interface 22 | 23 | There are two ways to use the pull (DOM-like) interface of picojson. One is to use operator<<, and the other is by specifying a set of iterators specifying the range from where the JSON stream should be read. 24 | 25 |
 26 | picojson::value v;
 27 | std::cin >> v;
 28 | std::string err = picojson::get_last_error();
 29 | if (! err.empty()) {
 30 |   std::cerr << err << std::endl;
 31 | }
 32 | 
33 | 34 |
 35 | std::istream_iterator input(cin);
 36 | picojson::value v;
 37 | std::string err;
 38 | input = picojson::parse(v, input, std::istream_iterator(), &err);
 39 | if (! err.empty()) {
 40 |   std::cerr << err << std::endl;
 41 | }
 42 | 
43 | 44 |
 45 | const char* json = "{\"a\":1}";
 46 | picojson::value v;
 47 | std::string err;
 48 | picojson::parse(v, json, json + strlen(json), &err);
 49 | if (! err.empty()) {
 50 |   std::cerr << err << std::endl;
 51 | }
 52 | 
53 | 54 | ## Accessing the values 55 | 56 | Values of a JSON object is represented as instances of picojson::value class. 57 | 58 |
 59 | namespace picojson {
 60 | 
 61 |   class value {
 62 |     ...
 63 | 
 64 |   public:
 65 | 
 66 |     typedef std::vector<value> array;
 67 |     typedef std::map<std::string, value> object;
 68 | 
 69 |     value();                               // create a null object
 70 |     explicit value(bool b);                // create a boolean object
 71 |     explicit value(double n);              // create a number object
 72 |     explicit value(const std::string& s);  // create a string object
 73 |     explicit value(const array& a);        // create an array object
 74 |     explicit value(const object& o);       // create an "object"
 75 | 
 76 |     bool is<picojson::null>() const;       // check if the object is "null"
 77 | 
 78 |     bool is<bool>() const;                 // check if the object is a boolean
 79 |     const bool& get<bool>() const;         // const accessor (usable only if the object is a boolean)
 80 |     bool& get<bool>();                     // non-const accessor (usable only if the object is a boolean)
 81 | 
 82 |     bool is<double>() const;               // check if the object is a number
 83 |     const double& get<double>() const;     // const accessor (usable only if the object is a number)
 84 |     double& get<double>();                 // non-const accessor (usable only if the object is a number)
 85 | 
 86 |     bool is<std::string>() const;          // check if the object is a string
 87 |     const std::string& get<std::string>() const;
 88 |                                            // const accessor (usable only if the object is a string)
 89 |     std::string& get<std::string>();       // non-const accessor (usable only if the object is a string)
 90 | 
 91 |     bool is<array>() const;                // check if the object is an array
 92 |     const array& get<array>() const;       // const accessor (usable only if the object is an array)
 93 |     array& get<array>();                   // non-const accessor (usable only if the object is an array)
 94 | 
 95 |     bool is<object>() const;               // check if the object is an "object"
 96 |     const object& get<object>() const;     // const accessor (usable only if the object is an object)
 97 |     object& get<object>();                 // non-const accessor (usable only if the object is an array)
 98 | 
 99 |     bool evaluate_as_boolean() const;      // evaluates the object as a boolean
100 | 
101 |     std::string serialize() const;         // returns the object in JSON representation
102 |     template void serialize(Iter os) const;
103 |                                            // serializes the object in JSON representation through an output iterator
104 | 
105 |     std::string to_str() const;            // returns the object in string (for casual use)
106 | 
107 |   };
108 | 
109 | }
110 | 
111 | 112 | The code below parses a JSON string and prints the contents of the object. 113 | 114 |
115 | picojson::value v;
116 | 
117 | // parse the input
118 | std::cin >> v;
119 | std::string err = picojson::get_last_error();
120 | if (! err.empty()) {
121 |   std::cerr << err << std::endl;
122 |   exit(1);
123 | }
124 | 
125 | // check if the type of the value is "object"
126 | if (! v.is<picojson::object>()) {
127 |   std::cerr << "JSON is not an object" << std::endl;
128 |   exit(2);
129 | }
130 | 
131 | // obtain a const reference to the map, and print the contents
132 | const picojson::value::object& obj = v.get<picojson::object>();
133 | for (picojson::value::object::const_iterator i = obj.begin();
134 |      i != obj.end();
135 |      ++i) {
136 |   std::cout << i->first << ': ' << i->second.to_str() << std::endl;
137 | }
138 | 
139 | 140 | Please note that the type check is mandatory; do not forget to check the type of the object by calling is<type>() before accessing the value by calling get<type>(). 141 | 142 | ## Reading JSON using the streaming (event-driven) interface 143 | 144 | Please refer to the implementation of picojson::default_parse_context and picojson::null_parse_context. There is also an example (examples/streaming.cc) . 145 | 146 | ## Serializing to JSON 147 | 148 | Instances of the picojson::value class can be serialized in three ways, to ostream, to std::string, or to an output iterator. 149 | 150 |
151 | picojson::value v;
152 | ...
153 | std::cout << v;
154 | 
155 | 156 |
157 | picojson::value v;
158 | ...
159 | std::string json = v.serialize();
160 | 
161 | 162 |
163 | picojson::value v;
164 | ...
165 | v.serialize(std::ostream_iterator(std::cout));
166 | 
167 | 168 | ## Experimental support for int64_t 169 | 170 | Experimental suport for int64_t becomes available if the code is compiled with preprocessor macro `PICOJSON_USE_INT64`. 171 | 172 | Turning on the feature will cause following changes to picojson: 173 | - new constructor `picojson::value(int64_t)` is defined 174 | - `is()` and `get()` become available 175 | - numerics in JSON within the bounds of int64_t and not using `.` nor `e`/`E` are considered as int64 type 176 | - the values are also avaliable as `double`s as well (i.e. all values which are `.is() == true` are also `.is() == true`) 177 | - int64 values are converted to double once `get()` is called 178 | 179 | Enabling the feature should not cause compatibility problem with code that do not use the feature. 180 | 181 | ## Further reading 182 | 183 | Examples can be found in the examples directory, and on the [Wiki](https://github.com/kazuho/picojson/wiki). Please add your favorite examples to the Wiki. 184 | -------------------------------------------------------------------------------- /src/deps/picojson/examples/github-issues.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009-2010 Cybozu Labs, Inc. 3 | * Copyright 2011-2014 Kazuho Oku 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | #include 29 | #include "../picojson.h" 30 | 31 | typedef struct { 32 | char* data; // response data from server 33 | size_t size; // response size of data 34 | } MEMFILE; 35 | 36 | MEMFILE* 37 | memfopen() { 38 | MEMFILE* mf = (MEMFILE*) malloc(sizeof(MEMFILE)); 39 | mf->data = NULL; 40 | mf->size = 0; 41 | return mf; 42 | } 43 | 44 | void 45 | memfclose(MEMFILE* mf) { 46 | if (mf->data) free(mf->data); 47 | free(mf); 48 | } 49 | 50 | size_t 51 | memfwrite(char* ptr, size_t size, size_t nmemb, void* stream) { 52 | MEMFILE* mf = (MEMFILE*) stream; 53 | int block = size * nmemb; 54 | if (!mf->data) 55 | mf->data = (char*) malloc(block); 56 | else 57 | mf->data = (char*) realloc(mf->data, mf->size + block); 58 | if (mf->data) { 59 | memcpy(mf->data + mf->size, ptr, block); 60 | mf->size += block; 61 | } 62 | return block; 63 | } 64 | 65 | char* 66 | memfstrdup(MEMFILE* mf) { 67 | char* buf = (char*)malloc(mf->size + 1); 68 | memcpy(buf, mf->data, mf->size); 69 | buf[mf->size] = 0; 70 | return buf; 71 | } 72 | 73 | using namespace std; 74 | using namespace picojson; 75 | 76 | int 77 | main(int argc, char* argv[]) { 78 | char error[256]; 79 | 80 | MEMFILE* mf = memfopen(); 81 | CURL* curl = curl_easy_init(); 82 | curl_easy_setopt(curl, CURLOPT_URL, "https://api.github.com/repos/kazuho/picojson/issues"); 83 | curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); 84 | curl_easy_setopt(curl, CURLOPT_USERAGENT, "curl"); 85 | curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error); 86 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, memfwrite); 87 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, mf); 88 | if (curl_easy_perform(curl) != CURLE_OK) { 89 | cerr << error << endl; 90 | } else { 91 | value v; 92 | string err; 93 | parse(v, mf->data, mf->data + mf->size, &err); 94 | if (err.empty()) { 95 | array arr = v.get(); 96 | array::iterator it; 97 | for (it = arr.begin(); it != arr.end(); it++) { 98 | object obj = it->get(); 99 | cout << "#" << obj["number"].to_str() << ": " << obj["title"].to_str() << endl; 100 | cout << " " << obj["html_url"].to_str() << endl << endl; 101 | } 102 | } else { 103 | cerr << err << endl; 104 | } 105 | } 106 | curl_easy_cleanup(curl); 107 | memfclose(mf); 108 | 109 | return 0; 110 | } 111 | -------------------------------------------------------------------------------- /src/deps/picojson/examples/iostream.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009-2010 Cybozu Labs, Inc. 3 | * Copyright 2011-2014 Kazuho Oku 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | #include "../picojson.h" 29 | 30 | int main(void) 31 | { 32 | picojson::value v; 33 | 34 | // read json value from stream 35 | std::cin >> v; 36 | if (std::cin.fail()) { 37 | std::cerr << picojson::get_last_error() << std::endl; 38 | return 1; 39 | } 40 | 41 | // dump json object 42 | std::cout << "---- dump input ----" << std::endl; 43 | std::cout << v << std::endl; 44 | 45 | // accessors 46 | std::cout << "---- analyzing input ----" << std::endl; 47 | if (v.is()) { 48 | std::cout << "input is null" << std::endl; 49 | } else if (v.is()) { 50 | std::cout << "input is " << (v.get() ? "true" : "false") << std::endl; 51 | } else if (v.is()) { 52 | std::cout << "input is " << v.get() << std::endl; 53 | } else if (v.is()) { 54 | std::cout << "input is " << v.get() << std::endl; 55 | } else if (v.is()) { 56 | std::cout << "input is an array" << std::endl; 57 | const picojson::array& a = v.get(); 58 | for (picojson::array::const_iterator i = a.begin(); i != a.end(); ++i) { 59 | std::cout << " " << *i << std::endl; 60 | } 61 | } else if (v.is()) { 62 | std::cout << "input is an object" << std::endl; 63 | const picojson::object& o = v.get(); 64 | for (picojson::object::const_iterator i = o.begin(); i != o.end(); ++i) { 65 | std::cout << i->first << " " << i->second << std::endl; 66 | } 67 | } 68 | 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /src/deps/picojson/examples/streaming.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009-2010 Cybozu Labs, Inc. 3 | * Copyright 2011-2014 Kazuho Oku 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | #include 29 | #include 30 | #include "../picojson.h" 31 | 32 | // this example reads a array of hashes (each item representing a 2D point), 33 | // and prints the x and y values to stdout 34 | 35 | namespace { 36 | 37 | class root_context : public picojson::deny_parse_context { 38 | public: 39 | bool parse_array_start() { 40 | return true; // only allow array as root 41 | } 42 | template bool parse_array_item(picojson::input& in, size_t) { 43 | picojson::value item; 44 | // parse the array item 45 | picojson::default_parse_context ctx(&item); 46 | if (! picojson::_parse(ctx, in)) { 47 | return false; 48 | } 49 | // assert that the array item is a hash 50 | if (! item.is()) { 51 | return false; 52 | } 53 | // print x and y 54 | std::cout << item.get("x") << ',' << item.get("y").to_str() 55 | << std::endl; 56 | return true; 57 | } 58 | }; 59 | 60 | } 61 | 62 | int main(void) 63 | { 64 | root_context ctx; 65 | std::string err; 66 | 67 | picojson::_parse(ctx, std::istream_iterator(std::cin), 68 | std::istream_iterator(), &err); 69 | 70 | if (! err.empty()) { 71 | std::cerr << err << std::endl; 72 | return 1; 73 | } 74 | 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /src/deps/picojson/picojson.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009-2010 Cybozu Labs, Inc. 3 | * Copyright 2011-2014 Kazuho Oku 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | #ifndef picojson_h 29 | #define picojson_h 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | // for isnan/isinf 44 | #if __cplusplus>=201103L 45 | # include 46 | #else 47 | extern "C" { 48 | # ifdef _MSC_VER 49 | # include 50 | # elif defined(__INTEL_COMPILER) 51 | # include 52 | # else 53 | # include 54 | # endif 55 | } 56 | #endif 57 | 58 | // experimental support for int64_t (see README.mkdn for detail) 59 | #ifdef PICOJSON_USE_INT64 60 | # define __STDC_FORMAT_MACROS 61 | # include 62 | # include 63 | #endif 64 | 65 | // to disable the use of localeconv(3), set PICOJSON_USE_LOCALE to 0 66 | #ifndef PICOJSON_USE_LOCALE 67 | # define PICOJSON_USE_LOCALE 1 68 | #endif 69 | #if PICOJSON_USE_LOCALE 70 | extern "C" { 71 | # include 72 | } 73 | #endif 74 | 75 | #ifndef PICOJSON_ASSERT 76 | # define PICOJSON_ASSERT(e) do { if (! (e)) throw std::runtime_error(#e); } while (0) 77 | #endif 78 | 79 | #ifdef _MSC_VER 80 | #define SNPRINTF _snprintf_s 81 | #pragma warning(push) 82 | #pragma warning(disable : 4244) // conversion from int to char 83 | #pragma warning(disable : 4127) // conditional expression is constant 84 | #pragma warning(disable : 4702) // unreachable code 85 | #else 86 | #define SNPRINTF snprintf 87 | #endif 88 | 89 | namespace picojson { 90 | 91 | enum { 92 | null_type, 93 | boolean_type, 94 | number_type, 95 | string_type, 96 | array_type, 97 | object_type 98 | #ifdef PICOJSON_USE_INT64 99 | , int64_type 100 | #endif 101 | }; 102 | 103 | enum { 104 | INDENT_WIDTH = 2 105 | }; 106 | 107 | struct null {}; 108 | 109 | class value { 110 | public: 111 | typedef std::vector array; 112 | typedef std::map object; 113 | union _storage { 114 | bool boolean_; 115 | double number_; 116 | #ifdef PICOJSON_USE_INT64 117 | int64_t int64_; 118 | #endif 119 | std::string* string_; 120 | array* array_; 121 | object* object_; 122 | }; 123 | protected: 124 | int type_; 125 | _storage u_; 126 | public: 127 | value(); 128 | value(int type, bool); 129 | explicit value(bool b); 130 | #ifdef PICOJSON_USE_INT64 131 | explicit value(int64_t i); 132 | #endif 133 | explicit value(double n); 134 | explicit value(const std::string& s); 135 | explicit value(const array& a); 136 | explicit value(const object& o); 137 | explicit value(const char* s); 138 | value(const char* s, size_t len); 139 | ~value(); 140 | value(const value& x); 141 | value& operator=(const value& x); 142 | void swap(value& x); 143 | template bool is() const; 144 | template const T& get() const; 145 | template T& get(); 146 | bool evaluate_as_boolean() const; 147 | const value& get(size_t idx) const; 148 | const value& get(const std::string& key) const; 149 | value& get(size_t idx); 150 | value& get(const std::string& key); 151 | 152 | bool contains(size_t idx) const; 153 | bool contains(const std::string& key) const; 154 | std::string to_str() const; 155 | template void serialize(Iter os, bool prettify = false) const; 156 | std::string serialize(bool prettify = false) const; 157 | private: 158 | template value(const T*); // intentionally defined to block implicit conversion of pointer to bool 159 | template static void _indent(Iter os, int indent); 160 | template void _serialize(Iter os, int indent) const; 161 | std::string _serialize(int indent) const; 162 | }; 163 | 164 | typedef value::array array; 165 | typedef value::object object; 166 | 167 | inline value::value() : type_(null_type) {} 168 | 169 | inline value::value(int type, bool) : type_(type) { 170 | switch (type) { 171 | #define INIT(p, v) case p##type: u_.p = v; break 172 | INIT(boolean_, false); 173 | INIT(number_, 0.0); 174 | #ifdef PICOJSON_USE_INT64 175 | INIT(int64_, 0); 176 | #endif 177 | INIT(string_, new std::string()); 178 | INIT(array_, new array()); 179 | INIT(object_, new object()); 180 | #undef INIT 181 | default: break; 182 | } 183 | } 184 | 185 | inline value::value(bool b) : type_(boolean_type) { 186 | u_.boolean_ = b; 187 | } 188 | 189 | #ifdef PICOJSON_USE_INT64 190 | inline value::value(int64_t i) : type_(int64_type) { 191 | u_.int64_ = i; 192 | } 193 | #endif 194 | 195 | inline value::value(double n) : type_(number_type) { 196 | if ( 197 | #ifdef _MSC_VER 198 | ! _finite(n) 199 | #elif __cplusplus>=201103L || !(defined(isnan) && defined(isinf)) 200 | std::isnan(n) || std::isinf(n) 201 | #else 202 | isnan(n) || isinf(n) 203 | #endif 204 | ) { 205 | throw std::overflow_error(""); 206 | } 207 | u_.number_ = n; 208 | } 209 | 210 | inline value::value(const std::string& s) : type_(string_type) { 211 | u_.string_ = new std::string(s); 212 | } 213 | 214 | inline value::value(const array& a) : type_(array_type) { 215 | u_.array_ = new array(a); 216 | } 217 | 218 | inline value::value(const object& o) : type_(object_type) { 219 | u_.object_ = new object(o); 220 | } 221 | 222 | inline value::value(const char* s) : type_(string_type) { 223 | u_.string_ = new std::string(s); 224 | } 225 | 226 | inline value::value(const char* s, size_t len) : type_(string_type) { 227 | u_.string_ = new std::string(s, len); 228 | } 229 | 230 | inline value::~value() { 231 | switch (type_) { 232 | #define DEINIT(p) case p##type: delete u_.p; break 233 | DEINIT(string_); 234 | DEINIT(array_); 235 | DEINIT(object_); 236 | #undef DEINIT 237 | default: break; 238 | } 239 | } 240 | 241 | inline value::value(const value& x) : type_(x.type_) { 242 | switch (type_) { 243 | #define INIT(p, v) case p##type: u_.p = v; break 244 | INIT(string_, new std::string(*x.u_.string_)); 245 | INIT(array_, new array(*x.u_.array_)); 246 | INIT(object_, new object(*x.u_.object_)); 247 | #undef INIT 248 | default: 249 | u_ = x.u_; 250 | break; 251 | } 252 | } 253 | 254 | inline value& value::operator=(const value& x) { 255 | if (this != &x) { 256 | this->~value(); 257 | new (this) value(x); 258 | } 259 | return *this; 260 | } 261 | 262 | inline void value::swap(value& x) { 263 | std::swap(type_, x.type_); 264 | std::swap(u_, x.u_); 265 | } 266 | 267 | #define IS(ctype, jtype) \ 268 | template <> inline bool value::is() const { \ 269 | return type_ == jtype##_type; \ 270 | } 271 | IS(null, null) 272 | IS(bool, boolean) 273 | #ifdef PICOJSON_USE_INT64 274 | IS(int64_t, int64) 275 | #endif 276 | IS(std::string, string) 277 | IS(array, array) 278 | IS(object, object) 279 | #undef IS 280 | template <> inline bool value::is() const { 281 | return type_ == number_type 282 | #ifdef PICOJSON_USE_INT64 283 | || type_ == int64_type 284 | #endif 285 | ; 286 | } 287 | 288 | #define GET(ctype, var) \ 289 | template <> inline const ctype& value::get() const { \ 290 | PICOJSON_ASSERT("type mismatch! call is() before get()" \ 291 | && is()); \ 292 | return var; \ 293 | } \ 294 | template <> inline ctype& value::get() { \ 295 | PICOJSON_ASSERT("type mismatch! call is() before get()" \ 296 | && is()); \ 297 | return var; \ 298 | } 299 | GET(bool, u_.boolean_) 300 | GET(std::string, *u_.string_) 301 | GET(array, *u_.array_) 302 | GET(object, *u_.object_) 303 | #ifdef PICOJSON_USE_INT64 304 | GET(double, (type_ == int64_type && (const_cast(this)->type_ = number_type, const_cast(this)->u_.number_ = u_.int64_), u_.number_)) 305 | GET(int64_t, u_.int64_) 306 | #else 307 | GET(double, u_.number_) 308 | #endif 309 | #undef GET 310 | 311 | inline bool value::evaluate_as_boolean() const { 312 | switch (type_) { 313 | case null_type: 314 | return false; 315 | case boolean_type: 316 | return u_.boolean_; 317 | case number_type: 318 | return u_.number_ != 0; 319 | case string_type: 320 | return ! u_.string_->empty(); 321 | default: 322 | return true; 323 | } 324 | } 325 | 326 | inline const value& value::get(size_t idx) const { 327 | static value s_null; 328 | PICOJSON_ASSERT(is()); 329 | return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null; 330 | } 331 | 332 | inline value& value::get(size_t idx) { 333 | static value s_null; 334 | PICOJSON_ASSERT(is()); 335 | return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null; 336 | } 337 | 338 | inline const value& value::get(const std::string& key) const { 339 | static value s_null; 340 | PICOJSON_ASSERT(is()); 341 | object::const_iterator i = u_.object_->find(key); 342 | return i != u_.object_->end() ? i->second : s_null; 343 | } 344 | 345 | inline value& value::get(const std::string& key) { 346 | static value s_null; 347 | PICOJSON_ASSERT(is()); 348 | object::iterator i = u_.object_->find(key); 349 | return i != u_.object_->end() ? i->second : s_null; 350 | } 351 | 352 | inline bool value::contains(size_t idx) const { 353 | PICOJSON_ASSERT(is()); 354 | return idx < u_.array_->size(); 355 | } 356 | 357 | inline bool value::contains(const std::string& key) const { 358 | PICOJSON_ASSERT(is()); 359 | object::const_iterator i = u_.object_->find(key); 360 | return i != u_.object_->end(); 361 | } 362 | 363 | inline std::string value::to_str() const { 364 | switch (type_) { 365 | case null_type: return "null"; 366 | case boolean_type: return u_.boolean_ ? "true" : "false"; 367 | #ifdef PICOJSON_USE_INT64 368 | case int64_type: { 369 | char buf[sizeof("-9223372036854775808")]; 370 | SNPRINTF(buf, sizeof(buf), "%" PRId64, u_.int64_); 371 | return buf; 372 | } 373 | #endif 374 | case number_type: { 375 | char buf[256]; 376 | double tmp; 377 | SNPRINTF(buf, sizeof(buf), fabs(u_.number_) < (1ULL << 53) && modf(u_.number_, &tmp) == 0 ? "%.f" : "%.4g", u_.number_); 378 | #if PICOJSON_USE_LOCALE 379 | char *decimal_point = localeconv()->decimal_point; 380 | if (strcmp(decimal_point, ".") != 0) { 381 | size_t decimal_point_len = strlen(decimal_point); 382 | for (char *p = buf; *p != '\0'; ++p) { 383 | if (strncmp(p, decimal_point, decimal_point_len) == 0) { 384 | return std::string(buf, p) + "." + (p + decimal_point_len); 385 | } 386 | } 387 | } 388 | #endif 389 | return buf; 390 | } 391 | case string_type: return *u_.string_; 392 | case array_type: return "array"; 393 | case object_type: return "object"; 394 | default: PICOJSON_ASSERT(0); 395 | #ifdef _MSC_VER 396 | __assume(0); 397 | #endif 398 | } 399 | return std::string(); 400 | } 401 | 402 | template void copy(const std::string& s, Iter oi) { 403 | std::copy(s.begin(), s.end(), oi); 404 | } 405 | 406 | template void serialize_str(const std::string& s, Iter oi) { 407 | *oi++ = '"'; 408 | for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) { 409 | switch (*i) { 410 | #define MAP(val, sym) case val: copy(sym, oi); break 411 | MAP('"', "\\\""); 412 | MAP('\\', "\\\\"); 413 | MAP('/', "\\/"); 414 | MAP('\b', "\\b"); 415 | MAP('\f', "\\f"); 416 | MAP('\n', "\\n"); 417 | MAP('\r', "\\r"); 418 | MAP('\t', "\\t"); 419 | #undef MAP 420 | default: 421 | if (static_cast(*i) < 0x20 || *i == 0x7f) { 422 | char buf[7]; 423 | SNPRINTF(buf, sizeof(buf), "\\u%04x", *i & 0xff); 424 | copy(buf, buf + 6, oi); 425 | } else { 426 | *oi++ = *i; 427 | } 428 | break; 429 | } 430 | } 431 | *oi++ = '"'; 432 | } 433 | 434 | template void value::serialize(Iter oi, bool prettify) const { 435 | return _serialize(oi, prettify ? 0 : -1); 436 | } 437 | 438 | inline std::string value::serialize(bool prettify) const { 439 | return _serialize(prettify ? 0 : -1); 440 | } 441 | 442 | template void value::_indent(Iter oi, int indent) { 443 | *oi++ = '\n'; 444 | for (int i = 0; i < indent * INDENT_WIDTH; ++i) { 445 | *oi++ = ' '; 446 | } 447 | } 448 | 449 | template void value::_serialize(Iter oi, int indent) const { 450 | switch (type_) { 451 | case string_type: 452 | serialize_str(*u_.string_, oi); 453 | break; 454 | case array_type: { 455 | *oi++ = '['; 456 | if (indent != -1) { 457 | ++indent; 458 | } 459 | for (array::const_iterator i = u_.array_->begin(); 460 | i != u_.array_->end(); 461 | ++i) { 462 | if (i != u_.array_->begin()) { 463 | *oi++ = ','; 464 | } 465 | if (indent != -1) { 466 | _indent(oi, indent); 467 | } 468 | i->_serialize(oi, indent); 469 | } 470 | if (indent != -1) { 471 | --indent; 472 | if (! u_.array_->empty()) { 473 | _indent(oi, indent); 474 | } 475 | } 476 | *oi++ = ']'; 477 | break; 478 | } 479 | case object_type: { 480 | *oi++ = '{'; 481 | if (indent != -1) { 482 | ++indent; 483 | } 484 | for (object::const_iterator i = u_.object_->begin(); 485 | i != u_.object_->end(); 486 | ++i) { 487 | if (i != u_.object_->begin()) { 488 | *oi++ = ','; 489 | } 490 | if (indent != -1) { 491 | _indent(oi, indent); 492 | } 493 | serialize_str(i->first, oi); 494 | *oi++ = ':'; 495 | if (indent != -1) { 496 | *oi++ = ' '; 497 | } 498 | i->second._serialize(oi, indent); 499 | } 500 | if (indent != -1) { 501 | --indent; 502 | if (! u_.object_->empty()) { 503 | _indent(oi, indent); 504 | } 505 | } 506 | *oi++ = '}'; 507 | break; 508 | } 509 | default: 510 | copy(to_str(), oi); 511 | break; 512 | } 513 | if (indent == 0) { 514 | *oi++ = '\n'; 515 | } 516 | } 517 | 518 | inline std::string value::_serialize(int indent) const { 519 | std::string s; 520 | _serialize(std::back_inserter(s), indent); 521 | return s; 522 | } 523 | 524 | template class input { 525 | protected: 526 | Iter cur_, end_; 527 | int last_ch_; 528 | bool ungot_; 529 | int line_; 530 | public: 531 | input(const Iter& first, const Iter& last) : cur_(first), end_(last), last_ch_(-1), ungot_(false), line_(1) {} 532 | int getc() { 533 | if (ungot_) { 534 | ungot_ = false; 535 | return last_ch_; 536 | } 537 | if (cur_ == end_) { 538 | last_ch_ = -1; 539 | return -1; 540 | } 541 | if (last_ch_ == '\n') { 542 | line_++; 543 | } 544 | last_ch_ = *cur_ & 0xff; 545 | ++cur_; 546 | return last_ch_; 547 | } 548 | void ungetc() { 549 | if (last_ch_ != -1) { 550 | PICOJSON_ASSERT(! ungot_); 551 | ungot_ = true; 552 | } 553 | } 554 | Iter cur() const { return cur_; } 555 | int line() const { return line_; } 556 | void skip_ws() { 557 | while (1) { 558 | int ch = getc(); 559 | if (! (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')) { 560 | ungetc(); 561 | break; 562 | } 563 | } 564 | } 565 | bool expect(int expect) { 566 | skip_ws(); 567 | if (getc() != expect) { 568 | ungetc(); 569 | return false; 570 | } 571 | return true; 572 | } 573 | bool match(const std::string& pattern) { 574 | for (std::string::const_iterator pi(pattern.begin()); 575 | pi != pattern.end(); 576 | ++pi) { 577 | if (getc() != *pi) { 578 | ungetc(); 579 | return false; 580 | } 581 | } 582 | return true; 583 | } 584 | }; 585 | 586 | template inline int _parse_quadhex(input &in) { 587 | int uni_ch = 0, hex; 588 | for (int i = 0; i < 4; i++) { 589 | if ((hex = in.getc()) == -1) { 590 | return -1; 591 | } 592 | if ('0' <= hex && hex <= '9') { 593 | hex -= '0'; 594 | } else if ('A' <= hex && hex <= 'F') { 595 | hex -= 'A' - 0xa; 596 | } else if ('a' <= hex && hex <= 'f') { 597 | hex -= 'a' - 0xa; 598 | } else { 599 | in.ungetc(); 600 | return -1; 601 | } 602 | uni_ch = uni_ch * 16 + hex; 603 | } 604 | return uni_ch; 605 | } 606 | 607 | template inline bool _parse_codepoint(String& out, input& in) { 608 | int uni_ch; 609 | if ((uni_ch = _parse_quadhex(in)) == -1) { 610 | return false; 611 | } 612 | if (0xd800 <= uni_ch && uni_ch <= 0xdfff) { 613 | if (0xdc00 <= uni_ch) { 614 | // a second 16-bit of a surrogate pair appeared 615 | return false; 616 | } 617 | // first 16-bit of surrogate pair, get the next one 618 | if (in.getc() != '\\' || in.getc() != 'u') { 619 | in.ungetc(); 620 | return false; 621 | } 622 | int second = _parse_quadhex(in); 623 | if (! (0xdc00 <= second && second <= 0xdfff)) { 624 | return false; 625 | } 626 | uni_ch = ((uni_ch - 0xd800) << 10) | ((second - 0xdc00) & 0x3ff); 627 | uni_ch += 0x10000; 628 | } 629 | if (uni_ch < 0x80) { 630 | out.push_back(uni_ch); 631 | } else { 632 | if (uni_ch < 0x800) { 633 | out.push_back(0xc0 | (uni_ch >> 6)); 634 | } else { 635 | if (uni_ch < 0x10000) { 636 | out.push_back(0xe0 | (uni_ch >> 12)); 637 | } else { 638 | out.push_back(0xf0 | (uni_ch >> 18)); 639 | out.push_back(0x80 | ((uni_ch >> 12) & 0x3f)); 640 | } 641 | out.push_back(0x80 | ((uni_ch >> 6) & 0x3f)); 642 | } 643 | out.push_back(0x80 | (uni_ch & 0x3f)); 644 | } 645 | return true; 646 | } 647 | 648 | template inline bool _parse_string(String& out, input& in) { 649 | while (1) { 650 | int ch = in.getc(); 651 | if (ch < ' ') { 652 | in.ungetc(); 653 | return false; 654 | } else if (ch == '"') { 655 | return true; 656 | } else if (ch == '\\') { 657 | if ((ch = in.getc()) == -1) { 658 | return false; 659 | } 660 | switch (ch) { 661 | #define MAP(sym, val) case sym: out.push_back(val); break 662 | MAP('"', '\"'); 663 | MAP('\\', '\\'); 664 | MAP('/', '/'); 665 | MAP('b', '\b'); 666 | MAP('f', '\f'); 667 | MAP('n', '\n'); 668 | MAP('r', '\r'); 669 | MAP('t', '\t'); 670 | #undef MAP 671 | case 'u': 672 | if (! _parse_codepoint(out, in)) { 673 | return false; 674 | } 675 | break; 676 | default: 677 | return false; 678 | } 679 | } else { 680 | out.push_back(ch); 681 | } 682 | } 683 | return false; 684 | } 685 | 686 | template inline bool _parse_array(Context& ctx, input& in) { 687 | if (! ctx.parse_array_start()) { 688 | return false; 689 | } 690 | size_t idx = 0; 691 | if (in.expect(']')) { 692 | return ctx.parse_array_stop(idx); 693 | } 694 | do { 695 | if (! ctx.parse_array_item(in, idx)) { 696 | return false; 697 | } 698 | idx++; 699 | } while (in.expect(',')); 700 | return in.expect(']') && ctx.parse_array_stop(idx); 701 | } 702 | 703 | template inline bool _parse_object(Context& ctx, input& in) { 704 | if (! ctx.parse_object_start()) { 705 | return false; 706 | } 707 | if (in.expect('}')) { 708 | return true; 709 | } 710 | do { 711 | std::string key; 712 | if (! in.expect('"') 713 | || ! _parse_string(key, in) 714 | || ! in.expect(':')) { 715 | return false; 716 | } 717 | if (! ctx.parse_object_item(in, key)) { 718 | return false; 719 | } 720 | } while (in.expect(',')); 721 | return in.expect('}'); 722 | } 723 | 724 | template inline std::string _parse_number(input& in) { 725 | std::string num_str; 726 | while (1) { 727 | int ch = in.getc(); 728 | if (('0' <= ch && ch <= '9') || ch == '+' || ch == '-' 729 | || ch == 'e' || ch == 'E') { 730 | num_str.push_back(ch); 731 | } else if (ch == '.') { 732 | #if PICOJSON_USE_LOCALE 733 | num_str += localeconv()->decimal_point; 734 | #else 735 | num_str.push_back('.'); 736 | #endif 737 | } else { 738 | in.ungetc(); 739 | break; 740 | } 741 | } 742 | return num_str; 743 | } 744 | 745 | template inline bool _parse(Context& ctx, input& in) { 746 | in.skip_ws(); 747 | int ch = in.getc(); 748 | switch (ch) { 749 | #define IS(ch, text, op) case ch: \ 750 | if (in.match(text) && op) { \ 751 | return true; \ 752 | } else { \ 753 | return false; \ 754 | } 755 | IS('n', "ull", ctx.set_null()); 756 | IS('f', "alse", ctx.set_bool(false)); 757 | IS('t', "rue", ctx.set_bool(true)); 758 | #undef IS 759 | case '"': 760 | return ctx.parse_string(in); 761 | case '[': 762 | return _parse_array(ctx, in); 763 | case '{': 764 | return _parse_object(ctx, in); 765 | default: 766 | if (('0' <= ch && ch <= '9') || ch == '-') { 767 | double f; 768 | char *endp; 769 | in.ungetc(); 770 | std::string num_str = _parse_number(in); 771 | if (num_str.empty()) { 772 | return false; 773 | } 774 | #ifdef PICOJSON_USE_INT64 775 | { 776 | errno = 0; 777 | intmax_t ival = strtoimax(num_str.c_str(), &endp, 10); 778 | if (errno == 0 779 | && std::numeric_limits::min() <= ival 780 | && ival <= std::numeric_limits::max() 781 | && endp == num_str.c_str() + num_str.size()) { 782 | ctx.set_int64(ival); 783 | return true; 784 | } 785 | } 786 | #endif 787 | f = strtod(num_str.c_str(), &endp); 788 | if (endp == num_str.c_str() + num_str.size()) { 789 | ctx.set_number(f); 790 | return true; 791 | } 792 | return false; 793 | } 794 | break; 795 | } 796 | in.ungetc(); 797 | return false; 798 | } 799 | 800 | class deny_parse_context { 801 | public: 802 | bool set_null() { return false; } 803 | bool set_bool(bool) { return false; } 804 | #ifdef PICOJSON_USE_INT64 805 | bool set_int64(int64_t) { return false; } 806 | #endif 807 | bool set_number(double) { return false; } 808 | template bool parse_string(input&) { return false; } 809 | bool parse_array_start() { return false; } 810 | template bool parse_array_item(input&, size_t) { 811 | return false; 812 | } 813 | bool parse_array_stop(size_t) { return false; } 814 | bool parse_object_start() { return false; } 815 | template bool parse_object_item(input&, const std::string&) { 816 | return false; 817 | } 818 | }; 819 | 820 | class default_parse_context { 821 | protected: 822 | value* out_; 823 | public: 824 | default_parse_context(value* out) : out_(out) {} 825 | bool set_null() { 826 | *out_ = value(); 827 | return true; 828 | } 829 | bool set_bool(bool b) { 830 | *out_ = value(b); 831 | return true; 832 | } 833 | #ifdef PICOJSON_USE_INT64 834 | bool set_int64(int64_t i) { 835 | *out_ = value(i); 836 | return true; 837 | } 838 | #endif 839 | bool set_number(double f) { 840 | *out_ = value(f); 841 | return true; 842 | } 843 | template bool parse_string(input& in) { 844 | *out_ = value(string_type, false); 845 | return _parse_string(out_->get(), in); 846 | } 847 | bool parse_array_start() { 848 | *out_ = value(array_type, false); 849 | return true; 850 | } 851 | template bool parse_array_item(input& in, size_t) { 852 | array& a = out_->get(); 853 | a.push_back(value()); 854 | default_parse_context ctx(&a.back()); 855 | return _parse(ctx, in); 856 | } 857 | bool parse_array_stop(size_t) { return true; } 858 | bool parse_object_start() { 859 | *out_ = value(object_type, false); 860 | return true; 861 | } 862 | template bool parse_object_item(input& in, const std::string& key) { 863 | object& o = out_->get(); 864 | default_parse_context ctx(&o[key]); 865 | return _parse(ctx, in); 866 | } 867 | private: 868 | default_parse_context(const default_parse_context&); 869 | default_parse_context& operator=(const default_parse_context&); 870 | }; 871 | 872 | class null_parse_context { 873 | public: 874 | struct dummy_str { 875 | void push_back(int) {} 876 | }; 877 | public: 878 | null_parse_context() {} 879 | bool set_null() { return true; } 880 | bool set_bool(bool) { return true; } 881 | #ifdef PICOJSON_USE_INT64 882 | bool set_int64(int64_t) { return true; } 883 | #endif 884 | bool set_number(double) { return true; } 885 | template bool parse_string(input& in) { 886 | dummy_str s; 887 | return _parse_string(s, in); 888 | } 889 | bool parse_array_start() { return true; } 890 | template bool parse_array_item(input& in, size_t) { 891 | return _parse(*this, in); 892 | } 893 | bool parse_array_stop(size_t) { return true; } 894 | bool parse_object_start() { return true; } 895 | template bool parse_object_item(input& in, const std::string&) { 896 | return _parse(*this, in); 897 | } 898 | private: 899 | null_parse_context(const null_parse_context&); 900 | null_parse_context& operator=(const null_parse_context&); 901 | }; 902 | 903 | // obsolete, use the version below 904 | template inline std::string parse(value& out, Iter& pos, const Iter& last) { 905 | std::string err; 906 | pos = parse(out, pos, last, &err); 907 | return err; 908 | } 909 | 910 | template inline Iter _parse(Context& ctx, const Iter& first, const Iter& last, std::string* err) { 911 | input in(first, last); 912 | if (! _parse(ctx, in) && err != NULL) { 913 | char buf[64]; 914 | SNPRINTF(buf, sizeof(buf), "syntax error at line %d near: ", in.line()); 915 | *err = buf; 916 | while (1) { 917 | int ch = in.getc(); 918 | if (ch == -1 || ch == '\n') { 919 | break; 920 | } else if (ch >= ' ') { 921 | err->push_back(ch); 922 | } 923 | } 924 | } 925 | return in.cur(); 926 | } 927 | 928 | template inline Iter parse(value& out, const Iter& first, const Iter& last, std::string* err) { 929 | default_parse_context ctx(&out); 930 | return _parse(ctx, first, last, err); 931 | } 932 | 933 | inline std::string parse(value& out, std::istream& is) { 934 | std::string err; 935 | parse(out, std::istreambuf_iterator(is.rdbuf()), 936 | std::istreambuf_iterator(), &err); 937 | return err; 938 | } 939 | 940 | template struct last_error_t { 941 | static std::string s; 942 | }; 943 | template std::string last_error_t::s; 944 | 945 | inline void set_last_error(const std::string& s) { 946 | last_error_t::s = s; 947 | } 948 | 949 | inline const std::string& get_last_error() { 950 | return last_error_t::s; 951 | } 952 | 953 | inline bool operator==(const value& x, const value& y) { 954 | if (x.is()) 955 | return y.is(); 956 | #define PICOJSON_CMP(type) \ 957 | if (x.is()) \ 958 | return y.is() && x.get() == y.get() 959 | PICOJSON_CMP(bool); 960 | PICOJSON_CMP(double); 961 | PICOJSON_CMP(std::string); 962 | PICOJSON_CMP(array); 963 | PICOJSON_CMP(object); 964 | #undef PICOJSON_CMP 965 | PICOJSON_ASSERT(0); 966 | #ifdef _MSC_VER 967 | __assume(0); 968 | #endif 969 | return false; 970 | } 971 | 972 | inline bool operator!=(const value& x, const value& y) { 973 | return ! (x == y); 974 | } 975 | } 976 | 977 | namespace std { 978 | template<> inline void swap(picojson::value& x, picojson::value& y) 979 | { 980 | x.swap(y); 981 | } 982 | } 983 | 984 | inline std::istream& operator>>(std::istream& is, picojson::value& x) 985 | { 986 | picojson::set_last_error(std::string()); 987 | std::string err = picojson::parse(x, is); 988 | if (! err.empty()) { 989 | picojson::set_last_error(err); 990 | is.setstate(std::ios::failbit); 991 | } 992 | return is; 993 | } 994 | 995 | inline std::ostream& operator<<(std::ostream& os, const picojson::value& x) 996 | { 997 | x.serialize(std::ostream_iterator(os)); 998 | return os; 999 | } 1000 | #ifdef _MSC_VER 1001 | #pragma warning(pop) 1002 | #endif 1003 | 1004 | #endif 1005 | #ifdef TEST_PICOJSON 1006 | #ifdef _MSC_VER 1007 | #pragma warning(disable : 4127) // conditional expression is constant 1008 | #endif 1009 | 1010 | using namespace std; 1011 | 1012 | static bool success = true; 1013 | static int test_num = 0; 1014 | 1015 | static void ok(bool b, const char* name = "") 1016 | { 1017 | if (! b) 1018 | success = false; 1019 | printf("%s %d - %s\n", b ? "ok" : "ng", ++test_num, name); 1020 | } 1021 | 1022 | static void done_testing() 1023 | { 1024 | printf("1..%d\n", test_num); 1025 | } 1026 | 1027 | template void is(const T& x, const T& y, const char* name = "") 1028 | { 1029 | if (x == y) { 1030 | ok(true, name); 1031 | } else { 1032 | ok(false, name); 1033 | } 1034 | } 1035 | 1036 | #include 1037 | #include 1038 | #include 1039 | #include 1040 | 1041 | int main(void) 1042 | { 1043 | #if PICOJSON_USE_LOCALE 1044 | setlocale(LC_ALL, ""); 1045 | #endif 1046 | 1047 | // constructors 1048 | #define TEST(expr, expected) \ 1049 | is(picojson::value expr .serialize(), string(expected), "picojson::value" #expr) 1050 | 1051 | TEST( (true), "true"); 1052 | TEST( (false), "false"); 1053 | TEST( (42.0), "42"); 1054 | TEST( (string("hello")), "\"hello\""); 1055 | TEST( ("hello"), "\"hello\""); 1056 | TEST( ("hello", 4), "\"hell\""); 1057 | 1058 | { 1059 | double a = 1; 1060 | for (int i = 0; i < 1024; i++) { 1061 | picojson::value vi(a); 1062 | std::stringstream ss; 1063 | ss << vi; 1064 | picojson::value vo; 1065 | ss >> vo; 1066 | double b = vo.get(); 1067 | if ((i < 53 && a != b) || fabs(a - b) / b > 1e-8) { 1068 | printf("ng i=%d a=%.18e b=%.18e\n", i, a, b); 1069 | } 1070 | a *= 2; 1071 | } 1072 | } 1073 | 1074 | #undef TEST 1075 | 1076 | #define TEST(in, type, cmp, serialize_test) { \ 1077 | picojson::value v; \ 1078 | const char* s = in; \ 1079 | string err = picojson::parse(v, s, s + strlen(s)); \ 1080 | ok(err.empty(), in " no error"); \ 1081 | ok(v.is(), in " check type"); \ 1082 | is(v.get(), cmp, in " correct output"); \ 1083 | is(*s, '\0', in " read to eof"); \ 1084 | if (serialize_test) { \ 1085 | is(v.serialize(), string(in), in " serialize"); \ 1086 | } \ 1087 | } 1088 | TEST("false", bool, false, true); 1089 | TEST("true", bool, true, true); 1090 | TEST("90.5", double, 90.5, false); 1091 | TEST("1.7976931348623157e+308", double, DBL_MAX, false); 1092 | TEST("\"hello\"", string, string("hello"), true); 1093 | TEST("\"\\\"\\\\\\/\\b\\f\\n\\r\\t\"", string, string("\"\\/\b\f\n\r\t"), 1094 | true); 1095 | TEST("\"\\u0061\\u30af\\u30ea\\u30b9\"", string, 1096 | string("a\xe3\x82\xaf\xe3\x83\xaa\xe3\x82\xb9"), false); 1097 | TEST("\"\\ud840\\udc0b\"", string, string("\xf0\xa0\x80\x8b"), false); 1098 | #ifdef PICOJSON_USE_INT64 1099 | TEST("0", int64_t, 0, true); 1100 | TEST("-9223372036854775808", int64_t, std::numeric_limits::min(), true); 1101 | TEST("9223372036854775807", int64_t, std::numeric_limits::max(), true); 1102 | #endif 1103 | #undef TEST 1104 | 1105 | #define TEST(type, expr) { \ 1106 | picojson::value v; \ 1107 | const char *s = expr; \ 1108 | string err = picojson::parse(v, s, s + strlen(s)); \ 1109 | ok(err.empty(), "empty " #type " no error"); \ 1110 | ok(v.is(), "empty " #type " check type"); \ 1111 | ok(v.get().empty(), "check " #type " array size"); \ 1112 | } 1113 | TEST(array, "[]"); 1114 | TEST(object, "{}"); 1115 | #undef TEST 1116 | 1117 | { 1118 | picojson::value v; 1119 | const char *s = "[1,true,\"hello\"]"; 1120 | string err = picojson::parse(v, s, s + strlen(s)); 1121 | ok(err.empty(), "array no error"); 1122 | ok(v.is(), "array check type"); 1123 | is(v.get().size(), size_t(3), "check array size"); 1124 | ok(v.contains(0), "check contains array[0]"); 1125 | ok(v.get(0).is(), "check array[0] type"); 1126 | is(v.get(0).get(), 1.0, "check array[0] value"); 1127 | ok(v.contains(1), "check contains array[1]"); 1128 | ok(v.get(1).is(), "check array[1] type"); 1129 | ok(v.get(1).get(), "check array[1] value"); 1130 | ok(v.contains(2), "check contains array[2]"); 1131 | ok(v.get(2).is(), "check array[2] type"); 1132 | is(v.get(2).get(), string("hello"), "check array[2] value"); 1133 | ok(!v.contains(3), "check not contains array[3]"); 1134 | } 1135 | 1136 | { 1137 | picojson::value v; 1138 | const char *s = "{ \"a\": true }"; 1139 | string err = picojson::parse(v, s, s + strlen(s)); 1140 | ok(err.empty(), "object no error"); 1141 | ok(v.is(), "object check type"); 1142 | is(v.get().size(), size_t(1), "check object size"); 1143 | ok(v.contains("a"), "check contains property"); 1144 | ok(v.get("a").is(), "check bool property exists"); 1145 | is(v.get("a").get(), true, "check bool property value"); 1146 | is(v.serialize(), string("{\"a\":true}"), "serialize object"); 1147 | ok(!v.contains("z"), "check not contains property"); 1148 | } 1149 | 1150 | #define TEST(json, msg) do { \ 1151 | picojson::value v; \ 1152 | const char *s = json; \ 1153 | string err = picojson::parse(v, s, s + strlen(s)); \ 1154 | is(err, string("syntax error at line " msg), msg); \ 1155 | } while (0) 1156 | TEST("falsoa", "1 near: oa"); 1157 | TEST("{]", "1 near: ]"); 1158 | TEST("\n\bbell", "2 near: bell"); 1159 | TEST("\"abc\nd\"", "1 near: "); 1160 | #undef TEST 1161 | 1162 | { 1163 | picojson::value v1, v2; 1164 | const char *s; 1165 | string err; 1166 | s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }"; 1167 | err = picojson::parse(v1, s, s + strlen(s)); 1168 | s = "{ \"d\": 2.0, \"b\": true, \"a\": [1,2,\"three\"] }"; 1169 | err = picojson::parse(v2, s, s + strlen(s)); 1170 | ok((v1 == v2), "check == operator in deep comparison"); 1171 | } 1172 | 1173 | { 1174 | picojson::value v1, v2; 1175 | const char *s; 1176 | string err; 1177 | s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }"; 1178 | err = picojson::parse(v1, s, s + strlen(s)); 1179 | s = "{ \"d\": 2.0, \"a\": [1,\"three\"], \"b\": true }"; 1180 | err = picojson::parse(v2, s, s + strlen(s)); 1181 | ok((v1 != v2), "check != operator for array in deep comparison"); 1182 | } 1183 | 1184 | { 1185 | picojson::value v1, v2; 1186 | const char *s; 1187 | string err; 1188 | s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }"; 1189 | err = picojson::parse(v1, s, s + strlen(s)); 1190 | s = "{ \"d\": 2.0, \"a\": [1,2,\"three\"], \"b\": false }"; 1191 | err = picojson::parse(v2, s, s + strlen(s)); 1192 | ok((v1 != v2), "check != operator for object in deep comparison"); 1193 | } 1194 | 1195 | { 1196 | picojson::value v1, v2; 1197 | const char *s; 1198 | string err; 1199 | s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }"; 1200 | err = picojson::parse(v1, s, s + strlen(s)); 1201 | picojson::object& o = v1.get(); 1202 | o.erase("b"); 1203 | picojson::array& a = o["a"].get(); 1204 | picojson::array::iterator i; 1205 | i = std::remove(a.begin(), a.end(), picojson::value(std::string("three"))); 1206 | a.erase(i, a.end()); 1207 | s = "{ \"a\": [1,2], \"d\": 2 }"; 1208 | err = picojson::parse(v2, s, s + strlen(s)); 1209 | ok((v1 == v2), "check erase()"); 1210 | } 1211 | 1212 | ok(picojson::value(3.0).serialize() == "3", 1213 | "integral number should be serialized as a integer"); 1214 | 1215 | { 1216 | const char* s = "{ \"a\": [1,2], \"d\": 2 }"; 1217 | picojson::null_parse_context ctx; 1218 | string err; 1219 | picojson::_parse(ctx, s, s + strlen(s), &err); 1220 | ok(err.empty(), "null_parse_context"); 1221 | } 1222 | 1223 | { 1224 | picojson::value v1, v2; 1225 | v1 = picojson::value(true); 1226 | swap(v1, v2); 1227 | ok(v1.is(), "swap (null)"); 1228 | ok(v2.get() == true, "swap (bool)"); 1229 | 1230 | v1 = picojson::value("a"); 1231 | v2 = picojson::value(1.0); 1232 | swap(v1, v2); 1233 | ok(v1.get() == 1.0, "swap (dobule)"); 1234 | ok(v2.get() == "a", "swap (string)"); 1235 | 1236 | v1 = picojson::value(picojson::object()); 1237 | v2 = picojson::value(picojson::array()); 1238 | swap(v1, v2); 1239 | ok(v1.is(), "swap (array)"); 1240 | ok(v2.is(), "swap (object)"); 1241 | } 1242 | 1243 | { 1244 | picojson::value v; 1245 | const char *s = "{ \"a\": 1, \"b\": [ 2, { \"b1\": \"abc\" } ], \"c\": {}, \"d\": [] }"; 1246 | string err; 1247 | err = picojson::parse(v, s, s + strlen(s)); 1248 | ok(err.empty(), "parse test data for prettifying output"); 1249 | ok(v.serialize() == "{\"a\":1,\"b\":[2,{\"b1\":\"abc\"}],\"c\":{},\"d\":[]}", "non-prettifying output"); 1250 | ok(v.serialize(true) == "{\n \"a\": 1,\n \"b\": [\n 2,\n {\n \"b1\": \"abc\"\n }\n ],\n \"c\": {},\n \"d\": []\n}\n", "prettifying output"); 1251 | } 1252 | 1253 | try { 1254 | picojson::value v(std::numeric_limits::quiet_NaN()); 1255 | ok(false, "should not accept NaN"); 1256 | } catch (std::overflow_error e) { 1257 | ok(true, "should not accept NaN"); 1258 | } 1259 | 1260 | try { 1261 | picojson::value v(std::numeric_limits::infinity()); 1262 | ok(false, "should not accept infinity"); 1263 | } catch (std::overflow_error e) { 1264 | ok(true, "should not accept infinity"); 1265 | } 1266 | 1267 | try { 1268 | picojson::value v(123.); 1269 | ok(! v.is(), "is() should return false"); 1270 | v.get(); 1271 | ok(false, "get() should raise an error"); 1272 | } catch (std::runtime_error e) { 1273 | ok(true, "get() should raise an error"); 1274 | } 1275 | 1276 | #ifdef PICOJSON_USE_INT64 1277 | { 1278 | picojson::value v1((int64_t)123); 1279 | ok(v1.is(), "is int64_t"); 1280 | ok(v1.is(), "is double as well"); 1281 | ok(v1.serialize() == "123", "serialize the value"); 1282 | ok(v1.get() == 123, "value is correct as int64_t"); 1283 | ok(v1.get(), "value is correct as double"); 1284 | 1285 | ok(! v1.is(), "is no more int64_type once get() is called"); 1286 | ok(v1.is(), "and is still a double"); 1287 | 1288 | const char *s = "-9223372036854775809"; 1289 | ok(picojson::parse(v1, s, s + strlen(s)).empty(), "parse underflowing int64_t"); 1290 | ok(! v1.is(), "underflowing int is not int64_t"); 1291 | ok(v1.is(), "underflowing int is double"); 1292 | ok(v1.get() + 9.22337203685478e+18 < 65536, "double value is somewhat correct"); 1293 | } 1294 | #endif 1295 | 1296 | done_testing(); 1297 | 1298 | return success ? 0 : 1; 1299 | } 1300 | 1301 | #endif 1302 | -------------------------------------------------------------------------------- /src/deps/sha1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sha1", 3 | "version": "0.0.1", 4 | "repo": "clibs/sha1", 5 | "description": "sha1 hash algorithm", 6 | "keywords": ["sha1", "hash"], 7 | "license": "public domain", 8 | "src": ["sha1.c", "sha1.h"] 9 | } 10 | -------------------------------------------------------------------------------- /src/deps/sha1/sha1.c: -------------------------------------------------------------------------------- 1 | /* 2 | SHA-1 in C 3 | By Steve Reid 4 | 100% Public Domain 5 | 6 | Test Vectors (from FIPS PUB 180-1) 7 | "abc" 8 | A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D 9 | "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" 10 | 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 11 | A million repetitions of "a" 12 | 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F 13 | */ 14 | 15 | /* #define LITTLE_ENDIAN * This should be #define'd already, if true. */ 16 | /* #define SHA1HANDSOFF * Copies data before messing with it. */ 17 | 18 | #define SHA1HANDSOFF 19 | 20 | #include 21 | #include 22 | 23 | /* for uint32_t */ 24 | #include 25 | 26 | #include "sha1.h" 27 | 28 | 29 | #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) 30 | 31 | /* blk0() and blk() perform the initial expand. */ 32 | /* I got the idea of expanding during the round function from SSLeay */ 33 | #if BYTE_ORDER == LITTLE_ENDIAN 34 | #define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ 35 | |(rol(block->l[i],8)&0x00FF00FF)) 36 | #elif BYTE_ORDER == BIG_ENDIAN 37 | #define blk0(i) block->l[i] 38 | #else 39 | #error "Endianness not defined!" 40 | #endif 41 | #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ 42 | ^block->l[(i+2)&15]^block->l[i&15],1)) 43 | 44 | /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ 45 | #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); 46 | #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); 47 | #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); 48 | #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); 49 | #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); 50 | 51 | 52 | /* Hash a single 512-bit block. This is the core of the algorithm. */ 53 | 54 | void SHA1Transform( 55 | uint32_t state[5], 56 | const unsigned char buffer[64] 57 | ) 58 | { 59 | uint32_t a, b, c, d, e; 60 | 61 | typedef union 62 | { 63 | unsigned char c[64]; 64 | uint32_t l[16]; 65 | } CHAR64LONG16; 66 | 67 | #ifdef SHA1HANDSOFF 68 | CHAR64LONG16 block[1]; /* use array to appear as a pointer */ 69 | 70 | memcpy(block, buffer, 64); 71 | #else 72 | /* The following had better never be used because it causes the 73 | * pointer-to-const buffer to be cast into a pointer to non-const. 74 | * And the result is written through. I threw a "const" in, hoping 75 | * this will cause a diagnostic. 76 | */ 77 | CHAR64LONG16 *block = (const CHAR64LONG16 *) buffer; 78 | #endif 79 | /* Copy context->state[] to working vars */ 80 | a = state[0]; 81 | b = state[1]; 82 | c = state[2]; 83 | d = state[3]; 84 | e = state[4]; 85 | /* 4 rounds of 20 operations each. Loop unrolled. */ 86 | R0(a, b, c, d, e, 0); 87 | R0(e, a, b, c, d, 1); 88 | R0(d, e, a, b, c, 2); 89 | R0(c, d, e, a, b, 3); 90 | R0(b, c, d, e, a, 4); 91 | R0(a, b, c, d, e, 5); 92 | R0(e, a, b, c, d, 6); 93 | R0(d, e, a, b, c, 7); 94 | R0(c, d, e, a, b, 8); 95 | R0(b, c, d, e, a, 9); 96 | R0(a, b, c, d, e, 10); 97 | R0(e, a, b, c, d, 11); 98 | R0(d, e, a, b, c, 12); 99 | R0(c, d, e, a, b, 13); 100 | R0(b, c, d, e, a, 14); 101 | R0(a, b, c, d, e, 15); 102 | R1(e, a, b, c, d, 16); 103 | R1(d, e, a, b, c, 17); 104 | R1(c, d, e, a, b, 18); 105 | R1(b, c, d, e, a, 19); 106 | R2(a, b, c, d, e, 20); 107 | R2(e, a, b, c, d, 21); 108 | R2(d, e, a, b, c, 22); 109 | R2(c, d, e, a, b, 23); 110 | R2(b, c, d, e, a, 24); 111 | R2(a, b, c, d, e, 25); 112 | R2(e, a, b, c, d, 26); 113 | R2(d, e, a, b, c, 27); 114 | R2(c, d, e, a, b, 28); 115 | R2(b, c, d, e, a, 29); 116 | R2(a, b, c, d, e, 30); 117 | R2(e, a, b, c, d, 31); 118 | R2(d, e, a, b, c, 32); 119 | R2(c, d, e, a, b, 33); 120 | R2(b, c, d, e, a, 34); 121 | R2(a, b, c, d, e, 35); 122 | R2(e, a, b, c, d, 36); 123 | R2(d, e, a, b, c, 37); 124 | R2(c, d, e, a, b, 38); 125 | R2(b, c, d, e, a, 39); 126 | R3(a, b, c, d, e, 40); 127 | R3(e, a, b, c, d, 41); 128 | R3(d, e, a, b, c, 42); 129 | R3(c, d, e, a, b, 43); 130 | R3(b, c, d, e, a, 44); 131 | R3(a, b, c, d, e, 45); 132 | R3(e, a, b, c, d, 46); 133 | R3(d, e, a, b, c, 47); 134 | R3(c, d, e, a, b, 48); 135 | R3(b, c, d, e, a, 49); 136 | R3(a, b, c, d, e, 50); 137 | R3(e, a, b, c, d, 51); 138 | R3(d, e, a, b, c, 52); 139 | R3(c, d, e, a, b, 53); 140 | R3(b, c, d, e, a, 54); 141 | R3(a, b, c, d, e, 55); 142 | R3(e, a, b, c, d, 56); 143 | R3(d, e, a, b, c, 57); 144 | R3(c, d, e, a, b, 58); 145 | R3(b, c, d, e, a, 59); 146 | R4(a, b, c, d, e, 60); 147 | R4(e, a, b, c, d, 61); 148 | R4(d, e, a, b, c, 62); 149 | R4(c, d, e, a, b, 63); 150 | R4(b, c, d, e, a, 64); 151 | R4(a, b, c, d, e, 65); 152 | R4(e, a, b, c, d, 66); 153 | R4(d, e, a, b, c, 67); 154 | R4(c, d, e, a, b, 68); 155 | R4(b, c, d, e, a, 69); 156 | R4(a, b, c, d, e, 70); 157 | R4(e, a, b, c, d, 71); 158 | R4(d, e, a, b, c, 72); 159 | R4(c, d, e, a, b, 73); 160 | R4(b, c, d, e, a, 74); 161 | R4(a, b, c, d, e, 75); 162 | R4(e, a, b, c, d, 76); 163 | R4(d, e, a, b, c, 77); 164 | R4(c, d, e, a, b, 78); 165 | R4(b, c, d, e, a, 79); 166 | /* Add the working vars back into context.state[] */ 167 | state[0] += a; 168 | state[1] += b; 169 | state[2] += c; 170 | state[3] += d; 171 | state[4] += e; 172 | /* Wipe variables */ 173 | a = b = c = d = e = 0; 174 | #ifdef SHA1HANDSOFF 175 | memset(block, '\0', sizeof(block)); 176 | #endif 177 | } 178 | 179 | 180 | /* SHA1Init - Initialize new context */ 181 | 182 | void SHA1Init( 183 | SHA1_CTX * context 184 | ) 185 | { 186 | /* SHA1 initialization constants */ 187 | context->state[0] = 0x67452301; 188 | context->state[1] = 0xEFCDAB89; 189 | context->state[2] = 0x98BADCFE; 190 | context->state[3] = 0x10325476; 191 | context->state[4] = 0xC3D2E1F0; 192 | context->count[0] = context->count[1] = 0; 193 | } 194 | 195 | 196 | /* Run your data through this. */ 197 | 198 | void SHA1Update( 199 | SHA1_CTX * context, 200 | const unsigned char *data, 201 | uint32_t len 202 | ) 203 | { 204 | uint32_t i; 205 | 206 | uint32_t j; 207 | 208 | j = context->count[0]; 209 | if ((context->count[0] += len << 3) < j) 210 | context->count[1]++; 211 | context->count[1] += (len >> 29); 212 | j = (j >> 3) & 63; 213 | if ((j + len) > 63) 214 | { 215 | memcpy(&context->buffer[j], data, (i = 64 - j)); 216 | SHA1Transform(context->state, context->buffer); 217 | for (; i + 63 < len; i += 64) 218 | { 219 | SHA1Transform(context->state, &data[i]); 220 | } 221 | j = 0; 222 | } 223 | else 224 | i = 0; 225 | memcpy(&context->buffer[j], &data[i], len - i); 226 | } 227 | 228 | 229 | /* Add padding and return the message digest. */ 230 | 231 | void SHA1Final( 232 | unsigned char digest[20], 233 | SHA1_CTX * context 234 | ) 235 | { 236 | unsigned i; 237 | 238 | unsigned char finalcount[8]; 239 | 240 | unsigned char c; 241 | 242 | #if 0 /* untested "improvement" by DHR */ 243 | /* Convert context->count to a sequence of bytes 244 | * in finalcount. Second element first, but 245 | * big-endian order within element. 246 | * But we do it all backwards. 247 | */ 248 | unsigned char *fcp = &finalcount[8]; 249 | 250 | for (i = 0; i < 2; i++) 251 | { 252 | uint32_t t = context->count[i]; 253 | 254 | int j; 255 | 256 | for (j = 0; j < 4; t >>= 8, j++) 257 | *--fcp = (unsigned char) t} 258 | #else 259 | for (i = 0; i < 8; i++) 260 | { 261 | finalcount[i] = (unsigned char) ((context->count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255); /* Endian independent */ 262 | } 263 | #endif 264 | c = 0200; 265 | SHA1Update(context, &c, 1); 266 | while ((context->count[0] & 504) != 448) 267 | { 268 | c = 0000; 269 | SHA1Update(context, &c, 1); 270 | } 271 | SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ 272 | for (i = 0; i < 20; i++) 273 | { 274 | digest[i] = (unsigned char) 275 | ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); 276 | } 277 | /* Wipe variables */ 278 | memset(context, '\0', sizeof(*context)); 279 | memset(&finalcount, '\0', sizeof(finalcount)); 280 | } 281 | 282 | void SHA1( 283 | char *hash_out, 284 | const char *str, 285 | unsigned int len) 286 | { 287 | SHA1_CTX ctx; 288 | unsigned int ii; 289 | 290 | SHA1Init(&ctx); 291 | for (ii=0; ii 7 | 100% Public Domain 8 | */ 9 | 10 | typedef struct 11 | { 12 | uint32_t state[5]; 13 | uint32_t count[2]; 14 | unsigned char buffer[64]; 15 | } SHA1_CTX; 16 | 17 | void SHA1Transform( 18 | uint32_t state[5], 19 | const unsigned char buffer[64] 20 | ); 21 | 22 | void SHA1Init( 23 | SHA1_CTX * context 24 | ); 25 | 26 | void SHA1Update( 27 | SHA1_CTX * context, 28 | const unsigned char *data, 29 | uint32_t len 30 | ); 31 | 32 | void SHA1Final( 33 | unsigned char digest[20], 34 | SHA1_CTX * context 35 | ); 36 | 37 | void SHA1( 38 | char *hash_out, 39 | const char *str, 40 | unsigned int len); 41 | 42 | #endif /* SHA1_H */ 43 | -------------------------------------------------------------------------------- /src/deps/tinyformat/README.rst: -------------------------------------------------------------------------------- 1 | ============ 2 | tinyformat.h 3 | ============ 4 | ---------------------------------------- 5 | A minimal type safe printf() replacement 6 | ---------------------------------------- 7 | 8 | **tinyformat.h** is a type safe printf replacement library in a single C++ 9 | header file. If you've ever wanted ``printf("%s", s)`` to just work regardless 10 | of the type of ``s``, tinyformat might be for you. Design goals include: 11 | 12 | * Type safety and extensibility for user defined types. 13 | * C99 ``printf()`` compatibility, to the extent possible using ``std::ostream`` 14 | * Simplicity and minimalism. A single header file to include and distribute 15 | with your projects. 16 | * Augment rather than replace the standard stream formatting mechanism 17 | * C++98 support, with optional C++11 niceties 18 | 19 | 20 | Example usage 21 | ------------- 22 | 23 | To print a date to ``std::cout``:: 24 | 25 | std::string weekday = "Wednesday"; 26 | const char* month = "July"; 27 | size_t day = 27; 28 | long hour = 14; 29 | int min = 44; 30 | 31 | tfm::printf("%s, %s %d, %.2d:%.2d\n", weekday, month, day, hour, min); 32 | 33 | The strange types here emphasize the type safety of the interface, for example 34 | it is possible to print a ``std::string`` using the ``"%s"`` conversion, and a 35 | ``size_t`` using the ``"%d"`` conversion. A similar result could be achieved 36 | using either of the ``tfm::format()`` functions. One prints on a user provided 37 | stream:: 38 | 39 | tfm::format(std::cerr, "%s, %s %d, %.2d:%.2d\n", 40 | weekday, month, day, hour, min); 41 | 42 | The other returns a ``std::string``:: 43 | 44 | std::string date = tfm::format("%s, %s %d, %.2d:%.2d\n", 45 | weekday, month, day, hour, min); 46 | std::cout << date; 47 | 48 | 49 | It is safe to use tinyformat inside a template function. For any type which 50 | has the usual stream insertion ``operator<<`` defined, the following will work 51 | as desired:: 52 | 53 | template 54 | void myPrint(const T& value) 55 | { 56 | tfm::printf("My value is '%s'\n", value); 57 | } 58 | 59 | (The above is a compile error for types ``T`` without a stream insertion 60 | operator.) 61 | 62 | 63 | Function reference 64 | ------------------ 65 | 66 | All user facing functions are defined in the namespace ``tinyformat``. A 67 | namespace alias ``tfm`` is provided to encourage brevity, but can easily be 68 | disabled if desired. 69 | 70 | Three main interface functions are available: an iostreams-based ``format()``, 71 | a string-based ``format()`` and a ``printf()`` replacement. These functions 72 | can be thought of as C++ replacements for C's ``fprintf()``, ``sprintf()`` and 73 | ``printf()`` functions respectively. All the interface functions can take an 74 | unlimited number of input arguments if compiled with C++11 variadic templates 75 | support. In C++98 mode, the number of arguments must be limited to some fixed 76 | upper bound which is currently 16 as of version 1.3 [#]_. 77 | 78 | The ``format()`` function which takes a stream as the first argument is the 79 | main part of the tinyformat interface. ``stream`` is the output stream, 80 | ``formatString`` is a format string in C99 ``printf()`` format, and the values 81 | to be formatted have arbitrary types:: 82 | 83 | template 84 | void format(std::ostream& stream, const char* formatString, 85 | const T1& value1, const Args&... args); 86 | 87 | The second version of ``format()`` is a convenience function which returns a 88 | ``std::string`` rather than printing onto a stream. This function simply 89 | calls the main version of ``format()`` using a ``std::ostringstream``, and 90 | returns the resulting string:: 91 | 92 | template 93 | std::string format(const char* formatString, 94 | const T1& value1, const Args&... args); 95 | 96 | Finally, ``printf()`` is a convenience function which calls ``format()`` with 97 | ``std::cout`` as the first argument:: 98 | 99 | template 100 | void printf(const char* formatString, 101 | const T1& value1, const Args&... args); 102 | 103 | .. [#] Generating the code to support more arguments is quite easy using the 104 | in-source code generator based on the excellent code generation script 105 | ``cog.py`` (http://nedbatchelder.com/code/cog): Set the ``maxParams`` 106 | parameter in the code generator and rerun cog using 107 | ``cog.py -r tinyformat.h``. Alternatively, it should be quite easy to simply 108 | add extra versions of the associated macros by hand. 109 | 110 | Format strings and type safety 111 | ------------------------------ 112 | 113 | Tinyformat parses C99 format strings to guide the formatting process --- please 114 | refer to any standard C99 printf documentation for format string syntax. In 115 | contrast to printf, tinyformat does not use the format string to decide on 116 | the type to be formatted so this does not compromise the type safety: *you may 117 | use any format specifier with any C++ type*. The author suggests standardising 118 | on the ``%s`` conversion unless formatting numeric types. 119 | 120 | Let's look at what happens when you execute the function call:: 121 | 122 | tfm::format(outStream, "%+6.4f", yourType); 123 | 124 | First, the library parses the format string, and uses it to modify the state of 125 | ``outStream``: 126 | 127 | 1. The ``outStream`` formatting flags are cleared and the width, precision and 128 | fill reset to the default. 129 | 2. The flag ``'+'`` means to prefix positive numbers with a ``'+'``; tinyformat 130 | executes ``outStream.setf(std::ios::showpos)`` 131 | 3. The number 6 gives the field width; execute ``outStream.width(6)``. 132 | 4. The number 4 gives the precision; execute ``outStream.precision(4)``. 133 | 5. The conversion specification character ``'f'`` means that floats should be 134 | formatted with a fixed number of digits; this corresponds to executing 135 | ``outStream.setf(std::ios::fixed, std::ios::floatfield);`` 136 | 137 | After all these steps, tinyformat executes:: 138 | 139 | outStream << yourType; 140 | 141 | and finally restores the stream flags, precision and fill. 142 | 143 | What happens if ``yourType`` isn't actually a floating point type? In this 144 | case the flags set above are probably irrelevant and will be ignored by the 145 | underlying ``std::ostream`` implementation. The field width of six may cause 146 | some padding in the output of ``yourType``, but that's about it. 147 | 148 | 149 | Special cases for "%p", "%c" and "%s" 150 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 151 | 152 | Tinyformat normally uses ``operator<<`` to convert types to strings. However, 153 | the "%p" and "%c" conversions require special rules for robustness. Consider:: 154 | 155 | uint8_t* pixels = get_pixels(/* ... */); 156 | tfm::printf("%p", pixels); 157 | 158 | Clearly the intention here is to print a representation of the *pointer* to 159 | ``pixels``, but since ``uint8_t`` is a character type the compiler would 160 | attempt to print it as a C string if we blindly fed it into ``operator<<``. To 161 | counter this kind of madness, tinyformat tries to static_cast any type fed to 162 | the "%p" conversion into a ``const void*`` before printing. If this can't be 163 | done at compile time the library falls back to using ``operator<<`` as usual. 164 | 165 | The "%c" conversion has a similar problem: it signifies that the given integral 166 | type should be converted into a ``char`` before printing. The solution is 167 | identical: attempt to convert the provided type into a char using 168 | ``static_cast`` if possible, and if not fall back to using ``operator<<``. 169 | 170 | The "%s" conversion sets the boolalpha flag on the formatting stream. This 171 | means that a ``bool`` variable printed with "%s" will come out as ``true`` or 172 | ``false`` rather than the ``1`` or ``0`` that you would otherwise get. 173 | 174 | 175 | Incompatibilities with C99 printf 176 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 177 | 178 | Not all features of printf can be simulated simply using standard iostreams. 179 | Here's a list of known incompatibilities: 180 | 181 | * The C99 ``"%a"`` and ``"%A"`` hexadecimal floating point conversions are not 182 | supported since the iostreams don't have the necessary flags. Using either 183 | of these flags will result in a call to ``TINYFORMAT_ERROR``. 184 | * The precision for integer conversions cannot be supported by the iostreams 185 | state independently of the field width. (Note: **this is only a 186 | problem for certain obscure integer conversions**; float conversions like 187 | ``%6.4f`` work correctly.) In tinyformat the field width takes precedence, 188 | so the 4 in ``%6.4d`` will be ignored. However, if the field width is not 189 | specified, the width used internally is set equal to the precision and padded 190 | with zeros on the left. That is, a conversion like ``%.4d`` effectively 191 | becomes ``%04d`` internally. This isn't correct for every case (eg, negative 192 | numbers end up with one less digit than desired) but it's about the closest 193 | simple solution within the iostream model. 194 | * The ``"%n"`` query specifier isn't supported to keep things simple and will 195 | result in a call to ``TINYFORMAT_ERROR``. 196 | * The ``"%ls"`` conversion is not supported, and attempting to format a 197 | ``wchar_t`` array will cause a compile time error to minimise unexpected 198 | surprises. If you know the encoding of your wchar_t strings, you could write 199 | your own ``std::ostream`` insertion operator for them, and disable the 200 | compile time check by defining the macro ``TINYFORMAT_ALLOW_WCHAR_STRINGS``. 201 | If you want to print the *address* of a wide character with the ``"%p"`` 202 | conversion, you should cast it to a ``void*`` before passing it to one of the 203 | formatting functions. 204 | 205 | 206 | Error handling 207 | -------------- 208 | 209 | By default, tinyformat calls ``assert()`` if it encounters an error in the 210 | format string or number of arguments. This behaviour can be changed (for 211 | example, to throw an exception) by defining the ``TINYFORMAT_ERROR`` macro 212 | before including tinyformat.h, or editing the config section of the header. 213 | 214 | 215 | Formatting user defined types 216 | ----------------------------- 217 | 218 | User defined types with a stream insertion operator will be formatted using 219 | ``operator<<(std::ostream&, T)`` by default. The ``"%s"`` format specifier is 220 | suggested for user defined types, unless the type is inherently numeric. 221 | 222 | For further customization, the user can override the ``formatValue()`` 223 | function to specify formatting independently of the stream insertion operator. 224 | If you override this function, the library will have already parsed the format 225 | specification and set the stream flags accordingly - see the source for details. 226 | 227 | 228 | Wrapping tfm::format() inside a user defined format function 229 | ------------------------------------------------------------ 230 | 231 | Suppose you wanted to define your own function which wraps ``tfm::format``. 232 | For example, consider an error function taking an error code, which in C++11 233 | might be written simply as:: 234 | 235 | template 236 | void error(int code, const char* fmt, const Args&... args) 237 | { 238 | std::cerr << "error (code " << code << ")"; 239 | tfm::format(std::cerr, fmt, args...); 240 | } 241 | 242 | Simulating this functionality in C++98 is pretty painful since it requires 243 | writing out a version of ``error()`` for each desired number of arguments. To 244 | make this bearable tinyformat comes with a set of macros which are used 245 | internally to generate the API, but which may also be used in user code. 246 | 247 | The three macros ``TINYFORMAT_ARGTYPES(n)``, ``TINYFORMAT_VARARGS(n)`` and 248 | ``TINYFORMAT_PASSARGS(n)`` will generate a list of ``n`` argument types, 249 | type/name pairs and argument names respectively when called with an integer 250 | ``n`` between 1 and 16. We can use these to define a macro which generates the 251 | desired user defined function with ``n`` arguments. This should be followed by 252 | a call to ``TINYFORMAT_FOREACH_ARGNUM`` to generate the set of functions for 253 | all supported ``n``:: 254 | 255 | #define MAKE_ERROR_FUNC(n) \ 256 | template \ 257 | void error(int code, const char* fmt, TINYFORMAT_VARARGS(n)) \ 258 | { \ 259 | std::cerr << "error (code " << code << ")"; \ 260 | tfm::format(std::cerr, fmt, TINYFORMAT_PASSARGS(n)); \ 261 | } 262 | TINYFORMAT_FOREACH_ARGNUM(MAKE_ERROR_FUNC) 263 | 264 | Sometimes it's useful to be able to pass a list of format arguments through to 265 | a non-template function. The ``FormatList`` class is provided as a way to do 266 | this by storing the argument list in a type-opaque way. For example:: 267 | 268 | template 269 | void error(int code, const char* fmt, const Args&... args) 270 | { 271 | tfm::FormatListRef formatList = tfm::makeFormatList(args...); 272 | errorImpl(code, fmt, formatList); 273 | } 274 | 275 | What's interesting here is that ``errorImpl()`` is a non-template function so 276 | it could be separately compiled if desired. The ``FormatList`` instance can be 277 | used via a call to the ``vformat()`` function (the name chosen for semantic 278 | similarity to ``vprintf()``):: 279 | 280 | void errorImpl(int code, const char* fmt, tfm::FormatListRef formatList) 281 | { 282 | std::cerr << "error (code " << code << ")"; 283 | tfm::vformat(std::cout, fmt, formatList); 284 | } 285 | 286 | The construction of a ``FormatList`` instance is very lightweight - it defers 287 | all formatting and simply stores a couple of function pointers and a value 288 | pointer per argument. Since most of the actual work is done inside 289 | ``vformat()``, any logic which causes an early exit of ``errorImpl()`` - 290 | filtering of verbose log messages based on error code for example - could be a 291 | useful optimization for programs using tinyformat. (A faster option would be 292 | to write any early bailout code inside ``error()``, though this must be done in 293 | the header.) 294 | 295 | 296 | Benchmarks 297 | ---------- 298 | 299 | Compile time and code bloat 300 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 301 | 302 | The script ``bloat_test.sh`` included in the repository tests whether 303 | tinyformat succeeds in avoiding compile time and code bloat for nontrivial 304 | projects. The idea is to include ``tinyformat.h`` into 100 translation units 305 | and use ``printf()`` five times in each to simulate a medium sized project. 306 | The resulting executable size and compile time (g++-4.8.2, linux ubuntu 14.04) 307 | is shown in the following tables, which can be regenerated using ``make 308 | bloat_test``: 309 | 310 | **Non-optimized build** 311 | 312 | ====================== ================== ========================== 313 | test name compiler wall time executable size (stripped) 314 | ====================== ================== ========================== 315 | libc printf 1.8s 48K (36K) 316 | std::ostream 10.7s 96K (76K) 317 | tinyformat, no inlines 18.9s 140K (104K) 318 | tinyformat 21.1s 220K (180K) 319 | tinyformat, c++0x mode 20.7s 220K (176K) 320 | boost::format 70.1s 844K (736K) 321 | ====================== ================== ========================== 322 | 323 | **Optimized build (-O3 -DNDEBUG)** 324 | 325 | ====================== ================== ========================== 326 | test name compiler wall time executable size (stripped) 327 | ====================== ================== ========================== 328 | libc printf 2.3s 40K (28K) 329 | std::ostream 11.8s 104K (80K) 330 | tinyformat, no inlines 23.0s 128K (104K) 331 | tinyformat 32.9s 128K (104K) 332 | tinyformat, c++0x mode 34.0s 128K (104K) 333 | boost::format 147.9s 644K (600K) 334 | ====================== ================== ========================== 335 | 336 | For large projects it's arguably worthwhile to do separate compilation of the 337 | non-templated parts of tinyformat, as shown in the rows labelled *tinyformat, 338 | no inlines*. These were generated by putting the implementation of ``vformat`` 339 | (``detail::formatImpl()`` etc) it into a separate file, tinyformat.cpp. Note 340 | that the results above can vary considerably with different compilers. For 341 | example, the ``-fipa-cp-clone`` optimization pass in g++-4.6 resulted in 342 | excessively large binaries. On the other hand, the g++-4.8 results are quite 343 | similar to using clang++-3.4. 344 | 345 | 346 | Speed tests 347 | ~~~~~~~~~~~ 348 | 349 | The following speed tests results were generated by building 350 | ``tinyformat_speed_test.cpp`` on an Intel core i7-2600K running Linux Ubuntu 351 | 14.04 with g++-4.8.2 using ``-O3 -DNDEBUG``. In the test, the format string 352 | ``"%0.10f:%04d:%+g:%s:%p:%c:%%\n"`` is filled 2000000 times with output sent to 353 | ``/dev/null``; for further details see the source and Makefile. 354 | 355 | ============== ======== 356 | test name run time 357 | ============== ======== 358 | libc printf 1.20s 359 | std::ostream 1.82s 360 | tinyformat 2.08s 361 | boost::format 9.04s 362 | ============== ======== 363 | 364 | It's likely that tinyformat has an advantage over boost.format because it tries 365 | reasonably hard to avoid formatting into temporary strings, preferring instead 366 | to send the results directly to the stream buffer. Tinyformat cannot 367 | be faster than the iostreams because it uses them internally, but it comes 368 | acceptably close. 369 | 370 | 371 | Rationale 372 | --------- 373 | 374 | Or, why did I reinvent this particularly well studied wheel? 375 | 376 | Nearly every program needs text formatting in some form but in many cases such 377 | formatting is *incidental* to the main purpose of the program. In these cases, 378 | you really want a library which is simple to use but as lightweight as 379 | possible. 380 | 381 | The ultimate in lightweight dependencies are the solutions provided by the C++ 382 | and C libraries. However, both the C++ iostreams and C's printf() have 383 | well known usability problems: iostreams are hopelessly verbose for complicated 384 | formatting and printf() lacks extensibility and type safety. For example:: 385 | 386 | // Verbose; hard to read, hard to type: 387 | std::cout << std::setprecision(2) << std::fixed << 1.23456 << "\n"; 388 | // The alternative using a format string is much easier on the eyes 389 | tfm::printf("%.2f\n", 1.23456); 390 | 391 | // Type mismatch between "%s" and int: will cause a segfault at runtime! 392 | printf("%s", 1); 393 | // The following is perfectly fine, and will result in "1" being printed. 394 | tfm::printf("%s", 1); 395 | 396 | On the other hand, there are plenty of excellent and complete libraries which 397 | solve the formatting problem in great generality (boost.format and fastformat 398 | come to mind, but there are many others). Unfortunately these kind of 399 | libraries tend to be rather heavy dependencies, far too heavy for projects 400 | which need to do only a little formatting. Problems include 401 | 402 | 1. Having many large source files. This makes a heavy dependency unsuitable to 403 | bundle within other projects for convenience. 404 | 2. Slow build times for every file using any sort of formatting (this is very 405 | noticeable with g++ and boost/format.hpp. I'm not sure about the various 406 | other alternatives.) 407 | 3. Code bloat due to instantiating many templates 408 | 409 | Tinyformat tries to solve these problems while providing formatting which is 410 | sufficiently general and fast for incidental day to day uses. 411 | 412 | 413 | License 414 | ------- 415 | 416 | For minimum license-related fuss, tinyformat.h is distributed under the boost 417 | software license, version 1.0. (Summary: you must keep the license text on 418 | all source copies, but don't have to mention tinyformat when distributing 419 | binaries.) 420 | 421 | 422 | Author and acknowledgements 423 | --------------------------- 424 | 425 | Tinyformat was written by Chris Foster, with contributions from various people 426 | as recorded in the git repository. 427 | The implementation owes a lot to ``boost::format`` for showing that it's fairly 428 | easy to use stream based formatting to simulate most of the ``printf()`` 429 | syntax. Douglas Gregor's introduction to variadic templates --- see 430 | http://www.generic-programming.org/~dgregor/cpp/variadic-templates.html --- was 431 | also helpful, especially since it solves exactly the ``printf()`` problem for 432 | the case of trivial format strings. 433 | 434 | Bugs 435 | ---- 436 | 437 | Here's a list of known bugs which are probably cumbersome to fix: 438 | 439 | * Field padding won't work correctly with complicated user defined types. For 440 | general types, the only way to do this correctly seems to be format to a 441 | temporary string stream, check the length, and finally send to the output 442 | stream with padding if necessary. Doing this for all types would be 443 | quite inelegant because it implies extra allocations to make the temporary 444 | stream. A workaround is to add logic to ``operator<<()`` for composite user 445 | defined types so they are aware of the stream field width. 446 | -------------------------------------------------------------------------------- /src/fs.cc: -------------------------------------------------------------------------------- 1 | #include "fs.hpp" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | using std::string; 16 | 17 | extern "C" { 18 | #include "deps/fs/fs.c" 19 | } 20 | 21 | const char fs::PATH_SEPARATOR = '/'; 22 | 23 | int fs::rename (const string& from, const string& to) { 24 | return fs_rename(from.c_str(), to.c_str()); 25 | } 26 | 27 | fs::stats * fs::stat (const string& path) { 28 | return fs_stat(path.c_str()); 29 | } 30 | 31 | fs::stats * fs::lstat (const string& path) { 32 | return fs_lstat(path.c_str()); 33 | } 34 | 35 | int fs::truncate (const string& path, int len) { 36 | return fs_truncate(path.c_str(), len); 37 | } 38 | 39 | int fs::chown (const string& path, int uid, int gid) { 40 | return fs_chown(path.c_str(), uid, gid); 41 | } 42 | 43 | int fs::lchown (const string& path, int uid, int gid) { 44 | return fs_lchown(path.c_str(), uid, gid); 45 | } 46 | 47 | size_t fs::size (const string& path) { 48 | return fs_size(path.c_str()); 49 | } 50 | 51 | static string stringize(char * buf) { 52 | if (!buf) return ""; 53 | string result = buf; 54 | free(buf); 55 | return result; 56 | } 57 | 58 | string fs::read (const string& path) { 59 | return stringize(fs_read(path.c_str())); 60 | } 61 | 62 | string fs::nread (const string& path, int len) { 63 | return stringize(fs_nread(path.c_str(), len)); 64 | } 65 | 66 | std::list fs::readlines(const string& path) { 67 | std::list result; 68 | std::stringstream ss(fs_read(path.c_str())); 69 | std::string line; 70 | 71 | while (std::getline(ss, line,'\n')) { 72 | result.push_back(line); 73 | } 74 | return result; 75 | } 76 | 77 | int fs::write (const string& path, const char *buffer){ 78 | return fs_write(path.c_str(), buffer); 79 | } 80 | 81 | int fs::nwrite (const string& path, const char *buffer, int len){ 82 | return fs_nwrite(path.c_str(), buffer, len); 83 | } 84 | 85 | int fs::mkdir (const string& path, int mode){ 86 | return fs_mkdir(path.c_str(), mode); 87 | } 88 | 89 | int fs::rmdir (const string& path){ 90 | return fs_rmdir(path.c_str()); 91 | } 92 | 93 | bool fs::exists (const string& path){ 94 | // fs_exists returns 0 if the file actually exists 95 | return fs_exists(path.c_str()) == 0; 96 | } 97 | 98 | 99 | string fs::join(const string& dirname, const string& basename) { 100 | size_t dirname_len = dirname.length(); 101 | size_t basename_len = basename.length(); 102 | int offset = 0; 103 | 104 | if (dirname_len == 0) return basename; 105 | else if (dirname[dirname_len - 1] == PATH_SEPARATOR) offset++; 106 | if (basename_len == 0) return dirname; 107 | else if (basename[0] == PATH_SEPARATOR) offset++; 108 | 109 | switch (offset) { 110 | case 0: 111 | return dirname + PATH_SEPARATOR + basename; 112 | case 2: 113 | return dirname + basename.substr(1); 114 | case 1: default: 115 | return dirname + basename; 116 | } 117 | } 118 | 119 | string fs::join(const string& path1, const string& path2, const string& path3) { 120 | return fs::join(fs::join(path1, path2), path3); 121 | } 122 | 123 | string fs::dirname(const string& path) { 124 | size_t pos = path.find_last_of(PATH_SEPARATOR); 125 | if (pos == string::npos) { 126 | return ""; 127 | } else { 128 | return path.substr(0, pos); 129 | } 130 | } 131 | 132 | string fs::basename(const string& path) { 133 | size_t pos = path.find_last_of(PATH_SEPARATOR); 134 | if (pos == string::npos) { 135 | return path; 136 | } else { 137 | return path.substr(pos + 1); 138 | } 139 | } 140 | 141 | string fs::extname(const string& path) { 142 | string name = fs::basename(path); 143 | size_t pos = name.find_last_of('.'); 144 | if (pos == string::npos) { 145 | return ""; 146 | } else { 147 | return name.substr(pos); 148 | } 149 | } 150 | 151 | bool fs::is_dir(const string& path) { 152 | struct stat buf; 153 | if (stat(path.c_str(), &buf) == -1) return 0; 154 | return S_ISDIR(buf.st_mode) ? 1 : 0; 155 | } 156 | 157 | bool fs::is_symlink(const string& path) { 158 | struct stat buf; 159 | if (lstat(path.c_str(), &buf) == -1) return 0; 160 | return S_ISLNK(buf.st_mode) ? 1 : 0; 161 | } 162 | 163 | bool fs::is_disconnected(const string& path) { 164 | struct stat buf; 165 | if (stat(path.c_str(), &buf) == -1) { 166 | return errno == ENOTCONN; 167 | } 168 | return false; 169 | } 170 | 171 | int fs::mkdir_p(const string& dir, const mode_t mode) { 172 | // do nothing if directory exists 173 | if (is_dir(dir)) return 0; 174 | 175 | // make each dirs 176 | const char * head = dir.c_str(); 177 | int nmkdir = 0; 178 | for (const char * p = head; *p; ++p) { 179 | if (*p == '/' && p > head) { 180 | int e = mkdir(dir.substr(0, p - head).c_str(), mode); 181 | if (e == 0) ++nmkdir; 182 | } 183 | } 184 | int e = mkdir(dir.c_str(), mode); 185 | 186 | if (e < 0 /* && errno != EEXIST */) return -1; 187 | return nmkdir; 188 | } 189 | 190 | int fs::rm_rf(const string& path) { 191 | // TODO use more efficient implement like coreutils/rm 192 | 193 | // try to remove single file or an empty dir 194 | if (unlink(path.c_str()) == 0) return 0; 195 | if (rmdir(path.c_str()) == 0) return 0; 196 | 197 | // try to list path contents 198 | struct dirent **namelist = 0; 199 | int nlist = scandir(path.c_str(), &namelist, 0, alphasort); 200 | 201 | for (int i = 0; i < nlist; ++i) { 202 | const char * name = namelist[i]->d_name; 203 | // skip . and .. 204 | if (strcmp(name, ".") != 0 && strcmp(name, "..") != 0) fs::rm_rf(path + "/" + name); 205 | free(namelist[i]); 206 | } 207 | 208 | if (namelist) free(namelist); 209 | 210 | // try remove empty dir again 211 | if (rmdir(path.c_str()) == 0) return 0; 212 | 213 | // otherwise something must went wrong 214 | return -1; 215 | } 216 | 217 | bool fs::is_absolute(const string& path) { 218 | return path.length() > 0 && path.data()[0] == PATH_SEPARATOR; 219 | } 220 | 221 | bool fs::is_accessible(const string& path, int mode, const string& work_dir) { 222 | int dirfd = AT_FDCWD; 223 | bool result = false; 224 | if (!work_dir.empty() && !is_absolute(path)) { 225 | dirfd = open(work_dir.c_str(), O_RDONLY); 226 | if (dirfd == -1) goto cleanup; 227 | } 228 | result = (faccessat(dirfd, path.c_str(), mode, 0) == 0); 229 | 230 | cleanup: 231 | if (dirfd != -1 && dirfd != AT_FDCWD) close(dirfd); 232 | return result; 233 | } 234 | 235 | bool fs::is_mounted(const string& path) { 236 | bool result = false; 237 | FILE *fp = setmntent("/proc/mounts", "r"); 238 | if (!fp) goto cleanup; 239 | 240 | for (struct mntent *ent; (ent = getmntent(fp));) { 241 | if (string(ent->mnt_dir) == path) { 242 | result = true; 243 | break; 244 | } 245 | } 246 | 247 | cleanup: 248 | if (fp) fclose(fp); 249 | return result; 250 | } 251 | 252 | bool fs::touch(const string& path) { 253 | FILE *fp = fopen(path.c_str(), "a"); 254 | if (!fp) return false; 255 | fclose(fp); 256 | return true; 257 | } 258 | 259 | std::list fs::scandir(const string& path) { 260 | std::list result; 261 | 262 | struct dirent **namelist = 0; 263 | int nlist = scandir(path.c_str(), &namelist, 0, alphasort); 264 | for (int i = 0; i < nlist; ++i) { 265 | const char * name = namelist[i]->d_name; 266 | // skip . and .. 267 | if (strcmp(name, ".") != 0 && strcmp(name, "..") != 0) { 268 | result.push_back(name); 269 | } 270 | free(namelist[i]); 271 | } 272 | if (namelist) free(namelist); 273 | 274 | return result; 275 | } 276 | 277 | string fs::resolve(const string& path) { 278 | string result = path; 279 | size_t buf_size = PATH_MAX; 280 | char *buf = (char*) malloc(buf_size + 1); 281 | 282 | if (!buf) goto cleanup; 283 | 284 | for (string link = path;;) { // recursively readlink 285 | for (;;) { 286 | // readlink requires unknown space, try until we got full path 287 | ssize_t out_size = readlinkat(AT_FDCWD, link.c_str(), buf, buf_size); 288 | if (out_size < 0) { 289 | goto cleanup; 290 | } else if ((size_t) out_size >= buf_size) { 291 | // try bigger 292 | char *new_buf = (char*) realloc(buf, buf_size + PATH_MAX + 1); 293 | if (new_buf) { 294 | buf = new_buf; 295 | buf_size += PATH_MAX; 296 | } else { 297 | // give up 298 | result = buf; 299 | break; 300 | } 301 | } else { 302 | buf[out_size] = 0; 303 | link = result = buf; 304 | break; 305 | } 306 | }; 307 | } 308 | 309 | cleanup: 310 | if (buf) free(buf); 311 | return result; 312 | } 313 | 314 | 315 | string fs::make_absolute(const string& path) { 316 | if (is_absolute(path)) return path; 317 | else { 318 | char buf[PATH_MAX]; 319 | char* succeed = getcwd(buf, PATH_MAX); 320 | if (NULL == succeed) { 321 | return path; 322 | } 323 | string result = join(string(succeed), path); 324 | return result; 325 | } 326 | } 327 | 328 | fs::ScopedFileLock::ScopedFileLock(const string& path) { 329 | int fd = open(path.c_str(), O_RDONLY); 330 | if (fd < 0) return; 331 | if (flock(fd, LOCK_EX) == 0) { 332 | this->fd_ = fd; 333 | } else { 334 | close(fd); 335 | this->fd_ = -1; 336 | } 337 | } 338 | 339 | fs::ScopedFileLock::~ScopedFileLock() { 340 | int fd = this->fd_; 341 | if (fd < 0) return; 342 | flock(fd, LOCK_UN); 343 | close(fd); 344 | } 345 | -------------------------------------------------------------------------------- /src/fs.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | extern "C" { 8 | #include "deps/fs/fs.h" 9 | } 10 | 11 | namespace fs { 12 | typedef fs_stats stats; 13 | 14 | // proxy to fs.h 15 | int rename(const std::string& from, const std::string& to); 16 | stats * stat(const std::string& path); 17 | stats * lstat(const std::string& path); 18 | int truncate(const std::string& path, int len); 19 | int chown(const std::string& path, int uid, int gid); 20 | int lchown(const std::string& path, int uid, int gid); 21 | size_t size(const std::string& path); 22 | std::string read(const std::string& path); 23 | std::string nread(const std::string& path, int len); 24 | std::list readlines(const std::string& path); 25 | int write(const std::string& path, const char *buffer); 26 | int nwrite(const std::string& path, const char *buffer, int len); 27 | int mkdir(const std::string& path, int mode); 28 | int rmdir(const std::string& path); 29 | bool exists(const std::string& path); 30 | 31 | // additional helper methods 32 | std::string join(const std::string& dirname, const std::string& basename); 33 | std::string join(const std::string&, const std::string&, const std::string&); 34 | std::string dirname(const std::string& path); 35 | std::string basename(const std::string& path); 36 | std::string extname(const std::string& path); 37 | bool is_disconnected(const std::string& path); 38 | bool is_dir(const std::string& path); 39 | bool is_symlink(const std::string& path); 40 | int mkdir_p(const std::string& dir, const mode_t mode = 0755); 41 | int rm_rf(const std::string& path); 42 | bool is_absolute(const std::string& path); 43 | bool is_accessible(const std::string& path, int mode = R_OK, const std::string& work_dir = ""); 44 | bool touch(const std::string& path); 45 | bool is_mounted(const std::string& path); 46 | std::list scandir(const std::string& path); 47 | std::string resolve(const std::string& path); 48 | std::string make_absolute(const std::string& path); 49 | 50 | extern const char PATH_SEPARATOR; 51 | 52 | class ScopedFileLock { 53 | public: 54 | ScopedFileLock(const std::string& path); 55 | ~ScopedFileLock(); 56 | private: 57 | int fd_; 58 | }; 59 | } 60 | -------------------------------------------------------------------------------- /src/sha1.cc: -------------------------------------------------------------------------------- 1 | #include "sha1.hpp" 2 | #include 3 | #include 4 | #include 5 | 6 | extern "C" { 7 | #include "deps/sha1/sha1.h" 8 | #include "deps/sha1/sha1.c" 9 | } 10 | 11 | std::string sha1(const std::string& content) { 12 | SHA1_CTX sha; 13 | uint8_t results[20]; 14 | 15 | SHA1Init(&sha); 16 | SHA1Update(&sha, (uint8_t *)content.data(), content.length()); 17 | SHA1Final(results, &sha); 18 | 19 | // Convert binary to string 20 | char result[41]; 21 | for (int n = 0; n < 20; n++) { 22 | snprintf(result + n * 2, 3, "%02x", results[n]); 23 | } 24 | 25 | return result; 26 | } 27 | -------------------------------------------------------------------------------- /src/sha1.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | std::string sha1(const std::string& content); 5 | -------------------------------------------------------------------------------- /src/term.cc: -------------------------------------------------------------------------------- 1 | #include "term.hpp" 2 | #include 3 | #include 4 | 5 | void term::set(int attr, int fg, int bg, FILE *fp) { 6 | if (!isatty(fileno(fp))) return; 7 | fprintf(fp, "\x1b[%d;%d;%dm", attr, fg, bg); 8 | } 9 | 10 | void term::set(int attr, int fg, FILE *fp) { 11 | if (!isatty(fileno(fp))) return; 12 | fprintf(fp, "\x1b[%d;%dm", attr, fg); 13 | } 14 | 15 | void term::set(int attr, FILE *fp) { 16 | if (!isatty(fileno(fp))) return; 17 | fprintf(fp, "\x1b[%dm", attr); 18 | } 19 | -------------------------------------------------------------------------------- /src/term.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace term { 6 | namespace attr { 7 | const int RESET = 0; 8 | const int BOLD = 1; 9 | const int UNDERSCORE = 4; 10 | const int BLINK = 5; 11 | const int REVERSE = 7; 12 | const int CONCEALED = 8; 13 | } 14 | 15 | namespace fg { 16 | const int BLACK = 30; 17 | const int RED = 31; 18 | const int GREEN = 32; 19 | const int YELLOW = 33; 20 | const int BLUE = 34; 21 | const int MAGENTA = 35; 22 | const int CYAN = 36; 23 | const int WHITE = 37; 24 | } 25 | 26 | namespace bg { 27 | const int BLACK = 40; 28 | const int RED = 41; 29 | const int GREEN = 42; 30 | const int YELLOW = 43; 31 | const int BLUE = 44; 32 | const int MAGENTA = 45; 33 | const int CYAN = 46; 34 | const int WHITE = 47; 35 | } 36 | 37 | extern void set(int attr, int fg, FILE *fp = stdout); 38 | extern void set(int attr, int fg, int bg, FILE *fp = stdout); 39 | extern void set(int attr = attr::RESET, FILE *fp = stdout); 40 | } 41 | --------------------------------------------------------------------------------