efl/src/examples/eina/eina_model_03.c

237 lines
6.9 KiB
C

//Compile with:
//gcc -g eina_model_03.c -o eina_model_03 `pkg-config --cflags --libs eina`
#include <Eina.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
static Eina_Model_Type *ADDRESS_BOOK_TYPE;
static Eina_Model_Type *PERSON_TYPE;
static void address_book_init(void);
int main(void)
{
Eina_Model *address_book;
Eina_Value val;
int i, count;
char *s;
eina_init();
address_book_init();
address_book = eina_model_new(ADDRESS_BOOK_TYPE);
eina_value_setup(&val, EINA_VALUE_TYPE_STRING);
eina_value_set(&val, "addr_book.txt");
eina_model_property_set(address_book, "filename", &val);
eina_value_flush(&val);
eina_model_load(address_book);
s = eina_model_to_string(address_book);
printf("model as string:\n%s\n\n", s);
free(s);
count = eina_model_child_count(address_book);
printf("Address Book with %d entries:\n", count);
for (i = 0; i < count; i++)
{
Eina_Model *person = eina_model_child_get(address_book, i);
Eina_Value nameval, emailval;
const char *name, *email;
eina_model_property_get(person, "name", &nameval);
eina_model_property_get(person, "email", &emailval);
eina_value_get(&nameval, &name);
eina_value_get(&emailval, &email);
printf("%02d \"%s\" <%s>\n", i, name, email);
// We don't need property values anymore
eina_value_flush(&nameval);
eina_value_flush(&emailval);
// We don't need our reference to person anymore
eina_model_unref(person);
}
eina_model_unref(address_book);
eina_shutdown();
return 0;
}
// Structure Descriptions are just used internally in the type constructors:
static Eina_Value_Struct_Desc *ADDRESS_BOOK_DESC;
static Eina_Value_Struct_Desc *PERSON_DESC;
static Eina_Bool
_person_constructor(Eina_Model *model)
{
// call parent type constructor, like "super" in other languages:
if (!eina_model_type_constructor(EINA_MODEL_TYPE_STRUCT, model))
return EINA_FALSE;
// Do specific setup of our internal structure, letting it know about
// our description
return eina_model_struct_set(model, PERSON_DESC, NULL);
}
static Eina_Bool
_address_book_constructor(Eina_Model *model)
{
// call parent type constructor, like "super" in other languages:
if (!eina_model_type_constructor(EINA_MODEL_TYPE_STRUCT, model))
return EINA_FALSE;
// Do specific setup of our internal structure, letting it know about
// our description
return eina_model_struct_set(model, ADDRESS_BOOK_DESC, NULL);
}
static Eina_Bool
_address_book_load(Eina_Model *model)
{
const char *filename;
Eina_Value val;
char buf[256];
FILE *f;
// We retrieve filename from property of same name:
eina_model_property_get(model, "filename", &val);
eina_value_get(&val, &filename);
EINA_SAFETY_ON_NULL_RETURN_VAL(filename, EINA_FALSE);
f = fopen(filename, "r");
// Now that we have used filename, we must free its memory holder:
eina_value_flush(&val);
EINA_SAFETY_ON_NULL_RETURN_VAL(f, EINA_FALSE);
while (fgets(buf, sizeof(buf), f))
{
Eina_Model *person;
char *name, *email;
if (strlen(buf) <= 1)
continue;
name = strtok(buf, "\t");
email = strtok(NULL, "\n");
if ((!name) || (!email)) continue;
// Create person
person = eina_model_new(PERSON_TYPE);
// Setup value type as string, as our properties are strings:
eina_value_setup(&val, EINA_VALUE_TYPE_STRING);
// Set string properties:
eina_value_set(&val, name);
eina_model_property_set(person, "name", &val);
eina_value_set(&val, email);
eina_model_property_set(person, "email", &val);
// Flush value, free string
eina_value_flush(&val);
// Add person to the end of model children
eina_model_child_append(model, person);
// Model already holds its reference to person, we release ours
eina_model_unref(person);
}
fclose(f);
return EINA_TRUE;
}
static void
address_book_init(void)
{
// Declare type for internal struct, this is just used to easily
// create Eina_Value_Struct_Member array for Eina_Value_Struct_Desc.
//
// We don't need this structure outside address_book_init()
// as it is managed automatically by Eina_Value_Struct, used by
// Eina_Model_Struct! Handy! :-)
typedef struct _Person Person;
struct _Person
{
const char *name;
const char *email;
};
static Eina_Value_Struct_Member person_members[] = {
// no eina_value_type as they are not constant initializers, see below.
EINA_VALUE_STRUCT_MEMBER(NULL, Person, name),
EINA_VALUE_STRUCT_MEMBER(NULL, Person, email)
};
// Values that cannot be set on static declarations since they are not
// constant initializers. It is a nitpick from C that we need to deal with
// here and on all our other declarations.
person_members[0].type = EINA_VALUE_TYPE_STRING;
person_members[1].type = EINA_VALUE_TYPE_STRING;
static Eina_Value_Struct_Desc person_desc = {
EINA_VALUE_STRUCT_DESC_VERSION,
NULL, // no special operations
person_members,
EINA_C_ARRAY_LENGTH(person_members),
sizeof(Person)
};
static Eina_Model_Type person_type = EINA_MODEL_TYPE_INIT_NOPRIVATE
("Person_Type",
Eina_Model_Type,
NULL, // no type as EINA_MODEL_TYPE_STRUCT is not constant initializer!
NULL, // no extra interfaces
NULL // no extra events);
);
person_type.parent = EINA_MODEL_TYPE_STRUCT;
// Set our overloaded methods:
person_type.constructor = _person_constructor;
typedef struct _Address_Book Address_Book;
struct _Address_Book
{
const char *filename;
};
static Eina_Value_Struct_Member address_book_members[] = {
// no eina_value_type as they are not constant initializers, see below.
EINA_VALUE_STRUCT_MEMBER(NULL, Address_Book, filename)
};
address_book_members[0].type = EINA_VALUE_TYPE_STRING;
static Eina_Value_Struct_Desc address_book_desc = {
EINA_VALUE_STRUCT_DESC_VERSION,
NULL, // no special operations
address_book_members,
EINA_C_ARRAY_LENGTH(address_book_members),
sizeof(Address_Book)
};
static Eina_Model_Type address_book_type = EINA_MODEL_TYPE_INIT_NOPRIVATE
("Address_Book_Type",
Eina_Model_Type,
NULL, // no type as EINA_MODEL_TYPE_STRUCT is not constant initializer!
NULL, // no extra interfaces
NULL // no extra events);
);
address_book_type.parent = EINA_MODEL_TYPE_STRUCT;
// Set our overloaded methods:
address_book_type.constructor = _address_book_constructor;
address_book_type.load = _address_book_load;
// Expose the configured pointers to public usage:
// NOTE: they are static, so they live after this function returns!
PERSON_TYPE = &person_type;
PERSON_DESC = &person_desc;
ADDRESS_BOOK_TYPE = &address_book_type;
ADDRESS_BOOK_DESC = &address_book_desc;
}