static gboolean
reader_fill_compound_gvalue (JsonReader *reader, TopicValueType type, GValue *value, GError **error)
{
	GDataFreebaseTopicObject *object;

	if (type != TYPE_COMPOUND)
		return FALSE;

	object = reader_create_object (reader, type);

	if (object == NULL)
		return FALSE;

	json_reader_read_member (reader, "property");

	if (json_reader_get_error (reader) != NULL) {
		json_reader_end_member (reader);
		gdata_freebase_topic_object_unref (object);
		return FALSE;
	}

	reader_get_properties (reader, object, error);
	json_reader_end_member (reader);

	g_value_init (value, GDATA_TYPE_FREEBASE_TOPIC_OBJECT);
	g_value_take_boxed (value, object);
	return TRUE;
}
/* Parsing functions to create GDataFreebaseTopicValues, and arrays of those */
static gchar *
reader_dup_member_string (JsonReader *reader, const gchar *member, GError **error)
{
	const GError *reader_error;
	gchar *str;

	if (error != NULL && *error != NULL)
		return NULL;

	json_reader_read_member (reader, member);
	str = g_strdup (json_reader_get_string_value (reader));
	reader_error = json_reader_get_error (reader);

	if (reader_error != NULL) {
		g_free (str);
		str = NULL;

		if (error != NULL)
			*error = g_error_copy (reader_error);
	}

	json_reader_end_member (reader);

	return str;
}
static gint64
reader_parse_timestamp (JsonReader *reader, const gchar *member, GError **error)
{
	const GError *reader_error;
	const gchar *date_str;
	gint64 timestamp = -1;

	if (error != NULL && *error != NULL)
		return -1;

	json_reader_read_member (reader, member);
	date_str = json_reader_get_string_value (reader);
	reader_error = json_reader_get_error (reader);

	if (reader_error != NULL) {
		if (error != NULL)
			*error = g_error_copy (reader_error);
	} else if (date_str) {
		if (!gdata_parser_int64_from_iso8601 (date_str, &timestamp))
			timestamp = -1;
	}

	json_reader_end_member (reader);

	return timestamp;
}
Exemplo n.º 4
0
/*
 * gdata_parser_boolean_from_json_member:
 * @reader: #JsonReader cursor object to read the JSON node from
 * @member_name: the name of the JSON object member to parse
 * @options: a bitwise combination of parsing options from #GDataParserOptions, or %P_NONE
 * @output: (out caller-allocates): the return location for the parsed boolean value
 * @success: (out caller-allocates): the return location for a value which is %TRUE if the boolean was parsed successfully, %FALSE if an error was encountered,
 * and undefined if @member_name was not found in the current object in @reader
 * @error: (allow-none): a #GError, or %NULL
 *
 * Gets the boolean value of the @member_name member of the current object in the #JsonReader, subject to various checks specified by @options.
 *
 * If no member matching @member_name can be found in the current @reader JSON object, %FALSE will be returned, @error will be unset and @success will be unset. @output will be undefined.
 *
 * If @member_name is found but one of the checks specified by @options fails, %TRUE will be returned, @error will be set to a
 * %GDATA_SERVICE_ERROR_PROTOCOL_ERROR error and @success will be set to %FALSE. @output will be undefined.
 *
 * If @member_name is found and all of the checks specified by @options pass, %TRUE will be returned, @error will be unset and
 * @success will be set to %TRUE. @output will be set to the parsed value.
 *
 * The reason for returning the success of the parsing in @success is so that calls to gdata_parser_boolean_from_json_node() can be chained
 * together in a large "or" statement based on their return values, for the purposes of determining whether any of the calls matched
 * a given JSON node. If any of the calls to gdata_parser_boolean_from_json_node() return %TRUE, the value of @success can be examined.
 *
 * Return value: %TRUE if @member_name was found, %FALSE otherwise
 *
 * Since: 0.15.0
 */
