Home modules.gotpike.org
Username: Password: [Create Account]
[Forgot Password?]

Modules

ADT
Database
GTK2
GUI
IP
PiJAX
Public
Sql
Stdio
Subversion
System
Tools
Xosd
lua
v4l2
wx

Recent Changes

Public.Parser.XML2 1.50
Public.ZeroMQ 1.1
Public.Template.Mustache 1.0
Public.Protocols.XMPP 1.4
Sql.Provider.jdbc 1.0

Popular Downloads

Public.Parser.JSON2 1.0
Public.Parser.JSON 0.2
GTK2 2.23
Public.Web.FCGI 1.8
Public.Parser.XML2 1.48


Module Information
Public.Parser.JSON
Viewing contents of Public_Parser_JSON-0.2/JSON.cmod

/* Pike "binding" for json-c (http://oss.metaparadigm.com/json-c/)
 *
 * - Johan Bjorklund 
 */

/* This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include "global.h"
#include "svalue.h"
#include "interpret.h"
#include "program.h"
#include "array.h"
#include "mapping.h"
#include "builtin_functions.h"

#include 
#include 

#include "module.h"

struct json_object *encode_object(struct object *o);
struct json_object *encode_array(struct array *a);
struct json_object *encode_mapping(struct mapping *a);

struct json_object *encode_svalue(struct svalue *val) {
  struct json_object *ret = NULL;
  switch(val->type) {
  case PIKE_T_STRING:
    ret = json_object_new_string_len( (char*) STR0(val->u.string),
				      ((struct pike_string *) val->u.string)->len * (((struct pike_string *) val->u.string)->size_shift+1) );
    break;
  case PIKE_T_INT:
    ret = json_object_new_int(val->u.integer);
    break;
  case PIKE_T_ARRAY:
    ret = encode_array(val->u.array);
    break;
  case PIKE_T_MAPPING:
    ret = encode_mapping(val->u.mapping);
    break;
  case PIKE_T_FLOAT:
    ret = json_object_new_double(val->u.float_number);
    break;
  case PIKE_T_OBJECT:
    ret = encode_object(val->u.object);
  }
  return ret;
}

struct json_object *encode_array(struct array *a) {
  int i;
  struct json_object *ret = NULL;
  struct json_object *new = NULL;
  for(i=0; i < a->size; i++) {
    if((new = encode_svalue(&ITEM(a)[i])) != NULL) {
      if(!ret)
	ret = json_object_new_array();
      json_object_array_add(ret, new);
    }
  }
  return ret;
}

char *itoa(int i) {
  int s=0;
  int a = i;
  while((a=(a/10)) > 0) s++;
  char *str = malloc(s+1);
  sprintf(str, "%d\0", i);
  return str;
}

struct json_object *encode_mapping(struct mapping *m) {  
  struct json_object *ret = NULL;
  struct json_object *new;
  INT32 e;
  struct keypair *k;
  char *ind;
  char freeind = 0;

  NEW_MAPPING_LOOP(m->data) {
    switch(k->ind.type) {
    case PIKE_T_STRING:
      ind = (char*) STR0(k->ind.u.string);
      freeind = 0;
      break;
    case PIKE_T_INT:
      ind = itoa(k->ind.u.integer);
      freeind = 1;
      break;
    default:
      ind = NULL;
    }
    if(ind != NULL) {
      if((new = encode_svalue(&k->val)) != NULL) {
	if(ret == NULL)
	  ret = json_object_new_object();
	json_object_object_add(ret, ind, new);
      }
      if(freeind)
	free(ind);
    }
  }
  return ret;
}

struct json_object *encode_object(struct object *o) {
  struct json_object *ret = NULL;
  struct json_object *new;
  struct svalue *val;
  struct array *indices = object_indices(o);
  int i;
  for(i=0; isize; i++) {
    struct svalue index = *(ITEM(indices) + i);
    object_index_no_free2(val, o, &index);
    if((new = encode_svalue(val)) != NULL) {
      if(!ret)
	ret = json_object_new_object();
      json_object_object_add(ret, (char*) STR0(index.u.string), new);
    }
  }
  return ret;
}

void is_ok (struct json_object *o) {
  if (is_error(o)) {
    switch (- (enum json_tokener_error) o) {
    case json_tokener_error_parse_array: Pike_error("Tokener error: parse array\n");
    case json_tokener_error_parse_boolean: Pike_error("Tokener error: parse boolean\n");
    case json_tokener_error_parse_comment: Pike_error("Tokener error: parse comment\n");
    case json_tokener_error_parse_eof: Pike_error("Tokener error: parse eof\n");
    case json_tokener_error_parse_null: Pike_error("Tokener error: parse null\n");
    case json_tokener_error_parse_number: Pike_error("Tokener error: parse number\n");
    case json_tokener_error_parse_string: Pike_error("Tokener error: parse string\n");
    case json_tokener_error_parse_unexpected: Pike_error("Tokener error: parse unexpected\n");
    }
    Pike_error("Tokener error\n");
  }
}

void decode_obj(struct json_object *o);
void decode_array(struct json_object *o);

void decode_val(struct json_object *o) {

  if (!o) {
    push_undefined();
    return;
  }

  switch(json_object_get_type(o)) {
  case json_type_boolean:
  case json_type_int:
    push_int(json_object_get_int(o));
    break;
  case json_type_double:
    push_float(json_object_get_double(o));
    break;
  case json_type_string:
    push_text(json_object_get_string(o));
    break;
  case json_type_array:
    decode_array(o);
    break;
  case json_type_object:
    decode_obj(o);
    break;
  case json_type_null:
  default:
    push_undefined();
  }
}

void decode_array(struct json_object *o) {
  struct json_object *obj;
  int n, l = json_object_array_length(o);
  for (n=0; n < l; n++) {
    obj = json_object_array_get_idx(o, n);
    decode_val(obj);
  }
  f_aggregate(n);
}

void decode_obj(struct json_object *o) {
  int n=0;
  json_object_object_foreach(o, key, val) {
    if (!key) continue;
    push_text(key);
    decode_val(val);
    n+=2;
  }
  f_aggregate_mapping(n);
}

void free_obj(struct json_object *o) {
  int n, l;
  switch (json_object_get_type(o)) {
  case json_type_object: {
    json_object_object_foreach(o, key, val)
      free_obj(val);
    json_object_put(o);
  }
    break;
  case json_type_array: {
    l = json_object_array_length(o);
    for (n=0; n < l; n++)
      free_obj(json_object_array_get_idx(o, n));
    json_object_put(o);
  }
    break;
  default:
    json_object_put(o);
  }
}

/*! @module Public
 */

