├── README.md ├── _config.yml ├── samples ├── c++ │ ├── CMakeLists.txt │ ├── cmake │ │ └── FindPoco.cmake │ ├── include │ │ ├── json.h │ │ └── ppe.h │ └── src │ │ ├── json.cpp │ │ ├── main.cpp │ │ └── ppe.cpp └── python │ └── sample.py └── whitepaper ├── cortexica_whitepaper_realtime_ppe_monitoring_edge.pdf └── images ├── access_control.jpg ├── arch.jpg ├── continuous_monitoring.png ├── iotswc.JPG ├── myriad-x.jpg ├── myriad-x.png ├── pharma-ppe.jpg ├── ppe-rrk.jpg ├── sample.png └── stats.png /README.md: -------------------------------------------------------------------------------- 1 | # Real-time PPE Monitoring on the Edge 2 | powered by the latest ultra-low-power high-performance [Intel Myriad X VPU](https://www.movidius.com/myriadx) 3 | 4 | [Martin Peniak, PhD](http://www.martinpeniak.com) — [Innovation Department](https://www.cortexica.com/research-innovation/) 5 | martin@cortexica.com 6 | 7 | ## Abstract 8 | Personal Protective Equipment (PPE) is the equipment that protects the user against health or safety risks. Not wearing PPE dramatically increases the chances of injuries and in many situations also of financial losses due to fines for injuries and death of workers as well as contamination caused by not wearing gloves, hairnets, shoe covers, etc. Recent advancements in edge computing hardware coupled with ever more efficient software have enabled novel solutions with the potential to prevent injuries, save lives as well as money and time. This document describes the world’s first edge compute solution for PPE ingress and real- time PPE compliance monitoring. 9 | 10 |

11 | 12 |

