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

File Contents

Contents of /Public_Parser_JSON-0.2/JSON.cmod:

/* Pike "binding" for json-c (http://oss.metaparadigm.com/json-c/)
 *
 * - Johan Bjorklund <johbjo09@kth.se>
 */

/* 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 <string.h>
#include <json/json.h>

#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; i<indices->size; 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 <johbjo09@kth.se>", 0);
  add_string_constant("__version", "0.2", 0);
}

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