зеркало из https://github.com/mozilla/eideticker.git
Bug 930715 - Allow configuration of camera settings via json config files;r=davehunt
This commit is contained in:
Родитель
61a029570a
Коммит
781b5a488b
|
@ -1,3 +1,5 @@
|
|||
*.d
|
||||
*.o
|
||||
*.pyc
|
||||
*~
|
||||
bin/activate
|
||||
|
@ -29,4 +31,7 @@ lib/
|
|||
src/videocapture/build/*
|
||||
src/videocapture/videocapture.egg-info/
|
||||
src/videocapture/videocapture/decklink/decklink-capture
|
||||
src/dashboard/httplogs/*.json
|
||||
src/videocapture/videocapture/pointgrey/pointgrey-capture
|
||||
src/videocapture/videocapture/pointgrey/get-camera-id
|
||||
src/videocapture/videocapture/pointgrey/dump-current-settings
|
||||
rc/dashboard/httplogs/*.json
|
||||
|
|
|
@ -36,6 +36,11 @@ supported_formats = {
|
|||
"720p@59.94": { "decklink_mode": 12 }
|
||||
}
|
||||
|
||||
camera_configs = {
|
||||
"Flea3 FL3-U3-13Y3M": "FL3-U3-13Y3M.json",
|
||||
"Flea3 FL3-U3-13E4C": "FL3-U3-13E4C.json"
|
||||
}
|
||||
|
||||
class CaptureProcess(multiprocessing.Process):
|
||||
|
||||
def __init__(self, capture_device, video_format, frame_counter,
|
||||
|
@ -68,7 +73,14 @@ class CaptureProcess(multiprocessing.Process):
|
|||
'-f',
|
||||
self.output_raw_filename)
|
||||
elif self.capture_device == "pointgrey":
|
||||
# get the device type
|
||||
camera_id = subprocess.check_output([os.path.join(POINTGREY_DIR, "get-camera-id")]).strip()
|
||||
camera_config = camera_configs.get(camera_id)
|
||||
if not camera_config:
|
||||
raise Exception("No camera configuration for model '%s'" % camera_id)
|
||||
args = (os.path.join(POINTGREY_DIR, 'pointgrey-capture'),
|
||||
'-c',
|
||||
os.path.join(POINTGREY_DIR, camera_config),
|
||||
'-o',
|
||||
'-n',
|
||||
'1200',
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/wait.h>
|
||||
#include <signal.h>
|
||||
|
@ -11,6 +12,7 @@
|
|||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#include "JSON.h"
|
||||
#include "FlyCapture2.h"
|
||||
|
||||
using namespace FlyCapture2;
|
||||
|
@ -31,7 +33,7 @@ int usage(char *progname, int status)
|
|||
" -d Output debugging information\n"
|
||||
" -o If specified, print frame numbers while capturing\n"
|
||||
" -f <outputdir> Directory video files will be written to\n"
|
||||
" -r <framerate> Framerate to capture at (default is 60)\n"
|
||||
" -c <configfile> Configuration file for camera (in JSON format)\n"
|
||||
" -n <frames> Max number of frames to capture (default is 20 * framerate)\n"
|
||||
"\n"
|
||||
"Capture video to a set of pngs.\n"
|
||||
|
@ -47,18 +49,98 @@ void printError( Error error )
|
|||
error.PrintErrorTrace();
|
||||
}
|
||||
|
||||
PropertyType getPropertyType(const std::wstring propertyTypeStr)
|
||||
{
|
||||
if (propertyTypeStr == L"BRIGHTNESS") return BRIGHTNESS;
|
||||
else if (propertyTypeStr == L"AUTO_EXPOSURE") return AUTO_EXPOSURE;
|
||||
else if (propertyTypeStr == L"SHARPNESS") return SHARPNESS;
|
||||
else if (propertyTypeStr == L"SHUTTER") return SHUTTER;
|
||||
else if (propertyTypeStr == L"GAIN") return GAIN;
|
||||
else if (propertyTypeStr == L"FRAME_RATE") return FRAME_RATE;
|
||||
else if (propertyTypeStr == L"WHITE_BALANCE") return WHITE_BALANCE;
|
||||
|
||||
char propertyLabel[40];
|
||||
wcstombs(propertyLabel, propertyTypeStr.c_str(), 40);
|
||||
fprintf(stderr, "Error: Unknown property type '%s'\n", propertyLabel);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void processPropertiesFile(const char *filename, Camera &cam)
|
||||
{
|
||||
struct stat st;
|
||||
if (stat(filename, &st) != 0) {
|
||||
fprintf(stderr, "Error processing prefs file '%s': can't stat", filename);
|
||||
}
|
||||
char *contents = new char[st.st_size + 1];
|
||||
FILE *fp = fopen(filename, "r");
|
||||
fread(contents, st.st_size, 1, fp);
|
||||
contents[st.st_size] = '\0';
|
||||
JSONValue *prefdict = JSON::Parse(contents);
|
||||
if (!prefdict) {
|
||||
fprintf(stderr, "Error processing prefs file '%s': not valid JSON\n", filename);
|
||||
exit(1);
|
||||
}
|
||||
if (!prefdict->IsObject()) {
|
||||
fprintf(stderr, "Error processing prefs file '%s': root not a JSON object\n", filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
JSONObject root = prefdict->AsObject();
|
||||
JSONObject properties = root[L"properties"]->AsObject();
|
||||
for (JSONObject::iterator iter = properties.begin();
|
||||
iter != properties.end(); iter++) {
|
||||
Property property;
|
||||
|
||||
property.type = getPropertyType(iter->first);
|
||||
cam.GetProperty(&property);
|
||||
char pname[512];
|
||||
wcstombs(pname, iter->first.c_str(), 512);
|
||||
|
||||
JSONObject propertySettings = iter->second->AsObject();
|
||||
for (JSONObject::iterator iter2 = propertySettings.begin();
|
||||
iter2 != propertySettings.end(); iter2++) {
|
||||
if (iter2->first == L"onOff" || iter2->first == L"autoManualMode") {
|
||||
if (!iter2->second->IsBool()) {
|
||||
fprintf(stderr, "Error: Expected onOff/auto property to be boolean, was not\n");
|
||||
exit(1);
|
||||
}
|
||||
if (iter2->first == L"onOff")
|
||||
property.onOff = iter2->second->AsBool();
|
||||
else
|
||||
property.autoManualMode = iter2->second->AsBool();
|
||||
}
|
||||
else if (iter2->first == L"absValue" || iter2->first == L"valueA" ||
|
||||
iter2->first == L"valueB") {
|
||||
if (!iter2->second->IsNumber()) {
|
||||
fprintf(stderr, "Error: Expected absValue/valueA/valueB property "
|
||||
"to be a number, was not\n");
|
||||
exit(1);
|
||||
}
|
||||
if (iter2->first == L"absValue")
|
||||
property.absValue = iter2->second->AsNumber();
|
||||
else if (iter2->first == L"valueA")
|
||||
property.valueA = iter2->second->AsNumber();
|
||||
else
|
||||
property.valueB = iter2->second->AsNumber();
|
||||
}
|
||||
}
|
||||
cam.SetProperty(&property);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
Error error;
|
||||
int ch;
|
||||
const char *videoOutputDir = NULL;
|
||||
const char *configFilename = NULL;
|
||||
int maxFrames = 0;
|
||||
int fps = 60;
|
||||
bool printFrameNums = false;
|
||||
bool debug = false;
|
||||
|
||||
// Parse command line options
|
||||
while ((ch = getopt(argc, argv, "do?h3f:n:r:")) != -1) {
|
||||
while ((ch = getopt(argc, argv, "do?h3f:n:r:c:")) != -1) {
|
||||
switch (ch) {
|
||||
case 'd':
|
||||
debug = true;
|
||||
|
@ -75,6 +157,9 @@ int main(int argc, char *argv[])
|
|||
case 'r':
|
||||
fps = atoi(optarg);
|
||||
break;
|
||||
case 'c':
|
||||
configFilename = optarg;
|
||||
break;
|
||||
case '?':
|
||||
case 'h':
|
||||
usage(argv[0], 0);
|
||||
|
@ -127,7 +212,6 @@ int main(int argc, char *argv[])
|
|||
cam.GetProperty(&frameRateProp);
|
||||
frameRateProp.onOff = true;
|
||||
frameRateProp.autoManualMode = false;
|
||||
frameRateProp.valueA = fps;
|
||||
frameRateProp.absValue = (float)fps;
|
||||
cam.SetProperty(&frameRateProp);
|
||||
}
|
||||
|
@ -146,17 +230,9 @@ int main(int argc, char *argv[])
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
// turn off all auto adjustments for eideticker
|
||||
PropertyType propTypes[5] = { AUTO_EXPOSURE, SHARPNESS, SHUTTER, GAIN, WHITE_BALANCE };
|
||||
for (int i=0; i<5; i++) {
|
||||
Property prop;
|
||||
prop.type = propTypes[i];
|
||||
cam.GetProperty(&prop);
|
||||
if (propTypes[i] == AUTO_EXPOSURE)
|
||||
prop.onOff = true;
|
||||
prop.autoManualMode = false;
|
||||
cam.SetProperty(&prop);
|
||||
}
|
||||
|
||||
if (configFilename)
|
||||
processPropertiesFile(configFilename, cam);
|
||||
|
||||
// setup signal handler for termination
|
||||
signal(SIGTERM, term);
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"properties": {
|
||||
"AUTO_EXPOSURE": {
|
||||
"absValue": 1.32196,
|
||||
"autoManualMode": false,
|
||||
"onOff": true,
|
||||
"valueA": 480,
|
||||
"valueB": 0
|
||||
},
|
||||
"GAIN": {
|
||||
"absValue": 18.06179,
|
||||
"autoManualMode": false,
|
||||
"onOff": true,
|
||||
"valueA": 162,
|
||||
"valueB": 0
|
||||
},
|
||||
"SHARPNESS": {
|
||||
"absValue": 0.0,
|
||||
"autoManualMode": false,
|
||||
"onOff": false,
|
||||
"valueA": 512,
|
||||
"valueB": 0
|
||||
},
|
||||
"SHUTTER": {
|
||||
"absValue": 3.078401,
|
||||
"autoManualMode": false,
|
||||
"onOff": true,
|
||||
"valueA": 196,
|
||||
"valueB": 0
|
||||
},
|
||||
"WHITE_BALANCE": {
|
||||
"absValue": 0.0,
|
||||
"autoManualMode": false,
|
||||
"onOff": false,
|
||||
"valueA": 0,
|
||||
"valueB": 0
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"properties": {
|
||||
"AUTO_EXPOSURE": {
|
||||
"absValue": -0.941101,
|
||||
"autoManualMode": false,
|
||||
"onOff": false,
|
||||
"valueA": 100,
|
||||
"valueB": 0
|
||||
},
|
||||
"GAIN": {
|
||||
"absValue": 18.056644,
|
||||
"autoManualMode": false,
|
||||
"onOff": true,
|
||||
"valueA": 305,
|
||||
"valueB": 0
|
||||
},
|
||||
"SHARPNESS": {
|
||||
"absValue": 0.0,
|
||||
"autoManualMode": false,
|
||||
"onOff": false,
|
||||
"valueA": 1024,
|
||||
"valueB": 0
|
||||
},
|
||||
"SHUTTER": {
|
||||
"absValue": 16.494692,
|
||||
"autoManualMode": false,
|
||||
"onOff": true,
|
||||
"valueA": 2315,
|
||||
"valueB": 0
|
||||
},
|
||||
"WHITE_BALANCE": {
|
||||
"absValue": 0.0,
|
||||
"autoManualMode": false,
|
||||
"onOff": false,
|
||||
"valueA": 0,
|
||||
"valueB": 0
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,280 @@
|
|||
/*
|
||||
* File JSON.cpp part of the SimpleJSON Library - http://mjpa.in/json
|
||||
*
|
||||
* Copyright (C) 2010 Mike Anchor
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "JSON.h"
|
||||
|
||||
/**
|
||||
* Blocks off the public constructor
|
||||
*
|
||||
* @access private
|
||||
*
|
||||
*/
|
||||
JSON::JSON()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a complete JSON encoded string
|
||||
* This is just a wrapper around the UNICODE Parse().
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @param char* data The JSON text
|
||||
*
|
||||
* @return JSONValue* Returns a JSON Value representing the root, or NULL on error
|
||||
*/
|
||||
JSONValue *JSON::Parse(const char *data)
|
||||
{
|
||||
size_t length = strlen(data) + 1;
|
||||
wchar_t *w_data = (wchar_t*)malloc(length * sizeof(wchar_t));
|
||||
|
||||
#if defined(WIN32) && !defined(__GNUC__)
|
||||
size_t ret_value = 0;
|
||||
if (mbstowcs_s(&ret_value, w_data, length, data, length) != 0)
|
||||
{
|
||||
free(w_data);
|
||||
return NULL;
|
||||
}
|
||||
#elif defined(ANDROID)
|
||||
// mbstowcs seems to misbehave on android
|
||||
for(size_t i = 0; i<length; i++)
|
||||
w_data[i] = (wchar_t)data[i];
|
||||
#else
|
||||
if (mbstowcs(w_data, data, length) == (size_t)-1)
|
||||
{
|
||||
free(w_data);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
JSONValue *value = JSON::Parse(w_data);
|
||||
free(w_data);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a complete JSON encoded string (UNICODE input version)
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @param wchar_t* data The JSON text
|
||||
*
|
||||
* @return JSONValue* Returns a JSON Value representing the root, or NULL on error
|
||||
*/
|
||||
JSONValue *JSON::Parse(const wchar_t *data)
|
||||
{
|
||||
// Skip any preceding whitespace, end of data = no JSON = fail
|
||||
if (!SkipWhitespace(&data))
|
||||
return NULL;
|
||||
|
||||
// We need the start of a value here now...
|
||||
JSONValue *value = JSONValue::Parse(&data);
|
||||
if (value == NULL)
|
||||
return NULL;
|
||||
|
||||
// Can be white space now and should be at the end of the string then...
|
||||
if (SkipWhitespace(&data))
|
||||
{
|
||||
delete value;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// We're now at the end of the string
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns the passed in JSONValue into a JSON encode string
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @param JSONValue* value The root value
|
||||
*
|
||||
* @return std::wstring Returns a JSON encoded string representation of the given value
|
||||
*/
|
||||
std::wstring JSON::Stringify(const JSONValue *value)
|
||||
{
|
||||
if (value != NULL)
|
||||
return value->Stringify();
|
||||
else
|
||||
return L"";
|
||||
}
|
||||
|
||||
/**
|
||||
* Skips over any whitespace characters (space, tab, \r or \n) defined by the JSON spec
|
||||
*
|
||||
* @access protected
|
||||
*
|
||||
* @param wchar_t** data Pointer to a wchar_t* that contains the JSON text
|
||||
*
|
||||
* @return bool Returns true if there is more data, or false if the end of the text was reached
|
||||
*/
|
||||
bool JSON::SkipWhitespace(const wchar_t **data)
|
||||
{
|
||||
while (**data != 0 && (**data == L' ' || **data == L'\t' || **data == L'\r' || **data == L'\n'))
|
||||
(*data)++;
|
||||
|
||||
return **data != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts a JSON String as defined by the spec - "<some chars>"
|
||||
* Any escaped characters are swapped out for their unescaped values
|
||||
*
|
||||
* @access protected
|
||||
*
|
||||
* @param wchar_t** data Pointer to a wchar_t* that contains the JSON text
|
||||
* @param std::wstring& str Reference to a std::wstring to receive the extracted string
|
||||
*
|
||||
* @return bool Returns true on success, false on failure
|
||||
*/
|
||||
bool JSON::ExtractString(const wchar_t **data, std::wstring &str)
|
||||
{
|
||||
str = L"";
|
||||
|
||||
while (**data != 0)
|
||||
{
|
||||
// Save the char so we can change it if need be
|
||||
wchar_t next_char = **data;
|
||||
|
||||
// Escaping something?
|
||||
if (next_char == L'\\')
|
||||
{
|
||||
// Move over the escape char
|
||||
(*data)++;
|
||||
|
||||
// Deal with the escaped char
|
||||
switch (**data)
|
||||
{
|
||||
case L'"': next_char = L'"'; break;
|
||||
case L'\\': next_char = L'\\'; break;
|
||||
case L'/': next_char = L'/'; break;
|
||||
case L'b': next_char = L'\b'; break;
|
||||
case L'f': next_char = L'\f'; break;
|
||||
case L'n': next_char = L'\n'; break;
|
||||
case L'r': next_char = L'\r'; break;
|
||||
case L't': next_char = L'\t'; break;
|
||||
case L'u':
|
||||
{
|
||||
// We need 5 chars (4 hex + the 'u') or its not valid
|
||||
if (!simplejson_wcsnlen(*data, 5))
|
||||
return false;
|
||||
|
||||
// Deal with the chars
|
||||
next_char = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
// Do it first to move off the 'u' and leave us on the
|
||||
// final hex digit as we move on by one later on
|
||||
(*data)++;
|
||||
|
||||
next_char <<= 4;
|
||||
|
||||
// Parse the hex digit
|
||||
if (**data >= '0' && **data <= '9')
|
||||
next_char |= (**data - '0');
|
||||
else if (**data >= 'A' && **data <= 'F')
|
||||
next_char |= (10 + (**data - 'A'));
|
||||
else if (**data >= 'a' && **data <= 'f')
|
||||
next_char |= (10 + (**data - 'a'));
|
||||
else
|
||||
{
|
||||
// Invalid hex digit = invalid JSON
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// By the spec, only the above cases are allowed
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// End of the string?
|
||||
else if (next_char == L'"')
|
||||
{
|
||||
(*data)++;
|
||||
str.reserve(); // Remove unused capacity
|
||||
return true;
|
||||
}
|
||||
|
||||
// Disallowed char?
|
||||
else if (next_char < L' ' && next_char != L'\t')
|
||||
{
|
||||
// SPEC Violation: Allow tabs due to real world cases
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add the next char
|
||||
str += next_char;
|
||||
|
||||
// Move on
|
||||
(*data)++;
|
||||
}
|
||||
|
||||
// If we're here, the string ended incorrectly
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses some text as though it is an integer
|
||||
*
|
||||
* @access protected
|
||||
*
|
||||
* @param wchar_t** data Pointer to a wchar_t* that contains the JSON text
|
||||
*
|
||||
* @return double Returns the double value of the number found
|
||||
*/
|
||||
double JSON::ParseInt(const wchar_t **data)
|
||||
{
|
||||
double integer = 0;
|
||||
while (**data != 0 && **data >= '0' && **data <= '9')
|
||||
integer = integer * 10 + (*(*data)++ - '0');
|
||||
|
||||
return integer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses some text as though it is a decimal
|
||||
*
|
||||
* @access protected
|
||||
*
|
||||
* @param wchar_t** data Pointer to a wchar_t* that contains the JSON text
|
||||
*
|
||||
* @return double Returns the double value of the decimal found
|
||||
*/
|
||||
double JSON::ParseDecimal(const wchar_t **data)
|
||||
{
|
||||
double decimal = 0.0;
|
||||
double factor = 0.1;
|
||||
while (**data != 0 && **data >= '0' && **data <= '9')
|
||||
{
|
||||
int digit = (*(*data)++ - '0');
|
||||
decimal = decimal + digit * factor;
|
||||
factor *= 0.1;
|
||||
}
|
||||
return decimal;
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* File JSON.h part of the SimpleJSON Library - http://mjpa.in/json
|
||||
*
|
||||
* Copyright (C) 2010 Mike Anchor
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _JSON_H_
|
||||
#define _JSON_H_
|
||||
|
||||
// Win32 incompatibilities
|
||||
#if defined(WIN32) && !defined(__GNUC__)
|
||||
#define wcsncasecmp _wcsnicmp
|
||||
static inline bool isnan(double x) { return x != x; }
|
||||
static inline bool isinf(double x) { return !isnan(x) && isnan(x - x); }
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
// Linux compile fix - from quaker66
|
||||
#ifdef __GNUC__
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#endif
|
||||
|
||||
// Mac compile fixes - from quaker66, Lion fix by dabrahams
|
||||
#if defined(__APPLE__) && __DARWIN_C_LEVEL < 200809L || (defined(WIN32) && defined(__GNUC__)) || defined(ANDROID)
|
||||
#include <wctype.h>
|
||||
#include <wchar.h>
|
||||
|
||||
static inline int wcsncasecmp(const wchar_t *s1, const wchar_t *s2, size_t n)
|
||||
{
|
||||
int lc1 = 0;
|
||||
int lc2 = 0;
|
||||
|
||||
while (n--)
|
||||
{
|
||||
lc1 = towlower (*s1);
|
||||
lc2 = towlower (*s2);
|
||||
|
||||
if (lc1 != lc2)
|
||||
return (lc1 - lc2);
|
||||
|
||||
if (!lc1)
|
||||
return 0;
|
||||
|
||||
++s1;
|
||||
++s2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Simple function to check a string 's' has at least 'n' characters
|
||||
static inline bool simplejson_wcsnlen(const wchar_t *s, size_t n) {
|
||||
if (s == 0)
|
||||
return false;
|
||||
|
||||
const wchar_t *save = s;
|
||||
while (n-- > 0)
|
||||
{
|
||||
if (*(save++) == 0) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Custom types
|
||||
class JSONValue;
|
||||
typedef std::vector<JSONValue*> JSONArray;
|
||||
typedef std::map<std::wstring, JSONValue*> JSONObject;
|
||||
|
||||
#include "JSONValue.h"
|
||||
|
||||
class JSON
|
||||
{
|
||||
friend class JSONValue;
|
||||
|
||||
public:
|
||||
static JSONValue* Parse(const char *data);
|
||||
static JSONValue* Parse(const wchar_t *data);
|
||||
static std::wstring Stringify(const JSONValue *value);
|
||||
protected:
|
||||
static bool SkipWhitespace(const wchar_t **data);
|
||||
static bool ExtractString(const wchar_t **data, std::wstring &str);
|
||||
static double ParseInt(const wchar_t **data);
|
||||
static double ParseDecimal(const wchar_t **data);
|
||||
private:
|
||||
JSON();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,803 @@
|
|||
/*
|
||||
* File JSONValue.cpp part of the SimpleJSON Library - http://mjpa.in/json
|
||||
*
|
||||
* Copyright (C) 2010 Mike Anchor
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <math.h>
|
||||
|
||||
#include "JSONValue.h"
|
||||
|
||||
// Macros to free an array/object
|
||||
#define FREE_ARRAY(x) { JSONArray::iterator iter; for (iter = x.begin(); iter != x.end(); iter++) { delete *iter; } }
|
||||
#define FREE_OBJECT(x) { JSONObject::iterator iter; for (iter = x.begin(); iter != x.end(); iter++) { delete (*iter).second; } }
|
||||
|
||||
/**
|
||||
* Parses a JSON encoded value to a JSONValue object
|
||||
*
|
||||
* @access protected
|
||||
*
|
||||
* @param wchar_t** data Pointer to a wchar_t* that contains the data
|
||||
*
|
||||
* @return JSONValue* Returns a pointer to a JSONValue object on success, NULL on error
|
||||
*/
|
||||
JSONValue *JSONValue::Parse(const wchar_t **data)
|
||||
{
|
||||
// Is it a string?
|
||||
if (**data == '"')
|
||||
{
|
||||
std::wstring str;
|
||||
if (!JSON::ExtractString(&(++(*data)), str))
|
||||
return NULL;
|
||||
else
|
||||
return new JSONValue(str);
|
||||
}
|
||||
|
||||
// Is it a boolean?
|
||||
else if ((simplejson_wcsnlen(*data, 4) && wcsncasecmp(*data, L"true", 4) == 0) || (simplejson_wcsnlen(*data, 5) && wcsncasecmp(*data, L"false", 5) == 0))
|
||||
{
|
||||
bool value = wcsncasecmp(*data, L"true", 4) == 0;
|
||||
(*data) += value ? 4 : 5;
|
||||
return new JSONValue(value);
|
||||
}
|
||||
|
||||
// Is it a null?
|
||||
else if (simplejson_wcsnlen(*data, 4) && wcsncasecmp(*data, L"null", 4) == 0)
|
||||
{
|
||||
(*data) += 4;
|
||||
return new JSONValue();
|
||||
}
|
||||
|
||||
// Is it a number?
|
||||
else if (**data == L'-' || (**data >= L'0' && **data <= L'9'))
|
||||
{
|
||||
// Negative?
|
||||
bool neg = **data == L'-';
|
||||
if (neg) (*data)++;
|
||||
|
||||
double number = 0.0;
|
||||
|
||||
// Parse the whole part of the number - only if it wasn't 0
|
||||
if (**data == L'0')
|
||||
(*data)++;
|
||||
else if (**data >= L'1' && **data <= L'9')
|
||||
number = JSON::ParseInt(data);
|
||||
else
|
||||
return NULL;
|
||||
|
||||
// Could be a decimal now...
|
||||
if (**data == '.')
|
||||
{
|
||||
(*data)++;
|
||||
|
||||
// Not get any digits?
|
||||
if (!(**data >= L'0' && **data <= L'9'))
|
||||
return NULL;
|
||||
|
||||
// Find the decimal and sort the decimal place out
|
||||
// Use ParseDecimal as ParseInt won't work with decimals less than 0.1
|
||||
// thanks to Javier Abadia for the report & fix
|
||||
double decimal = JSON::ParseDecimal(data);
|
||||
|
||||
// Save the number
|
||||
number += decimal;
|
||||
}
|
||||
|
||||
// Could be an exponent now...
|
||||
if (**data == L'E' || **data == L'e')
|
||||
{
|
||||
(*data)++;
|
||||
|
||||
// Check signage of expo
|
||||
bool neg_expo = false;
|
||||
if (**data == L'-' || **data == L'+')
|
||||
{
|
||||
neg_expo = **data == L'-';
|
||||
(*data)++;
|
||||
}
|
||||
|
||||
// Not get any digits?
|
||||
if (!(**data >= L'0' && **data <= L'9'))
|
||||
return NULL;
|
||||
|
||||
// Sort the expo out
|
||||
double expo = JSON::ParseInt(data);
|
||||
for (double i = 0.0; i < expo; i++)
|
||||
number = neg_expo ? (number / 10.0) : (number * 10.0);
|
||||
}
|
||||
|
||||
// Was it neg?
|
||||
if (neg) number *= -1;
|
||||
|
||||
return new JSONValue(number);
|
||||
}
|
||||
|
||||
// An object?
|
||||
else if (**data == L'{')
|
||||
{
|
||||
JSONObject object;
|
||||
|
||||
(*data)++;
|
||||
|
||||
while (**data != 0)
|
||||
{
|
||||
// Whitespace at the start?
|
||||
if (!JSON::SkipWhitespace(data))
|
||||
{
|
||||
FREE_OBJECT(object);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Special case - empty object
|
||||
if (object.size() == 0 && **data == L'}')
|
||||
{
|
||||
(*data)++;
|
||||
return new JSONValue(object);
|
||||
}
|
||||
|
||||
// We want a string now...
|
||||
std::wstring name;
|
||||
if (!JSON::ExtractString(&(++(*data)), name))
|
||||
{
|
||||
FREE_OBJECT(object);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// More whitespace?
|
||||
if (!JSON::SkipWhitespace(data))
|
||||
{
|
||||
FREE_OBJECT(object);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Need a : now
|
||||
if (*((*data)++) != L':')
|
||||
{
|
||||
FREE_OBJECT(object);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// More whitespace?
|
||||
if (!JSON::SkipWhitespace(data))
|
||||
{
|
||||
FREE_OBJECT(object);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// The value is here
|
||||
JSONValue *value = Parse(data);
|
||||
if (value == NULL)
|
||||
{
|
||||
FREE_OBJECT(object);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Add the name:value
|
||||
if (object.find(name) != object.end())
|
||||
delete object[name];
|
||||
object[name] = value;
|
||||
|
||||
// More whitespace?
|
||||
if (!JSON::SkipWhitespace(data))
|
||||
{
|
||||
FREE_OBJECT(object);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// End of object?
|
||||
if (**data == L'}')
|
||||
{
|
||||
(*data)++;
|
||||
return new JSONValue(object);
|
||||
}
|
||||
|
||||
// Want a , now
|
||||
if (**data != L',')
|
||||
{
|
||||
FREE_OBJECT(object);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
(*data)++;
|
||||
}
|
||||
|
||||
// Only here if we ran out of data
|
||||
FREE_OBJECT(object);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// An array?
|
||||
else if (**data == L'[')
|
||||
{
|
||||
JSONArray array;
|
||||
|
||||
(*data)++;
|
||||
|
||||
while (**data != 0)
|
||||
{
|
||||
// Whitespace at the start?
|
||||
if (!JSON::SkipWhitespace(data))
|
||||
{
|
||||
FREE_ARRAY(array);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Special case - empty array
|
||||
if (array.size() == 0 && **data == L']')
|
||||
{
|
||||
(*data)++;
|
||||
return new JSONValue(array);
|
||||
}
|
||||
|
||||
// Get the value
|
||||
JSONValue *value = Parse(data);
|
||||
if (value == NULL)
|
||||
{
|
||||
FREE_ARRAY(array);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Add the value
|
||||
array.push_back(value);
|
||||
|
||||
// More whitespace?
|
||||
if (!JSON::SkipWhitespace(data))
|
||||
{
|
||||
FREE_ARRAY(array);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// End of array?
|
||||
if (**data == L']')
|
||||
{
|
||||
(*data)++;
|
||||
return new JSONValue(array);
|
||||
}
|
||||
|
||||
// Want a , now
|
||||
if (**data != L',')
|
||||
{
|
||||
FREE_ARRAY(array);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
(*data)++;
|
||||
}
|
||||
|
||||
// Only here if we ran out of data
|
||||
FREE_ARRAY(array);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Ran out of possibilites, it's bad!
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic constructor for creating a JSON Value of type NULL
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
JSONValue::JSONValue(/*NULL*/)
|
||||
{
|
||||
type = JSONType_Null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic constructor for creating a JSON Value of type String
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @param wchar_t* m_char_value The string to use as the value
|
||||
*/
|
||||
JSONValue::JSONValue(const wchar_t *m_char_value)
|
||||
{
|
||||
type = JSONType_String;
|
||||
string_value = std::wstring(m_char_value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic constructor for creating a JSON Value of type String
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @param std::wstring m_string_value The string to use as the value
|
||||
*/
|
||||
JSONValue::JSONValue(const std::wstring &m_string_value)
|
||||
{
|
||||
type = JSONType_String;
|
||||
string_value = m_string_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic constructor for creating a JSON Value of type Bool
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @param bool m_bool_value The bool to use as the value
|
||||
*/
|
||||
JSONValue::JSONValue(bool m_bool_value)
|
||||
{
|
||||
type = JSONType_Bool;
|
||||
bool_value = m_bool_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic constructor for creating a JSON Value of type Number
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @param double m_number_value The number to use as the value
|
||||
*/
|
||||
JSONValue::JSONValue(double m_number_value)
|
||||
{
|
||||
type = JSONType_Number;
|
||||
number_value = m_number_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic constructor for creating a JSON Value of type Array
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @param JSONArray m_array_value The JSONArray to use as the value
|
||||
*/
|
||||
JSONValue::JSONValue(const JSONArray &m_array_value)
|
||||
{
|
||||
type = JSONType_Array;
|
||||
array_value = m_array_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic constructor for creating a JSON Value of type Object
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @param JSONObject m_object_value The JSONObject to use as the value
|
||||
*/
|
||||
JSONValue::JSONValue(const JSONObject &m_object_value)
|
||||
{
|
||||
type = JSONType_Object;
|
||||
object_value = m_object_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* The destructor for the JSON Value object
|
||||
* Handles deleting the objects in the array or the object value
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
JSONValue::~JSONValue()
|
||||
{
|
||||
if (type == JSONType_Array)
|
||||
{
|
||||
JSONArray::iterator iter;
|
||||
for (iter = array_value.begin(); iter != array_value.end(); iter++)
|
||||
delete *iter;
|
||||
}
|
||||
else if (type == JSONType_Object)
|
||||
{
|
||||
JSONObject::iterator iter;
|
||||
for (iter = object_value.begin(); iter != object_value.end(); iter++)
|
||||
{
|
||||
delete (*iter).second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the value is a NULL
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return bool Returns true if it is a NULL value, false otherwise
|
||||
*/
|
||||
bool JSONValue::IsNull() const
|
||||
{
|
||||
return type == JSONType_Null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the value is a String
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return bool Returns true if it is a String value, false otherwise
|
||||
*/
|
||||
bool JSONValue::IsString() const
|
||||
{
|
||||
return type == JSONType_String;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the value is a Bool
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return bool Returns true if it is a Bool value, false otherwise
|
||||
*/
|
||||
bool JSONValue::IsBool() const
|
||||
{
|
||||
return type == JSONType_Bool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the value is a Number
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return bool Returns true if it is a Number value, false otherwise
|
||||
*/
|
||||
bool JSONValue::IsNumber() const
|
||||
{
|
||||
return type == JSONType_Number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the value is an Array
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return bool Returns true if it is an Array value, false otherwise
|
||||
*/
|
||||
bool JSONValue::IsArray() const
|
||||
{
|
||||
return type == JSONType_Array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the value is an Object
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return bool Returns true if it is an Object value, false otherwise
|
||||
*/
|
||||
bool JSONValue::IsObject() const
|
||||
{
|
||||
return type == JSONType_Object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the String value of this JSONValue
|
||||
* Use IsString() before using this method.
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return std::wstring Returns the string value
|
||||
*/
|
||||
const std::wstring &JSONValue::AsString() const
|
||||
{
|
||||
return string_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the Bool value of this JSONValue
|
||||
* Use IsBool() before using this method.
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return bool Returns the bool value
|
||||
*/
|
||||
bool JSONValue::AsBool() const
|
||||
{
|
||||
return bool_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the Number value of this JSONValue
|
||||
* Use IsNumber() before using this method.
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return double Returns the number value
|
||||
*/
|
||||
double JSONValue::AsNumber() const
|
||||
{
|
||||
return number_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the Array value of this JSONValue
|
||||
* Use IsArray() before using this method.
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return JSONArray Returns the array value
|
||||
*/
|
||||
const JSONArray &JSONValue::AsArray() const
|
||||
{
|
||||
return array_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the Object value of this JSONValue
|
||||
* Use IsObject() before using this method.
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return JSONObject Returns the object value
|
||||
*/
|
||||
const JSONObject &JSONValue::AsObject() const
|
||||
{
|
||||
return object_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the number of children of this JSONValue.
|
||||
* This number will be 0 or the actual number of children
|
||||
* if IsArray() or IsObject().
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return The number of children.
|
||||
*/
|
||||
std::size_t JSONValue::CountChildren() const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case JSONType_Array:
|
||||
return array_value.size();
|
||||
case JSONType_Object:
|
||||
return object_value.size();
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this JSONValue has a child at the given index.
|
||||
* Use IsArray() before using this method.
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return bool Returns true if the array has a value at the given index.
|
||||
*/
|
||||
bool JSONValue::HasChild(std::size_t index) const
|
||||
{
|
||||
if (type == JSONType_Array)
|
||||
{
|
||||
return index < array_value.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the child of this JSONValue at the given index.
|
||||
* Use IsArray() before using this method.
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return JSONValue* Returns JSONValue at the given index or NULL
|
||||
* if it doesn't exist.
|
||||
*/
|
||||
JSONValue *JSONValue::Child(std::size_t index)
|
||||
{
|
||||
if (index < array_value.size())
|
||||
{
|
||||
return array_value[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this JSONValue has a child at the given key.
|
||||
* Use IsObject() before using this method.
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return bool Returns true if the object has a value at the given key.
|
||||
*/
|
||||
bool JSONValue::HasChild(const wchar_t* name) const
|
||||
{
|
||||
if (type == JSONType_Object)
|
||||
{
|
||||
return object_value.find(name) != object_value.end();
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the child of this JSONValue at the given key.
|
||||
* Use IsObject() before using this method.
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return JSONValue* Returns JSONValue for the given key in the object
|
||||
* or NULL if it doesn't exist.
|
||||
*/
|
||||
JSONValue* JSONValue::Child(const wchar_t* name)
|
||||
{
|
||||
JSONObject::const_iterator it = object_value.find(name);
|
||||
if (it != object_value.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JSON encoded string for the value with all necessary characters escaped
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @return std::wstring Returns the JSON string
|
||||
*/
|
||||
std::wstring JSONValue::Stringify() const
|
||||
{
|
||||
std::wstring ret_string;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case JSONType_Null:
|
||||
ret_string = L"null";
|
||||
break;
|
||||
|
||||
case JSONType_String:
|
||||
ret_string = StringifyString(string_value);
|
||||
break;
|
||||
|
||||
case JSONType_Bool:
|
||||
ret_string = bool_value ? L"true" : L"false";
|
||||
break;
|
||||
|
||||
case JSONType_Number:
|
||||
{
|
||||
if (isinf(number_value) || isnan(number_value))
|
||||
ret_string = L"null";
|
||||
else
|
||||
{
|
||||
std::wstringstream ss;
|
||||
ss.precision(15);
|
||||
ss << number_value;
|
||||
ret_string = ss.str();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case JSONType_Array:
|
||||
{
|
||||
ret_string = L"[";
|
||||
JSONArray::const_iterator iter = array_value.begin();
|
||||
while (iter != array_value.end())
|
||||
{
|
||||
ret_string += (*iter)->Stringify();
|
||||
|
||||
// Not at the end - add a separator
|
||||
if (++iter != array_value.end())
|
||||
ret_string += L",";
|
||||
}
|
||||
ret_string += L"]";
|
||||
break;
|
||||
}
|
||||
|
||||
case JSONType_Object:
|
||||
{
|
||||
ret_string = L"{";
|
||||
JSONObject::const_iterator iter = object_value.begin();
|
||||
while (iter != object_value.end())
|
||||
{
|
||||
ret_string += StringifyString((*iter).first);
|
||||
ret_string += L":";
|
||||
ret_string += (*iter).second->Stringify();
|
||||
|
||||
// Not at the end - add a separator
|
||||
if (++iter != object_value.end())
|
||||
ret_string += L",";
|
||||
}
|
||||
ret_string += L"}";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret_string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JSON encoded string with all required fields escaped
|
||||
* Works from http://www.ecma-internationl.org/publications/files/ECMA-ST/ECMA-262.pdf
|
||||
* Section 15.12.3.
|
||||
*
|
||||
* @access private
|
||||
*
|
||||
* @param std::wstring str The string that needs to have the characters escaped
|
||||
*
|
||||
* @return std::wstring Returns the JSON string
|
||||
*/
|
||||
std::wstring JSONValue::StringifyString(const std::wstring &str)
|
||||
{
|
||||
std::wstring str_out = L"\"";
|
||||
|
||||
std::wstring::const_iterator iter = str.begin();
|
||||
while (iter != str.end())
|
||||
{
|
||||
wchar_t chr = *iter;
|
||||
|
||||
if (chr == L'"' || chr == L'\\' || chr == L'/')
|
||||
{
|
||||
str_out += L'\\';
|
||||
str_out += chr;
|
||||
}
|
||||
else if (chr == L'\b')
|
||||
{
|
||||
str_out += L"\\b";
|
||||
}
|
||||
else if (chr == L'\f')
|
||||
{
|
||||
str_out += L"\\f";
|
||||
}
|
||||
else if (chr == L'\n')
|
||||
{
|
||||
str_out += L"\\n";
|
||||
}
|
||||
else if (chr == L'\r')
|
||||
{
|
||||
str_out += L"\\r";
|
||||
}
|
||||
else if (chr == L'\t')
|
||||
{
|
||||
str_out += L"\\t";
|
||||
}
|
||||
else if (chr < L' ')
|
||||
{
|
||||
str_out += L"\\u";
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
int value = (chr >> 12) & 0xf;
|
||||
if (value >= 0 && value <= 9)
|
||||
str_out += (wchar_t)('0' + value);
|
||||
else if (value >= 10 && value <= 15)
|
||||
str_out += (wchar_t)('A' + (value - 10));
|
||||
chr <<= 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
str_out += chr;
|
||||
}
|
||||
|
||||
iter++;
|
||||
}
|
||||
|
||||
str_out += L"\"";
|
||||
return str_out;
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* File JSONValue.h part of the SimpleJSON Library - http://mjpa.in/json
|
||||
*
|
||||
* Copyright (C) 2010 Mike Anchor
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _JSONVALUE_H_
|
||||
#define _JSONVALUE_H_
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "JSON.h"
|
||||
|
||||
class JSON;
|
||||
|
||||
enum JSONType { JSONType_Null, JSONType_String, JSONType_Bool, JSONType_Number, JSONType_Array, JSONType_Object };
|
||||
|
||||
class JSONValue
|
||||
{
|
||||
friend class JSON;
|
||||
|
||||
public:
|
||||
JSONValue(/*NULL*/);
|
||||
JSONValue(const wchar_t *m_char_value);
|
||||
JSONValue(const std::wstring &m_string_value);
|
||||
JSONValue(bool m_bool_value);
|
||||
JSONValue(double m_number_value);
|
||||
JSONValue(const JSONArray &m_array_value);
|
||||
JSONValue(const JSONObject &m_object_value);
|
||||
~JSONValue();
|
||||
|
||||
bool IsNull() const;
|
||||
bool IsString() const;
|
||||
bool IsBool() const;
|
||||
bool IsNumber() const;
|
||||
bool IsArray() const;
|
||||
bool IsObject() const;
|
||||
|
||||
const std::wstring &AsString() const;
|
||||
bool AsBool() const;
|
||||
double AsNumber() const;
|
||||
const JSONArray &AsArray() const;
|
||||
const JSONObject &AsObject() const;
|
||||
|
||||
std::size_t CountChildren() const;
|
||||
bool HasChild(std::size_t index) const;
|
||||
JSONValue *Child(std::size_t index);
|
||||
bool HasChild(const wchar_t* name) const;
|
||||
JSONValue *Child(const wchar_t* name);
|
||||
|
||||
std::wstring Stringify() const;
|
||||
|
||||
protected:
|
||||
static JSONValue *Parse(const wchar_t **data);
|
||||
|
||||
private:
|
||||
static std::wstring StringifyString(const std::wstring &str);
|
||||
|
||||
JSONType type;
|
||||
std::wstring string_value;
|
||||
bool bool_value;
|
||||
double number_value;
|
||||
JSONArray array_value;
|
||||
JSONObject object_value;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,9 +1,29 @@
|
|||
CC = g++
|
||||
CFLAGS = -I/usr/include/flycapture
|
||||
LDFLAGS = -lflycapture
|
||||
OBJECTS = Capture.o JSON.o JSONValue.o
|
||||
|
||||
pointgrey-capture: Capture.cpp
|
||||
$(CC) -o pointgrey-capture Capture.cpp $(CFLAGS) $(LDFLAGS)
|
||||
%.o: %.cpp
|
||||
g++ $< -c -o $@ $(CFLAGS) -g
|
||||
@g++ $< -MM $(CFLAGS) > $*.d
|
||||
@mv -f $*.d $*.d.tmp
|
||||
@sed -e 's|.*:|$*.o:|' < $*.d.tmp > $*.d
|
||||
@sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | \
|
||||
sed -e 's/^ *//' -e 's/$$/:/' >> $*.d
|
||||
@rm -f $*.d.tmp
|
||||
|
||||
default: pointgrey-capture get-camera-id dump-current-settings
|
||||
|
||||
pointgrey-capture: $(OBJECTS)
|
||||
$(CC) -o $@ $(OBJECTS) $(CFLAGS) $(LDFLAGS)
|
||||
|
||||
dump-current-settings: dump-current-settings.o
|
||||
$(CC) -o $@ dump-current-settings.o $(CFLAGS) $(LDFLAGS)
|
||||
|
||||
get-camera-id: get-camera-id.o
|
||||
$(CC) -o $@ get-camera-id.o $(CFLAGS) $(LDFLAGS)
|
||||
|
||||
clean:
|
||||
rm -f pointgrey-capture
|
||||
rm -f pointgrey-capture get-camera-id dump-current-settings *.o *.d
|
||||
|
||||
-include $(OBJECTS:.o=.d)
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#include "FlyCapture2.h"
|
||||
|
||||
using namespace FlyCapture2;
|
||||
|
||||
void printError(Error error)
|
||||
{
|
||||
error.PrintErrorTrace();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
BusManager busMgr;
|
||||
PGRGuid guid;
|
||||
Error error;
|
||||
|
||||
error = busMgr.GetCameraFromIndex(0, &guid);
|
||||
if (error != PGRERROR_OK) {
|
||||
printError(error);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
Camera cam;
|
||||
error = cam.Connect(&guid);
|
||||
if (error != PGRERROR_OK) {
|
||||
printError(error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// do different things depending on camera model detected...
|
||||
CameraInfo camInfo;
|
||||
error = cam.GetCameraInfo(&camInfo);
|
||||
if (error != PGRERROR_OK) {
|
||||
printError(error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("{\n \"properties\": {\n");
|
||||
|
||||
PropertyType propTypes[5] = { AUTO_EXPOSURE, SHARPNESS, SHUTTER, GAIN,
|
||||
WHITE_BALANCE };
|
||||
const char *propTypeNames[5] = { "AUTO_EXPOSURE", "SHARPNESS", "SHUTTER",
|
||||
"GAIN", "WHITE_BALANCE" };
|
||||
for (int i=0; i<5; i++) {
|
||||
Property property;
|
||||
property.type = propTypes[i];
|
||||
cam.GetProperty(&property);
|
||||
|
||||
if (i>0)
|
||||
printf(",\n");
|
||||
printf(" \"%s\": { \"onOff\": %s, \"autoManualMode\": %s, \"absValue\": %f, "
|
||||
"\"valueA\": %d, \"valueB\": %d }", propTypeNames[i],
|
||||
property.onOff ? "true" : "false",
|
||||
property.autoManualMode ? "true" : "false",
|
||||
(float)property.absValue, property.valueA, property.valueB);
|
||||
}
|
||||
printf("\n }\n}\n");
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#include "FlyCapture2.h"
|
||||
|
||||
using namespace FlyCapture2;
|
||||
|
||||
void printError(Error error)
|
||||
{
|
||||
error.PrintErrorTrace();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
BusManager busMgr;
|
||||
PGRGuid guid;
|
||||
Error error;
|
||||
|
||||
error = busMgr.GetCameraFromIndex(0, &guid);
|
||||
if (error != PGRERROR_OK) {
|
||||
printError(error);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
Camera cam;
|
||||
error = cam.Connect(&guid);
|
||||
if (error != PGRERROR_OK) {
|
||||
printError(error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// do different things depending on camera model detected...
|
||||
CameraInfo camInfo;
|
||||
error = cam.GetCameraInfo(&camInfo);
|
||||
if (error != PGRERROR_OK) {
|
||||
printError(error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s\n", camInfo.modelName);
|
||||
}
|
Загрузка…
Ссылка в новой задаче