13 | 14 | ## Introduction 15 | Cortexica has been at the forefront of the machine vision revolution. We have reverse-engineered parts of the human visual cortex, which allowed us to develop a powerful image search engine nowadays widely used to solve many real-world problems. Partnering with various world-leading businesses allows us to identify numerous real-world problems that can be addressed by applying machine vision methods. Some of the solutions to these problems are often very specific while others are widely applicable and have the potential to save lives. Probably the best example of this is our family of solutions designed for PPE ingress and real-time PPE compliance monitoring (see Figures 1 and 2). 16 | 17 | PPE is designed to protect users from serious injuries or illnesses resulting from a physical, mechanical, electrical, chemical or radiological contact. The importance of PPE is paramount because it serves as the last line of defence against an injury or death. Unfortunately, studies have demonstrated that 98% of workers said they have seen others not wearing PPE when they should have been and 30% of those said this happens regularly. Head injuries, constituting 9% of all injuries, can be fatal and yet 84% of these were caused by not wearing a helmet [1]. Most of these injuries could have been prevented had there been a system in place that would continuously monitor for PPE compliance. 18 | 19 | Recent advancements in edge computing gave raise to novel applications designed to process data right at its source effectively minimising latency and allowing real-time processing. This paper presents a solution for PPE ingress and compliance monitoring that runs in real-time and entirely on the edge. 20 | 21 |
22 | 23 |
24 | 25 | *Fig.1 - Cortexica PPE ingress solution installed at Axis Experience Centre, Madrid. This solution detects if a person is wearing a helmet and a high visibility jacket. A person is only allowed to enter a workplace once all the PPE checks have been approved.* 26 | 27 |
28 | 29 |
30 | 31 | *Fig.2 - Cortexica real-time PPE compliance monitoring solution installed at Axis Experience Centre, Madrid. This solution is continuously scanning workplace and raises an alarm if a person is not wearing a helmet and a high visibility jacket. The scanning is done using Axis pan/tilt/zoom (PTZ) camera and Axis radar capable of detecting motion within 50 meters range. The radar detects motion and then automatically moves the camera to the point of interest.* 32 | 33 |
34 | 35 |
36 | 37 | *Fig.3 - Cortexica PPE ingress solution designed for a pharmaceutical company. This solution detects if an employee is wearing boots, overall, gloves, hairnet, beardnet, head cover and transparent glasses. An employee is only allowed to enter a workplace once all the PPE checks have been approved.* 38 | 39 |
40 | 41 |
42 | 43 | *Fig.4 - Cortexica was the first and only company to present a working demonstration utilising the latest Intel Myriad X VPU. This image shows one of our AI Safety (PPE) demos at the Intel booth. The second demo was installed at AAEON (Asus asoc.) stand.* 44 | 45 | ## Development Kit Overview 46 | It takes more than algorithms to deliver an AI driven product that solves a real-life problem. Working in partnership with UP we have developed UP Squared AI Edge-PPE monitoring, a development kit (see Figure 5) for health and safety professionals to create proof of concepts (POC) to full blown AI applications ready for live deployment. The development kit offers the following: 47 | 48 | * Real-time video analysis with advanced algorithms and machine learning to ensure employees are wearing the correct PPE for their working environment 49 | * Parallel detection of PPE, Face, Person, and Body parts leveraging CPU, GPU and VPU processors 50 | * Powered by the latest ultra-low-power high-performance Intel Myriad X VPU (see Figures 6 and 7) 51 | * Single image mode 52 | * Real-time mode 53 | * Made for POCs 54 | 55 |
56 | 57 |
58 | 59 | *Fig.5 - The PPE monitoring development kit is available to purchase as an off-the-shelf solution, complete with hardware and software configuration, and detailed step-by-step guides to help you start prototyping your next AI monitoring or video surveillance project. For health and safety professions, this development kit assists the creation of a PPE monitoring system, and for industries at large, an AI driven surveillance application.* 60 | 61 |
62 | 63 |
64 | 65 | *Fig.6 - The AI CORE X is powered by the recently released Intel® Movidius Myriad X, a third-generation vision processing unit (VPU) that is the first in its class to include a Neural Compute Engine – a dedicated hardware accelerator for deep neural networks, trainable with industry-standard tools.* 66 | 67 |
68 | 69 |
70 | 71 | *Fig.7 - Myriad™X features the all-new Neural Compute Engine - a purpose-built hardware accelerator designed to dramatically increase performance of deep neural networks without compromising the low power characteristics of the Myriad VPU product line. Featuring an array of MAC blocks and directly interfacing with the intelligent memory fabric, the Neural Compute Engine is able to rapidly perform the calculations necessary for deep inference without hitting the so-called "data wall" bottleneck encountered by other processor designs. Combining the neural network performance of the 16 proprietary SHAVE cores with the neural compute engine, Myriad X delivers 10X the performance compared to previous generations.* 72 | 73 | ## Software 74 | This section provides a detailed description of the software architecture, its components and their integration through the REST API. 75 | 76 |
77 | 78 |
79 | 80 | *Fig.8 - Software architecture diagram showing the PPE service and the demo sample. The PPE service receives an image and a JSON specifying simple options and returns a JSON with detection results containing bounding boxes, corresponding object classes and the time in milliseconds that it took to run a single inference.* 81 | 82 | ### PPE Service 83 | The PPE service is a C++ application running a HTTP server with a REST API. This service is able to run inference on multiple deep learning models in parallel on all the available CPU, GPU and VPU processors to obtain the results in the shortest time possible. The service starts automatically running after the operating system is initialised and then continues running on the port 8081. The REST API has the following endpoints that can be used to interact with the service: 84 | 85 | * **/ppe** – single image mode allowing maximum of 30 requests followed by 90 seconds timeout 86 | * **/continuous-ppe** – continuous mode allowing unlimited number of images within 60 seconds followed by 90 seconds timeout 87 | 88 | Both endpoints accept multipart/form-data POST requests containing an image and a JSON specifying the query options. For example the following JSON options example enables all the four models with thresholds set to 60% confidence. The threshold parameters are optional and if no threshold is set then the default value of 50% confidence will be applied. 89 | 90 | ```javascript 91 | { 92 | “detectPPE”: true, 93 | “detectFaces”: true, 94 | “detectPersons”: true, 95 | “detectBodyParts”: true, 96 | “ppeThreshold”: 0.6, 97 | “faceThreshold”: 0.6, 98 | “personThreshold”: 0.6, 99 | “bodyPartsThreshold”: 0.6 100 | } 101 | ``` 102 | 103 | Since the PPE service provides the REST interface the integration with your own application is very easy and can be also done accross the network. The sample application described in the next section shows how to achieve this integration using C++ but you can use any programming language or method. For example, here is a curl request code: 104 | 105 | ```shell 106 | curl 107 | −−request POST 108 | −−url http://localhost:8081/ppe 109 | −−header ’content−type:multipart/form−data; boundary=−−−−WebKitFormBoundary’ 110 | −−form’ options={ 111 | “detectPPE “ : true, 112 | “detectFaces “ : true, 113 | “detectPersons “ : true, 114 | “detectBodyParts “ : true, 115 | “ppeThreshold “ : 0.6, 116 | “faceThreshold “ : 0.6, 117 | “personThreshold “ : 0.6, 118 | “bodyPartsThreshold “ : 0.6}’ 119 | −−form image=@example.png 120 | ``` 121 | 122 | The following snipped shows a JSON results example: 123 | 124 | ```javascript 125 | { 126 | "ms": 49, 127 | "result": [ 128 | { 129 | "categoryClass": "vest", 130 | "confidence": 0.92055, 131 | "xEnd": 0.82968, 132 | "xStart": 0.4789, 133 | "yEnd": 0.99027, 134 | "yStart": 0.36382 135 | }, 136 | { 137 | "categoryClass": "helmet", 138 | "confidence": 0.95361, 139 | "xEnd": 0.74687, 140 | "xStart": 0.58749, 141 | "yEnd": 0.21527, 142 | "yStart": 0.03449 143 | }, 144 | { 145 | "categoryClass": "face", 146 | "confidence": 1, 147 | "xEnd": 0.92653, 148 | "xStart": 0.61093, 149 | "yEnd": 0.41527, 150 | "yStart": 0.13194 151 | } 152 | ], 153 | "status": 0 154 | } 155 | ``` 156 | 157 | where **ms** is inference time in milliseconds, **categoryClass** is the class of the detected object, confidence is the detection confidence level (e.g. 0.95 =95% confidence) and **xStart**, **xEnd**, **yStart**, **yEnd** define the bounding boxes of the detected object. When multiplied with the image dimensions, pixel coordinates can be obtained. For example, a bounding box in OpenCV can be created using: 158 | 159 | ``` 160 | cv::Rect rect(cv::Point(xStart * width, yStart * height), cv::Point(xEnd * width, yEnd * height)) 161 | ``` 162 | 163 | ### PPE Demo Sample 164 | This sample application was written in C++ to demonstrate how to send queries to and receive results from the PPE service via the REST API. The application source code is located under /home/upsquared/cortexica/sample/ and the compiled binary under the bin subdirectory. The application depends only on OpenCV and Poco libraries. To compile the sample run the following commands: 165 | 166 | ```shell 167 | $ cd /home/upsquared/cortexica/sample/ 168 | $ mkdir build 169 | $ cd build 170 | $ source /opt/intel/computer_vision_sdk/bin/setupvars.sh 171 | $ cmake .. 172 | $ make 173 | ``` 174 | 175 | You can run the application using as follows: 176 | 177 | ```shell 178 | $ bin/sample 179 | ``` 180 | Here is an example of sample application front-end showing the detection results plotted as bounding boxes. The four sliders at the top are used to adjust the sensitivity of the models or to turn them off completely. 181 | 182 |
183 | 184 |
185 | 186 | ### License and Limitations 187 | The development kit has been primarily designed to enable the evaluation of our technology and to facilitate seamless integration with other applications with the goal of creating POCs. If a client is satisfied with the POC and wants to use it for commercial purposes then the client should contact us to obtain a license and a production grade software with models optimised for that specific use case. As a consequence, using this development kit for commercial purposes is prohibited. The following measures have been implemented to prevent unauthorised use of this development kit: 188 | 189 | * The PPE service will expire in one year from its first use 190 | * Models have been encrypted to prevent unauthorised use 191 | * Single image mode is restricted to a maximum of 30 consecutive requests 192 | * There is a 90 seconds time out afterwards during which no requests can be made 193 | * Additional requests can be made after this time out has finished 194 | * Real-time mode allows unlimited number of frames within a 60 seconds period 195 | * There is a 90 seconds time out after these 20 seconds during which no requests can be made 196 | * Additional requests can be made after this time out has finished 197 | 198 | ## Videos 199 | * [AI-Safe](https://vimeo.com/333964736) 200 | * [PPE Ingress](https://vimeo.com/cortexica/ingressconstruction) 201 | * [PPE Continuous Monitoring](https://vimeo.com/cortexica/continuousmonitoringradar) 202 | * [Artificial Intelligence on the Edge - Safety](https://player.vimeo.com/video/297960010) 203 | 204 | ## References 205 | [1] U.S. Department of Labor, Bureau of Labor Statistics, Accidents Involving Head Injuries, Report 605, (Washington, D.C., Government Printing Office, July 1980) p. 1 206 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman 2 | -------------------------------------------------------------------------------- /samples/c++/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.2) 2 | 3 | project(sample) 4 | 5 | set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) 6 | 7 | find_package(OpenCV REQUIRED) 8 | find_package(Poco REQUIRED COMPONENTS Foundation Net NetSSL Util) 9 | 10 | set(CMAKE_BUILD_TYPE Release) 11 | set(CMAKE_CXX_FLAGS_RELEASE "-O3") 12 | set(CMAKE_CXX_STANDARD 14) 13 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin) 14 | 15 | FILE(GLOB INCLUDES include/*.h) 16 | FILE(GLOB SOURCES src/*.cpp) 17 | 18 | source_group("Header Files" FILES ${INCLUDES}) 19 | source_group("Source Files" FILES ${SOURCES}) 20 | 21 | add_executable(${PROJECT_NAME} ${INCLUDES} ${SOURCES}) 22 | 23 | include_directories(${PROJECT_SOURCE_DIR}/include) 24 | 25 | target_link_libraries(${PROJECT_NAME} ${Poco_LIBRARIES} ${OpenCV_LIBS}) 26 | install(TARGETS ${PROJECT_NAME} DESTINATION /home/upsquared/cortexica/samples/c++/bin/) 27 | -------------------------------------------------------------------------------- /samples/c++/cmake/FindPoco.cmake: -------------------------------------------------------------------------------- 1 | # - Find the Poco includes and libraries. 2 | # The following variables are set if Poco is found. If Poco is not 3 | # found, Poco_FOUND is set to false. 4 | # Poco_FOUND - True when the Poco include directory is found. 5 | # Poco_INCLUDE_DIRS - the path to where the poco include files are. 6 | # Poco_LIBRARY_DIR - The path to where the poco library files are. 7 | # Poco_BINARY_DIRS - The path to where the poco dlls are. 8 | # Poco_LIBRARIES - list of all libs from requested components. 9 | 10 | # ---------------------------------------------------------------------------- 11 | # If you have installed Poco in a non-standard location. 12 | # Then you have three options. 13 | # In the following comments, it is assumed that 14 | # points to the root directory of the include directory of Poco. e.g 15 | # If you have put poco in C:\development\Poco then is 16 | # "C:/development/Poco" and in this directory there will be two 17 | # directories called "include" and "lib". 18 | # 1) After CMake runs, set Poco_INCLUDE_DIR to /poco<-version> 19 | # 2) Use CMAKE_INCLUDE_PATH to set a path to /poco<-version>. This will allow FIND_PATH() 20 | # to locate Poco_INCLUDE_DIR by utilizing the PATH_SUFFIXES option. e.g. 21 | # SET(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "/include") 22 | # 3) Set an environment variable called ${POCO_ROOT} that points to the root of where you have 23 | # installed Poco, e.g. . It is assumed that there is at least a subdirectory called 24 | # Foundation/include/Poco in this path. 25 | # 26 | # Note: 27 | # 1) If you are just using the poco headers, then you do not need to use 28 | # Poco_LIBRARY_DIR in your CMakeLists.txt file. 29 | # 2) If Poco has not been installed, then when setting Poco_LIBRARY_DIR 30 | # the script will look for /lib first and, if this fails, then for /stage/lib. 31 | # 32 | # Usage: 33 | # In your CMakeLists.txt file do something like this: 34 | # ... 35 | # # Poco 36 | # FIND_PACKAGE(Poco COMPONENTS XML Net Data...) 37 | # ... 38 | # INCLUDE_DIRECTORIES(${Poco_INCLUDE_DIRS}) 39 | # LINK_DIRECTORIES(${Poco_LIBRARY_DIR}) 40 | # 41 | # In Windows, we make the assumption that, if the Poco files are installed, the default directory 42 | # will be C:\poco or C:\Program Files\Poco or C:\Programme\Poco. 43 | 44 | MESSAGE(STATUS "Searching for Poco library...") 45 | 46 | SET(POCO_INCLUDE_PATH_DESCRIPTION "top-level directory containing the poco include directories. E.g /usr/local/include/ or c:\\poco\\include\\poco-1.3.2") 47 | SET(POCO_INCLUDE_DIR_MESSAGE "Set the Poco_INCLUDE_DIR cmake cache entry to the ${POCO_INCLUDE_PATH_DESCRIPTION}") 48 | SET(POCO_LIBRARY_PATH_DESCRIPTION "top-level directory containing the poco libraries.") 49 | SET(POCO_LIBRARY_DIR_MESSAGE "Set the Poco_LIBRARY_DIR cmake cache entry to the ${POCO_LIBRARY_PATH_DESCRIPTION}") 50 | 51 | 52 | SET(POCO_DIR_SEARCH $ENV{POCO_ROOT}) 53 | IF(POCO_DIR_SEARCH) 54 | FILE(TO_CMAKE_PATH ${POCO_DIR_SEARCH} POCO_DIR_SEARCH) 55 | ENDIF(POCO_DIR_SEARCH) 56 | 57 | 58 | IF(WIN32) 59 | SET(POCO_DIR_SEARCH 60 | ${POCO_DIR_SEARCH} 61 | C:/poco 62 | D:/poco 63 | "C:/Program Files/poco" 64 | "C:/Programme/poco" 65 | "D:/Program Files/poco" 66 | "D:/Programme/poco" 67 | ) 68 | ENDIF(WIN32) 69 | 70 | # Add in some path suffixes. These will have to be updated whenever a new Poco version comes out. 71 | SET(SUFFIX_FOR_INCLUDE_PATH 72 | poco-1.3.2 73 | poco-1.3.3 74 | poco-1.3.4 75 | poco-1.3.5 76 | poco-1.3.6 77 | ) 78 | 79 | SET(SUFFIX_FOR_LIBRARY_PATH 80 | poco-1.3.2/lib 81 | poco-1.3.2/lib/Linux/i686 82 | poco-1.3.2/lib/Linux/x86_64 83 | poco-1.3.3/lib 84 | poco-1.3.3/lib/Linux/i686 85 | poco-1.3.3/lib/Linux/x86_64 86 | poco-1.3.4/lib 87 | poco-1.3.4/lib/Linux/i686 88 | poco-1.3.4/lib/Linux/x86_64 89 | poco-1.3.5/lib 90 | poco-1.3.5/lib/Linux/i686 91 | poco-1.3.5/lib/Linux/x86_64 92 | poco-1.3.6/lib 93 | poco-1.3.6/lib/Linux/i686 94 | poco-1.3.6/lib/Linux/x86_64 95 | lib 96 | lib/Linux/i686 97 | lib/Linux/x86_64 98 | ) 99 | 100 | # 101 | # Look for an installation. 102 | # 103 | FIND_PATH(Poco_INCLUDE_DIR NAMES Foundation/include/Poco/SharedLibrary.h PATH_SUFFIXES ${SUFFIX_FOR_INCLUDE_PATH} PATHS 104 | 105 | # Look in other places. 106 | ${POCO_DIR_SEARCH} 107 | 108 | # Help the user find it if we cannot. 109 | DOC "The ${POCO_INCLUDE_PATH_DESCRIPTION}" 110 | ) 111 | 112 | IF(NOT Poco_INCLUDE_DIR) 113 | 114 | # Look for standard unix include paths 115 | FIND_PATH(Poco_INCLUDE_DIR Poco/Poco.h DOC "The ${POCO_INCLUDE_PATH_DESCRIPTION}") 116 | 117 | ENDIF(NOT Poco_INCLUDE_DIR) 118 | 119 | # Assume we didn't find it. 120 | SET(Poco_FOUND 0) 121 | 122 | # Now try to get the include and library path. 123 | IF(Poco_INCLUDE_DIR) 124 | IF(EXISTS "${Poco_INCLUDE_DIR}/Foundation/include/Poco/SharedLibrary.h") 125 | SET(Poco_INCLUDE_DIRS 126 | ${Poco_INCLUDE_DIR}/CppUnit/include 127 | ${Poco_INCLUDE_DIR}/Foundation/include 128 | ${Poco_INCLUDE_DIR}/Net/include 129 | ${Poco_INCLUDE_DIR}/Util/include 130 | ${Poco_INCLUDE_DIR}/XML/include 131 | ) 132 | SET(Poco_FOUND 1) 133 | ELSEIF(EXISTS "${Poco_INCLUDE_DIR}/Poco/Poco.h") 134 | SET(Poco_INCLUDE_DIRS 135 | ${Poco_INCLUDE_DIR} 136 | ) 137 | SET(Poco_FOUND 1) 138 | ENDIF() 139 | 140 | IF(NOT Poco_LIBRARY_DIR) 141 | 142 | FIND_LIBRARY(Poco_FOUNDATION_LIB NAMES PocoFoundation PocoFoundationd PATH_SUFFIXES ${SUFFIX_FOR_LIBRARY_PATH} PATHS 143 | 144 | # Look in other places. 145 | ${Poco_INCLUDE_DIR} 146 | ${POCO_DIR_SEARCH} 147 | 148 | # Help the user find it if we cannot. 149 | DOC "The ${POCO_LIBRARY_PATH_DESCRIPTION}" 150 | ) 151 | SET(Poco_LIBRARY_DIR "" CACHE PATH POCO_LIBARARY_PATH_DESCRIPTION) 152 | GET_FILENAME_COMPONENT(Poco_LIBRARY_DIR ${Poco_FOUNDATION_LIB} PATH) 153 | SET(Poco_LIBRARIES "") 154 | SET(Comp_List "") 155 | IF(Poco_LIBRARY_DIR AND Poco_FOUNDATION_LIB) 156 | # Look for the poco binary path. 157 | SET(Poco_BINARY_DIR ${Poco_INCLUDE_DIR}) 158 | IF(Poco_BINARY_DIR AND EXISTS "${Poco_BINARY_DIR}/bin") 159 | SET(Poco_BINARY_DIRS ${Poco_BINARY_DIR}/bin) 160 | ENDIF(Poco_BINARY_DIR AND EXISTS "${Poco_BINARY_DIR}/bin") 161 | ENDIF(Poco_LIBRARY_DIR AND Poco_FOUNDATION_LIB) 162 | IF(Poco_FOUNDATION_LIB) 163 | IF ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") 164 | SET(DBG "d") 165 | ELSE ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") 166 | SET(DBG "") 167 | ENDIF ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") 168 | SET(Comp_List "Foundation${DBG}") 169 | FOREACH(COMPONENT ${Poco_FIND_COMPONENTS}) 170 | FIND_LIBRARY(LIB${COMPONENT} "Poco${COMPONENT}${DBG}" Poco_LIBRARY_DIR) 171 | IF (LIB${COMPONENT}) 172 | LIST(APPEND Poco_LIBRARIES "${LIB${COMPONENT}}") 173 | LIST(APPEND Comp_List "${COMPONENT}${DBG}") 174 | ENDIF(LIB${COMPONENT}) 175 | ENDFOREACH(COMPONENT) 176 | LIST(REMOVE_DUPLICATES Comp_List) 177 | ENDIF(Poco_FOUNDATION_LIB) 178 | ENDIF(NOT Poco_LIBRARY_DIR) 179 | ENDIF(Poco_INCLUDE_DIR) 180 | 181 | IF(NOT Poco_FOUND) 182 | IF(Poco_FIND_QUIETLY) 183 | MESSAGE(STATUS "Poco was not found. ${POCO_INCLUDE_DIR_MESSAGE}") 184 | ELSE(Poco_FIND_QUIETLY) 185 | IF(Poco_FIND_REQUIRED) 186 | MESSAGE(FATAL_ERROR "Poco was not found. ${POCO_INCLUDE_DIR_MESSAGE}") 187 | ENDIF(Poco_FIND_REQUIRED) 188 | ENDIF(Poco_FIND_QUIETLY) 189 | ELSE(NOT Poco_FOUND) 190 | MESSAGE(STATUS " Found Poco!") 191 | SET(COMPONENT_STR "components found:") 192 | FOREACH(comp ${Comp_List}) 193 | SET(COMPONENT_STR "${COMPONENT_STR}, ${comp}") 194 | 195 | ENDFOREACH(comp ${Comp_List}) 196 | STRING(REPLACE ":," ":" COMPONENT_LSTR ${COMPONENT_STR}) 197 | MESSAGE(STATUS "${COMPONENT_LSTR}.") 198 | ENDIF(NOT Poco_FOUND) 199 | 200 | #I added this in to add "libdl" on non-Windows systems. Technically dl is only neded if the "Foundation" component is used, 201 | #but i doesn't hurt to add it in anyway - mas 202 | if(Poco_FOUND AND NOT WIN32) 203 | LIST(APPEND Poco_LIBRARIES "dl") 204 | endif(Poco_FOUND AND NOT WIN32) -------------------------------------------------------------------------------- /samples/c++/include/json.h: -------------------------------------------------------------------------------- 1 | /// Json-cpp amalgated header (http://jsoncpp.sourceforge.net/). 2 | /// It is intended to be used with #include "json/json.h" 3 | 4 | // ////////////////////////////////////////////////////////////////////// 5 | // Beginning of content of file: LICENSE 6 | // ////////////////////////////////////////////////////////////////////// 7 | 8 | /* 9 | The JsonCpp library's source code, including accompanying documentation, 10 | tests and demonstration applications, are licensed under the following 11 | conditions... 12 | 13 | The author (Baptiste Lepilleur) explicitly disclaims copyright in all 14 | jurisdictions which recognize such a disclaimer. In such jurisdictions, 15 | this software is released into the Public Domain. 16 | 17 | In jurisdictions which do not recognize Public Domain property (e.g. Germany as of 18 | 2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is 19 | released under the terms of the MIT License (see below). 20 | 21 | In jurisdictions which recognize Public Domain property, the user of this 22 | software may choose to accept it either as 1) Public Domain, 2) under the 23 | conditions of the MIT License (see below), or 3) under the terms of dual 24 | Public Domain/MIT License conditions described here, as they choose. 25 | 26 | The MIT License is about as close to Public Domain as a license can get, and is 27 | described in clear, concise terms at: 28 | 29 | http://en.wikipedia.org/wiki/MIT_License 30 | 31 | The full text of the MIT License follows: 32 | 33 | ======================================================================== 34 | Copyright (c) 2007-2010 Baptiste Lepilleur 35 | 36 | Permission is hereby granted, free of charge, to any person 37 | obtaining a copy of this software and associated documentation 38 | files (the "Software"), to deal in the Software without 39 | restriction, including without limitation the rights to use, copy, 40 | modify, merge, publish, distribute, sublicense, and/or sell copies 41 | of the Software, and to permit persons to whom the Software is 42 | furnished to do so, subject to the following conditions: 43 | 44 | The above copyright notice and this permission notice shall be 45 | included in all copies or substantial portions of the Software. 46 | 47 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 48 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 49 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 50 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 51 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 52 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 53 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 54 | SOFTWARE. 55 | ======================================================================== 56 | (END LICENSE TEXT) 57 | 58 | The MIT license is compatible with both the GPL and commercial 59 | software, affording one all of the rights of Public Domain with the 60 | minor nuisance of being required to keep the above copyright notice 61 | and license text in the source code. Note also that by accepting the 62 | Public Domain "license" you can re-license your copy using whatever 63 | license you like. 64 | 65 | */ 66 | 67 | // ////////////////////////////////////////////////////////////////////// 68 | // End of content of file: LICENSE 69 | // ////////////////////////////////////////////////////////////////////// 70 | 71 | #ifndef JSON_AMALGATED_H_INCLUDED 72 | #define JSON_AMALGATED_H_INCLUDED 73 | /// If defined, indicates that the source file is amalgated 74 | /// to prevent private header inclusion. 75 | #define JSON_IS_AMALGAMATION 76 | 77 | // ////////////////////////////////////////////////////////////////////// 78 | // Beginning of content of file: include/json/version.h 79 | // ////////////////////////////////////////////////////////////////////// 80 | 81 | // DO NOT EDIT. This file (and "version") is generated by CMake. 82 | // Run CMake configure step to update it. 83 | #ifndef JSON_VERSION_H_INCLUDED 84 | #define JSON_VERSION_H_INCLUDED 85 | 86 | #define JSONCPP_VERSION_STRING "1.6.5" 87 | #define JSONCPP_VERSION_MAJOR 1 88 | #define JSONCPP_VERSION_MINOR 6 89 | #define JSONCPP_VERSION_PATCH 5 90 | #define JSONCPP_VERSION_QUALIFIER 91 | #define JSONCPP_VERSION_HEXA \ 92 | ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8)) 93 | 94 | #endif // JSON_VERSION_H_INCLUDED 95 | 96 | // ////////////////////////////////////////////////////////////////////// 97 | // End of content of file: include/json/version.h 98 | // ////////////////////////////////////////////////////////////////////// 99 | 100 | // ////////////////////////////////////////////////////////////////////// 101 | // Beginning of content of file: include/json/config.h 102 | // ////////////////////////////////////////////////////////////////////// 103 | 104 | // Copyright 2007-2010 Baptiste Lepilleur 105 | // Distributed under MIT license, or public domain if desired and 106 | // recognized in your jurisdiction. 107 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 108 | 109 | #ifndef JSON_CONFIG_H_INCLUDED 110 | #define JSON_CONFIG_H_INCLUDED 111 | 112 | /// If defined, indicates that json library is embedded in CppTL library. 113 | //# define JSON_IN_CPPTL 1 114 | 115 | /// If defined, indicates that json may leverage CppTL library 116 | //# define JSON_USE_CPPTL 1 117 | /// If defined, indicates that cpptl vector based map should be used instead of 118 | /// std::map 119 | /// as Value container. 120 | //# define JSON_USE_CPPTL_SMALLMAP 1 121 | 122 | // If non-zero, the library uses exceptions to report bad input instead of C 123 | // assertion macros. The default is to use exceptions. 124 | #ifndef JSON_USE_EXCEPTION 125 | #define JSON_USE_EXCEPTION 1 126 | #endif 127 | 128 | /// If defined, indicates that the source file is amalgated 129 | /// to prevent private header inclusion. 130 | /// Remarks: it is automatically defined in the generated amalgated header. 131 | // #define JSON_IS_AMALGAMATION 132 | 133 | #ifdef JSON_IN_CPPTL 134 | #include 135 | #ifndef JSON_USE_CPPTL 136 | #define JSON_USE_CPPTL 1 137 | #endif 138 | #endif 139 | 140 | #ifdef JSON_IN_CPPTL 141 | #define JSON_API CPPTL_API 142 | #elif defined(JSON_DLL_BUILD) 143 | #if defined(_MSC_VER) 144 | #define JSON_API __declspec(dllexport) 145 | #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING 146 | #endif // if defined(_MSC_VER) 147 | #elif defined(JSON_DLL) 148 | #if defined(_MSC_VER) 149 | #define JSON_API __declspec(dllimport) 150 | #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING 151 | #endif // if defined(_MSC_VER) 152 | #endif // ifdef JSON_IN_CPPTL 153 | #if !defined(JSON_API) 154 | #define JSON_API 155 | #endif 156 | 157 | // If JSON_NO_INT64 is defined, then Json only support C++ "int" type for 158 | // integer 159 | // Storages, and 64 bits integer support is disabled. 160 | // #define JSON_NO_INT64 1 161 | 162 | #if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6 163 | // Microsoft Visual Studio 6 only support conversion from __int64 to double 164 | // (no conversion from unsigned __int64). 165 | #define JSON_USE_INT64_DOUBLE_CONVERSION 1 166 | // Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255' 167 | // characters in the debug information) 168 | // All projects I've ever seen with VS6 were using this globally (not bothering 169 | // with pragma push/pop). 170 | #pragma warning(disable : 4786) 171 | #endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6 172 | 173 | #if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008 174 | /// Indicates that the following function is deprecated. 175 | #define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) 176 | #elif defined(__clang__) && defined(__has_feature) 177 | #if __has_feature(attribute_deprecated_with_message) 178 | #define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) 179 | #endif 180 | #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) 181 | #define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) 182 | #elif defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) 183 | #define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__)) 184 | #endif 185 | 186 | #if !defined(JSONCPP_DEPRECATED) 187 | #define JSONCPP_DEPRECATED(message) 188 | #endif // if !defined(JSONCPP_DEPRECATED) 189 | 190 | namespace Json 191 | { 192 | typedef int Int; 193 | typedef unsigned int UInt; 194 | #if defined(JSON_NO_INT64) 195 | typedef int LargestInt; 196 | typedef unsigned int LargestUInt; 197 | #undef JSON_HAS_INT64 198 | #else // if defined(JSON_NO_INT64) 199 | // For Microsoft Visual use specific types as long long is not supported 200 | #if defined(_MSC_VER) // Microsoft Visual Studio 201 | typedef __int64 Int64; 202 | typedef unsigned __int64 UInt64; 203 | #else // if defined(_MSC_VER) // Other platforms, use long long 204 | typedef long long int Int64; 205 | typedef unsigned long long int UInt64; 206 | #endif // if defined(_MSC_VER) 207 | typedef Int64 LargestInt; 208 | typedef UInt64 LargestUInt; 209 | #define JSON_HAS_INT64 210 | #endif // if defined(JSON_NO_INT64) 211 | } // end namespace Json 212 | 213 | #endif // JSON_CONFIG_H_INCLUDED 214 | 215 | // ////////////////////////////////////////////////////////////////////// 216 | // End of content of file: include/json/config.h 217 | // ////////////////////////////////////////////////////////////////////// 218 | 219 | // ////////////////////////////////////////////////////////////////////// 220 | // Beginning of content of file: include/json/forwards.h 221 | // ////////////////////////////////////////////////////////////////////// 222 | 223 | // Copyright 2007-2010 Baptiste Lepilleur 224 | // Distributed under MIT license, or public domain if desired and 225 | // recognized in your jurisdiction. 226 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 227 | 228 | #ifndef JSON_FORWARDS_H_INCLUDED 229 | #define JSON_FORWARDS_H_INCLUDED 230 | 231 | #if !defined(JSON_IS_AMALGAMATION) 232 | #include "config.h" 233 | #endif // if !defined(JSON_IS_AMALGAMATION) 234 | 235 | namespace Json 236 | { 237 | 238 | // writer.h 239 | class FastWriter; 240 | class StyledWriter; 241 | 242 | // reader.h 243 | class Reader; 244 | 245 | // features.h 246 | class Features; 247 | 248 | // value.h 249 | typedef unsigned int ArrayIndex; 250 | class StaticString; 251 | class Path; 252 | class PathArgument; 253 | class Value; 254 | class ValueIteratorBase; 255 | class ValueIterator; 256 | class ValueConstIterator; 257 | 258 | } // namespace Json 259 | 260 | #endif // JSON_FORWARDS_H_INCLUDED 261 | 262 | // ////////////////////////////////////////////////////////////////////// 263 | // End of content of file: include/json/forwards.h 264 | // ////////////////////////////////////////////////////////////////////// 265 | 266 | // ////////////////////////////////////////////////////////////////////// 267 | // Beginning of content of file: include/json/features.h 268 | // ////////////////////////////////////////////////////////////////////// 269 | 270 | // Copyright 2007-2010 Baptiste Lepilleur 271 | // Distributed under MIT license, or public domain if desired and 272 | // recognized in your jurisdiction. 273 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 274 | 275 | #ifndef CPPTL_JSON_FEATURES_H_INCLUDED 276 | #define CPPTL_JSON_FEATURES_H_INCLUDED 277 | 278 | #if !defined(JSON_IS_AMALGAMATION) 279 | #include "forwards.h" 280 | #endif // if !defined(JSON_IS_AMALGAMATION) 281 | 282 | namespace Json 283 | { 284 | 285 | /** \brief Configuration passed to reader and writer. 286 | * This configuration object can be used to force the Reader or Writer 287 | * to behave in a standard conforming way. 288 | */ 289 | class JSON_API Features 290 | { 291 | public: 292 | /** \brief A configuration that allows all features and assumes all strings 293 | * are UTF-8. 294 | * - C & C++ comments are allowed 295 | * - Root object can be any JSON value 296 | * - Assumes Value strings are encoded in UTF-8 297 | */ 298 | static Features all(); 299 | 300 | /** \brief A configuration that is strictly compatible with the JSON 301 | * specification. 302 | * - Comments are forbidden. 303 | * - Root object must be either an array or an object value. 304 | * - Assumes Value strings are encoded in UTF-8 305 | */ 306 | static Features strictMode(); 307 | 308 | /** \brief Initialize the configuration like JsonConfig::allFeatures; 309 | */ 310 | Features(); 311 | 312 | /// \c true if comments are allowed. Default: \c true. 313 | bool allowComments_; 314 | 315 | /// \c true if root must be either an array or an object value. Default: \c 316 | /// false. 317 | bool strictRoot_; 318 | 319 | /// \c true if dropped null placeholders are allowed. Default: \c false. 320 | bool allowDroppedNullPlaceholders_; 321 | 322 | /// \c true if numeric object key are allowed. Default: \c false. 323 | bool allowNumericKeys_; 324 | }; 325 | 326 | } // namespace Json 327 | 328 | #endif // CPPTL_JSON_FEATURES_H_INCLUDED 329 | 330 | // ////////////////////////////////////////////////////////////////////// 331 | // End of content of file: include/json/features.h 332 | // ////////////////////////////////////////////////////////////////////// 333 | 334 | // ////////////////////////////////////////////////////////////////////// 335 | // Beginning of content of file: include/json/value.h 336 | // ////////////////////////////////////////////////////////////////////// 337 | 338 | // Copyright 2007-2010 Baptiste Lepilleur 339 | // Distributed under MIT license, or public domain if desired and 340 | // recognized in your jurisdiction. 341 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 342 | 343 | #ifndef CPPTL_JSON_H_INCLUDED 344 | #define CPPTL_JSON_H_INCLUDED 345 | 346 | #if !defined(JSON_IS_AMALGAMATION) 347 | #include "forwards.h" 348 | #endif // if !defined(JSON_IS_AMALGAMATION) 349 | #include 350 | #include 351 | #include 352 | 353 | #ifndef JSON_USE_CPPTL_SMALLMAP 354 | #include 355 | #else 356 | #include 357 | #endif 358 | #ifdef JSON_USE_CPPTL 359 | #include 360 | #endif 361 | 362 | // Disable warning C4251: : needs to have dll-interface to 363 | // be used by... 364 | #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 365 | #pragma warning(push) 366 | #pragma warning(disable : 4251) 367 | #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 368 | 369 | /** \brief JSON (JavaScript Object Notation). 370 | */ 371 | namespace Json 372 | { 373 | 374 | /** Base class for all exceptions we throw. 375 | * 376 | * We use nothing but these internally. Of course, STL can throw others. 377 | */ 378 | class JSON_API Exception : public std::exception 379 | { 380 | public: 381 | Exception(std::string const& msg); 382 | virtual ~Exception() throw(); 383 | virtual char const* what() const throw(); 384 | 385 | protected: 386 | std::string const msg_; 387 | }; 388 | 389 | /** Exceptions which the user cannot easily avoid. 390 | * 391 | * E.g. out-of-memory (when we use malloc), stack-overflow, malicious input 392 | * 393 | * \remark derived from Json::Exception 394 | */ 395 | class JSON_API RuntimeError : public Exception 396 | { 397 | public: 398 | RuntimeError(std::string const& msg); 399 | }; 400 | 401 | /** Exceptions thrown by JSON_ASSERT/JSON_FAIL macros. 402 | * 403 | * These are precondition-violations (user bugs) and internal errors (our bugs). 404 | * 405 | * \remark derived from Json::Exception 406 | */ 407 | class JSON_API LogicError : public Exception 408 | { 409 | public: 410 | LogicError(std::string const& msg); 411 | }; 412 | 413 | /// used internally 414 | void throwRuntimeError(std::string const& msg); 415 | /// used internally 416 | void throwLogicError(std::string const& msg); 417 | 418 | /** \brief Type of the value held by a Value object. 419 | */ 420 | enum ValueType 421 | { 422 | nullValue = 0, ///< 'null' value 423 | intValue, ///< signed integer value 424 | uintValue, ///< unsigned integer value 425 | realValue, ///< double value 426 | stringValue, ///< UTF-8 string value 427 | booleanValue, ///< bool value 428 | arrayValue, ///< array value (ordered list) 429 | objectValue ///< object value (collection of name/value pairs). 430 | }; 431 | 432 | enum CommentPlacement 433 | { 434 | commentBefore = 0, ///< a comment placed on the line before a value 435 | commentAfterOnSameLine, ///< a comment just after a value on the same line 436 | commentAfter, ///< a comment on the line after a value (only make sense for 437 | /// root value) 438 | numberOfCommentPlacement 439 | }; 440 | 441 | //# ifdef JSON_USE_CPPTL 442 | // typedef CppTL::AnyEnumerator EnumMemberNames; 443 | // typedef CppTL::AnyEnumerator EnumValues; 444 | //# endif 445 | 446 | /** \brief Lightweight wrapper to tag static string. 447 | * 448 | * Value constructor and objectValue member assignement takes advantage of the 449 | * StaticString and avoid the cost of string duplication when storing the 450 | * string or the member name. 451 | * 452 | * Example of usage: 453 | * \code 454 | * Json::Value aValue( StaticString("some text") ); 455 | * Json::Value object; 456 | * static const StaticString code("code"); 457 | * object[code] = 1234; 458 | * \endcode 459 | */ 460 | class JSON_API StaticString 461 | { 462 | public: 463 | explicit StaticString(const char* czstring) : c_str_(czstring) 464 | { 465 | } 466 | 467 | operator const char*() const 468 | { 469 | return c_str_; 470 | } 471 | 472 | const char* c_str() const 473 | { 474 | return c_str_; 475 | } 476 | 477 | private: 478 | const char* c_str_; 479 | }; 480 | 481 | /** \brief Represents a JSON value. 482 | * 483 | * This class is a discriminated union wrapper that can represents a: 484 | * - signed integer [range: Value::minInt - Value::maxInt] 485 | * - unsigned integer (range: 0 - Value::maxUInt) 486 | * - double 487 | * - UTF-8 string 488 | * - boolean 489 | * - 'null' 490 | * - an ordered list of Value 491 | * - collection of name/value pairs (javascript object) 492 | * 493 | * The type of the held value is represented by a #ValueType and 494 | * can be obtained using type(). 495 | * 496 | * Values of an #objectValue or #arrayValue can be accessed using operator[]() 497 | * methods. 498 | * Non-const methods will automatically create the a #nullValue element 499 | * if it does not exist. 500 | * The sequence of an #arrayValue will be automatically resized and initialized 501 | * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue. 502 | * 503 | * The get() methods can be used to obtain default value in the case the 504 | * required element does not exist. 505 | * 506 | * It is possible to iterate over the list of a #objectValue values using 507 | * the getMemberNames() method. 508 | * 509 | * \note #Value string-length fit in size_t, but keys must be < 2^30. 510 | * (The reason is an implementation detail.) A #CharReader will raise an 511 | * exception if a bound is exceeded to avoid security holes in your app, 512 | * but the Value API does *not* check bounds. That is the responsibility 513 | * of the caller. 514 | */ 515 | class JSON_API Value 516 | { 517 | friend class ValueIteratorBase; 518 | 519 | public: 520 | typedef std::vector Members; 521 | typedef ValueIterator iterator; 522 | typedef ValueConstIterator const_iterator; 523 | typedef Json::UInt UInt; 524 | typedef Json::Int Int; 525 | #if defined(JSON_HAS_INT64) 526 | typedef Json::UInt64 UInt64; 527 | typedef Json::Int64 Int64; 528 | #endif // defined(JSON_HAS_INT64) 529 | typedef Json::LargestInt LargestInt; 530 | typedef Json::LargestUInt LargestUInt; 531 | typedef Json::ArrayIndex ArrayIndex; 532 | 533 | static const Value& null; ///< We regret this reference to a global instance; prefer the simpler Value(). 534 | static const Value& nullRef; ///< just a kludge for binary-compatibility; same as null 535 | /// Minimum signed integer value that can be stored in a Json::Value. 536 | static const LargestInt minLargestInt; 537 | /// Maximum signed integer value that can be stored in a Json::Value. 538 | static const LargestInt maxLargestInt; 539 | /// Maximum unsigned integer value that can be stored in a Json::Value. 540 | static const LargestUInt maxLargestUInt; 541 | 542 | /// Minimum signed int value that can be stored in a Json::Value. 543 | static const Int minInt; 544 | /// Maximum signed int value that can be stored in a Json::Value. 545 | static const Int maxInt; 546 | /// Maximum unsigned int value that can be stored in a Json::Value. 547 | static const UInt maxUInt; 548 | 549 | #if defined(JSON_HAS_INT64) 550 | /// Minimum signed 64 bits int value that can be stored in a Json::Value. 551 | static const Int64 minInt64; 552 | /// Maximum signed 64 bits int value that can be stored in a Json::Value. 553 | static const Int64 maxInt64; 554 | /// Maximum unsigned 64 bits int value that can be stored in a Json::Value. 555 | static const UInt64 maxUInt64; 556 | #endif // defined(JSON_HAS_INT64) 557 | 558 | private: 559 | #ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION 560 | class CZString 561 | { 562 | public: 563 | enum DuplicationPolicy 564 | { 565 | noDuplication = 0, 566 | duplicate, 567 | duplicateOnCopy 568 | }; 569 | CZString(ArrayIndex index); 570 | CZString(char const* str, unsigned length, DuplicationPolicy allocate); 571 | CZString(CZString const& other); 572 | ~CZString(); 573 | CZString& operator=(CZString other); 574 | bool operator<(CZString const& other) const; 575 | bool operator==(CZString const& other) const; 576 | ArrayIndex index() const; 577 | // const char* c_str() const; ///< \deprecated 578 | char const* data() const; 579 | unsigned length() const; 580 | bool isStaticString() const; 581 | 582 | private: 583 | void swap(CZString& other); 584 | 585 | struct StringStorage 586 | { 587 | unsigned policy_ : 2; 588 | unsigned length_ : 30; // 1GB max 589 | }; 590 | 591 | char const* cstr_; // actually, a prefixed string, unless policy is noDup 592 | union 593 | { 594 | ArrayIndex index_; 595 | StringStorage storage_; 596 | }; 597 | }; 598 | 599 | public: 600 | #ifndef JSON_USE_CPPTL_SMALLMAP 601 | typedef std::map ObjectValues; 602 | #else 603 | typedef CppTL::SmallMap ObjectValues; 604 | #endif // ifndef JSON_USE_CPPTL_SMALLMAP 605 | #endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION 606 | 607 | public: 608 | /** \brief Create a default Value of the given type. 609 | 610 | This is a very useful constructor. 611 | To create an empty array, pass arrayValue. 612 | To create an empty object, pass objectValue. 613 | Another Value can then be set to this one by assignment. 614 | This is useful since clear() and resize() will not alter types. 615 | 616 | Examples: 617 | \code 618 | Json::Value null_value; // null 619 | Json::Value arr_value(Json::arrayValue); // [] 620 | Json::Value obj_value(Json::objectValue); // {} 621 | \endcode 622 | */ 623 | Value(ValueType type = nullValue); 624 | Value(Int value); 625 | Value(UInt value); 626 | #if defined(JSON_HAS_INT64) 627 | Value(Int64 value); 628 | Value(UInt64 value); 629 | #endif // if defined(JSON_HAS_INT64) 630 | Value(double value); 631 | Value(const char* value); ///< Copy til first 0. (NULL causes to seg-fault.) 632 | Value(const char* begin, const char* end); ///< Copy all, incl zeroes. 633 | /** \brief Constructs a value from a static string. 634 | 635 | * Like other value string constructor but do not duplicate the string for 636 | * internal storage. The given string must remain alive after the call to this 637 | * constructor. 638 | * \note This works only for null-terminated strings. (We cannot change the 639 | * size of this class, so we have nowhere to store the length, 640 | * which might be computed later for various operations.) 641 | * 642 | * Example of usage: 643 | * \code 644 | * static StaticString foo("some text"); 645 | * Json::Value aValue(foo); 646 | * \endcode 647 | */ 648 | Value(const StaticString& value); 649 | Value(const std::string& value); ///< Copy data() til size(). Embedded zeroes too. 650 | #ifdef JSON_USE_CPPTL 651 | Value(const CppTL::ConstString& value); 652 | #endif 653 | Value(bool value); 654 | /// Deep copy. 655 | Value(const Value& other); 656 | ~Value(); 657 | 658 | /// Deep copy, then swap(other). 659 | /// \note Over-write existing comments. To preserve comments, use #swapPayload(). 660 | Value& operator=(Value other); 661 | /// Swap everything. 662 | void swap(Value& other); 663 | /// Swap values but leave comments and source offsets in place. 664 | void swapPayload(Value& other); 665 | 666 | ValueType type() const; 667 | 668 | /// Compare payload only, not comments etc. 669 | bool operator<(const Value& other) const; 670 | bool operator<=(const Value& other) const; 671 | bool operator>=(const Value& other) const; 672 | bool operator>(const Value& other) const; 673 | bool operator==(const Value& other) const; 674 | bool operator!=(const Value& other) const; 675 | int compare(const Value& other) const; 676 | 677 | const char* asCString() const; ///< Embedded zeroes could cause you trouble! 678 | std::string asString() const; ///< Embedded zeroes are possible. 679 | /** Get raw char* of string-value. 680 | * \return false if !string. (Seg-fault if str or end are NULL.) 681 | */ 682 | bool getString(char const** begin, char const** end) const; 683 | #ifdef JSON_USE_CPPTL 684 | CppTL::ConstString asConstString() const; 685 | #endif 686 | Int asInt() const; 687 | UInt asUInt() const; 688 | #if defined(JSON_HAS_INT64) 689 | Int64 asInt64() const; 690 | UInt64 asUInt64() const; 691 | #endif // if defined(JSON_HAS_INT64) 692 | LargestInt asLargestInt() const; 693 | LargestUInt asLargestUInt() const; 694 | float asFloat() const; 695 | double asDouble() const; 696 | bool asBool() const; 697 | 698 | bool isNull() const; 699 | bool isBool() const; 700 | bool isInt() const; 701 | bool isInt64() const; 702 | bool isUInt() const; 703 | bool isUInt64() const; 704 | bool isIntegral() const; 705 | bool isDouble() const; 706 | bool isNumeric() const; 707 | bool isString() const; 708 | bool isArray() const; 709 | bool isObject() const; 710 | 711 | bool isConvertibleTo(ValueType other) const; 712 | 713 | /// Number of values in array or object 714 | ArrayIndex size() const; 715 | 716 | /// \brief Return true if empty array, empty object, or null; 717 | /// otherwise, false. 718 | bool empty() const; 719 | 720 | /// Return isNull() 721 | bool operator!() const; 722 | 723 | /// Remove all object members and array elements. 724 | /// \pre type() is arrayValue, objectValue, or nullValue 725 | /// \post type() is unchanged 726 | void clear(); 727 | 728 | /// Resize the array to size elements. 729 | /// New elements are initialized to null. 730 | /// May only be called on nullValue or arrayValue. 731 | /// \pre type() is arrayValue or nullValue 732 | /// \post type() is arrayValue 733 | void resize(ArrayIndex size); 734 | 735 | /// Access an array element (zero based index ). 736 | /// If the array contains less than index element, then null value are 737 | /// inserted 738 | /// in the array so that its size is index+1. 739 | /// (You may need to say 'value[0u]' to get your compiler to distinguish 740 | /// this from the operator[] which takes a string.) 741 | Value& operator[](ArrayIndex index); 742 | 743 | /// Access an array element (zero based index ). 744 | /// If the array contains less than index element, then null value are 745 | /// inserted 746 | /// in the array so that its size is index+1. 747 | /// (You may need to say 'value[0u]' to get your compiler to distinguish 748 | /// this from the operator[] which takes a string.) 749 | Value& operator[](int index); 750 | 751 | /// Access an array element (zero based index ) 752 | /// (You may need to say 'value[0u]' to get your compiler to distinguish 753 | /// this from the operator[] which takes a string.) 754 | const Value& operator[](ArrayIndex index) const; 755 | 756 | /// Access an array element (zero based index ) 757 | /// (You may need to say 'value[0u]' to get your compiler to distinguish 758 | /// this from the operator[] which takes a string.) 759 | const Value& operator[](int index) const; 760 | 761 | /// If the array contains at least index+1 elements, returns the element 762 | /// value, 763 | /// otherwise returns defaultValue. 764 | Value get(ArrayIndex index, const Value& defaultValue) const; 765 | /// Return true if index < size(). 766 | bool isValidIndex(ArrayIndex index) const; 767 | /// \brief Append value to array at the end. 768 | /// 769 | /// Equivalent to jsonvalue[jsonvalue.size()] = value; 770 | Value& append(const Value& value); 771 | 772 | /// Access an object value by name, create a null member if it does not exist. 773 | /// \note Because of our implementation, keys are limited to 2^30 -1 chars. 774 | /// Exceeding that will cause an exception. 775 | Value& operator[](const char* key); 776 | /// Access an object value by name, returns null if there is no member with 777 | /// that name. 778 | const Value& operator[](const char* key) const; 779 | /// Access an object value by name, create a null member if it does not exist. 780 | /// \param key may contain embedded nulls. 781 | Value& operator[](const std::string& key); 782 | /// Access an object value by name, returns null if there is no member with 783 | /// that name. 784 | /// \param key may contain embedded nulls. 785 | const Value& operator[](const std::string& key) const; 786 | /** \brief Access an object value by name, create a null member if it does not 787 | exist. 788 | 789 | * If the object has no entry for that name, then the member name used to store 790 | * the new entry is not duplicated. 791 | * Example of use: 792 | * \code 793 | * Json::Value object; 794 | * static const StaticString code("code"); 795 | * object[code] = 1234; 796 | * \endcode 797 | */ 798 | Value& operator[](const StaticString& key); 799 | #ifdef JSON_USE_CPPTL 800 | /// Access an object value by name, create a null member if it does not exist. 801 | Value& operator[](const CppTL::ConstString& key); 802 | /// Access an object value by name, returns null if there is no member with 803 | /// that name. 804 | const Value& operator[](const CppTL::ConstString& key) const; 805 | #endif 806 | /// Return the member named key if it exist, defaultValue otherwise. 807 | /// \note deep copy 808 | Value get(const char* key, const Value& defaultValue) const; 809 | /// Return the member named key if it exist, defaultValue otherwise. 810 | /// \note deep copy 811 | /// \note key may contain embedded nulls. 812 | Value get(const char* begin, const char* end, const Value& defaultValue) const; 813 | /// Return the member named key if it exist, defaultValue otherwise. 814 | /// \note deep copy 815 | /// \param key may contain embedded nulls. 816 | Value get(const std::string& key, const Value& defaultValue) const; 817 | #ifdef JSON_USE_CPPTL 818 | /// Return the member named key if it exist, defaultValue otherwise. 819 | /// \note deep copy 820 | Value get(const CppTL::ConstString& key, const Value& defaultValue) const; 821 | #endif 822 | /// Most general and efficient version of isMember()const, get()const, 823 | /// and operator[]const 824 | /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 825 | Value const* find(char const* begin, char const* end) const; 826 | /// Most general and efficient version of object-mutators. 827 | /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 828 | /// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue. 829 | Value const* demand(char const* begin, char const* end); 830 | /// \brief Remove and return the named member. 831 | /// 832 | /// Do nothing if it did not exist. 833 | /// \return the removed Value, or null. 834 | /// \pre type() is objectValue or nullValue 835 | /// \post type() is unchanged 836 | /// \deprecated 837 | Value removeMember(const char* key); 838 | /// Same as removeMember(const char*) 839 | /// \param key may contain embedded nulls. 840 | /// \deprecated 841 | Value removeMember(const std::string& key); 842 | /// Same as removeMember(const char* begin, const char* end, Value* removed), 843 | /// but 'key' is null-terminated. 844 | bool removeMember(const char* key, Value* removed); 845 | /** \brief Remove the named map member. 846 | 847 | Update 'removed' iff removed. 848 | \param key may contain embedded nulls. 849 | \return true iff removed (no exceptions) 850 | */ 851 | bool removeMember(std::string const& key, Value* removed); 852 | /// Same as removeMember(std::string const& key, Value* removed) 853 | bool removeMember(const char* begin, const char* end, Value* removed); 854 | /** \brief Remove the indexed array element. 855 | 856 | O(n) expensive operations. 857 | Update 'removed' iff removed. 858 | \return true iff removed (no exceptions) 859 | */ 860 | bool removeIndex(ArrayIndex i, Value* removed); 861 | 862 | /// Return true if the object has a member named key. 863 | /// \note 'key' must be null-terminated. 864 | bool isMember(const char* key) const; 865 | /// Return true if the object has a member named key. 866 | /// \param key may contain embedded nulls. 867 | bool isMember(const std::string& key) const; 868 | /// Same as isMember(std::string const& key)const 869 | bool isMember(const char* begin, const char* end) const; 870 | #ifdef JSON_USE_CPPTL 871 | /// Return true if the object has a member named key. 872 | bool isMember(const CppTL::ConstString& key) const; 873 | #endif 874 | 875 | /// \brief Return a list of the member names. 876 | /// 877 | /// If null, return an empty list. 878 | /// \pre type() is objectValue or nullValue 879 | /// \post if type() was nullValue, it remains nullValue 880 | Members getMemberNames() const; 881 | 882 | //# ifdef JSON_USE_CPPTL 883 | // EnumMemberNames enumMemberNames() const; 884 | // EnumValues enumValues() const; 885 | //# endif 886 | 887 | /// \deprecated Always pass len. 888 | JSONCPP_DEPRECATED("Use setComment(std::string const&) instead.") 889 | void setComment(const char* comment, CommentPlacement placement); 890 | /// Comments must be //... or /* ... */ 891 | void setComment(const char* comment, size_t len, CommentPlacement placement); 892 | /// Comments must be //... or /* ... */ 893 | void setComment(const std::string& comment, CommentPlacement placement); 894 | bool hasComment(CommentPlacement placement) const; 895 | /// Include delimiters and embedded newlines. 896 | std::string getComment(CommentPlacement placement) const; 897 | 898 | std::string toStyledString() const; 899 | 900 | const_iterator begin() const; 901 | const_iterator end() const; 902 | 903 | iterator begin(); 904 | iterator end(); 905 | 906 | // Accessors for the [start, limit) range of bytes within the JSON text from 907 | // which this value was parsed, if any. 908 | void setOffsetStart(size_t start); 909 | void setOffsetLimit(size_t limit); 910 | size_t getOffsetStart() const; 911 | size_t getOffsetLimit() const; 912 | 913 | private: 914 | void initBasic(ValueType type, bool allocated = false); 915 | 916 | Value& resolveReference(const char* key); 917 | Value& resolveReference(const char* key, const char* end); 918 | 919 | struct CommentInfo 920 | { 921 | CommentInfo(); 922 | ~CommentInfo(); 923 | 924 | void setComment(const char* text, size_t len); 925 | 926 | char* comment_; 927 | }; 928 | 929 | // struct MemberNamesTransform 930 | //{ 931 | // typedef const char *result_type; 932 | // const char *operator()( const CZString &name ) const 933 | // { 934 | // return name.c_str(); 935 | // } 936 | //}; 937 | 938 | union ValueHolder 939 | { 940 | LargestInt int_; 941 | LargestUInt uint_; 942 | double real_; 943 | bool bool_; 944 | char* string_; // actually ptr to unsigned, followed by str, unless !allocated_ 945 | ObjectValues* map_; 946 | } value_; 947 | ValueType type_ : 8; 948 | unsigned int allocated_ : 1; // Notes: if declared as bool, bitfield is useless. 949 | // If not allocated_, string_ must be null-terminated. 950 | CommentInfo* comments_; 951 | 952 | // [start, limit) byte offsets in the source JSON text from which this Value 953 | // was extracted. 954 | size_t start_; 955 | size_t limit_; 956 | }; 957 | 958 | /** \brief Experimental and untested: represents an element of the "path" to 959 | * access a node. 960 | */ 961 | class JSON_API PathArgument 962 | { 963 | public: 964 | friend class Path; 965 | 966 | PathArgument(); 967 | PathArgument(ArrayIndex index); 968 | PathArgument(const char* key); 969 | PathArgument(const std::string& key); 970 | 971 | private: 972 | enum Kind 973 | { 974 | kindNone = 0, 975 | kindIndex, 976 | kindKey 977 | }; 978 | std::string key_; 979 | ArrayIndex index_; 980 | Kind kind_; 981 | }; 982 | 983 | /** \brief Experimental and untested: represents a "path" to access a node. 984 | * 985 | * Syntax: 986 | * - "." => root node 987 | * - ".[n]" => elements at index 'n' of root node (an array value) 988 | * - ".name" => member named 'name' of root node (an object value) 989 | * - ".name1.name2.name3" 990 | * - ".[0][1][2].name1[3]" 991 | * - ".%" => member name is provided as parameter 992 | * - ".[%]" => index is provied as parameter 993 | */ 994 | class JSON_API Path 995 | { 996 | public: 997 | Path(const std::string& path, 998 | const PathArgument& a1 = PathArgument(), 999 | const PathArgument& a2 = PathArgument(), 1000 | const PathArgument& a3 = PathArgument(), 1001 | const PathArgument& a4 = PathArgument(), 1002 | const PathArgument& a5 = PathArgument()); 1003 | 1004 | const Value& resolve(const Value& root) const; 1005 | Value resolve(const Value& root, const Value& defaultValue) const; 1006 | /// Creates the "path" to access the specified node and returns a reference on 1007 | /// the node. 1008 | Value& make(Value& root) const; 1009 | 1010 | private: 1011 | typedef std::vector InArgs; 1012 | typedef std::vector Args; 1013 | 1014 | void makePath(const std::string& path, const InArgs& in); 1015 | void addPathInArg(const std::string& path, 1016 | const InArgs& in, 1017 | InArgs::const_iterator& itInArg, 1018 | PathArgument::Kind kind); 1019 | void invalidPath(const std::string& path, int location); 1020 | 1021 | Args args_; 1022 | }; 1023 | 1024 | /** \brief base class for Value iterators. 1025 | * 1026 | */ 1027 | class JSON_API ValueIteratorBase 1028 | { 1029 | public: 1030 | typedef std::bidirectional_iterator_tag iterator_category; 1031 | typedef unsigned int size_t; 1032 | typedef int difference_type; 1033 | typedef ValueIteratorBase SelfType; 1034 | 1035 | bool operator==(const SelfType& other) const 1036 | { 1037 | return isEqual(other); 1038 | } 1039 | 1040 | bool operator!=(const SelfType& other) const 1041 | { 1042 | return !isEqual(other); 1043 | } 1044 | 1045 | difference_type operator-(const SelfType& other) const 1046 | { 1047 | return other.computeDistance(*this); 1048 | } 1049 | 1050 | /// Return either the index or the member name of the referenced value as a 1051 | /// Value. 1052 | Value key() const; 1053 | 1054 | /// Return the index of the referenced Value, or -1 if it is not an arrayValue. 1055 | UInt index() const; 1056 | 1057 | /// Return the member name of the referenced Value, or "" if it is not an 1058 | /// objectValue. 1059 | /// \note Avoid `c_str()` on result, as embedded zeroes are possible. 1060 | std::string name() const; 1061 | 1062 | /// Return the member name of the referenced Value. "" if it is not an 1063 | /// objectValue. 1064 | /// \deprecated This cannot be used for UTF-8 strings, since there can be embedded nulls. 1065 | JSONCPP_DEPRECATED("Use `key = name();` instead.") 1066 | char const* memberName() const; 1067 | /// Return the member name of the referenced Value, or NULL if it is not an 1068 | /// objectValue. 1069 | /// \note Better version than memberName(). Allows embedded nulls. 1070 | char const* memberName(char const** end) const; 1071 | 1072 | protected: 1073 | Value& deref() const; 1074 | 1075 | void increment(); 1076 | 1077 | void decrement(); 1078 | 1079 | difference_type computeDistance(const SelfType& other) const; 1080 | 1081 | bool isEqual(const SelfType& other) const; 1082 | 1083 | void copy(const SelfType& other); 1084 | 1085 | private: 1086 | Value::ObjectValues::iterator current_; 1087 | // Indicates that iterator is for a null value. 1088 | bool isNull_; 1089 | 1090 | public: 1091 | // For some reason, BORLAND needs these at the end, rather 1092 | // than earlier. No idea why. 1093 | ValueIteratorBase(); 1094 | explicit ValueIteratorBase(const Value::ObjectValues::iterator& current); 1095 | }; 1096 | 1097 | /** \brief const iterator for object and array value. 1098 | * 1099 | */ 1100 | class JSON_API ValueConstIterator : public ValueIteratorBase 1101 | { 1102 | friend class Value; 1103 | 1104 | public: 1105 | typedef const Value value_type; 1106 | // typedef unsigned int size_t; 1107 | // typedef int difference_type; 1108 | typedef const Value& reference; 1109 | typedef const Value* pointer; 1110 | typedef ValueConstIterator SelfType; 1111 | 1112 | ValueConstIterator(); 1113 | 1114 | private: 1115 | /*! \internal Use by Value to create an iterator. 1116 | */ 1117 | explicit ValueConstIterator(const Value::ObjectValues::iterator& current); 1118 | 1119 | public: 1120 | SelfType& operator=(const ValueIteratorBase& other); 1121 | 1122 | SelfType operator++(int) 1123 | { 1124 | SelfType temp(*this); 1125 | ++*this; 1126 | return temp; 1127 | } 1128 | 1129 | SelfType operator--(int) 1130 | { 1131 | SelfType temp(*this); 1132 | --*this; 1133 | return temp; 1134 | } 1135 | 1136 | SelfType& operator--() 1137 | { 1138 | decrement(); 1139 | return *this; 1140 | } 1141 | 1142 | SelfType& operator++() 1143 | { 1144 | increment(); 1145 | return *this; 1146 | } 1147 | 1148 | reference operator*() const 1149 | { 1150 | return deref(); 1151 | } 1152 | 1153 | pointer operator->() const 1154 | { 1155 | return &deref(); 1156 | } 1157 | }; 1158 | 1159 | /** \brief Iterator for object and array value. 1160 | */ 1161 | class JSON_API ValueIterator : public ValueIteratorBase 1162 | { 1163 | friend class Value; 1164 | 1165 | public: 1166 | typedef Value value_type; 1167 | typedef unsigned int size_t; 1168 | typedef int difference_type; 1169 | typedef Value& reference; 1170 | typedef Value* pointer; 1171 | typedef ValueIterator SelfType; 1172 | 1173 | ValueIterator(); 1174 | ValueIterator(const ValueConstIterator& other); 1175 | ValueIterator(const ValueIterator& other); 1176 | 1177 | private: 1178 | /*! \internal Use by Value to create an iterator. 1179 | */ 1180 | explicit ValueIterator(const Value::ObjectValues::iterator& current); 1181 | 1182 | public: 1183 | SelfType& operator=(const SelfType& other); 1184 | 1185 | SelfType operator++(int) 1186 | { 1187 | SelfType temp(*this); 1188 | ++*this; 1189 | return temp; 1190 | } 1191 | 1192 | SelfType operator--(int) 1193 | { 1194 | SelfType temp(*this); 1195 | --*this; 1196 | return temp; 1197 | } 1198 | 1199 | SelfType& operator--() 1200 | { 1201 | decrement(); 1202 | return *this; 1203 | } 1204 | 1205 | SelfType& operator++() 1206 | { 1207 | increment(); 1208 | return *this; 1209 | } 1210 | 1211 | reference operator*() const 1212 | { 1213 | return deref(); 1214 | } 1215 | 1216 | pointer operator->() const 1217 | { 1218 | return &deref(); 1219 | } 1220 | }; 1221 | 1222 | } // namespace Json 1223 | 1224 | namespace std 1225 | { 1226 | /// Specialize std::swap() for Json::Value. 1227 | template <> 1228 | inline void swap(Json::Value& a, Json::Value& b) 1229 | { 1230 | a.swap(b); 1231 | } 1232 | } 1233 | 1234 | #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 1235 | #pragma warning(pop) 1236 | #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 1237 | 1238 | #endif // CPPTL_JSON_H_INCLUDED 1239 | 1240 | // ////////////////////////////////////////////////////////////////////// 1241 | // End of content of file: include/json/value.h 1242 | // ////////////////////////////////////////////////////////////////////// 1243 | 1244 | // ////////////////////////////////////////////////////////////////////// 1245 | // Beginning of content of file: include/json/reader.h 1246 | // ////////////////////////////////////////////////////////////////////// 1247 | 1248 | // Copyright 2007-2010 Baptiste Lepilleur 1249 | // Distributed under MIT license, or public domain if desired and 1250 | // recognized in your jurisdiction. 1251 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 1252 | 1253 | #ifndef CPPTL_JSON_READER_H_INCLUDED 1254 | #define CPPTL_JSON_READER_H_INCLUDED 1255 | 1256 | #if !defined(JSON_IS_AMALGAMATION) 1257 | #include "features.h" 1258 | #include "value.h" 1259 | #endif // if !defined(JSON_IS_AMALGAMATION) 1260 | #include 1261 | #include 1262 | #include 1263 | #include 1264 | #include 1265 | 1266 | // Disable warning C4251: : needs to have dll-interface to 1267 | // be used by... 1268 | #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 1269 | #pragma warning(push) 1270 | #pragma warning(disable : 4251) 1271 | #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 1272 | 1273 | namespace Json 1274 | { 1275 | 1276 | /** \brief Unserialize a JSON document into a 1277 | *Value. 1278 | * 1279 | * \deprecated Use CharReader and CharReaderBuilder. 1280 | */ 1281 | class JSON_API Reader 1282 | { 1283 | public: 1284 | typedef char Char; 1285 | typedef const Char* Location; 1286 | 1287 | /** \brief An error tagged with where in the JSON text it was encountered. 1288 | * 1289 | * The offsets give the [start, limit) range of bytes within the text. Note 1290 | * that this is bytes, not codepoints. 1291 | * 1292 | */ 1293 | struct StructuredError 1294 | { 1295 | size_t offset_start; 1296 | size_t offset_limit; 1297 | std::string message; 1298 | }; 1299 | 1300 | /** \brief Constructs a Reader allowing all features 1301 | * for parsing. 1302 | */ 1303 | Reader(); 1304 | 1305 | /** \brief Constructs a Reader allowing the specified feature set 1306 | * for parsing. 1307 | */ 1308 | Reader(const Features& features); 1309 | 1310 | /** \brief Read a Value from a JSON 1311 | * document. 1312 | * \param document UTF-8 encoded string containing the document to read. 1313 | * \param root [out] Contains the root value of the document if it was 1314 | * successfully parsed. 1315 | * \param collectComments \c true to collect comment and allow writing them 1316 | * back during 1317 | * serialization, \c false to discard comments. 1318 | * This parameter is ignored if 1319 | * Features::allowComments_ 1320 | * is \c false. 1321 | * \return \c true if the document was successfully parsed, \c false if an 1322 | * error occurred. 1323 | */ 1324 | bool parse(const std::string& document, Value& root, bool collectComments = true); 1325 | 1326 | /** \brief Read a Value from a JSON 1327 | document. 1328 | * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the 1329 | document to read. 1330 | * \param endDoc Pointer on the end of the UTF-8 encoded string of the 1331 | document to read. 1332 | * Must be >= beginDoc. 1333 | * \param root [out] Contains the root value of the document if it was 1334 | * successfully parsed. 1335 | * \param collectComments \c true to collect comment and allow writing them 1336 | back during 1337 | * serialization, \c false to discard comments. 1338 | * This parameter is ignored if 1339 | Features::allowComments_ 1340 | * is \c false. 1341 | * \return \c true if the document was successfully parsed, \c false if an 1342 | error occurred. 1343 | */ 1344 | bool parse(const char* beginDoc, const char* endDoc, Value& root, bool collectComments = true); 1345 | 1346 | /// \brief Parse from input stream. 1347 | /// \see Json::operator>>(std::istream&, Json::Value&). 1348 | bool parse(std::istream& is, Value& root, bool collectComments = true); 1349 | 1350 | /** \brief Returns a user friendly string that list errors in the parsed 1351 | * document. 1352 | * \return Formatted error message with the list of errors with their location 1353 | * in 1354 | * the parsed document. An empty string is returned if no error 1355 | * occurred 1356 | * during parsing. 1357 | * \deprecated Use getFormattedErrorMessages() instead (typo fix). 1358 | */ 1359 | JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.") 1360 | std::string getFormatedErrorMessages() const; 1361 | 1362 | /** \brief Returns a user friendly string that list errors in the parsed 1363 | * document. 1364 | * \return Formatted error message with the list of errors with their location 1365 | * in 1366 | * the parsed document. An empty string is returned if no error 1367 | * occurred 1368 | * during parsing. 1369 | */ 1370 | std::string getFormattedErrorMessages() const; 1371 | 1372 | /** \brief Returns a vector of structured erros encounted while parsing. 1373 | * \return A (possibly empty) vector of StructuredError objects. Currently 1374 | * only one error can be returned, but the caller should tolerate 1375 | * multiple 1376 | * errors. This can occur if the parser recovers from a non-fatal 1377 | * parse error and then encounters additional errors. 1378 | */ 1379 | std::vector getStructuredErrors() const; 1380 | 1381 | /** \brief Add a semantic error message. 1382 | * \param value JSON Value location associated with the error 1383 | * \param message The error message. 1384 | * \return \c true if the error was successfully added, \c false if the 1385 | * Value offset exceeds the document size. 1386 | */ 1387 | bool pushError(const Value& value, const std::string& message); 1388 | 1389 | /** \brief Add a semantic error message with extra context. 1390 | * \param value JSON Value location associated with the error 1391 | * \param message The error message. 1392 | * \param extra Additional JSON Value location to contextualize the error 1393 | * \return \c true if the error was successfully added, \c false if either 1394 | * Value offset exceeds the document size. 1395 | */ 1396 | bool pushError(const Value& value, const std::string& message, const Value& extra); 1397 | 1398 | /** \brief Return whether there are any errors. 1399 | * \return \c true if there are no errors to report \c false if 1400 | * errors have occurred. 1401 | */ 1402 | bool good() const; 1403 | 1404 | private: 1405 | enum TokenType 1406 | { 1407 | tokenEndOfStream = 0, 1408 | tokenObjectBegin, 1409 | tokenObjectEnd, 1410 | tokenArrayBegin, 1411 | tokenArrayEnd, 1412 | tokenString, 1413 | tokenNumber, 1414 | tokenTrue, 1415 | tokenFalse, 1416 | tokenNull, 1417 | tokenArraySeparator, 1418 | tokenMemberSeparator, 1419 | tokenComment, 1420 | tokenError 1421 | }; 1422 | 1423 | class Token 1424 | { 1425 | public: 1426 | TokenType type_; 1427 | Location start_; 1428 | Location end_; 1429 | }; 1430 | 1431 | class ErrorInfo 1432 | { 1433 | public: 1434 | Token token_; 1435 | std::string message_; 1436 | Location extra_; 1437 | }; 1438 | 1439 | typedef std::deque Errors; 1440 | 1441 | bool readToken(Token& token); 1442 | void skipSpaces(); 1443 | bool match(Location pattern, int patternLength); 1444 | bool readComment(); 1445 | bool readCStyleComment(); 1446 | bool readCppStyleComment(); 1447 | bool readString(); 1448 | void readNumber(); 1449 | bool readValue(); 1450 | bool readObject(Token& token); 1451 | bool readArray(Token& token); 1452 | bool decodeNumber(Token& token); 1453 | bool decodeNumber(Token& token, Value& decoded); 1454 | bool decodeString(Token& token); 1455 | bool decodeString(Token& token, std::string& decoded); 1456 | bool decodeDouble(Token& token); 1457 | bool decodeDouble(Token& token, Value& decoded); 1458 | bool decodeUnicodeCodePoint(Token& token, Location& current, Location end, unsigned int& unicode); 1459 | bool decodeUnicodeEscapeSequence(Token& token, Location& current, Location end, unsigned int& unicode); 1460 | bool addError(const std::string& message, Token& token, Location extra = 0); 1461 | bool recoverFromError(TokenType skipUntilToken); 1462 | bool addErrorAndRecover(const std::string& message, Token& token, TokenType skipUntilToken); 1463 | void skipUntilSpace(); 1464 | Value& currentValue(); 1465 | Char getNextChar(); 1466 | void getLocationLineAndColumn(Location location, int& line, int& column) const; 1467 | std::string getLocationLineAndColumn(Location location) const; 1468 | void addComment(Location begin, Location end, CommentPlacement placement); 1469 | void skipCommentTokens(Token& token); 1470 | 1471 | typedef std::stack Nodes; 1472 | Nodes nodes_; 1473 | Errors errors_; 1474 | std::string document_; 1475 | Location begin_; 1476 | Location end_; 1477 | Location current_; 1478 | Location lastValueEnd_; 1479 | Value* lastValue_; 1480 | std::string commentsBefore_; 1481 | Features features_; 1482 | bool collectComments_; 1483 | }; // Reader 1484 | 1485 | /** Interface for reading JSON from a char array. 1486 | */ 1487 | class JSON_API CharReader 1488 | { 1489 | public: 1490 | virtual ~CharReader() 1491 | { 1492 | } 1493 | /** \brief Read a Value from a JSON 1494 | document. 1495 | * The document must be a UTF-8 encoded string containing the document to read. 1496 | * 1497 | * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the 1498 | document to read. 1499 | * \param endDoc Pointer on the end of the UTF-8 encoded string of the 1500 | document to read. 1501 | * Must be >= beginDoc. 1502 | * \param root [out] Contains the root value of the document if it was 1503 | * successfully parsed. 1504 | * \param errs [out] Formatted error messages (if not NULL) 1505 | * a user friendly string that lists errors in the parsed 1506 | * document. 1507 | * \return \c true if the document was successfully parsed, \c false if an 1508 | error occurred. 1509 | */ 1510 | virtual bool parse(char const* beginDoc, char const* endDoc, Value* root, std::string* errs) = 0; 1511 | 1512 | class Factory 1513 | { 1514 | public: 1515 | virtual ~Factory() 1516 | { 1517 | } 1518 | /** \brief Allocate a CharReader via operator new(). 1519 | * \throw std::exception if something goes wrong (e.g. invalid settings) 1520 | */ 1521 | virtual CharReader* newCharReader() const = 0; 1522 | }; // Factory 1523 | }; // CharReader 1524 | 1525 | /** \brief Build a CharReader implementation. 1526 | 1527 | Usage: 1528 | \code 1529 | using namespace Json; 1530 | CharReaderBuilder builder; 1531 | builder["collectComments"] = false; 1532 | Value value; 1533 | std::string errs; 1534 | bool ok = parseFromStream(builder, std::cin, &value, &errs); 1535 | \endcode 1536 | */ 1537 | class JSON_API CharReaderBuilder : public CharReader::Factory 1538 | { 1539 | public: 1540 | // Note: We use a Json::Value so that we can add data-members to this class 1541 | // without a major version bump. 1542 | /** Configuration of this builder. 1543 | These are case-sensitive. 1544 | Available settings (case-sensitive): 1545 | - `"collectComments": false or true` 1546 | - true to collect comment and allow writing them 1547 | back during serialization, false to discard comments. 1548 | This parameter is ignored if allowComments is false. 1549 | - `"allowComments": false or true` 1550 | - true if comments are allowed. 1551 | - `"strictRoot": false or true` 1552 | - true if root must be either an array or an object value 1553 | - `"allowDroppedNullPlaceholders": false or true` 1554 | - true if dropped null placeholders are allowed. (See StreamWriterBuilder.) 1555 | - `"allowNumericKeys": false or true` 1556 | - true if numeric object keys are allowed. 1557 | - `"allowSingleQuotes": false or true` 1558 | - true if '' are allowed for strings (both keys and values) 1559 | - `"stackLimit": integer` 1560 | - Exceeding stackLimit (recursive depth of `readValue()`) will 1561 | cause an exception. 1562 | - This is a security issue (seg-faults caused by deeply nested JSON), 1563 | so the default is low. 1564 | - `"failIfExtra": false or true` 1565 | - If true, `parse()` returns false when extra non-whitespace trails 1566 | the JSON value in the input string. 1567 | - `"rejectDupKeys": false or true` 1568 | - If true, `parse()` returns false when a key is duplicated within an object. 1569 | 1570 | You can examine 'settings_` yourself 1571 | to see the defaults. You can also write and read them just like any 1572 | JSON Value. 1573 | \sa setDefaults() 1574 | */ 1575 | Json::Value settings_; 1576 | 1577 | CharReaderBuilder(); 1578 | virtual ~CharReaderBuilder(); 1579 | 1580 | virtual CharReader* newCharReader() const; 1581 | 1582 | /** \return true if 'settings' are legal and consistent; 1583 | * otherwise, indicate bad settings via 'invalid'. 1584 | */ 1585 | bool validate(Json::Value* invalid) const; 1586 | 1587 | /** A simple way to update a specific setting. 1588 | */ 1589 | Value& operator[](std::string key); 1590 | 1591 | /** Called by ctor, but you can use this to reset settings_. 1592 | * \pre 'settings' != NULL (but Json::null is fine) 1593 | * \remark Defaults: 1594 | * \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults 1595 | */ 1596 | static void setDefaults(Json::Value* settings); 1597 | /** Same as old Features::strictMode(). 1598 | * \pre 'settings' != NULL (but Json::null is fine) 1599 | * \remark Defaults: 1600 | * \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode 1601 | */ 1602 | static void strictMode(Json::Value* settings); 1603 | }; 1604 | 1605 | /** Consume entire stream and use its begin/end. 1606 | * Someday we might have a real StreamReader, but for now this 1607 | * is convenient. 1608 | */ 1609 | bool JSON_API parseFromStream(CharReader::Factory const&, std::istream&, Value* root, std::string* errs); 1610 | 1611 | /** \brief Read from 'sin' into 'root'. 1612 | 1613 | Always keep comments from the input JSON. 1614 | 1615 | This can be used to read a file into a particular sub-object. 1616 | For example: 1617 | \code 1618 | Json::Value root; 1619 | cin >> root["dir"]["file"]; 1620 | cout << root; 1621 | \endcode 1622 | Result: 1623 | \verbatim 1624 | { 1625 | "dir": { 1626 | "file": { 1627 | // The input stream JSON would be nested here. 1628 | } 1629 | } 1630 | } 1631 | \endverbatim 1632 | \throw std::exception on parse error. 1633 | \see Json::operator<<() 1634 | */ 1635 | JSON_API std::istream& operator>>(std::istream&, Value&); 1636 | 1637 | } // namespace Json 1638 | 1639 | #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 1640 | #pragma warning(pop) 1641 | #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 1642 | 1643 | #endif // CPPTL_JSON_READER_H_INCLUDED 1644 | 1645 | // ////////////////////////////////////////////////////////////////////// 1646 | // End of content of file: include/json/reader.h 1647 | // ////////////////////////////////////////////////////////////////////// 1648 | 1649 | // ////////////////////////////////////////////////////////////////////// 1650 | // Beginning of content of file: include/json/writer.h 1651 | // ////////////////////////////////////////////////////////////////////// 1652 | 1653 | // Copyright 2007-2010 Baptiste Lepilleur 1654 | // Distributed under MIT license, or public domain if desired and 1655 | // recognized in your jurisdiction. 1656 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 1657 | 1658 | #ifndef JSON_WRITER_H_INCLUDED 1659 | #define JSON_WRITER_H_INCLUDED 1660 | 1661 | #if !defined(JSON_IS_AMALGAMATION) 1662 | #include "value.h" 1663 | #endif // if !defined(JSON_IS_AMALGAMATION) 1664 | #include 1665 | #include 1666 | #include 1667 | 1668 | // Disable warning C4251: : needs to have dll-interface to 1669 | // be used by... 1670 | #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 1671 | #pragma warning(push) 1672 | #pragma warning(disable : 4251) 1673 | #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 1674 | 1675 | namespace Json 1676 | { 1677 | 1678 | class Value; 1679 | 1680 | /** 1681 | 1682 | Usage: 1683 | \code 1684 | using namespace Json; 1685 | void writeToStdout(StreamWriter::Factory const& factory, Value const& value) { 1686 | std::unique_ptr const writer( 1687 | factory.newStreamWriter()); 1688 | writer->write(value, &std::cout); 1689 | std::cout << std::endl; // add lf and flush 1690 | } 1691 | \endcode 1692 | */ 1693 | class JSON_API StreamWriter 1694 | { 1695 | protected: 1696 | std::ostream* sout_; // not owned; will not delete 1697 | public: 1698 | StreamWriter(); 1699 | virtual ~StreamWriter(); 1700 | /** Write Value into document as configured in sub-class. 1701 | Do not take ownership of sout, but maintain a reference during function. 1702 | \pre sout != NULL 1703 | \return zero on success (For now, we always return zero, so check the stream instead.) 1704 | \throw std::exception possibly, depending on configuration 1705 | */ 1706 | virtual int write(Value const& root, std::ostream* sout) = 0; 1707 | 1708 | /** \brief A simple abstract factory. 1709 | */ 1710 | class JSON_API Factory 1711 | { 1712 | public: 1713 | virtual ~Factory(); 1714 | /** \brief Allocate a CharReader via operator new(). 1715 | * \throw std::exception if something goes wrong (e.g. invalid settings) 1716 | */ 1717 | virtual StreamWriter* newStreamWriter() const = 0; 1718 | }; // Factory 1719 | }; // StreamWriter 1720 | 1721 | /** \brief Write into stringstream, then return string, for convenience. 1722 | * A StreamWriter will be created from the factory, used, and then deleted. 1723 | */ 1724 | std::string JSON_API writeString(StreamWriter::Factory const& factory, Value const& root); 1725 | 1726 | /** \brief Build a StreamWriter implementation. 1727 | 1728 | Usage: 1729 | \code 1730 | using namespace Json; 1731 | Value value = ...; 1732 | StreamWriterBuilder builder; 1733 | builder["commentStyle"] = "None"; 1734 | builder["indentation"] = " "; // or whatever you like 1735 | std::unique_ptr writer( 1736 | builder.newStreamWriter()); 1737 | writer->write(value, &std::cout); 1738 | std::cout << std::endl; // add lf and flush 1739 | \endcode 1740 | */ 1741 | class JSON_API StreamWriterBuilder : public StreamWriter::Factory 1742 | { 1743 | public: 1744 | // Note: We use a Json::Value so that we can add data-members to this class 1745 | // without a major version bump. 1746 | /** Configuration of this builder. 1747 | Available settings (case-sensitive): 1748 | - "commentStyle": "None" or "All" 1749 | - "indentation": "" 1750 | - "enableYAMLCompatibility": false or true 1751 | - slightly change the whitespace around colons 1752 | - "dropNullPlaceholders": false or true 1753 | - Drop the "null" string from the writer's output for nullValues. 1754 | Strictly speaking, this is not valid JSON. But when the output is being 1755 | fed to a browser's Javascript, it makes for smaller output and the 1756 | browser can handle the output just fine. 1757 | 1758 | You can examine 'settings_` yourself 1759 | to see the defaults. You can also write and read them just like any 1760 | JSON Value. 1761 | \sa setDefaults() 1762 | */ 1763 | Json::Value settings_; 1764 | 1765 | StreamWriterBuilder(); 1766 | virtual ~StreamWriterBuilder(); 1767 | 1768 | /** 1769 | * \throw std::exception if something goes wrong (e.g. invalid settings) 1770 | */ 1771 | virtual StreamWriter* newStreamWriter() const; 1772 | 1773 | /** \return true if 'settings' are legal and consistent; 1774 | * otherwise, indicate bad settings via 'invalid'. 1775 | */ 1776 | bool validate(Json::Value* invalid) const; 1777 | /** A simple way to update a specific setting. 1778 | */ 1779 | Value& operator[](std::string key); 1780 | 1781 | /** Called by ctor, but you can use this to reset settings_. 1782 | * \pre 'settings' != NULL (but Json::null is fine) 1783 | * \remark Defaults: 1784 | * \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults 1785 | */ 1786 | static void setDefaults(Json::Value* settings); 1787 | }; 1788 | 1789 | /** \brief Abstract class for writers. 1790 | * \deprecated Use StreamWriter. (And really, this is an implementation detail.) 1791 | */ 1792 | class JSON_API Writer 1793 | { 1794 | public: 1795 | virtual ~Writer(); 1796 | 1797 | virtual std::string write(const Value& root) = 0; 1798 | }; 1799 | 1800 | /** \brief Outputs a Value in JSON format 1801 | *without formatting (not human friendly). 1802 | * 1803 | * The JSON document is written in a single line. It is not intended for 'human' 1804 | *consumption, 1805 | * but may be usefull to support feature such as RPC where bandwith is limited. 1806 | * \sa Reader, Value 1807 | * \deprecated Use StreamWriterBuilder. 1808 | */ 1809 | class JSON_API FastWriter : public Writer 1810 | { 1811 | 1812 | public: 1813 | FastWriter(); 1814 | virtual ~FastWriter() 1815 | { 1816 | } 1817 | 1818 | void enableYAMLCompatibility(); 1819 | 1820 | /** \brief Drop the "null" string from the writer's output for nullValues. 1821 | * Strictly speaking, this is not valid JSON. But when the output is being 1822 | * fed to a browser's Javascript, it makes for smaller output and the 1823 | * browser can handle the output just fine. 1824 | */ 1825 | void dropNullPlaceholders(); 1826 | 1827 | void omitEndingLineFeed(); 1828 | 1829 | public: // overridden from Writer 1830 | virtual std::string write(const Value& root); 1831 | 1832 | private: 1833 | void writeValue(const Value& value); 1834 | 1835 | std::string document_; 1836 | bool yamlCompatiblityEnabled_; 1837 | bool dropNullPlaceholders_; 1838 | bool omitEndingLineFeed_; 1839 | }; 1840 | 1841 | /** \brief Writes a Value in JSON format in a 1842 | *human friendly way. 1843 | * 1844 | * The rules for line break and indent are as follow: 1845 | * - Object value: 1846 | * - if empty then print {} without indent and line break 1847 | * - if not empty the print '{', line break & indent, print one value per 1848 | *line 1849 | * and then unindent and line break and print '}'. 1850 | * - Array value: 1851 | * - if empty then print [] without indent and line break 1852 | * - if the array contains no object value, empty array or some other value 1853 | *types, 1854 | * and all the values fit on one lines, then print the array on a single 1855 | *line. 1856 | * - otherwise, it the values do not fit on one line, or the array contains 1857 | * object or non empty array, then print one value per line. 1858 | * 1859 | * If the Value have comments then they are outputed according to their 1860 | *#CommentPlacement. 1861 | * 1862 | * \sa Reader, Value, Value::setComment() 1863 | * \deprecated Use StreamWriterBuilder. 1864 | */ 1865 | class JSON_API StyledWriter : public Writer 1866 | { 1867 | public: 1868 | StyledWriter(); 1869 | virtual ~StyledWriter() 1870 | { 1871 | } 1872 | 1873 | public: // overridden from Writer 1874 | /** \brief Serialize a Value in JSON format. 1875 | * \param root Value to serialize. 1876 | * \return String containing the JSON document that represents the root value. 1877 | */ 1878 | virtual std::string write(const Value& root); 1879 | 1880 | private: 1881 | void writeValue(const Value& value); 1882 | void writeArrayValue(const Value& value); 1883 | bool isMultineArray(const Value& value); 1884 | void pushValue(const std::string& value); 1885 | void writeIndent(); 1886 | void writeWithIndent(const std::string& value); 1887 | void indent(); 1888 | void unindent(); 1889 | void writeCommentBeforeValue(const Value& root); 1890 | void writeCommentAfterValueOnSameLine(const Value& root); 1891 | bool hasCommentForValue(const Value& value); 1892 | static std::string normalizeEOL(const std::string& text); 1893 | 1894 | typedef std::vector ChildValues; 1895 | 1896 | ChildValues childValues_; 1897 | std::string document_; 1898 | std::string indentString_; 1899 | int rightMargin_; 1900 | int indentSize_; 1901 | bool addChildValues_; 1902 | }; 1903 | 1904 | /** \brief Writes a Value in JSON format in a 1905 | human friendly way, 1906 | to a stream rather than to a string. 1907 | * 1908 | * The rules for line break and indent are as follow: 1909 | * - Object value: 1910 | * - if empty then print {} without indent and line break 1911 | * - if not empty the print '{', line break & indent, print one value per 1912 | line 1913 | * and then unindent and line break and print '}'. 1914 | * - Array value: 1915 | * - if empty then print [] without indent and line break 1916 | * - if the array contains no object value, empty array or some other value 1917 | types, 1918 | * and all the values fit on one lines, then print the array on a single 1919 | line. 1920 | * - otherwise, it the values do not fit on one line, or the array contains 1921 | * object or non empty array, then print one value per line. 1922 | * 1923 | * If the Value have comments then they are outputed according to their 1924 | #CommentPlacement. 1925 | * 1926 | * \param indentation Each level will be indented by this amount extra. 1927 | * \sa Reader, Value, Value::setComment() 1928 | * \deprecated Use StreamWriterBuilder. 1929 | */ 1930 | class JSON_API StyledStreamWriter 1931 | { 1932 | public: 1933 | StyledStreamWriter(std::string indentation = "\t"); 1934 | ~StyledStreamWriter() 1935 | { 1936 | } 1937 | 1938 | public: 1939 | /** \brief Serialize a Value in JSON format. 1940 | * \param out Stream to write to. (Can be ostringstream, e.g.) 1941 | * \param root Value to serialize. 1942 | * \note There is no point in deriving from Writer, since write() should not 1943 | * return a value. 1944 | */ 1945 | void write(std::ostream& out, const Value& root); 1946 | 1947 | private: 1948 | void writeValue(const Value& value); 1949 | void writeArrayValue(const Value& value); 1950 | bool isMultineArray(const Value& value); 1951 | void pushValue(const std::string& value); 1952 | void writeIndent(); 1953 | void writeWithIndent(const std::string& value); 1954 | void indent(); 1955 | void unindent(); 1956 | void writeCommentBeforeValue(const Value& root); 1957 | void writeCommentAfterValueOnSameLine(const Value& root); 1958 | bool hasCommentForValue(const Value& value); 1959 | static std::string normalizeEOL(const std::string& text); 1960 | 1961 | typedef std::vector ChildValues; 1962 | 1963 | ChildValues childValues_; 1964 | std::ostream* document_; 1965 | std::string indentString_; 1966 | int rightMargin_; 1967 | std::string indentation_; 1968 | bool addChildValues_ : 1; 1969 | bool indented_ : 1; 1970 | }; 1971 | 1972 | #if defined(JSON_HAS_INT64) 1973 | std::string JSON_API valueToString(Int value); 1974 | std::string JSON_API valueToString(UInt value); 1975 | #endif // if defined(JSON_HAS_INT64) 1976 | std::string JSON_API valueToString(LargestInt value); 1977 | std::string JSON_API valueToString(LargestUInt value); 1978 | std::string JSON_API valueToString(double value); 1979 | std::string JSON_API valueToString(bool value); 1980 | std::string JSON_API valueToQuotedString(const char* value); 1981 | 1982 | /// \brief Output using the StyledStreamWriter. 1983 | /// \see Json::operator>>() 1984 | JSON_API std::ostream& operator<<(std::ostream&, const Value& root); 1985 | 1986 | } // namespace Json 1987 | 1988 | #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 1989 | #pragma warning(pop) 1990 | #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 1991 | 1992 | #endif // JSON_WRITER_H_INCLUDED 1993 | 1994 | // ////////////////////////////////////////////////////////////////////// 1995 | // End of content of file: include/json/writer.h 1996 | // ////////////////////////////////////////////////////////////////////// 1997 | 1998 | // ////////////////////////////////////////////////////////////////////// 1999 | // Beginning of content of file: include/json/assertions.h 2000 | // ////////////////////////////////////////////////////////////////////// 2001 | 2002 | // Copyright 2007-2010 Baptiste Lepilleur 2003 | // Distributed under MIT license, or public domain if desired and 2004 | // recognized in your jurisdiction. 2005 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 2006 | 2007 | #ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED 2008 | #define CPPTL_JSON_ASSERTIONS_H_INCLUDED 2009 | 2010 | #include 2011 | #include 2012 | 2013 | #if !defined(JSON_IS_AMALGAMATION) 2014 | #include "config.h" 2015 | #endif // if !defined(JSON_IS_AMALGAMATION) 2016 | 2017 | /** It should not be possible for a maliciously designed file to 2018 | * cause an abort() or seg-fault, so these macros are used only 2019 | * for pre-condition violations and internal logic errors. 2020 | */ 2021 | #if JSON_USE_EXCEPTION 2022 | 2023 | // @todo <= add detail about condition in exception 2024 | #define JSON_ASSERT(condition) \ 2025 | { \ 2026 | if (!(condition)) \ 2027 | { \ 2028 | Json::throwLogicError("assert json failed"); \ 2029 | } \ 2030 | } 2031 | 2032 | #define JSON_FAIL_MESSAGE(message) \ 2033 | { \ 2034 | std::ostringstream oss; \ 2035 | oss << message; \ 2036 | Json::throwLogicError(oss.str()); \ 2037 | abort(); \ 2038 | } 2039 | 2040 | #else // JSON_USE_EXCEPTION 2041 | 2042 | #define JSON_ASSERT(condition) assert(condition) 2043 | 2044 | // The call to assert() will show the failure message in debug builds. In 2045 | // release builds we abort, for a core-dump or debugger. 2046 | #define JSON_FAIL_MESSAGE(message) \ 2047 | { \ 2048 | std::ostringstream oss; \ 2049 | oss << message; \ 2050 | assert(false && oss.str().c_str()); \ 2051 | abort(); \ 2052 | } 2053 | 2054 | #endif 2055 | 2056 | #define JSON_ASSERT_MESSAGE(condition, message) \ 2057 | if (!(condition)) \ 2058 | { \ 2059 | JSON_FAIL_MESSAGE(message); \ 2060 | } 2061 | 2062 | #endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED 2063 | 2064 | // ////////////////////////////////////////////////////////////////////// 2065 | // End of content of file: include/json/assertions.h 2066 | // ////////////////////////////////////////////////////////////////////// 2067 | 2068 | #endif // ifndef JSON_AMALGATED_H_INCLUDED 2069 | -------------------------------------------------------------------------------- /samples/c++/include/ppe.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace Json 6 | { 7 | class Value; 8 | } 9 | 10 | /** 11 | * @brief The PPE class. 12 | */ 13 | class PPE 14 | { 15 | public: 16 | /** 17 | * @brief PPE 18 | */ 19 | PPE(); 20 | 21 | /** 22 | * @brief Main loop 23 | * @return - EXIT_SUCCESS or EXIT_FAILURE 24 | */ 25 | int run() const; 26 | 27 | private: 28 | /** 29 | * @brief Sends a multipart form data request to the REST API of PPE service. 30 | * @param frame - image to be used for the inference 31 | * @param continuous - specifies whether this request is for continuous mode 32 | * @return - JSON containing query results 33 | */ 34 | Json::Value sendRequest(const cv::Mat& frame, const bool continuous) const; 35 | 36 | /** 37 | * @brief Draws results. 38 | * @param results - JSON containing results 39 | * @param frame - image on which to draw 40 | */ 41 | void drawResults(const Json::Value& results, cv::Mat& frame) const; 42 | 43 | /** 44 | * @brief Callback for trackbars. 45 | */ 46 | static void onTrackbar(int, void*); 47 | 48 | const std::string m_windowName; 49 | static int m_ppeThreshold; 50 | static int m_faceThreshold; 51 | static int m_personThreshold; 52 | static int m_bodyPartsThreshold; 53 | }; 54 | -------------------------------------------------------------------------------- /samples/c++/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ppe.h" 2 | 3 | int main() 4 | { 5 | PPE ppe; 6 | return ppe.run(); 7 | } 8 | -------------------------------------------------------------------------------- /samples/c++/src/ppe.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "json.h" 13 | #include "ppe.h" 14 | 15 | using namespace cv; 16 | using namespace std; 17 | using namespace Poco; 18 | using namespace Poco::Net; 19 | using namespace Poco::Util; 20 | 21 | // Initialise static variables for thresholds 22 | int PPE::m_ppeThreshold = 50; 23 | int PPE::m_personThreshold = 50; 24 | int PPE::m_bodyPartsThreshold = 50; 25 | int PPE::m_faceThreshold = 50; 26 | 27 | PPE::PPE() : m_windowName("Cortexica PPE sample") 28 | { 29 | namedWindow(m_windowName, WINDOW_NORMAL); 30 | resizeWindow(m_windowName, 1920, 1080); 31 | setWindowProperty(m_windowName, CV_WND_PROP_FULLSCREEN, CV_WINDOW_FULLSCREEN); 32 | 33 | createTrackbar("PPE detection threshold", m_windowName, &m_ppeThreshold, 100, onTrackbar); 34 | createTrackbar("Person detection threshold", m_windowName, &m_personThreshold, 100, onTrackbar); 35 | createTrackbar("Body parts detectiwon threshold", m_windowName, &m_bodyPartsThreshold, 100, onTrackbar); 36 | createTrackbar("Face detection threshold", m_windowName, &m_faceThreshold, 100, onTrackbar); 37 | } 38 | 39 | int PPE::run() const 40 | { 41 | VideoCapture capture(0); 42 | capture.set(CAP_PROP_FRAME_WIDTH, 1280); 43 | capture.set(CAP_PROP_FRAME_HEIGHT, 720); 44 | capture.set(CV_CAP_PROP_FOURCC, CV_FOURCC('M', 'J', 'P', 'G')); 45 | 46 | if (!capture.isOpened()) 47 | { 48 | cerr << "Error: Could not initialise camera" << endl; 49 | return EXIT_FAILURE; 50 | } 51 | 52 | bool continuousPPEInProgress = true; 53 | 54 | while (true) 55 | { 56 | Mat frame; 57 | capture.read(frame); 58 | putText(frame, "esc - exit", Point(0, 10), 1, 1, Scalar(255, 0, 0)); 59 | putText(frame, "space - single query", Point(0, 25), 1, 1, Scalar(255, 0, 0)); 60 | putText(frame, "c - continuous queries", Point(0, 40), 1, 1, Scalar(255, 0, 0)); 61 | 62 | if (continuousPPEInProgress) 63 | { 64 | const Json::Value results = sendRequest(frame, true); 65 | const int status = results["status"].asInt(); 66 | 67 | // The time limit for the continuous mode has been reached 68 | if (status == 50100) 69 | { 70 | continuousPPEInProgress = false; 71 | continue; 72 | } 73 | 74 | drawResults(results, frame); 75 | } 76 | else 77 | { 78 | imshow(m_windowName, frame); 79 | } 80 | 81 | const char key = static_cast(waitKey(1)); 82 | if (key == ' ' && !continuousPPEInProgress) 83 | { 84 | const Json::Value results = sendRequest(frame, false); 85 | drawResults(results, frame); 86 | waitKey(0); 87 | } 88 | else if (key == 'c') 89 | { 90 | continuousPPEInProgress = true; 91 | } 92 | else if (key == 27) // ESC 93 | { 94 | break; 95 | } 96 | } 97 | 98 | return EXIT_SUCCESS; 99 | } 100 | 101 | Json::Value PPE::sendRequest(const Mat& frame, const bool continuous) const 102 | { 103 | const string endpoint = continuous ? "/continuous-ppe" : "/ppe"; 104 | const string host = "localhost"; 105 | const Poco::UInt16 port = 8081; 106 | HTTPClientSession session(host, port); 107 | HTTPRequest request(HTTPRequest::HTTP_POST, endpoint, HTTPMessage::HTTP_1_1); 108 | 109 | request.setKeepAlive(true); 110 | const string boundary = MultipartWriter::createBoundary(); 111 | request.setContentType("multipart/form-data; boundary=" + boundary); 112 | request.setChunkedTransferEncoding(false); 113 | 114 | stringstream body; 115 | MultipartWriter multipartWriter(body, boundary); 116 | 117 | MessageHeader messageHeader; 118 | const string dispJson("form-data; name=\"options\""); 119 | messageHeader.set("Content-Disposition", dispJson); 120 | multipartWriter.nextPart(messageHeader); 121 | 122 | vector imageData; 123 | imencode(".jpg", frame, imageData); 124 | stringstream dataStream; 125 | dataStream.write(reinterpret_cast(imageData.data()), imageData.size()); 126 | 127 | Json::Value jsonHeader; 128 | jsonHeader["detectPPE"] = m_ppeThreshold > 0 ? true : false; 129 | jsonHeader["detectPersons"] = m_personThreshold > 0 ? true : false; 130 | jsonHeader["detectBodyParts"] = m_bodyPartsThreshold > 0 ? true : false; 131 | jsonHeader["detectFaces"] = m_faceThreshold > 0 ? true : false; 132 | jsonHeader["ppeThreshold"] = m_ppeThreshold / 100.0f; 133 | jsonHeader["personThreshold"] = m_personThreshold / 100.0f; 134 | jsonHeader["bodyPartsThreshold"] = m_bodyPartsThreshold / 100.0f; 135 | jsonHeader["faceThreshold"] = m_faceThreshold / 100.0f; 136 | 137 | Json::FastWriter fastwriter; 138 | body << fastwriter.write(jsonHeader); 139 | 140 | dataStream.rdbuf()->pubseekpos(0); 141 | if (dataStream.rdbuf()->in_avail() > 0) 142 | { 143 | messageHeader.clear(); 144 | const string dispData("form-data; name=\"image\""); 145 | messageHeader.set("Content-Disposition", dispData); 146 | multipartWriter.nextPart(messageHeader); 147 | body << dataStream.rdbuf(); 148 | } 149 | 150 | multipartWriter.close(); 151 | 152 | const unsigned int contentLength = body.str().size(); 153 | request.setContentLength(contentLength); 154 | 155 | ostream& requestStream = session.sendRequest(request); // Send request header 156 | requestStream << body.rdbuf(); // Send request body 157 | requestStream.flush(); 158 | 159 | Poco::Net::HTTPResponse res; 160 | stringstream resultsStream; 161 | std::istream& is = session.receiveResponse(res); 162 | Json::Reader reader; 163 | Json::Value results; 164 | Poco::StreamCopier::copyStream(is, resultsStream); 165 | 166 | if (!reader.parse(resultsStream.str(), results)) 167 | { 168 | cerr << reader.getFormattedErrorMessages(); 169 | } 170 | else 171 | { 172 | cout << "Received results: " << results.toStyledString() << endl; 173 | } 174 | 175 | return results; 176 | } 177 | 178 | void PPE::drawResults(const Json::Value& results, Mat& frame) const 179 | { 180 | vector ppe; 181 | vector persons[2]; 182 | vector objects; 183 | vector categoryClasses; 184 | vector confidenceLevels; 185 | const Json::Value classifications = results["result"]; 186 | bool helmetFound = false; 187 | bool vestFound = false; 188 | 189 | for (size_t i = 0; i < classifications.size(); i++) 190 | { 191 | const Json::Value values = classifications.get(i, Json::Value()); 192 | const string categoryClass = values.get("categoryClass", Json::Value()).asString(); 193 | const float confidence = values.get("confidence", Json::Value()).asFloat(); 194 | const float xStart = values.get("xStart", Json::Value()).asFloat(); 195 | const float xEnd = values.get("xEnd", Json::Value()).asFloat(); 196 | const float yStart = values.get("yStart", Json::Value()).asFloat(); 197 | const float yEnd = values.get("yEnd", Json::Value()).asFloat(); 198 | const unsigned int width = static_cast(frame.cols); 199 | const unsigned int height = static_cast(frame.rows); 200 | 201 | categoryClasses.push_back(categoryClass); 202 | confidenceLevels.push_back(confidence); 203 | const Rect rect(Point(xStart * width, yStart * height), Point(xEnd * width, yEnd * height)); 204 | 205 | if (categoryClass == "helmet") 206 | { 207 | helmetFound = true; 208 | ppe.push_back(rect); 209 | } 210 | else if (categoryClass == "vest") 211 | { 212 | vestFound = true; 213 | ppe.push_back(rect); 214 | } 215 | else if (categoryClass == "face") 216 | { 217 | Rect expandedRect = rect; 218 | expandedRect += Size(0, frame.rows - rect.height); 219 | expandedRect -= Point(0, rect.y); 220 | persons[0].push_back(rect); 221 | persons[1].push_back(expandedRect); 222 | } 223 | 224 | objects.push_back(rect); 225 | } 226 | 227 | const bool ppeFound = helmetFound && vestFound; 228 | const double fontScale = 1.15; 229 | const int verticalTextOffset = 8; 230 | const unsigned int thickness = 1; 231 | const unsigned int fontFace = 1; 232 | 233 | // Draw all boxes in white 234 | for (size_t i = 0; i < objects.size(); i++) 235 | { 236 | rectangle(frame, objects.at(i), Scalar::all(255), thickness, cv::LINE_AA); 237 | Point textPosition(objects.at(i).x, objects.at(i).y - verticalTextOffset); 238 | putText(frame, to_string(confidenceLevels.at(i)), textPosition, fontFace, fontScale, Scalar::all(255)); 239 | textPosition.y -= verticalTextOffset * 2; 240 | putText(frame, categoryClasses.at(i), textPosition, fontFace, fontScale, Scalar::all(255)); 241 | } 242 | 243 | // Draw PPE and person boxes in red or green depending on whether required PPE was found or not 244 | for (size_t i = 0; i < persons[1].size(); i++) 245 | { 246 | Scalar colour = Scalar(0, 0, 255); 247 | for (size_t j = 0; j < ppe.size(); j++) 248 | { 249 | const bool intersects = ((persons[1].at(i) & ppe.at(j)).area() > 0); 250 | if (intersects) 251 | { 252 | colour = ppeFound ? Scalar(0, 255, 0) : Scalar(0, 0, 255); 253 | rectangle(frame, ppe.at(j), colour, thickness + 2, cv::LINE_AA); 254 | ppe.erase(ppe.begin(), ppe.begin() + j); 255 | } 256 | } 257 | rectangle(frame, persons[0].at(i), colour, thickness + 2, cv::LINE_AA); 258 | } 259 | 260 | imshow(m_windowName, frame); 261 | } 262 | 263 | void PPE::onTrackbar(int, void*) 264 | { 265 | } 266 | -------------------------------------------------------------------------------- /samples/python/sample.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import json 3 | import requests 4 | 5 | cap = cv2.VideoCapture(0) 6 | cv2.namedWindow("Cortexica PPE sample", cv2.WND_PROP_FULLSCREEN) 7 | cv2.setWindowProperty("Cortexica PPE sample", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN) 8 | 9 | while(True): 10 | ret, frame = cap.read() 11 | rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2BGRA) 12 | key = cv2.waitKey(1) 13 | 14 | if key & 0xFF == ord(' '): 15 | try: 16 | imencoded = cv2.imencode(".jpg", rgb)[1] 17 | multipart_form_data = { 18 | 'image': ('', imencoded.tostring()), 19 | 'options': ('', '{"detectPPE": true, "detectFaces": true, "detectPersons": true, "detectBodyParts": true, "ppeThreshold": 0.5, "faceThreshold": 0.5, "personThreshold": 0.5, "bodyPartsThreshold": 0.5}'), 20 | } 21 | response = requests.post('http://127.0.0.1:8081/ppe', files=multipart_form_data) 22 | except requests.exceptions.RequestException as e: # This is the correct syntax 23 | print(e) 24 | break; 25 | 26 | json_object = json.loads(response.text) 27 | print('\n') 28 | 29 | if json_object['status'] == 50100 : 30 | print(json_object['errorMessage']) 31 | else: 32 | print('Inference time: ' + str(json_object['ms']) + 'ms') 33 | for obj in json_object['result'] or []: 34 | categoryClass = obj['categoryClass'] 35 | confidence = obj['confidence'] 36 | xStart = int(obj['xStart'] * rgb.shape[1]) 37 | xEnd = int(obj['xEnd'] * rgb.shape[1]) 38 | yStart = int(obj['yStart'] * rgb.shape[0]) 39 | yEnd = int(obj['yEnd'] * rgb.shape[0]) 40 | width = xEnd - xStart 41 | height = yEnd - yStart 42 | cv2.rectangle(rgb,(xStart, yStart),(xStart + width, yStart + height), (255, 255, 255), 2) 43 | cv2.putText(rgb, categoryClass,(xStart + width + 10, yStart + height), 0 , 0.5, (255, 255, 255)) 44 | 45 | print('\n') 46 | print(' categoryClass: ' + categoryClass) 47 | print(' confidence: ' + str(confidence)) 48 | print(' xStart: ' + str(xStart)) 49 | print(' xEnd: ' + str(xEnd)) 50 | print(' yStart: ' + str(yStart)) 51 | print(' yEnd: ' + str(yEnd)) 52 | 53 | cv2.imshow('Cortexica PPE sample', rgb) 54 | cv2.waitKey(0) 55 | else: 56 | cv2.putText(rgb, 'esc - exit', (0, 10), 1 , 1, (255, 0, 0)) 57 | cv2.putText(rgb, 'space - single query', (0, 25), 1 , 1, (255, 0, 0)) 58 | cv2.imshow('Cortexica PPE sample', rgb) 59 | if key & 0xFF == 27: # This is the escape key code 60 | break 61 | 62 | cap.release() 63 | cv2.destroyAllWindows() 64 | -------------------------------------------------------------------------------- /whitepaper/cortexica_whitepaper_realtime_ppe_monitoring_edge.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cortexica/intel-rrk-safety/61bd82f062f6f15e57f569d6bf691c01efdba719/whitepaper/cortexica_whitepaper_realtime_ppe_monitoring_edge.pdf -------------------------------------------------------------------------------- /whitepaper/images/access_control.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cortexica/intel-rrk-safety/61bd82f062f6f15e57f569d6bf691c01efdba719/whitepaper/images/access_control.jpg -------------------------------------------------------------------------------- /whitepaper/images/arch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cortexica/intel-rrk-safety/61bd82f062f6f15e57f569d6bf691c01efdba719/whitepaper/images/arch.jpg -------------------------------------------------------------------------------- /whitepaper/images/continuous_monitoring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cortexica/intel-rrk-safety/61bd82f062f6f15e57f569d6bf691c01efdba719/whitepaper/images/continuous_monitoring.png -------------------------------------------------------------------------------- /whitepaper/images/iotswc.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cortexica/intel-rrk-safety/61bd82f062f6f15e57f569d6bf691c01efdba719/whitepaper/images/iotswc.JPG -------------------------------------------------------------------------------- /whitepaper/images/myriad-x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cortexica/intel-rrk-safety/61bd82f062f6f15e57f569d6bf691c01efdba719/whitepaper/images/myriad-x.jpg -------------------------------------------------------------------------------- /whitepaper/images/myriad-x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cortexica/intel-rrk-safety/61bd82f062f6f15e57f569d6bf691c01efdba719/whitepaper/images/myriad-x.png -------------------------------------------------------------------------------- /whitepaper/images/pharma-ppe.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cortexica/intel-rrk-safety/61bd82f062f6f15e57f569d6bf691c01efdba719/whitepaper/images/pharma-ppe.jpg -------------------------------------------------------------------------------- /whitepaper/images/ppe-rrk.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cortexica/intel-rrk-safety/61bd82f062f6f15e57f569d6bf691c01efdba719/whitepaper/images/ppe-rrk.jpg -------------------------------------------------------------------------------- /whitepaper/images/sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cortexica/intel-rrk-safety/61bd82f062f6f15e57f569d6bf691c01efdba719/whitepaper/images/sample.png -------------------------------------------------------------------------------- /whitepaper/images/stats.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cortexica/intel-rrk-safety/61bd82f062f6f15e57f569d6bf691c01efdba719/whitepaper/images/stats.png --------------------------------------------------------------------------------