EFL 1.7 svn doobies
[profile/ivi/eina.git] / src / tests / ecore_strings.c
1 #include <stdlib.h>
2 #include <string.h>
3
4 #include "Ecore_Data.h"
5
6 static void ecore_string_free_cb(void *data);
7
8 static Ecore_Hash *ecore_strings = NULL;
9 static int ecore_string_init_count = 0;
10
11 /**
12  * @defgroup Ecore_String_Group String Instance Functions
13  *
14  * These functions allow you to store one copy of a string, and use it
15  * throughout your program.
16  *
17  * This is a method to reduce the number of duplicated strings kept in
18  * memory. It's pretty common for the same strings to be dynamically
19  * allocated repeatedly between applications and libraries, especially in
20  * circumstances where you could have multiple copies of a structure that
21  * allocates the string. So rather than duplicating and freeing these
22  * strings, you request a read-only pointer to an existing string and
23  * only incur the overhead of a hash lookup.
24  *
25  * It sounds like micro-optimizing, but profiling has shown this can have
26  * a significant impact as you scale the number of copies up. It improves
27  * string creation/destruction speed, reduces memory use and decreases
28  * memory fragmentation, so a win all-around.
29  */
30
31 /**
32  * Initialize the ecore string internal structure.
33  * @return  Zero on failure, non-zero on successful initialization.
34  */
35 EAPI int
36 ecore_string_init()
37 {
38    /*
39     * No strings have been loaded at this point, so create the hash
40     * table for storing string info for later.
41     */
42    if (!ecore_string_init_count)
43      {
44         ecore_strings = ecore_hash_new(ecore_str_hash, ecore_str_compare);
45         if (!ecore_strings)
46            return 0;
47
48         ecore_hash_free_value_cb_set(ecore_strings, ecore_string_free_cb);
49      }
50
51    ecore_string_init_count++;
52
53    return 1;
54 }
55
56 /**
57  * Retrieves an instance of a string for use in an ecore program.
58  * @param   string The string to retrieve an instance of.
59  * @return  A pointer to an instance of the string on success.
60  *          @c NULL on failure.
61  * @ingroup Ecore_String_Group
62  */
63 EAPI const char *
64 ecore_string_instance(const char *string)
65 {
66    Ecore_String *str;
67
68    CHECK_PARAM_POINTER_RETURN("string", string, NULL);
69
70    /*
71     * Check for a previous instance of the string, if not found, create
72     * it.
73     */
74    str = ecore_hash_get(ecore_strings, string);
75    if (!str)
76      {
77         int length;
78
79         /*
80          * Allocate and initialize a new string reference.
81          */
82         length = strlen(string) + 1;
83
84         str =
85            (Ecore_String *)malloc(sizeof(Ecore_String) + length * sizeof(char));
86
87         str->string = (char *)(str + 1);
88         str->references = 0;
89
90         memcpy(str->string, string, length);
91
92         ecore_hash_set(ecore_strings, str->string, str);
93      }
94
95    str->references++;
96
97    return str->string;
98 }
99
100 /**
101  * Notes that the given string has lost an instance.
102  *
103  * It will free the string if no other instances are left.
104  *
105  * @param   string The given string.
106  * @ingroup Ecore_String_Group
107  */
108 EAPI void
109 ecore_string_release(const char *string)
110 {
111    Ecore_String *str;
112
113    CHECK_PARAM_POINTER("string", string);
114
115    str = ecore_hash_get(ecore_strings, (char *)string);
116    if (!str)
117       return;
118
119    str->references--;
120    if (str->references < 1)
121      {
122         ecore_hash_remove(ecore_strings, (char *)string);
123         FREE(str);
124      }
125 }
126
127 EAPI void
128 ecore_string_hash_dump_graph(void)
129 {
130    ecore_hash_dump_graph(ecore_strings);
131 }
132
133 EAPI void
134 ecore_string_hash_dump_stats(void)
135 {
136    ecore_hash_dump_stats(ecore_strings);
137 }
138
139 /**
140  * Shutdown the ecore string internal structures
141  */
142 EAPI void
143 ecore_string_shutdown()
144 {
145    --ecore_string_init_count;
146    if (!ecore_string_init_count)
147      {
148         ecore_hash_destroy(ecore_strings);
149         ecore_strings = NULL;
150      }
151 }
152
153 static void
154 ecore_string_free_cb(void *data)
155 {
156    Ecore_String *str;
157
158    str = data;
159    FREE(str);
160 }