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