|
Packit |
712bc5 |
/*
|
|
Packit |
712bc5 |
* Copyright (C) 2008 OpenedHand Ltd.
|
|
Packit |
712bc5 |
*
|
|
Packit |
712bc5 |
* Authors: Jorn Baayen <jorn@openedhand.com>
|
|
Packit |
712bc5 |
*
|
|
Packit |
712bc5 |
* This library is free software; you can redistribute it and/or
|
|
Packit |
712bc5 |
* modify it under the terms of the GNU Library General Public
|
|
Packit |
712bc5 |
* License as published by the Free Software Foundation; either
|
|
Packit |
712bc5 |
* version 2 of the License, or (at your option) any later version.
|
|
Packit |
712bc5 |
*
|
|
Packit |
712bc5 |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
712bc5 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
712bc5 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
712bc5 |
* Library General Public License for more details.
|
|
Packit |
712bc5 |
*
|
|
Packit |
712bc5 |
* You should have received a copy of the GNU Library General Public
|
|
Packit |
712bc5 |
* License along with this library; if not, write to the
|
|
Packit |
712bc5 |
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
Packit |
712bc5 |
* Boston, MA 02110-1301, USA.
|
|
Packit |
712bc5 |
*/
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/**
|
|
Packit |
712bc5 |
* SECTION:gupnp-search-criteria-parser
|
|
Packit |
712bc5 |
* @short_description: A/V search criteria parser
|
|
Packit |
712bc5 |
*
|
|
Packit |
712bc5 |
* #GUPnPSearchCriteriaParser parses ContentDirectory search criteria
|
|
Packit |
712bc5 |
* strings.
|
|
Packit |
712bc5 |
*
|
|
Packit |
712bc5 |
* Note that no signals will be emitted if a wildcard is specified,
|
|
Packit |
712bc5 |
* and that the user is responsible for ensuring precedence of conjunction
|
|
Packit |
712bc5 |
* over disjunction.
|
|
Packit |
712bc5 |
*/
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
#include <string.h>
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
#include "gupnp-search-criteria-parser.h"
|
|
Packit |
712bc5 |
#include "gupnp-av-marshal.h"
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/* GType for GUPNPSearchCriteriaOp */
|
|
Packit |
712bc5 |
GType
|
|
Packit |
712bc5 |
gupnp_search_criteria_op_get_type (void)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
static GType type = 0;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
if (type == 0) {
|
|
Packit |
712bc5 |
static const GEnumValue values[] = {
|
|
Packit |
712bc5 |
{ GUPNP_SEARCH_CRITERIA_OP_EQ,
|
|
Packit |
712bc5 |
"GUPNP_SEARCH_CRITERIA_OP_EQ",
|
|
Packit |
712bc5 |
"EQ" },
|
|
Packit |
712bc5 |
{ GUPNP_SEARCH_CRITERIA_OP_NEQ,
|
|
Packit |
712bc5 |
"GUPNP_SEARCH_CRITERIA_OP_NEQ",
|
|
Packit |
712bc5 |
"NEQ" },
|
|
Packit |
712bc5 |
{ GUPNP_SEARCH_CRITERIA_OP_LESS,
|
|
Packit |
712bc5 |
"GUPNP_SEARCH_CRITERIA_OP_LESS",
|
|
Packit |
712bc5 |
"LESS" },
|
|
Packit |
712bc5 |
{ GUPNP_SEARCH_CRITERIA_OP_LEQ,
|
|
Packit |
712bc5 |
"GUPNP_SEARCH_CRITERIA_OP_LEQ",
|
|
Packit |
712bc5 |
"LEQ" },
|
|
Packit |
712bc5 |
{ GUPNP_SEARCH_CRITERIA_OP_GREATER,
|
|
Packit |
712bc5 |
"GUPNP_SEARCH_CRITERIA_OP_GREATER",
|
|
Packit |
712bc5 |
"GREATER" },
|
|
Packit |
712bc5 |
{ GUPNP_SEARCH_CRITERIA_OP_GEQ,
|
|
Packit |
712bc5 |
"GUPNP_SEARCH_CRITERIA_OP_GEQ",
|
|
Packit |
712bc5 |
"GEQ" },
|
|
Packit |
712bc5 |
{ GUPNP_SEARCH_CRITERIA_OP_CONTAINS,
|
|
Packit |
712bc5 |
"GUPNP_SEARCH_CRITERIA_OP_CONTAINS",
|
|
Packit |
712bc5 |
"CONTAINS" },
|
|
Packit |
712bc5 |
{ GUPNP_SEARCH_CRITERIA_OP_DOES_NOT_CONTAIN,
|
|
Packit |
712bc5 |
"GUPNP_SEARCH_CRITERIA_OP_DOES_NOT_CONTAIN",
|
|
Packit |
712bc5 |
"DOES_NOT_CONTAIN" },
|
|
Packit |
712bc5 |
{ GUPNP_SEARCH_CRITERIA_OP_DERIVED_FROM,
|
|
Packit |
712bc5 |
"GUPNP_SEARCH_CRITERIA_OP_DERIVED_FROM",
|
|
Packit |
712bc5 |
"DERIVED_FROM" },
|
|
Packit |
712bc5 |
{ GUPNP_SEARCH_CRITERIA_OP_EXISTS,
|
|
Packit |
712bc5 |
"GUPNP_SEARCH_CRITERIA_OP_EXISTS",
|
|
Packit |
712bc5 |
"EXISTS" },
|
|
Packit |
712bc5 |
{ 0, NULL, NULL }
|
|
Packit |
712bc5 |
};
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
type = g_enum_register_static
|
|
Packit |
712bc5 |
(g_intern_static_string (
|
|
Packit |
712bc5 |
"GUPnPSearchCriteriaOp"),
|
|
Packit |
712bc5 |
values);
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return type;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/* GUPnPSearchCriteriaParserError */
|
|
Packit |
712bc5 |
GQuark
|
|
Packit |
712bc5 |
gupnp_search_criteria_parser_error_quark (void)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
return g_quark_from_static_string
|
|
Packit |
712bc5 |
("gupnp-search-criteria-parser-error-quark");
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/* GUPnPSearchCriteriaParser */
|
|
Packit |
712bc5 |
G_DEFINE_TYPE (GUPnPSearchCriteriaParser,
|
|
Packit |
712bc5 |
gupnp_search_criteria_parser,
|
|
Packit |
712bc5 |
G_TYPE_OBJECT);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
struct _GUPnPSearchCriteriaParserPrivate {
|
|
Packit |
712bc5 |
GScanner *scanner;
|
|
Packit |
712bc5 |
};
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
enum {
|
|
Packit |
712bc5 |
BEGIN_PARENS,
|
|
Packit |
712bc5 |
END_PARENS,
|
|
Packit |
712bc5 |
CONJUNCTION,
|
|
Packit |
712bc5 |
DISJUNCTION,
|
|
Packit |
712bc5 |
EXPRESSION,
|
|
Packit |
712bc5 |
SIGNAL_LAST
|
|
Packit |
712bc5 |
};
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
static guint signals[SIGNAL_LAST];
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/* Additional parsable symbols */
|
|
Packit |
712bc5 |
enum {
|
|
Packit |
712bc5 |
SYMBOL_ASTERISK = G_TOKEN_LAST + 11,
|
|
Packit |
712bc5 |
SYMBOL_AND = G_TOKEN_LAST + 12,
|
|
Packit |
712bc5 |
SYMBOL_OR = G_TOKEN_LAST + 13,
|
|
Packit |
712bc5 |
SYMBOL_TRUE = G_TOKEN_LAST + 14,
|
|
Packit |
712bc5 |
SYMBOL_FALSE = G_TOKEN_LAST + 15
|
|
Packit |
712bc5 |
};
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
#define NUM_SYMBOLS 15
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
struct {
|
|
Packit |
712bc5 |
const char *name;
|
|
Packit |
712bc5 |
int token;
|
|
Packit |
712bc5 |
} symbols[NUM_SYMBOLS] = {
|
|
Packit |
712bc5 |
{ "*",
|
|
Packit |
712bc5 |
SYMBOL_ASTERISK },
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
{ "and",
|
|
Packit |
712bc5 |
SYMBOL_AND },
|
|
Packit |
712bc5 |
{ "or",
|
|
Packit |
712bc5 |
SYMBOL_OR },
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
{ "=",
|
|
Packit |
712bc5 |
GUPNP_SEARCH_CRITERIA_OP_EQ },
|
|
Packit |
712bc5 |
{ "!=",
|
|
Packit |
712bc5 |
GUPNP_SEARCH_CRITERIA_OP_NEQ },
|
|
Packit |
712bc5 |
{ "<",
|
|
Packit |
712bc5 |
GUPNP_SEARCH_CRITERIA_OP_LESS },
|
|
Packit |
712bc5 |
{ "<=",
|
|
Packit |
712bc5 |
GUPNP_SEARCH_CRITERIA_OP_LEQ },
|
|
Packit |
712bc5 |
{ ">",
|
|
Packit |
712bc5 |
GUPNP_SEARCH_CRITERIA_OP_GREATER },
|
|
Packit |
712bc5 |
{ ">=",
|
|
Packit |
712bc5 |
GUPNP_SEARCH_CRITERIA_OP_GEQ },
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
{ "contains",
|
|
Packit |
712bc5 |
GUPNP_SEARCH_CRITERIA_OP_CONTAINS },
|
|
Packit |
712bc5 |
{ "doesNotContain",
|
|
Packit |
712bc5 |
GUPNP_SEARCH_CRITERIA_OP_DOES_NOT_CONTAIN },
|
|
Packit |
712bc5 |
{ "derivedfrom",
|
|
Packit |
712bc5 |
GUPNP_SEARCH_CRITERIA_OP_DERIVED_FROM },
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
{ "exists",
|
|
Packit |
712bc5 |
GUPNP_SEARCH_CRITERIA_OP_EXISTS },
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
{ "true",
|
|
Packit |
712bc5 |
SYMBOL_TRUE },
|
|
Packit |
712bc5 |
{ "false",
|
|
Packit |
712bc5 |
SYMBOL_FALSE }
|
|
Packit |
712bc5 |
};
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
static void
|
|
Packit |
712bc5 |
gupnp_search_criteria_parser_init (GUPnPSearchCriteriaParser *parser)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
int i;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
parser->priv = G_TYPE_INSTANCE_GET_PRIVATE
|
|
Packit |
712bc5 |
(parser,
|
|
Packit |
712bc5 |
GUPNP_TYPE_SEARCH_CRITERIA_PARSER,
|
|
Packit |
712bc5 |
GUPnPSearchCriteriaParserPrivate);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/* Set up GScanner */
|
|
Packit |
712bc5 |
parser->priv->scanner = g_scanner_new (NULL);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
parser->priv->scanner->config->cset_skip_characters = (char *)" \t\n\r\012"
|
|
Packit |
712bc5 |
"\013\014\015";
|
|
Packit |
712bc5 |
parser->priv->scanner->config->scan_identifier_1char = TRUE;
|
|
Packit |
712bc5 |
parser->priv->scanner->config->cset_identifier_first = (char *) G_CSET_a_2_z
|
|
Packit |
712bc5 |
"_*<>=!@"
|
|
Packit |
712bc5 |
G_CSET_A_2_Z;
|
|
Packit |
712bc5 |
parser->priv->scanner->config->cset_identifier_nth = (char *)G_CSET_a_2_z
|
|
Packit |
712bc5 |
"_0123456789=:@"
|
|
Packit |
712bc5 |
G_CSET_A_2_Z
|
|
Packit |
712bc5 |
G_CSET_LATINS
|
|
Packit |
712bc5 |
G_CSET_LATINC;
|
|
Packit |
712bc5 |
parser->priv->scanner->config->symbol_2_token = TRUE;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/* Add symbols */
|
|
Packit |
712bc5 |
for (i = 0; i < NUM_SYMBOLS; i++) {
|
|
Packit |
712bc5 |
g_scanner_scope_add_symbol (parser->priv->scanner,
|
|
Packit |
712bc5 |
0,
|
|
Packit |
712bc5 |
symbols[i].name,
|
|
Packit |
712bc5 |
GINT_TO_POINTER (symbols[i].token));
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
static void
|
|
Packit |
712bc5 |
gupnp_search_criteria_parser_finalize (GObject *object)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
GObjectClass *gobject_class;
|
|
Packit |
712bc5 |
GUPnPSearchCriteriaParser *parser;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
parser = GUPNP_SEARCH_CRITERIA_PARSER (object);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/* Destroy GScanner */
|
|
Packit |
712bc5 |
g_scanner_destroy (parser->priv->scanner);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
gobject_class =
|
|
Packit |
712bc5 |
G_OBJECT_CLASS (gupnp_search_criteria_parser_parent_class);
|
|
Packit |
712bc5 |
gobject_class->dispose (object);
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
static void
|
|
Packit |
712bc5 |
gupnp_search_criteria_parser_class_init
|
|
Packit |
712bc5 |
(GUPnPSearchCriteriaParserClass *klass)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
GObjectClass *object_class;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
object_class = G_OBJECT_CLASS (klass);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
object_class->finalize = gupnp_search_criteria_parser_finalize;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/**
|
|
Packit |
712bc5 |
* GUPnPSearchCriteriaParser::begin-parens:
|
|
Packit |
712bc5 |
* @parser: The #GUPnPSearchCriteriaParser that received the signal
|
|
Packit |
712bc5 |
*
|
|
Packit |
712bc5 |
* The ::begin_parens signal is emitted to mark the beginning of a
|
|
Packit |
712bc5 |
* parenthetical expression.
|
|
Packit |
712bc5 |
**/
|
|
Packit |
712bc5 |
signals[BEGIN_PARENS] =
|
|
Packit |
712bc5 |
g_signal_new ("begin-parens",
|
|
Packit |
712bc5 |
GUPNP_TYPE_SEARCH_CRITERIA_PARSER,
|
|
Packit |
712bc5 |
G_SIGNAL_RUN_LAST,
|
|
Packit |
712bc5 |
G_STRUCT_OFFSET (GUPnPSearchCriteriaParserClass,
|
|
Packit |
712bc5 |
begin_parens),
|
|
Packit |
712bc5 |
NULL,
|
|
Packit |
712bc5 |
NULL,
|
|
Packit |
712bc5 |
g_cclosure_marshal_VOID__VOID,
|
|
Packit |
712bc5 |
G_TYPE_NONE,
|
|
Packit |
712bc5 |
0);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/**
|
|
Packit |
712bc5 |
* GUPnPSearchCriteriaParser::end-parens:
|
|
Packit |
712bc5 |
* @parser: The #GUPnPSearchCriteriaParser that received the signal
|
|
Packit |
712bc5 |
*
|
|
Packit |
712bc5 |
* The ::end_parens signal is emitted to mark the end of a parenthetical
|
|
Packit |
712bc5 |
* expression.
|
|
Packit |
712bc5 |
**/
|
|
Packit |
712bc5 |
signals[END_PARENS] =
|
|
Packit |
712bc5 |
g_signal_new ("end-parens",
|
|
Packit |
712bc5 |
GUPNP_TYPE_SEARCH_CRITERIA_PARSER,
|
|
Packit |
712bc5 |
G_SIGNAL_RUN_LAST,
|
|
Packit |
712bc5 |
G_STRUCT_OFFSET (GUPnPSearchCriteriaParserClass,
|
|
Packit |
712bc5 |
end_parens),
|
|
Packit |
712bc5 |
NULL,
|
|
Packit |
712bc5 |
NULL,
|
|
Packit |
712bc5 |
g_cclosure_marshal_VOID__VOID,
|
|
Packit |
712bc5 |
G_TYPE_NONE,
|
|
Packit |
712bc5 |
0);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/**
|
|
Packit |
712bc5 |
* GUPnPSearchCriteriaParser::conjunction:
|
|
Packit |
712bc5 |
* @parser: The #GUPnPSearchCriteriaParser that received the signal
|
|
Packit |
712bc5 |
*
|
|
Packit |
712bc5 |
* The ::conjuction signal is emitted whenever a conjuction marker
|
|
Packit |
712bc5 |
* (and) is parsed.
|
|
Packit |
712bc5 |
**/
|
|
Packit |
712bc5 |
signals[CONJUNCTION] =
|
|
Packit |
712bc5 |
g_signal_new ("conjunction",
|
|
Packit |
712bc5 |
GUPNP_TYPE_SEARCH_CRITERIA_PARSER,
|
|
Packit |
712bc5 |
G_SIGNAL_RUN_LAST,
|
|
Packit |
712bc5 |
G_STRUCT_OFFSET (GUPnPSearchCriteriaParserClass,
|
|
Packit |
712bc5 |
conjunction),
|
|
Packit |
712bc5 |
NULL,
|
|
Packit |
712bc5 |
NULL,
|
|
Packit |
712bc5 |
g_cclosure_marshal_VOID__VOID,
|
|
Packit |
712bc5 |
G_TYPE_NONE,
|
|
Packit |
712bc5 |
0);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/**
|
|
Packit |
712bc5 |
* GUPnPSearchCriteriaParser::disjunction:
|
|
Packit |
712bc5 |
* @parser: The #GUPnPSearchCriteriaParser that received the signal
|
|
Packit |
712bc5 |
*
|
|
Packit |
712bc5 |
* The ::disjuction signal is emitted whenever a disjuction marker
|
|
Packit |
712bc5 |
* (or&rpar is parsed.
|
|
Packit |
712bc5 |
**/
|
|
Packit |
712bc5 |
signals[DISJUNCTION] =
|
|
Packit |
712bc5 |
g_signal_new ("disjunction",
|
|
Packit |
712bc5 |
GUPNP_TYPE_SEARCH_CRITERIA_PARSER,
|
|
Packit |
712bc5 |
G_SIGNAL_RUN_LAST,
|
|
Packit |
712bc5 |
G_STRUCT_OFFSET (GUPnPSearchCriteriaParserClass,
|
|
Packit |
712bc5 |
disjunction),
|
|
Packit |
712bc5 |
NULL,
|
|
Packit |
712bc5 |
NULL,
|
|
Packit |
712bc5 |
g_cclosure_marshal_VOID__VOID,
|
|
Packit |
712bc5 |
G_TYPE_NONE,
|
|
Packit |
712bc5 |
0);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/**
|
|
Packit |
712bc5 |
* GUPnPSearchCriteriaParser::expression:
|
|
Packit |
712bc5 |
* @parser: The #GUPnPSearchCriteriaParser that received the signal
|
|
Packit |
712bc5 |
* @property: The property
|
|
Packit |
712bc5 |
* @op: The operator as #GUPnPSearchCriteriaOp
|
|
Packit |
712bc5 |
* @value: The value as string
|
|
Packit |
712bc5 |
* @error: Place-holder for any possible errors from handler
|
|
Packit |
712bc5 |
*
|
|
Packit |
712bc5 |
* The ::expression signal is emitted whenever an expression is parsed.
|
|
Packit |
712bc5 |
* Set @error and return %FALSE if an error occurred.
|
|
Packit |
712bc5 |
**/
|
|
Packit |
712bc5 |
signals[EXPRESSION] =
|
|
Packit |
712bc5 |
g_signal_new ("expression",
|
|
Packit |
712bc5 |
GUPNP_TYPE_SEARCH_CRITERIA_PARSER,
|
|
Packit |
712bc5 |
G_SIGNAL_RUN_LAST,
|
|
Packit |
712bc5 |
G_STRUCT_OFFSET (GUPnPSearchCriteriaParserClass,
|
|
Packit |
712bc5 |
expression),
|
|
Packit |
712bc5 |
NULL,
|
|
Packit |
712bc5 |
NULL,
|
|
Packit |
712bc5 |
gupnp_av_marshal_BOOLEAN__STRING_UINT_STRING_POINTER,
|
|
Packit |
712bc5 |
G_TYPE_BOOLEAN,
|
|
Packit |
712bc5 |
4,
|
|
Packit |
712bc5 |
G_TYPE_STRING,
|
|
Packit |
712bc5 |
GUPNP_TYPE_SEARCH_CRITERIA_OP,
|
|
Packit |
712bc5 |
G_TYPE_STRING,
|
|
Packit |
712bc5 |
G_TYPE_POINTER);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
g_type_class_add_private (klass,
|
|
Packit |
712bc5 |
sizeof (GUPnPSearchCriteriaParserPrivate));
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/**
|
|
Packit |
712bc5 |
* gupnp_search_criteria_parser_new:
|
|
Packit |
712bc5 |
*
|
|
Packit |
712bc5 |
* Return value: A new #GUPnPSearchCriteriaParser object.
|
|
Packit |
712bc5 |
**/
|
|
Packit |
712bc5 |
GUPnPSearchCriteriaParser *
|
|
Packit |
712bc5 |
gupnp_search_criteria_parser_new (void)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
return g_object_new (GUPNP_TYPE_SEARCH_CRITERIA_PARSER, NULL);
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/* Scan a relExp portion of a search criteria string */
|
|
Packit |
712bc5 |
static gboolean
|
|
Packit |
712bc5 |
scan_rel_exp (GUPnPSearchCriteriaParser *parser,
|
|
Packit |
712bc5 |
GError **error)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
GTokenValue value;
|
|
Packit |
712bc5 |
gboolean ret;
|
|
Packit |
712bc5 |
guint token;
|
|
Packit |
712bc5 |
GUPnPSearchCriteriaOp op;
|
|
Packit |
712bc5 |
char *arg1;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
token = g_scanner_get_next_token (parser->priv->scanner);
|
|
Packit |
712bc5 |
g_assert (token == G_TOKEN_IDENTIFIER); /* Already checked */
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
value = g_scanner_cur_value (parser->priv->scanner);
|
|
Packit |
712bc5 |
arg1 = g_strdup (value.v_string);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
token = g_scanner_get_next_token (parser->priv->scanner);
|
|
Packit |
712bc5 |
switch (token) {
|
|
Packit |
712bc5 |
case GUPNP_SEARCH_CRITERIA_OP_EQ:
|
|
Packit |
712bc5 |
case GUPNP_SEARCH_CRITERIA_OP_NEQ:
|
|
Packit |
712bc5 |
case GUPNP_SEARCH_CRITERIA_OP_LESS:
|
|
Packit |
712bc5 |
case GUPNP_SEARCH_CRITERIA_OP_LEQ:
|
|
Packit |
712bc5 |
case GUPNP_SEARCH_CRITERIA_OP_GREATER:
|
|
Packit |
712bc5 |
case GUPNP_SEARCH_CRITERIA_OP_GEQ:
|
|
Packit |
712bc5 |
case GUPNP_SEARCH_CRITERIA_OP_CONTAINS:
|
|
Packit |
712bc5 |
case GUPNP_SEARCH_CRITERIA_OP_DOES_NOT_CONTAIN:
|
|
Packit |
712bc5 |
case GUPNP_SEARCH_CRITERIA_OP_DERIVED_FROM:
|
|
Packit |
712bc5 |
op = token;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
token = g_scanner_get_next_token (parser->priv->scanner);
|
|
Packit |
712bc5 |
if (token != G_TOKEN_STRING) {
|
|
Packit |
712bc5 |
g_set_error
|
|
Packit |
712bc5 |
(error,
|
|
Packit |
712bc5 |
GUPNP_SEARCH_CRITERIA_PARSER_ERROR,
|
|
Packit |
712bc5 |
GUPNP_SEARCH_CRITERIA_PARSER_ERROR_FAILED,
|
|
Packit |
712bc5 |
"Expected quoted string at position %u",
|
|
Packit |
712bc5 |
g_scanner_cur_position
|
|
Packit |
712bc5 |
(parser->priv->scanner));
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
ret = FALSE;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
break;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
value = g_scanner_cur_value (parser->priv->scanner);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
g_signal_emit (parser, signals[EXPRESSION], 0,
|
|
Packit |
712bc5 |
arg1, op, value.v_string, error, &ret;;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
break;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
case GUPNP_SEARCH_CRITERIA_OP_EXISTS:
|
|
Packit |
712bc5 |
op = token;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
token = g_scanner_get_next_token (parser->priv->scanner);
|
|
Packit |
712bc5 |
switch (token) {
|
|
Packit |
712bc5 |
case SYMBOL_TRUE:
|
|
Packit |
712bc5 |
g_signal_emit (parser, signals[EXPRESSION], 0,
|
|
Packit |
712bc5 |
arg1, op, "true", error, &ret;;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
break;
|
|
Packit |
712bc5 |
case SYMBOL_FALSE:
|
|
Packit |
712bc5 |
g_signal_emit (parser, signals[EXPRESSION], 0,
|
|
Packit |
712bc5 |
arg1, op, "false", error, &ret;;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
break;
|
|
Packit |
712bc5 |
default:
|
|
Packit |
712bc5 |
g_set_error
|
|
Packit |
712bc5 |
(error,
|
|
Packit |
712bc5 |
GUPNP_SEARCH_CRITERIA_PARSER_ERROR,
|
|
Packit |
712bc5 |
GUPNP_SEARCH_CRITERIA_PARSER_ERROR_FAILED,
|
|
Packit |
712bc5 |
"Expected boolean value at position %u",
|
|
Packit |
712bc5 |
g_scanner_cur_position
|
|
Packit |
712bc5 |
(parser->priv->scanner));
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
ret = FALSE;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
break;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
break;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
default:
|
|
Packit |
712bc5 |
g_set_error (error,
|
|
Packit |
712bc5 |
GUPNP_SEARCH_CRITERIA_PARSER_ERROR,
|
|
Packit |
712bc5 |
GUPNP_SEARCH_CRITERIA_PARSER_ERROR_FAILED,
|
|
Packit |
712bc5 |
"Expected operator at position %u",
|
|
Packit |
712bc5 |
g_scanner_cur_position
|
|
Packit |
712bc5 |
(parser->priv->scanner));
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
ret = FALSE;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
g_free (arg1);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return ret;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
static gboolean
|
|
Packit |
712bc5 |
scan_search_exp (GUPnPSearchCriteriaParser *parser,
|
|
Packit |
712bc5 |
GError **error);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/* Scan a Logical operator and the part after that */
|
|
Packit |
712bc5 |
static gboolean
|
|
Packit |
712bc5 |
scan_logical_op (GUPnPSearchCriteriaParser *parser,
|
|
Packit |
712bc5 |
GError **error)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
gboolean ret;
|
|
Packit |
712bc5 |
guint token;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
token = g_scanner_peek_next_token (parser->priv->scanner);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
switch (token) {
|
|
Packit |
712bc5 |
case SYMBOL_AND:
|
|
Packit |
712bc5 |
g_scanner_get_next_token (parser->priv->scanner);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
g_signal_emit (parser, signals[CONJUNCTION], 0);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
ret = scan_search_exp (parser, error);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
break;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
case SYMBOL_OR:
|
|
Packit |
712bc5 |
g_scanner_get_next_token (parser->priv->scanner);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
g_signal_emit (parser, signals[DISJUNCTION], 0);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
ret = scan_search_exp (parser, error);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
break;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
default:
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
ret = TRUE;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
break;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return ret;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/* Scan a searchExp portion of a search criteria string */
|
|
Packit |
712bc5 |
static gboolean
|
|
Packit |
712bc5 |
scan_search_exp (GUPnPSearchCriteriaParser *parser,
|
|
Packit |
712bc5 |
GError **error)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
gboolean ret;
|
|
Packit |
712bc5 |
guint token;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
token = g_scanner_peek_next_token (parser->priv->scanner);
|
|
Packit |
712bc5 |
switch (token) {
|
|
Packit |
712bc5 |
case G_TOKEN_LEFT_PAREN:
|
|
Packit |
712bc5 |
g_scanner_get_next_token (parser->priv->scanner);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
g_signal_emit (parser, signals[BEGIN_PARENS], 0);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
ret = scan_search_exp (parser, error);
|
|
Packit |
712bc5 |
if (ret == FALSE)
|
|
Packit |
712bc5 |
break;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
token = g_scanner_get_next_token (parser->priv->scanner);
|
|
Packit |
712bc5 |
if (token != G_TOKEN_RIGHT_PAREN) {
|
|
Packit |
712bc5 |
g_set_error
|
|
Packit |
712bc5 |
(error,
|
|
Packit |
712bc5 |
GUPNP_SEARCH_CRITERIA_PARSER_ERROR,
|
|
Packit |
712bc5 |
GUPNP_SEARCH_CRITERIA_PARSER_ERROR_FAILED,
|
|
Packit |
712bc5 |
"Expected right parenthesis at position %u",
|
|
Packit |
712bc5 |
g_scanner_cur_position
|
|
Packit |
712bc5 |
(parser->priv->scanner));
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
ret = FALSE;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
break;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
g_signal_emit (parser, signals[END_PARENS], 0);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
ret = scan_logical_op (parser, error);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
break;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
case G_TOKEN_IDENTIFIER:
|
|
Packit |
712bc5 |
ret = scan_rel_exp (parser, error);
|
|
Packit |
712bc5 |
if (ret == FALSE)
|
|
Packit |
712bc5 |
break;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
ret = scan_logical_op (parser, error);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
break;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
default:
|
|
Packit |
712bc5 |
g_scanner_get_next_token (parser->priv->scanner);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
g_set_error (error,
|
|
Packit |
712bc5 |
GUPNP_SEARCH_CRITERIA_PARSER_ERROR,
|
|
Packit |
712bc5 |
GUPNP_SEARCH_CRITERIA_PARSER_ERROR_FAILED,
|
|
Packit |
712bc5 |
"Expected property name or left parenthesis at "
|
|
Packit |
712bc5 |
"position %u",
|
|
Packit |
712bc5 |
g_scanner_cur_position (parser->priv->scanner));
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
ret = FALSE;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return ret;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/**
|
|
Packit |
712bc5 |
* gupnp_search_criteria_parser_parse_text:
|
|
Packit |
712bc5 |
* @parser: A #GUPnPSearchCriteriaParser
|
|
Packit |
712bc5 |
* @text: The search criteria string to be parsed
|
|
Packit |
712bc5 |
* @error: The location where to store the error information if any, or NULL
|
|
Packit |
712bc5 |
*
|
|
Packit |
712bc5 |
* Parses @text, emitting the various defined signals on the way. If an
|
|
Packit |
712bc5 |
* error occured @error will be set.
|
|
Packit |
712bc5 |
*
|
|
Packit |
712bc5 |
* Return value: TRUE on success.
|
|
Packit |
712bc5 |
**/
|
|
Packit |
712bc5 |
gboolean
|
|
Packit |
712bc5 |
gupnp_search_criteria_parser_parse_text (GUPnPSearchCriteriaParser *parser,
|
|
Packit |
712bc5 |
const char *text,
|
|
Packit |
712bc5 |
GError **error)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
gboolean ret;
|
|
Packit |
712bc5 |
guint token;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
g_return_val_if_fail (GUPNP_IS_SEARCH_CRITERIA_PARSER (parser),
|
|
Packit |
712bc5 |
FALSE);
|
|
Packit |
712bc5 |
g_return_val_if_fail (text != NULL, FALSE);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/* Feed into scanner */
|
|
Packit |
712bc5 |
g_scanner_input_text (parser->priv->scanner, text, strlen (text));
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
token = g_scanner_peek_next_token (parser->priv->scanner);
|
|
Packit |
712bc5 |
if (token == SYMBOL_ASTERISK) {
|
|
Packit |
712bc5 |
g_scanner_get_next_token (parser->priv->scanner);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/* Do nothing. */
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
ret = TRUE;
|
|
Packit |
712bc5 |
} else
|
|
Packit |
712bc5 |
ret = scan_search_exp (parser, error);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
if (ret == TRUE) {
|
|
Packit |
712bc5 |
/* Confirm that we have EOF now */
|
|
Packit |
712bc5 |
token = g_scanner_get_next_token (parser->priv->scanner);
|
|
Packit |
712bc5 |
if (token != G_TOKEN_EOF) {
|
|
Packit |
712bc5 |
g_set_error
|
|
Packit |
712bc5 |
(error,
|
|
Packit |
712bc5 |
GUPNP_SEARCH_CRITERIA_PARSER_ERROR,
|
|
Packit |
712bc5 |
GUPNP_SEARCH_CRITERIA_PARSER_ERROR_FAILED,
|
|
Packit |
712bc5 |
"Expected EOF at position %u",
|
|
Packit |
712bc5 |
g_scanner_cur_position
|
|
Packit |
712bc5 |
(parser->priv->scanner));
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return ret;
|
|
Packit |
712bc5 |
}
|