/*! @module Parser
 */

/*! @module JSON
 */

/*! @decl mapping decode(string s)
 *!
 *! Parses a JSON-formatted string and returns the corresponding mapping.
 */

PIKEFUN mapping decode(string stream)
{
  struct json_object *o;
  pop_stack();
  if(stream->size_shift == 0) {
    o = json_tokener_parse((char*)STR0(stream));
    is_ok(o);
    decode_obj(o);
    json_object_put(o);
  } else {
    Pike_error("Size shift = 1, don't know what to do.");
  }
}

/*! @decl string encode(object|mapping o)
 *!
 *! Converts an object or mapping to a JSON-formatted string.
 */

PIKEFUN string encode(object|mapping o);
{
  struct pike_string *ret = NULL;
  struct json_object *jso = NULL;
  if(o) {
    switch(o->type) {
    case PIKE_T_OBJECT: {
      struct object *obj = o->u.object;
      if (obj)
	jso = encode_object(obj);
    }
    case PIKE_T_MAPPING: {
      struct mapping *m = o->u.mapping;
      if (m)
	jso = encode_mapping(m);
    }
    }
  }
  if (jso) {
    ret = make_shared_string(json_object_to_json_string(jso));
    free_obj(jso);
  } else {
    ret = make_shared_binary_string("", 0);
  }
  RETURN ret;
}

/*! @endmodule
 */

/*! @endmodule
 */

/*! @endmodule
 */

EXTRA {
  add_string_constant("__author", "Johan Björklund ", 0);
  add_string_constant("__version", "0.2", 0);
}


gotpike.org | Copyright © 2004 - 2019 | Pike is a trademark of Department of Computer and Information Science, Linköping University