gboolean
gdata_parser_boolean_from_json_member (JsonReader *reader, const gchar *member_name, GDataParserOptions options, gboolean *output, gboolean *success, GError **error)
{
	gboolean val;
	const GError *child_error = NULL;

	/* Check if there's such an element. */
	if (g_strcmp0 (json_reader_get_member_name (reader), member_name) != 0) {
		return FALSE;
	}

	/* Get the boolean. Check for parse errors. */
	val = json_reader_get_boolean_value (reader);
	child_error = json_reader_get_error (reader);
	if (child_error != NULL) {
		*success = parser_error_from_json_error (reader, child_error, error);
		return TRUE;
	}

	/* Success! */
	*output = val;
	*success = TRUE;

	return TRUE;
}
Exemplo n.º 5
0
/*
 * gdata_parser_string_from_json_member:
 * @reader: #JsonReader cursor object to read JSON node from
 * @member_name: the name of the member to parse
 * @options: a bitwise combination of parsing options from #GDataParserOptions, or %P_NONE
 * @output: the return location for the parsed string content
 * @success: the return location for a value which is %TRUE if the string was parsed successfully, %FALSE if an error was encountered,
 * and undefined if @element didn't match @element_name
 * @error: a #GError, or %NULL
 *
 * Gets the string content of @element if its name is @element_name, subject to various checks specified by @options.
 *
 * If @element doesn't match @element_name, %FALSE will be returned, @error will be unset and @success will be unset.
 *
 * If @element matches @element_name but one of the checks specified by @options fails, %TRUE will be returned, @error will be set to a
 * %GDATA_SERVICE_ERROR_PROTOCOL_ERROR error and @success will be set to %FALSE.
 *
 * If @element matches @element_name and all of the checks specified by @options pass, %TRUE will be returned, @error will be unset and
 * @success will be set to %TRUE.
 *
 * The reason for returning the success of the parsing in @success is so that calls to gdata_parser_string_from_element() can be chained
 * together in a large "or" statement based on their return values, for the purposes of determining whether any of the calls matched
 * a given @element. If any of the calls to gdata_parser_string_from_element() return %TRUE, the value of @success can be examined.
 *
 * Return value: %TRUE if @element matched @element_name, %FALSE otherwise
 *
 * Since: 0.15.0
 */
