Skip to content

Instantly share code, notes, and snippets.

@gadamc
Created August 10, 2011 15:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gadamc/1137159 to your computer and use it in GitHub Desktop.
Save gadamc/1137159 to your computer and use it in GitHub Desktop.
/*
Copyright (c) 2009 Dave Gamble
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.
*/
//April 28, 2011.-----------------------------------------
This code/document was modified by Adam Cox on April 28 to incorporate
this library into KData. All of the names, cJSON were changed to KJson in
order to make this easily integrate into the KData build system and to "naturally"
fit into the rest of the KData framework. All strings found in the code and
in this documentation that are "KJson", were originally "cJSON".
If you want to compile a program that uses KJson,
you don't need to do anything special. Just include the the header as normal.
Read below for the documentation on using KJson/cJSON. Also, check out the .h file
for a list of the available functions
https://edwdev-ik.fzk.de/kdata_dev_ref/src/KJson.h.html
//--------------------------------------------------------
Welcome to KJson. (AKA cJSON)
KJson aims to be the dumbest possible parser that you can get your job done with.
It's a single file of C, and a single header file.
JSON is described best here: http://www.json.org/
It's like XML, but fat-free. You use it to move data around, store things, or just
generally represent your program's state.
As a library, KJson exists to take away as much legwork as it can, but not get in your way.
As a point of pragmatism (i.e. ignoring the truth), I'm going to say that you can use it
in one of two modes: Auto and Manual. Let's have a quick run-through.
I lifted some JSON from this page: http://www.json.org/fatfree.html
That page inspired me to write KJson, which is a parser that tries to share the same
philosophy as JSON itself. Simple, dumb, out of the way.
Some JSON:
{
"name": "Jack (\"Bee\") Nimble",
"format": {
"type": "rect",
"width": 1920,
"height": 1080,
"interlace": false,
"frame rate": 24
}
}
Assume that you got this from a file, a webserver, or magic JSON elves, whatever,
you have a char * to it. Everything is a KJson struct.
Get it parsed:
KJson *root = KJson::Parse(my_json_string);
This is an object. We're in C. We don't have objects. But we do have structs.
What's the framerate?
KJson *format = KJson::GetObjectItem(root,"format");
int framerate = KJson::GetObjectItem(format,"frame rate")->valueint;
Want to change the framerate?
KJson::GetObjectItem(format,"frame rate")->valueint=25;
Back to disk?
char *rendered=KJson::Print(root);
Finished? Delete the root (this takes care of everything else).
KJson::Delete(root);
That's AUTO mode. If you're going to use Auto mode, you really ought to check pointers
before you dereference them. If you want to see how you'd build this struct in code?
KJson *root,*fmt;
root=KJson::CreateObject();
KJson::AddItemToObject(root, "name", KJson::CreateString("Jack (\"Bee\") Nimble"));
KJson::AddItemToObject(root, "format", fmt=KJson::CreateObject());
KJson::AddItemToObject(fmt, "type", KJson::CreateString("type") );
KJson::AddItemToObject(fmt, "width", KJson::CreateNumber(1920) );
KJson::AddItemToObject(fmt, "height", KJson::CreateNumber(1080) );
KJson::AddItemToObject(fmt, "interlace", KJson::CreateFalse() );
KJson::AddItemToObject(fmt, "frame rate", KJson::CreateNumber(24) );
Hopefully we can agree that's not a lot of code? There's no overhead, no unnecessary setup.
Look at test.c for a bunch of nice examples, mostly all ripped off the json.org site, and
a few from elsewhere.
What about manual mode? First up you need some detail.
Let's cover how the KJson objects represent the JSON data.
KJson doesn't distinguish arrays from objects in handling; just type.
Each KJson has, potentially, a child, siblings, value, a name.
The root object has: Object Type and a Child
The Child has name "name", with value "Jack ("Bee") Nimble", and a sibling:
Sibling has type Object, name "format", and a child.
That child has type String, name "type", value "rect", and a sibling:
Sibling has type Number, name "width", value 1920, and a sibling:
Sibling has type Number, name "height", value 1080, and a sibling:
Sibling hs type False, name "interlace", and a sibling:
Sibling has type Number, name "frame rate", value 24
Here's the structure:
typedef struct KJson {
struct KJson *next,*prev;
struct KJson *child;
int type;
char *valuestring;
int valueint;
double valuedouble;
char *key;
} KJson;
By default all values are 0 unless set by virtue of being meaningful.
next/prev is a doubly linked list of siblings. next takes you to your sibling,
prev takes you back from your sibling to you.
Only objects and arrays have a "child", and it's the head of the doubly linked list.
A "child" entry will have prev==0, but next potentially points on. The last sibling has next=0.
The type expresses Null/True/False/Number/String/Array/Object, all of which are #defined in
KJson.h
A Number has valueint and valuedouble. If you're expecting an int, read valueint, if not read
valuedouble.
Any entry which is in the linked list which is the child of an object will have a "key"
which is the "name" of the entry. When I said "name" in the above example, that's "key".
"key" is the JSON name for the 'variable name' if you will.
Now you can trivially walk the lists, recursively, and parse as you please.
You can invoke KJson::Parse to get KJson to parse for you, and then you can take
the root object, and traverse the structure (which is, formally, an N-tree),
and tokenise as you please. If you wanted to build a callback style parser, this is how
you'd do it (just an example, since these things are very specific):
void parse_and_callback(KJson *item,const char *prefix)
{
while (item)
{
char *newprefix=malloc(strlen(prefix)+strlen(item->name)+2);
sprintf(newprefix,"%s/%s",prefix,item->name);
int dorecurse=callback(newprefix, item->type, item);
if (item->child && dorecurse) parse_and_callback(item->child,newprefix);
item=item->next;
free(newprefix);
}
}
The prefix process will build you a separated list, to simplify your callback handling.
The 'dorecurse' flag would let the callback decide to handle sub-arrays on it's own, or
let you invoke it per-item. For the item above, your callback might look like this:
int callback(const char *name,int type,KJson *item)
{
if (!strcmp(name,"name")) { /* populate name */ }
else if (!strcmp(name,"format/type") { /* handle "rect" */ }
else if (!strcmp(name,"format/width") { /* 800 */ }
else if (!strcmp(name,"format/height") { /* 600 */ }
else if (!strcmp(name,"format/interlace") { /* false */ }
else if (!strcmp(name,"format/frame rate") { /* 24 */ }
return 1;
}
Alternatively, you might like to parse iteratively.
You'd use:
void parse_object(KJson *item)
{
int i; for (i=0;i<KJson::GetArraySize(item);i++)
{
KJson *subitem=KJson::GetArrayItem(item,i);
// handle subitem.
}
}
Or, for PROPER manual mode:
void parse_object(KJson *item)
{
KJson *subitem=item->child;
while (subitem)
{
// handle subitem
if (subitem->child) parse_object(subitem->child);
subitem=subitem->next;
}
}
Of course, this should look familiar, since this is just a stripped-down version
of the callback-parser.
This should cover most uses you'll find for parsing. The rest should be possible
to infer.. and if in doubt, read the source! There's not a lot of it! ;)
In terms of constructing JSON data, the example code above is the right way to do it.
You can, of course, hand your sub-objects to other functions to populate.
Also, if you find a use for it, you can manually build the objects.
For instance, suppose you wanted to build an array of objects?
KJson *objects[24];
KJson *Create_array_of_anything(KJson **items,int num)
{
int i;KJson *prev, *root=KJson::CreateArray();
for (i=0;i<24;i++)
{
if (!i) root->child=objects[i];
else prev->next=objects[i], objects[i]->prev=prev;
prev=objects[i];
}
return root;
}
and simply: Create_array_of_anything(objects,24);
KJson doesn't make any assumptions about what order you create things in.
You can attach the objects, as above, and later add children to each
of those objects.
As soon as you call KJson::Print, it renders the structure to text.
Enjoy KJson!
- Dave Gamble, Aug 2009
//______________________________________________________________________
//
// KCurl.cxx
// Author: Adam Cox <mailto:adam.cox@kit.edu>
//
// *Copyright 2011 Karlsruhe Inst. of Technology. All Rights Reserved.
//
//
// Created Friday 04. February 2011
//
//
// This is a wrapper class for using simple libcurl commands in
// KData in order to facilitate using the edelweiss couchdb.
//
#include "KCurl.h"
#include <curl/curl.h>
ClassImp(KCurl);
KCurl::KCurl(void)
{
SetVerbose(0);
fReturn = "";
}
KCurl::~KCurl(void)
{
curl_global_cleanup();
}
Int_t KCurl::Get(const char* url, const char* item, const char* opt)
{
//Gets the response from the following HTTP GET command
//HTTP GET url/item
//If you need to use authentication, then you should
//set url to be "http://username:password@address", for example
//"http://user:secret@127.0.0.1:5984"
//This will call
//HTTP GET http://user:secret@127.0.0.1:5984/item"
//
//This is exactly the same as using the UNIX program 'curl' from the
//command line
//
// $> curl url/item
//
// If you want to use SSL with HTTP, use https://
// For CouchDB, the SSL port is 6984. In order to ignore self-signed SSL
// certificates, use the -a option.
//
//For Edelweiss CouchDB access, typical values are
// url = https://edwdbik.fzk.de:6984 (the database is readable by all, but you must use a username/password to write)
// item = (a docid, a view, or even _all_docs).
// If you are accessing a database, your item should look something like
// "databasename/item", where "edwdb" is the standard database name
// and item is the docid, view, _all_docs, etc....
// see the couchdb documentation
//
// opt is a string of characters separated by a space (' ') and preceded with a dash ('-')
// -a = accept the SSL certificate without a Certified Authorization. This is needed for self-signed certificates.
//
//The return value is the value received from libcurl. You can get the full
//string response by calling GetReturn. If the return is 0, then
//the curl transaction seems to have worked without error.
//
char errorBuf[CURL_ERROR_SIZE+1]; //use this buffer to save any curl errors.
CURL *curlhandle = 0;
curlhandle = curl_easy_init();
CURLcode res;
fReturn = "";
if(curlhandle) {
string myurl;
myurl.append(url);
myurl.append("/");
myurl.append(item);
curl_easy_setopt(curlhandle, CURLOPT_URL, myurl.c_str());
//set the curl options for this transaction
curl_easy_setopt(curlhandle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); //catch the output from couch and deal with it with this function
curl_easy_setopt(curlhandle, CURLOPT_WRITEDATA, this); //checkCouchDBReturn will pass the output to this object
curl_easy_setopt(curlhandle, CURLOPT_ERRORBUFFER, errorBuf); //hold any errors here.
if(opt){
if(DoAcceptSSLCertificate(opt)){
curl_easy_setopt(curlhandle, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(curlhandle, CURLOPT_SSL_VERIFYPEER, 0L);
}
}
//using verbose output for debugging.
if(GetVerbose()) curl_easy_setopt(curlhandle, CURLOPT_VERBOSE, 1L);
//perform the transaction
res = curl_easy_perform(curlhandle);
//printf("The callback was called %d times\n", count);
//check for errors
if(res){ //if res == 0, everything went well
cerr << "Curl returned an error." << endl;
cerr << "Error code: " << res << endl;
cerr << "Error: " << errorBuf << endl;
}
curl_easy_cleanup(curlhandle); //always cleanup curl handles
}
return res;
}
Int_t KCurl::Put(const char* url, const char* item, const char* thedoc, const char* opt)
{
//calls the following
//HTTP PUT url/item -d "thedoc"
//If you need to use authentication, then you should
//set url to be "username:password@url", for example
//"http://user:secret@127.0.0.1:5984"
//This will call
//HTTP PUT http://user:secret@url/item
//
//If thedoc == 0, then the ' -d "thedoc" ' is excluded.
//
//
// If you want to use SSL with HTTP, use https://
// For CouchDB, the SSL port is 6984. In order to ignore self-signed SSL
// certificates, use the -a option.
//
//For Edelweiss CouchDB access, typical values are
// url = https://edwdbik.fzk.de:6984 (the database is readable by all, but you must use a username/password to write)
// item = (a docid, a view, or even _all_docs).
// If you are putting a file on the database, your item should look something like
// "databasename/docid", where "edwdb" is the standard database name
// and item is the docid.
// If you are trying to create a new database, your item should be
// "databasename" and the "thedoc" should be a NULL pointer.
// see the couchdb documentation
//
// thedoc = a JSON document that you will likely be puting on a couchdb.
// NOTE: You must be sure that 'thedoc' is in proper JSON format
// This method does not check the format for you. If it is not in proper
// JSON format, then you will see an error in the returned string (KCurl::GetReturn())
//
// opt = currently this function just supports one option.
// -a = accept the SSL certificate without a Certified Authorization. This is needed for self-signed certificates.
//
//The return value is the value received from libcurl.
//You can get the full string by calling GetReturn. If the return is 0, then
//the curl transaction seems to have worked without error.
//
char errorBuf[CURL_ERROR_SIZE+1]; //use this buffer to save any curl errors.
CURL *curlhandle = 0;
curlhandle = curl_easy_init();
CURLcode res;
fReturn = "";
if(curlhandle) {
string myurl;
myurl.append(url);
myurl.append("/");
myurl.append(item);;
readarg_t mydoc;
mydoc.len = 0;
mydoc.pos = 0;
mydoc.buf = 0;
if(thedoc) {
mydoc.len = strlen(thedoc);
mydoc.pos = 0;
mydoc.buf = thedoc;
}
curl_easy_setopt(curlhandle, CURLOPT_URL, myurl.c_str());
//use appropriate json header for curl
if(thedoc){
struct curl_slist *jsonheader = NULL;
jsonheader = curl_slist_append(jsonheader, "Content-Type: application/json");
curl_easy_setopt(curlhandle, CURLOPT_HTTPHEADER, jsonheader);
}
//set the curl options for this transaction
curl_easy_setopt(curlhandle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); //catch the output from couch and deal with it with this function
curl_easy_setopt(curlhandle, CURLOPT_WRITEDATA, this);
if(thedoc) {
curl_easy_setopt(curlhandle, CURLOPT_READFUNCTION, ReadBufferCallback); //calls this function to get data to PUT to the couchdb server
curl_easy_setopt(curlhandle, CURLOPT_READDATA, &mydoc);//passJsonString will get buf data using this pointer
curl_easy_setopt(curlhandle, CURLOPT_INFILESIZE_LARGE, (curl_off_t)mydoc.len); //the length of buf that will be PUT
}
curl_easy_setopt(curlhandle, CURLOPT_ERRORBUFFER, errorBuf); //hold any errors here.
curl_easy_setopt(curlhandle, CURLOPT_UPLOAD, 1); //tell curl to upload the contents that passJsonString tells it to.
if(opt){
if(DoAcceptSSLCertificate(opt)){
curl_easy_setopt(curlhandle, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(curlhandle, CURLOPT_SSL_VERIFYPEER, 0L);
}
}
//using verbose output for debugging.
if(GetVerbose()) curl_easy_setopt(curlhandle, CURLOPT_VERBOSE, 1);
//perform the transaction
res = curl_easy_perform(curlhandle);
//printf("The callback was called %d times\n", count);
//check for errors
if(res){ //if res == 0, everything went well
cerr << "Curl returned an error." << endl;
cerr << "Error code: " << res << endl;
cerr << "Error: " << errorBuf << endl;
cerr << "Error String: " << curl_easy_strerror(res);
}
curl_easy_cleanup(curlhandle); //always cleanup curl handles
}
return res;
}
bool KCurl::DoAcceptSSLCertificate(const char* opt)
{
string sOpts = opt;
string token;
istringstream iss(sOpts);
while ( getline(iss, token, ' ') )
{
if (token.compare("-a")==0){
return true;
}
}
return false;
}
/*
bool KCurl::DoUseSSL(const char* opt)
{
string sOpts = opt;
string token;
istringstream iss(sOpts);
while ( getline(iss, token, ' ') )
{
cout << token << endl;
if (token.compare("-s")==0){
return true;
}
}
return false;
}
*/
//______________________________________________________________________
//
// KCurl.h
// Author: Adam Cox <mailto:adam.cox@kit.edu>
//
// *Copyright 2011 Karlsruhe Inst. of Technology. All Rights Reserved.
//
// Created Friday 04. February 2011
//
#ifndef __KCURL_H__
#define __KCURL_H__
#include "Rtypes.h"
#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <sstream>
using namespace std;
class KCurl {
public:
//Constructors
KCurl(void);
virtual ~KCurl(void);
//void* POST()
//void* DELETE();
Int_t Put(const char* url, const char* item, const char* thedoc = 0, const char* opt = "-a");
Int_t Get(const char* url, const char* item, const char* opt = "-a");
const char* GetReturn(void) const {return fReturn.c_str();}
size_t GetReturnSize(void) const {return fReturn.size();}
Bool_t GetVerbose(void) const { return fVerbose;}
void SetVerbose(Bool_t aVal = true) {fVerbose = aVal;}
private:
string fReturn;
typedef struct{
const char* buf;
int len;
int pos;
} readarg_t;
Bool_t fVerbose;
static size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
{ KCurl *mem = (KCurl *)data;
const char* stringdata = (const char*)ptr;
if(size*nmemb > 0)
mem->fReturn.append(stringdata, size*nmemb);
return size * nmemb;
}
static size_t ReadBufferCallback(char *bufptr, size_t size, size_t nitems, void *userp)
{
readarg_t *rarg = (readarg_t *)userp;
size_t len = rarg->len - rarg->pos;
if (len > size * nitems)
len = size * nitems;
memcpy(bufptr, rarg->buf + rarg->pos, len);
rarg->pos += len;
return len;
}
bool DoAcceptSSLCertificate(const char* opt);
//bool DoUseSSL(const char* opt);
ClassDef(KCurl,1);
};
#endif // __KCURL_H__
/*
Copyright (c) 2009 Dave Gamble
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.
*/
/* KJson */
/* JSON parser in C. */
#include "KJson.h"
static const char *ep;
const char *KJson::GetErrorPtr() {return ep;}
static int KJson_strcasecmp(const char *s1,const char *s2)
{
if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0;
return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
}
static void *(*KJson_malloc)(size_t sz) = malloc;
static void (*KJson_free)(void *ptr) = free;
static char* KJson_strdup(const char* str)
{
size_t len;
char* copy;
len = strlen(str) + 1;
if (!(copy = (char*)KJson_malloc(len))) return 0;
memcpy(copy,str,len);
return copy;
}
void KJson::InitHooks(Hooks* hooks)
{
if (!hooks) { /* Reset hooks */
KJson_malloc = malloc;
KJson_free = free;
return;
}
KJson_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
KJson_free = (hooks->free_fn)?hooks->free_fn:free;
}
/* Internal constructor. */
static KJson *KJson_New_Item()
{
KJson* node = (KJson*)KJson_malloc(sizeof(KJson));
if (node) memset(node,0,sizeof(KJson));
return node;
}
/* Delete a KJson structure. */
void KJson::Delete(KJson *c)
{
KJson *next;
while (c)
{
next=c->next;
if (!(c->type&KJson_IsReference) && c->child) Delete(c->child);
if (!(c->type&KJson_IsReference) && c->valuestring) KJson_free(c->valuestring);
if (c->key) KJson_free(c->key);
KJson_free(c);
c=next;
}
}
/* Parse the input text to generate a number, and populate the result into item. */
static const char *parse_number(KJson *item,const char *num)
{
double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;
/* Could use sscanf for this? */
if (*num=='-') sign=-1,num++; /* Has sign? */
if (*num=='0') num++; /* is zero */
if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */
if (*num=='.') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */
if (*num=='e' || *num=='E') /* Exponent? */
{ num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */
while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */
}
n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */
item->valuedouble=n;
item->valueint=(int)n;
item->type=KJson_Number;
return num;
}
/* Render the number nicely from the given item into a string. */
static char *print_number(KJson *item)
{
char *str;
double d=item->valuedouble;
if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
{
str=(char*)KJson_malloc(21); /* 2^64+1 can be represented in 21 chars. */
if (str) sprintf(str,"%d",item->valueint);
}
else
{
str=(char*)KJson_malloc(64); /* This is a nice tradeoff. */
if (str)
{
if (fabs(floor(d)-d)<=DBL_EPSILON) sprintf(str,"%.0f",d);
else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d);
else sprintf(str,"%f",d);
}
}
return str;
}
/* Parse the input text into an unescaped cstring, and populate item. */
static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
static const char *parse_string(KJson *item,const char *str)
{
const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc;
if (*str!='\"') {ep=str;return 0;} /* not a string! */
while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */
out=(char*)KJson_malloc(len+1); /* This is how long we need for the string, roughly. */
if (!out) return 0;
ptr=str+1;ptr2=out;
while (*ptr!='\"' && *ptr)
{
if (*ptr!='\\') *ptr2++=*ptr++;
else
{
ptr++;
switch (*ptr)
{
case 'b': *ptr2++='\b'; break;
case 'f': *ptr2++='\f'; break;
case 'n': *ptr2++='\n'; break;
case 'r': *ptr2++='\r'; break;
case 't': *ptr2++='\t'; break;
case 'u': /* transcode utf16 to utf8. DOES NOT SUPPORT SURROGATE PAIRS CORRECTLY. */
sscanf(ptr+1,"%4x",&uc); /* get the unicode char. */
len=3;if (uc<0x80) len=1;else if (uc<0x800) len=2;ptr2+=len;
switch (len) {
case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
case 1: *--ptr2 =(uc | firstByteMark[len]);
}
ptr2+=len;ptr+=4;
break;
default: *ptr2++=*ptr; break;
}
ptr++;
}
}
*ptr2=0;
if (*ptr=='\"') ptr++;
item->valuestring=out;
item->type=KJson_String;
return ptr;
}
/* Render the cstring provided to an escaped version that can be printed. */
static char *print_string_ptr(const char *str)
{
const char *ptr;char *ptr2,*out;int len=0;unsigned char token;
if (!str) return KJson_strdup("");
ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
out=(char*)KJson_malloc(len+3);
if (!out) return 0;
ptr2=out;ptr=str;
*ptr2++='\"';
while (*ptr)
{
if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
else
{
*ptr2++='\\';
switch (token=*ptr++)
{
case '\\': *ptr2++='\\'; break;
case '\"': *ptr2++='\"'; break;
case '\b': *ptr2++='b'; break;
case '\f': *ptr2++='f'; break;
case '\n': *ptr2++='n'; break;
case '\r': *ptr2++='r'; break;
case '\t': *ptr2++='t'; break;
default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */
}
}
}
*ptr2++='\"';*ptr2++=0;
return out;
}
/* Invote print_string_ptr (which is useful) on an item. */
static char *print_string(KJson *item) {return print_string_ptr(item->valuestring);}
/* Predeclare these prototypes. */
static const char *parse_value(KJson *item,const char *value);
static char *print_value(KJson *item,int depth,int fmt);
static const char *parse_array(KJson *item,const char *value);
static char *print_array(KJson *item,int depth,int fmt);
static const char *parse_object(KJson *item,const char *value);
static char *print_object(KJson *item,int depth,int fmt);
/* Utility to jump whitespace and cr/lf */
static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;}
/* Parser core - when encountering text, process appropriately. */
static const char *parse_value(KJson *item,const char *value)
{
if (!value) return 0; /* Fail on null. */
if (!strncmp(value,"null",4)) { item->type=KJson_NULL; return value+4; }
if (!strncmp(value,"false",5)) { item->type=KJson_False; return value+5; }
if (!strncmp(value,"true",4)) { item->type=KJson_True; item->valueint=1; return value+4; }
if (*value=='\"') { return parse_string(item,value); }
if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); }
if (*value=='[') { return parse_array(item,value); }
if (*value=='{') { return parse_object(item,value); }
ep=value;return 0; /* failure. */
}
/* Render a value to text. */
static char *print_value(KJson *item,int depth,int fmt)
{
char *out=0;
if (!item) return 0;
switch ((item->type)&255)
{
case KJson_NULL: out=KJson_strdup("null"); break;
case KJson_False: out=KJson_strdup("false");break;
case KJson_True: out=KJson_strdup("true"); break;
case KJson_Number: out=print_number(item);break;
case KJson_String: out=print_string(item);break;
case KJson_Array: out=print_array(item,depth,fmt);break;
case KJson_Object: out=print_object(item,depth,fmt);break;
}
return out;
}
/* Build an array from input text. */
static const char *parse_array(KJson *item,const char *value)
{
KJson *child;
if (*value!='[') {ep=value;return 0;} /* not an array! */
item->type=KJson_Array;
value=skip(value+1);
if (*value==']') return value+1; /* empty array. */
item->child=child=KJson_New_Item();
if (!item->child) return 0; /* memory fail */
value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */
if (!value) return 0;
while (*value==',')
{
KJson *new_item;
if (!(new_item=KJson_New_Item())) return 0; /* memory fail */
child->next=new_item;new_item->prev=child;child=new_item;
value=skip(parse_value(child,skip(value+1)));
if (!value) return 0; /* memory fail */
}
if (*value==']') return value+1; /* end of array */
ep=value;return 0; /* malformed. */
}
/* Render an array to text */
static char *print_array(KJson *item,int depth,int fmt)
{
char **entries;
char *out=0,*ptr,*ret;int len=5;
KJson *child=item->child;
int numentries=0,i=0,fail=0;
/* How many entries in the array? */
while (child) numentries++,child=child->next;
/* Allocate an array to hold the values for each */
entries=(char**)KJson_malloc(numentries*sizeof(char*));
if (!entries) return 0;
memset(entries,0,numentries*sizeof(char*));
/* Retrieve all the results: */
child=item->child;
while (child && !fail)
{
ret=print_value(child,depth+1,fmt);
entries[i++]=ret;
if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
child=child->next;
}
/* If we didn't fail, try to malloc the output string */
if (!fail) out=(char*)KJson_malloc(len);
/* If that fails, we fail. */
if (!out) fail=1;
/* Handle failure. */
if (fail)
{
for (i=0;i<numentries;i++) if (entries[i]) KJson_free(entries[i]);
KJson_free(entries);
return 0;
}
/* Compose the output array. */
*out='[';
ptr=out+1;*ptr=0;
for (i=0;i<numentries;i++)
{
strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
KJson_free(entries[i]);
}
KJson_free(entries);
*ptr++=']';*ptr++=0;
return out;
}
/* Build an object from the text. */
static const char *parse_object(KJson *item,const char *value)
{
KJson *child;
if (*value!='{') {ep=value;return 0;} /* not an object! */
item->type=KJson_Object;
value=skip(value+1);
if (*value=='}') return value+1; /* empty array. */
item->child=child=KJson_New_Item();
if (!item->child) return 0;
value=skip(parse_string(child,skip(value)));
if (!value) return 0;
child->key=child->valuestring;child->valuestring=0;
if (*value!=':') {ep=value;return 0;} /* fail! */
value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
if (!value) return 0;
while (*value==',')
{
KJson *new_item;
if (!(new_item=KJson_New_Item())) return 0; /* memory fail */
child->next=new_item;new_item->prev=child;child=new_item;
value=skip(parse_string(child,skip(value+1)));
if (!value) return 0;
child->key=child->valuestring;child->valuestring=0;
if (*value!=':') {ep=value;return 0;} /* fail! */
value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
if (!value) return 0;
}
if (*value=='}') return value+1; /* end of array */
ep=value;return 0; /* malformed. */
}
/* Render an object to text. */
static char *print_object(KJson *item,int depth,int fmt)
{
char **entries=0,**names=0;
char *out=0,*ptr,*ret,*str;int len=7,i=0,j;
KJson *child=item->child;
int numentries=0,fail=0;
/* Count the number of entries. */
while (child) numentries++,child=child->next;
/* Allocate space for the names and the objects */
entries=(char**)KJson_malloc(numentries*sizeof(char*));
if (!entries) return 0;
names=(char**)KJson_malloc(numentries*sizeof(char*));
if (!names) {KJson_free(entries);return 0;}
memset(entries,0,sizeof(char*)*numentries);
memset(names,0,sizeof(char*)*numentries);
/* Collect all the results into our arrays: */
child=item->child;depth++;if (fmt) len+=depth;
while (child)
{
names[i]=str=print_string_ptr(child->key);
entries[i++]=ret=print_value(child,depth,fmt);
if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
child=child->next;
}
/* Try to allocate the output string */
if (!fail) out=(char*)KJson_malloc(len);
if (!out) fail=1;
/* Handle failure */
if (fail)
{
for (i=0;i<numentries;i++) {if (names[i]) KJson_free(names[i]);if (entries[i]) KJson_free(entries[i]);}
KJson_free(names);KJson_free(entries);
return 0;
}
/* Compose the output: */
*out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
for (i=0;i<numentries;i++)
{
if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
strcpy(ptr,names[i]);ptr+=strlen(names[i]);
*ptr++=':';if (fmt) *ptr++='\t';
strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
if (i!=numentries-1) *ptr++=',';
if (fmt) *ptr++='\n';*ptr=0;
KJson_free(names[i]);KJson_free(entries[i]);
}
KJson_free(names);KJson_free(entries);
if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
*ptr++='}';*ptr++=0;
return out;
}
/* Utility for array list handling. */
static void suffix_object(KJson *prev,KJson *item) {prev->next=item;item->prev=prev;}
/* Utility for handling references. */
static KJson *create_reference(KJson *item) {KJson *ref=KJson_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(KJson));ref->key=0;ref->type|=KJson_IsReference;ref->next=ref->prev=0;return ref;}
/* Parse an object - create a new root, and populate. */
KJson *KJson::Parse(const char *value)
{
KJson *c=KJson_New_Item();
ep=0;
if (!c) return 0; /* memory fail */
if (!parse_value(c,skip(value))) {Delete(c);return 0;}
return c;
}
/* Render a KJson item/entity/structure to text. */
char *KJson::Print(KJson *item) {return print_value(item,0,1);}
char *KJson::PrintUnformatted(KJson *item) {return print_value(item,0,0);}
/* Get Array size/item / object item. */
int KJson::GetArraySize(KJson *array) {KJson *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
KJson *KJson::GetArrayItem(KJson *array,int item) {KJson *c=array->child; while (c && item>0) item--,c=c->next; return c;}
KJson *KJson::GetObjectItem(KJson *object,const char *akey) {KJson *c=object->child; while (c && KJson_strcasecmp(c->key,akey)) c=c->next; return c;}
/* Add item to array/object. */
void KJson::AddItemToArray(KJson *array, KJson *item) {KJson *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}}
void KJson::AddItemToObject(KJson *object,const char *akey,KJson *item) {if (!item) return; if (item->key) KJson_free(item->key);item->key=KJson_strdup(akey);AddItemToArray(object,item);}
void KJson::AddItemReferenceToArray(KJson *array, KJson *item) {AddItemToArray(array,create_reference(item));}
void KJson::AddItemReferenceToObject(KJson *object,const char *akey,KJson *item) {AddItemToObject(object,akey,create_reference(item));}
KJson *KJson::DetachItemFromArray(KJson *array,int which) {KJson *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;}
void KJson::DeleteItemFromArray(KJson *array,int which) {Delete(DetachItemFromArray(array,which));}
KJson *KJson::DetachItemFromObject(KJson *object,const char *akey) {int i=0;KJson *c=object->child;while (c && KJson_strcasecmp(c->key,akey)) i++,c=c->next;if (c) return DetachItemFromArray(object,i);return 0;}
void KJson::DeleteItemFromObject(KJson *object,const char *akey) {Delete(DetachItemFromObject(object,akey));}
/* Replace array/object items with new ones. */
void KJson::ReplaceItemInArray(KJson *array,int which,KJson *newitem) {KJson *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return;
newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;
if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;Delete(c);}
void KJson::ReplaceItemInObject(KJson *object,const char *akey,KJson *newitem){int i=0;KJson *c=object->child;while(c && KJson_strcasecmp(c->key,akey))i++,c=c->next;if(c){newitem->key=KJson_strdup(akey);ReplaceItemInArray(object,i,newitem);}}
/* Create basic types: */
KJson *KJson::CreateNull() {KJson *item=KJson_New_Item();if(item)item->type=KJson_NULL;return item;}
KJson *KJson::CreateTrue() {KJson *item=KJson_New_Item();if(item)item->type=KJson_True;return item;}
KJson *KJson::CreateFalse() {KJson *item=KJson_New_Item();if(item)item->type=KJson_False;return item;}
KJson *KJson::CreateBool(int b) {KJson *item=KJson_New_Item();if(item)item->type=b?KJson_True:KJson_False;return item;}
KJson *KJson::CreateNumber(double num) {KJson *item=KJson_New_Item();if(item){item->type=KJson_Number;item->valuedouble=num;item->valueint=(int)num;}return item;}
KJson *KJson::CreateString(const char *akey) {KJson *item=KJson_New_Item();if(item){item->type=KJson_String;item->valuestring=KJson_strdup(akey);}return item;}
KJson *KJson::CreateArray() {KJson *item=KJson_New_Item();if(item)item->type=KJson_Array;return item;}
KJson *KJson::CreateObject() {KJson *item=KJson_New_Item();if(item)item->type=KJson_Object;return item;}
/* Create Arrays: */
KJson *KJson::CreateIntArray(int *numbers,int count) {int i;KJson *n=0,*p=0,*a=CreateArray();for(i=0;a && i<count;i++){n=CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
KJson *KJson::CreateFloatArray(float *numbers,int count) {int i;KJson *n=0,*p=0,*a=CreateArray();for(i=0;a && i<count;i++){n=CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
KJson *KJson::CreateDoubleArray(double *numbers,int count) {int i;KJson *n=0,*p=0,*a=CreateArray();for(i=0;a && i<count;i++){n=CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
KJson *KJson::CreateStringArray(const char **strings,int count) {int i;KJson *n=0,*p=0,*a=CreateArray();for(i=0;a && i<count;i++){n=CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
void KJson::AddNullToObject(KJson* object,const char* name){return AddItemToObject(object, name, CreateNull());}
void KJson::AddTrueToObject(KJson* object,const char* name){ return AddItemToObject(object, name, CreateTrue());}
void KJson::AddFalseToObject(KJson* object,const char* name){return AddItemToObject(object, name, CreateFalse());}
void KJson::AddNumberToObject(KJson* object,const char* name,double n){return AddItemToObject(object, name, CreateNumber(n)); }
void KJson::AddStringToObject(KJson* object,const char* name,const char* s){ return AddItemToObject(object, name, CreateString(s));}
/*
Copyright (c) 2009 Dave Gamble
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.
Modified: april 28 2011 Adam Cox
Modified: aug 10 2011 Adam Cox. I moved everything inside of a KJson class.
Works better now with KData / ROOT.
The code is now some weird hybrid between C and C++.
Please, be my guest to clean this code up and make it all C++!!!
*/
#ifndef KJson__h
#define KJson__h
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <float.h>
#include <limits.h>
#include <ctype.h>
enum KJson_types
{KJson_False=0,
KJson_True,
KJson_NULL,
KJson_Number,
KJson_String,
KJson_Array,
KJson_Object,
KJson_IsReference= 256
};
/* The KJson structure: */
class KJson {
public:
KJson *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
KJson *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
int type; /* The type of the item, as above. */
char *valuestring; /* The item's string, if type==KJson_String */
int valueint; /* The item's number, if type==KJson_Number */
double valuedouble; /* The item's number, if type==KJson_Number */
char *key; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
typedef struct Hooks {
void *(*malloc_fn)(size_t sz);
void (*free_fn)(void *ptr);
} Hooks;
/* Supply malloc, realloc and free functions to KJson */
static void InitHooks(Hooks* hooks);
/* Supply a block of JSON, and this returns a KJson object you can interrogate. Call Delete when finished. */
static KJson *Parse(const char *value);
/* Render a KJson entity to text for transfer/storage. Free the char* when finished. */
static char *Print(KJson *item);
/* Render a KJson entity to text for transfer/storage without any formatting. Free the char* when finished. */
static char *PrintUnformatted(KJson *item);
/* Delete a KJson entity and all subentities. */
static void Delete(KJson *c);
/* Returns the number of items in an array (or object). */
static int GetArraySize(KJson *array);
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
static KJson *GetArrayItem(KJson *array,int item);
/* Get item "string" from object. Case insensitive. */
static KJson *GetObjectItem(KJson *object,const char *string);
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when Parse() returns 0. 0 when Parse() succeeds. */
static const char *GetErrorPtr();
/* These calls create a KJson item of the appropriate type. */
static KJson *CreateNull();
static KJson *CreateTrue();
static KJson *CreateFalse();
static KJson *CreateBool(int b);
static KJson *CreateNumber(double num);
static KJson *CreateString(const char *key);
static KJson *CreateArray();
static KJson *CreateObject();
/* These utilities create an Array of count items. */
static KJson *CreateIntArray(int *numbers,int count);
static KJson *CreateFloatArray(float *numbers,int count);
static KJson *CreateDoubleArray(double *numbers,int count);
static KJson *CreateStringArray(const char **keys,int count);
/* Append item to the specified array/object. */
static void AddItemToArray(KJson *array, KJson *item);
static void AddItemToObject(KJson *object,const char *key,KJson *item);
/* Append reference to item to the specified array/object. Use this when you want to add an existing KJson to a new KJson, but don't want to corrupt your existing KJson. */
static void AddItemReferenceToArray(KJson *array, KJson *item);
static void AddItemReferenceToObject(KJson *object,const char *key,KJson *item);
/* Remove/Detatch items from Arrays/Objects. */
static KJson *DetachItemFromArray(KJson *array,int which);
static void DeleteItemFromArray(KJson *array,int which);
static KJson *DetachItemFromObject(KJson *object,const char *key);
static void DeleteItemFromObject(KJson *object,const char *key);
/* Update array items. */
static void ReplaceItemInArray(KJson *array,int which,KJson *newitem);
static void ReplaceItemInObject(KJson *object,const char *key,KJson *newitem);
static void AddNullToObject(KJson* object,const char* name);
static void AddTrueToObject(KJson* object,const char* name);
static void AddFalseToObject(KJson* object,const char* name);
static void AddNumberToObject(KJson* object,const char* name,double n);
static void AddStringToObject(KJson* object,const char* name,const char* s);
};
#endif
/*
* testread.c
* kData
*
* Created by Adam Cox on 4/3/11.
* Copyright 2011 Karlsruhe Institute of Technology. All rights reserved.
*
*/
#include "KJson.h"
#include "KCurl.h"
using namespace std;
int main (int /*argc*/, char** argv)
{
//
//usage:
//testread <url> <item>
//
// <url> -- the CouchDB URL (https://edwdbik.fzk.de:6984)
//
// <item> -- the CouchDB API call.
// so, something like this. <database name>/<doc_id>
//
// "analysis/run12analysisconstants_ID6"
// or
// "fabdb/detector_FID402"
//
// or
// "edwdb/_design/proc/_view/proc0?reduce=false&include_docs=true"
KCurl c;
char myurl[1000];
sprintf(myurl, "%s", argv[1]);
string myitem = "";
myitem += argv[2];
cout << myurl << endl;
cout << myitem << endl;
c.Get(myurl, myitem.data());
string myreturn = c.GetReturn();
KJson *doc = KJson::Parse( myreturn.data() );
char *rendered=KJson::Print(doc);
cout << "The Return " << endl;
cout << rendered << endl;
return 0;
}
#include "KJson.h"
#include "KCurl.h"
using namespace std;
int main (int /*argc*/, char** argv)
{
//
//usage:
//testwrite2 <url> <database> <doc_id>
//
// <url> -- don't include http:// use just 127.0.0.1:5984 or 134.158.176.27:5984
// <database> = testdb
// <doc_id> -- provide a unique document id for the json doc you will upload to the db.
//
KJson *doc = KJson::CreateObject();
//add some key/value pairs.
KJson::AddItemToObject(doc, "author", KJson::CreateString("samba"));
KJson::AddItemToObject(doc, "type", KJson::CreateString("samba run header"));
KJson::AddItemToObject(doc, "Temperature", KJson::CreateNumber(0.02002));
KJson::AddItemToObject(doc, "Year", KJson::CreateNumber(2011));
//add a subdoc (a nested set of key/value pairs) to doc
KJson *fmt;
KJson::AddItemToObject(doc, "Bolo.reglages", fmt=KJson::CreateObject());
KJson::AddItemToObject(fmt, "polar-centre", KJson::CreateNumber(4.0));
KJson::AddItemToObject(fmt, "polar-garde", KJson::CreateNumber(1.5));
//add an array to doc
KJson *array;
KJson::AddItemToObject(doc, "Date", array=KJson::CreateArray());
KJson::AddItemToArray(array, KJson::CreateNumber(2011));
KJson::AddItemToArray(array, KJson::CreateNumber(4));
KJson::AddItemToArray(array, KJson::CreateNumber(2));
//print out the json document just to check what it looks like
char* buf = KJson::Print(doc);
printf("\nHere is the document we're about to send.");
cout << "The ID will be appended. _id : " << argv[5] << endl;
printf("\n%s\n\n",buf);
unsigned int len = strlen(buf); //** I save the length here and use it later with curl call!
printf("It has a length of %u\n\n", len);
//now send the json document to the server with KCurl
KCurl c;
char myurl[1000];
sprintf(myurl, "%s", argv[1]);
string myitem = "";
myitem += argv[2];
myitem += "/";
myitem += argv[3];
printf("will call curl PUT %s\n\n", myurl);
c.Put(myurl, myitem.data(), KJson::PrintUnformatted(doc));
cout << "The Return " << endl;
cout << c.GetReturn() << endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment