Another example for eina_model.

Patch by: "Jonas M. Gastal" <jgastal@profusion.mobi>



SVN revision: 67832
This commit is contained in:
Jonas M. Gastal 2012-02-10 17:18:10 +00:00 committed by Gustavo Sverzut Barbieri
parent d5cbba52ef
commit 27f0f4cceb
4 changed files with 368 additions and 2 deletions

View File

@ -39,7 +39,8 @@ SRCS = \
eina_strbuf_01.c \
eina_tiler_01.c \
eina_model_01.c \
eina_model_02.c
eina_model_02.c \
eina_model_03.c
examples_PROGRAMS =
@ -77,7 +78,8 @@ examples_PROGRAMS += \
eina_str_01 \
eina_strbuf_01 \
eina_model_01 \
eina_model_02
eina_model_02 \
eina_model_03
if BUILD_TILER_EXAMPLE
AM_CPPFLAGS += @ECORE_EVAS_CFLAGS@

View File

@ -0,0 +1,7 @@
Kara Thrace starbuck@bsg.com
Sharon Valerii boomer@bsg.com
Sharon Aghaton athena@bsg.com
Karl Aghaton helo@bsg.com
Louanne Katraine kat@bsg.com
Lee Adama apolo@bsg.com

View File

@ -0,0 +1,233 @@
#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;
}

View File

@ -114,6 +114,128 @@
* @example eina_model_02.c
*/
/**
* @page eina_model_03_example_page Using Eina_Model and inheritance
* @dontinclude eina_model_03.c
*
* This example will use two custom defined eina model types: @c PERSON_TYPE to
* represent a person and @c ADDRESS_BOOK_TYPE to represent the an address book.
* Both our types inherit from EINA_MODEL_TYPE_STRUCT, and, therefore,
* store it's data on a struct. Our address book will be very simple it will
* only contain one property, the name of the file where we store our address
* book. The person type will contain two fields a name and en email. Let's look
* at the code.
*
* We'll start with declaring the variables and functions we'll need to define
* our custom type. This will all be explained when the variables get used.
* @until address_book_init
*
* We then jump into our @c main function, declare a couple of variables and
* initialize eina:
* @until eina_init
*
* After eina is initialized we'll @c address_book_init() which will initialize
* both our @c PERSON_TYPE and our @c ADDRESS_BOOK_TYPE. Details of this will be
* shown latter on:
* @until address_book_init
*
* Now that everything is correctly initialized we can create the model that
* will represent our address book's
* @until eina_model_new
*
* Before we can load data into our model we need to tell it where to load from,
* we do this by setting it's filename property:
* @until value_flush
*
* We then load data into our model and display it as a string:
* @until free
*
* While @c eina_model_to_string allows you to see the contents of the model,
* it's display format is not user friendly, it's best used for debugging. So
* let's now print our model in a user friendly way.
*
* First we see how many people are in our address book and print that:
* @until printf
*
* And now we iterate over every child of our address book model, which
* represents a person:
* @until person
*
* But again simply calling @c eina_model_to_string would result in not very
* user friendly output, so we'll need to get the properties of the person(name
* and email) and print them with some formatting:
* @until printf
*
* We then free the resources we allocated to print this person:
* @until }
*
* And that's it for our main function, now just freeing our resources:
* @until }
*
* This however obviously doesn't conclude our example we need to examine how
* the the loading of data works to really understand what is happening in the
* @c main function.
*
* Let's start with the constructors(and the variables they use). Both our
* constructors do two very important tasks:
* @li Calls our parent's constructor, and
* @li Sets the description of the struct on our model
*
* For these constructors that's all we need to do since most of our
* functionality is provided by @c EINA_MODEL_TYPE_STRUCT.
* @until }
* @until }
*
* And now we have our load function, it opens the file from which we'll
* read the address book:
* @until EINA_SAFETY_ON_NULL_RETURN_VAL
*
* Once the file has been opened we read from it line by line and for each
* non-blank line we get a name and an email:
* @until email
* @until email
*
* Once we have the name and email we create our person model, set it's
* properties and make our person a child of the address book:
* @until }
*
* And now that we're done reading the file we close it:
* @until }
*
* This next function is perphaps the most interesting one of our example, it's
* the one that creates the definition of our derived types.
*
* First thing we'll do is the description of the members of our person type.
* @until person_members[1].type
* Now the description of the struct itself(which uses the members):
* @until }
* And finally we define the person type itself:
* @until person_type.constructor
*
* With the person now described we'll do the same process for our address book
* type:
* @until address_book_type.load
*
* So far everything we created has been in the scope of our function to make
* this available outside(such as in the @c main function where we use @c
* ADDRESS_BOOK_TYPE and on @c _address_book_load function where we use @c
* PERSON_TYPE) we need to assign our descriptions and type to global variables:
* @until }
*
* This concludes this example. A good exercise for the reader is to extend this
* example to have the model save the addres book, for example once it's
* unloaded, this can be done by overriding the .unload property of @c
* ADDRESS_BOOK_TYPE.
*
* For the full code see: @ref eina_model_03_c
*/
/**
* @page eina_model_03_c eina_model_03.c
* @include eina_model_03.c
* @example eina_model_03.c
*/
/**
* @addtogroup Eina_Data_Types_Group Data Types
*
@ -149,6 +271,8 @@
*
* An inheritance example: @ref eina_model_01_c
*
* And a explained inheritance example: @ref eina_model_03_example_page
*
* @{
*/