gboolean
gdata_parser_string_from_json_member (JsonReader *reader, const gchar *member_name, GDataParserOptions options,
                                      gchar **output, gboolean *success, GError **error)
{
	const gchar *text;
	const GError *child_error = NULL;

	/* Check if there's such element */
	if (g_strcmp0 (json_reader_get_member_name (reader), member_name) != 0) {
		return FALSE;
	}

	/* Check if the output string has already been set. The JSON parser guarantees this can't happen. */
	g_assert (!(options & P_NO_DUPES) || *output == NULL);

	/* Get the string and check it for NULLness or emptiness. Check for parser errors first. */
	text = json_reader_get_string_value (reader);
	child_error = json_reader_get_error (reader);
	if (child_error != NULL) {
		*success = parser_error_from_json_error (reader, child_error, error);
		return TRUE;
	} else if ((options & P_REQUIRED && text == NULL) || (options & P_NON_EMPTY && text != NULL && *text == '\0')) {
		*success = gdata_parser_error_required_json_content_missing (reader, error);
		return TRUE;
	} else if (options & P_DEFAULT && (text == NULL || *text == '\0')) {
		text = "";
	}

	/* Success! */
	g_free (*output);
	*output = g_strdup (text);
	*success = TRUE;

	return TRUE;
}
static gboolean
reader_fill_simple_gvalue (JsonReader *reader, TopicValueType type, GValue *value)
{
	gboolean retval = TRUE;
	gint64 datetime;

	json_reader_read_member (reader, "value");

	if (json_reader_get_error (reader) != NULL) {
		json_reader_end_member (reader);
		return FALSE;
	}

	switch (type) {
	case TYPE_BOOL:
	case TYPE_INT:
	case TYPE_DOUBLE:
	case TYPE_STRING:
		json_node_get_value (json_reader_get_value (reader), value);
		break;
	case TYPE_DATETIME:
		if (gdata_parser_int64_from_iso8601 (json_reader_get_string_value (reader), &datetime) ||
		    gdata_parser_int64_from_date (json_reader_get_string_value (reader), &datetime)) {
			g_value_init (value, G_TYPE_INT64);
			g_value_set_int64 (value, datetime);
		} else {
			retval = FALSE;
		}

		break;
	case TYPE_NONE:
	case TYPE_COMPOUND:
	case TYPE_OBJECT:
	case TYPE_KEY:
	case TYPE_URI:
	default:
		retval = FALSE;
	}

	json_reader_end_member (reader);
	return retval;
}
static GDataFreebaseTopicObject *
reader_create_object (JsonReader *reader, TopicValueType type)
{
	GDataFreebaseTopicObject *object;

	if (type != TYPE_OBJECT && type != TYPE_COMPOUND)
		return NULL;

	json_reader_read_member (reader, "id");

	if (json_reader_get_error (reader) != NULL) {
		json_reader_end_member (reader);
		return NULL;
	}

	object = object_new (json_reader_get_string_value (reader));
	json_reader_end_member (reader);

	return object;
}
static guint
reader_get_value_type (JsonReader *reader, const gchar *property, GError **error)
{
	TopicValueType type = TYPE_NONE;
	const GError *reader_error;
	const gchar *valuestr;

	json_reader_read_member (reader, "valuetype");
	valuestr = json_reader_get_string_value (reader);

	reader_error = json_reader_get_error (reader);

	if (reader_error != NULL) {
		if (error != NULL && *error == NULL)
			*error = g_error_copy (reader_error);
	} else {
		if (strcmp (valuestr, "key") == 0)
			type = TYPE_KEY;
		else if (strcmp (valuestr, "uri") == 0)
			type = TYPE_URI;
		else if (strcmp (valuestr, "compound") == 0)
			type = TYPE_COMPOUND;
		else if (strcmp (valuestr, "object") == 0)
			type = TYPE_OBJECT;
		else if (strcmp (valuestr, "float") == 0)
			type = TYPE_DOUBLE;
		else if (strcmp (valuestr, "string") == 0)
			type = TYPE_STRING;
		else if (strcmp (valuestr, "int") == 0)
			type = TYPE_INT;
		else if (strcmp (valuestr, "bool") == 0)
			type = TYPE_BOOL;
		else if (strcmp (valuestr, "datetime") == 0)
			type = TYPE_DATETIME;
		else
			gdata_parser_error_required_json_content_missing (reader, error);
	}

	json_reader_end_member (reader);
	return type;
}
Exemplo n.º 9
0
/*
 * gdata_parser_int64_time_from_json_member:
 * @reader: #JsonReader cursor object to read JSON node from
 * @element_name: the name of the element to parse
 * @options: a bitwise combination of parsing options from #GDataParserOptions, or %P_NONE
 * @output: (out caller-allocates): the return location for the parsed time value
 * @success: the return location for a value which is %TRUE if the time val was parsed successfully, %FALSE if an error was encountered,
 * and undefined if @element didn't match @element_name
 * @error: a #GError, or %NULL
 *
 * Gets the time value of @element if its name is @element_name, subject to various checks specified by @options. It expects the text content
 * of @element to be a date or time value in ISO 8601 format. The returned time value will be a UNIX timestamp (seconds since the epoch).
 *
 * If @element doesn't match @element_name, %FALSE will be returned, @error will be unset and @success will be unset.
 *
 * If @element matches @element_name but one of the checks specified by @options fails, %TRUE will be returned, @error will be set to a
 * %GDATA_SERVICE_ERROR_PROTOCOL_ERROR error and @success will be set to %FALSE.
 *
 * If @element matches @element_name and all of the checks specified by @options pass, %TRUE will be returned, @error will be unset and
 * @success will be set to %TRUE.
 *
 * The reason for returning the success of the parsing in @success is so that calls to gdata_parser_int64_time_from_element() can be chained
 * together in a large "or" statement based on their return values, for the purposes of determining whether any of the calls matched
 * a given @element. If any of the calls to gdata_parser_int64_time_from_element() return %TRUE, the value of @success can be examined.
 *
 * Return value: %TRUE if @element matched @element_name, %FALSE otherwise
 *
 * Since: 0.15.0
 */
gboolean
gdata_parser_int64_time_from_json_member (JsonReader *reader, const gchar *member_name, GDataParserOptions options,
                                          gint64 *output, gboolean *success, GError **error)
{
	const gchar *text;
	GTimeVal time_val;
	const GError *child_error = NULL;

	/* Check if there's such element */
	if (g_strcmp0 (json_reader_get_member_name (reader), member_name) != 0) {
		return FALSE;
	}

	/* Check if the output time val has already been set. The JSON parser guarantees this can't happen. */
	g_assert (!(options & P_NO_DUPES) || *output == -1);

	/* Get the string and check it for NULLness. Check for errors first. */
	text = json_reader_get_string_value (reader);
	child_error = json_reader_get_error (reader);
	if (child_error != NULL) {
		*success = parser_error_from_json_error (reader, child_error, error);
		return TRUE;
	} else if (options & P_REQUIRED && (text == NULL || *text == '\0')) {
		*success = gdata_parser_error_required_json_content_missing (reader, error);
		return TRUE;
	}

	/* Attempt to parse the string as a GTimeVal */
	if (g_time_val_from_iso8601 ((gchar*) text, &time_val) == FALSE) {
		*success = gdata_parser_error_not_iso8601_format_json (reader, text, error);
		return TRUE;
	}

	/* Success! */
	*output = time_val.tv_sec;
	*success = TRUE;

	return TRUE;
}
Exemplo n.º 10
0
/* Save key/values on the table in the stack if the value is an
 * object or an array, it calls recursively the function again.
 *
 * @param L, pointer to the L with nil on top of it;
 * @param reader, pointed to the first element of main object;
 *
 * returns: the table in the stack with all json values
 */
static void
build_table_from_json_reader (lua_State *L,
                              JsonReader *reader)
{
  const GError *err = json_reader_get_error (reader);
  if (err != NULL) {
    GRL_WARNING ("Error when building json: %s", err->message);
    return;
  }

  if (lua_isnil (L, -1)) {
    /* In the first execution of this recursive call, the main json object
     * does not have a member name. The nil is in the top of the stack and
     * it shall be converted to the table with json content */
    lua_pop (L, 1);

  } else if (lua_istable (L, -1)) {
    const gchar *member_name = json_reader_get_member_name (reader);
    if (member_name)
      lua_pushstring (L, member_name);

  } else if (!lua_isnumber (L, -1)) {
    GRL_DEBUG ("getting value to either table or array");
    return;
  }

  if (json_reader_is_object (reader)) {
    guint index_member = 0;
    guint num_members = json_reader_count_members (reader);

    lua_createtable (L, num_members, 0);
    for (index_member = 0; index_member < num_members; index_member++) {
      json_reader_read_element (reader, index_member);
      build_table_from_json_reader (L, reader);
      json_reader_end_element (reader);
    }

  } else if (json_reader_is_array (reader)) {
    guint index_element = 0;
    guint num_elements = json_reader_count_elements (reader);

    lua_createtable (L, num_elements, 0);
    for (index_element = 0; index_element < num_elements; index_element++) {
      json_reader_read_element (reader, index_element);
      lua_pushinteger (L, index_element + 1);
      build_table_from_json_reader (L, reader);
      json_reader_end_element (reader);
    }

  } else if (json_reader_is_value (reader)) {
    if (json_reader_get_null_value (reader)) {
      lua_pushnil (L);
    } else {
      /* value of the element */
      JsonNode *value = json_reader_get_value (reader);
      switch (json_node_get_value_type (value)) {
      case G_TYPE_STRING:
        lua_pushstring (L, json_reader_get_string_value (reader));
        break;
      case G_TYPE_INT64:
        lua_pushinteger (L, json_reader_get_int_value (reader));
        break;
      case G_TYPE_DOUBLE:
        lua_pushnumber (L, json_reader_get_double_value (reader));
        break;
      case G_TYPE_BOOLEAN:
        lua_pushnumber (L, json_reader_get_boolean_value (reader));
        break;
      default:
        GRL_DEBUG ("'%d' (json-node-type) is not being handled",
                   (gint) json_node_get_value_type (value));
        lua_pushnil (L);
      }
    }
  }

  if (lua_gettop (L) > 3) {
    /* save this key/value on previous table */
    lua_settable (L, -3);
  }
}
Exemplo n.º 11
0
static void restore_state(session_callback_type type, gpointer data, gpointer user_data) {
    JsonParser* jp = NULL;
    JsonReader* jr = NULL;

    const gchar* sqs;
    saved_state* s = NULL;

    GError* err = NULL;

    /* Is it the callback we're interested in? */
    if (type != SPOP_SESSION_LOGGED_IN)
        return;

    /* First disable the callback so it's not called again */
    session_remove_callback(restore_state, NULL);

    g_debug("savestate: reading saved state...");
    s = g_new0(saved_state, 1);

    /* Read and parse state file */
    jp = json_parser_new();
    if (!json_parser_load_from_file(jp, g_state_file_path, &err)) {
        g_warning("savestate: error while reading state file: %s", err->message);
        goto restorestate_error;
    }

    jr = json_reader_new(json_parser_get_root(jp));

    /* Read basic state */
    if (!json_reader_read_member(jr, "status")) goto restorestate_jr_error;
    sqs = json_reader_get_string_value(jr);
    json_reader_end_member(jr);
    if      (strcmp(sqs, "stopped")) s->qs = STOPPED;
    else if (strcmp(sqs, "playing")) s->qs = PLAYING;
    else if (strcmp(sqs, "paused"))  s->qs = PAUSED;
    else {
        g_warning("savestate: bad value for queue status: %s", sqs);
        goto restorestate_error;
    }

    if (!json_reader_read_member(jr, "repeat")) goto restorestate_jr_error;
    s->repeat = json_reader_get_boolean_value(jr);
    json_reader_end_member(jr);

    if (!json_reader_read_member(jr, "shuffle")) goto restorestate_jr_error;
    s->shuffle = json_reader_get_boolean_value(jr);
    json_reader_end_member(jr);

    if (!json_reader_read_member(jr, "current_track")) goto restorestate_jr_error;
    s->cur_track = json_reader_get_int_value(jr);
    json_reader_end_member(jr);

    /* Now read tracks URIs */
    if (!json_reader_read_member(jr, "tracks")) goto restorestate_jr_error;
    if (!json_reader_is_array(jr)) {
        g_warning("savestate: error while parsing JSON: tracks is not an array");
        goto restorestate_error;
    }
    gint tracks = json_reader_count_elements(jr);
    if (s->cur_track >= tracks) {
        g_warning("savestate: incoherent state file: cur_track >= tracks");
        goto restorestate_error;
    }

    s->tracks = g_array_sized_new(FALSE, FALSE, sizeof(sp_track*), tracks);
    if (!s->tracks)
        g_error("Can't allocate array of %d tracks.", tracks);

    size_t i;
    gboolean can_restore_now = TRUE;
    for (i=0; i < tracks; i++) {
        json_reader_read_element(jr, i);
        const gchar* uri = json_reader_get_string_value(jr);
        json_reader_end_element(jr);

        sp_link* lnk = sp_link_create_from_string(uri);
        sp_linktype lt = sp_link_type(lnk);
        if (lt != SP_LINKTYPE_TRACK) {
            g_warning("savestate: invalid link type for track %zu: %d", i, lt);
            sp_link_release(lnk);
            goto restorestate_error;
        }
        sp_track* tr = sp_link_as_track(lnk);
        sp_track_add_ref(tr);
        sp_link_release(lnk);
        g_array_append_val(s->tracks, tr);
        if (!sp_track_is_loaded(tr))
            can_restore_now = FALSE;
    }

    /* If possible, restore now, else wait for all tracks to be loaded */
    if (can_restore_now)
        really_restore_state(s);
    else {
        g_timeout_add(100, (GSourceFunc) really_restore_state, s);
        g_debug("savestate: waiting for all tracks to be loaded before restoring saved state...");
    }

    /* Add a notification callback */
    if (!interface_notify_add_callback(savestate_notification_callback, NULL))
        g_error("Could not add savestate callback.");

    goto restorestate_clean;

 restorestate_jr_error:
    err = (GError*) json_reader_get_error(jr);
    g_warning("savestate: error while parsing JSON: %s", err->message);

 restorestate_error:
    if (s) {
        if (s->tracks)
            g_array_free(s->tracks, TRUE);
        g_free(s);
    }

 restorestate_clean:
    if (jp)
        g_object_unref(jp);
    if (jr)
        g_object_unref(jr);
}