1 /* EINA - EFL data type library 2 * Copyright (C) 2002-2008 Carsten Haitzler, Jorge Luis Zapata Muga, Cedric Bail 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; 16 * if not, see <http://www.gnu.org/licenses/>. 17 * 18 * This file incorporates work covered by the following copyright and 19 * permission notice: 20 * 21 * Copyright (C) 2008 Peter Wehrfritz 22 * 23 * Permission is hereby granted, free of charge, to any person obtaining a copy 24 * of this software and associated documentation files (the "Software"), to 25 * deal in the Software without restriction, including without limitation the 26 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 27 * sell copies of the Software, and to permit persons to whom the Software is 28 * furnished to do so, subject to the following conditions: 29 * 30 * The above copyright notice and this permission notice shall be included in 31 * all copies of the Software and its Copyright notices. In addition publicly 32 * documented acknowledgment must be given that this software has been used if no 33 * source code of this software is made available publicly. This includes 34 * acknowledgments in either Copyright notices, Manuals, Publicity and Marketing 35 * documents or any documentation provided with any product containing this 36 * software. This License does not apply to any software that links to the 37 * libraries provided by this software (statically or dynamically), but only to 38 * the software provided. 39 * 40 * Please see the OLD-COPYING.PLAIN for a plain-english explanation of this notice 41 * and it's intent. 42 * 43 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 44 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 45 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 46 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 47 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 48 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 49 */ 50 51 #ifndef EINA_STRINGSHARE_H_ 52 #define EINA_STRINGSHARE_H_ 53 54 #include <stdarg.h> 55 56 #include "eina_types.h" 57 #include "eina_slice.h" 58 59 /** 60 * @page eina_stringshare_example_01_page 61 * @dontinclude eina_stringshare_01.c 62 * 63 * Like all examples we start by including Eina: 64 * @skip #include 65 * @line #include 66 * 67 * Here we declare some variables and initialize eina: 68 * @until eina_init 69 * 70 * We start the substantive part of the example by showing how to make a part 71 * of a string shared and how to get the length of a shared string: 72 * @until stringshare_strlen 73 * As we add shared strings we also need to delete them when done using them: 74 * @line del 75 * 76 * There are many ways of creating shared strings including an equivalent to 77 * sprintf: 78 * @until del 79 * 80 * An equivalent to snprintf: 81 * @until printf 82 * 83 * But the simplest way of creating a shared string is through 84 * eina_stringshare_add(): 85 * @until printf 86 * 87 * Sometimes you already have a pointer to a shared string and want to use it, 88 * so to make sure the provider of the pointer won't free it while you're using 89 * it you can increase the shared string's ref count: 90 * @until printf 91 * 92 * Whenever you have a pointer to a shared string and would like to change it's 93 * value you should use eina_stringshare_replace(): 94 * @until printf 95 * @warning @b Don't use eina_stringshare_del() followed by 96 * eina_share_common_add(), under some circumstances you might end up deleting 97 * a shared string some other piece of code is using. 98 * 99 * We created str but haven't deleted it yet, and while we called 100 * eina_stringshare_del() on str2, we created it and then increased the ref 101 * count so it's still alive: 102 * @until str2 103 * 104 * You can see the full source code @ref eina_stringshare_example_01 "here". 105 */ 106 /** 107 * @page eina_stringshare_example_01 108 * @include eina_stringshare_01.c 109 * @example eina_stringshare_01.c 110 */ 111 /** 112 * @addtogroup Eina_Stringshare_Group Stringshare 113 * 114 * These functions allow you to store a single copy of a string, and use in 115 * multiple places throughout your program. 116 * 117 * This is a method to reduce the number of duplicated strings kept in 118 * memory. It's pretty common for the same strings to be dynamically 119 * allocated repeatedly between applications and libraries, especially in 120 * circumstances where you could have multiple copies of a structure that 121 * allocates the string. So rather than duplicating and freeing these 122 * strings, you request a read-only pointer to an existing string and 123 * only incur the overhead of a hash lookup. 124 * 125 * It sounds like micro-optimizing, but profiling has shown this can have 126 * a significant impact as you scale the number of copies up. It improves 127 * string creation/destruction speed, reduces memory use and decreases 128 * memory fragmentation, so a win all-around. 129 * 130 * Using eina stringshares usually boils down to: 131 * @code 132 * const char *str = eina_stringshare_add("My string"); 133 * ... 134 * //Use str 135 * ... 136 * eina_stringshare_del(str); 137 * @endcode 138 * @note It's very important to note that string shares are @b @c const, 139 * changing them will result in undefined behavior. 140 * @note eina_stringshare_del() @b doesn't guarantee the string share will be 141 * freed, it releases a reference to it, but if other references to it still 142 * exist the string share will live until those are released. 143 * 144 * The following diagram gives an idea of what happens as you create strings 145 * with eina_stringshare_add(): 146 * 147 * @image html eina_stringshare.png 148 * @image latex eina_stringshare.eps "" height=\textheight 149 * 150 * For more information, see @ref eina_stringshare_example_01_page 151 * "this example". 152 */ 153 154 /** 155 * @addtogroup Eina_Data_Types_Group Data Types 156 * 157 * @{ 158 */ 159 160 /** 161 * @defgroup Eina_Stringshare_Group Stringshare 162 * 163 * @{ 164 */ 165 166 /** 167 * @typedef Eina_Stringshare 168 * 169 * "Eina_Stringshare *" is interchangeable with "const char *" but still a good 170 * visual hint for the purpose. Maybe in the far far future we'll even add 171 * strict type checking. 172 * 173 * @since 1.2.0 174 */ 175 typedef const char Eina_Stringshare; 176 177 /** 178 * @brief Retrieves an instance of a string with a specific size for use in a 179 * program. 180 * 181 * @param[in] str The string to retrieve an instance of. 182 * @param[in] slen The string size (<= strlen(str)). 183 * @return A pointer to an instance of the string on success, 184 * @c NULL on failure. 185 * 186 * This function retrieves an instance of @p str. If @p str is 187 * @c NULL, then @c NULL is returned. If @p str is already stored, it 188 * is just returned and its reference counter is increased. Otherwise 189 * a duplicated string of @p str is returned. 190 * 191 * This function does not check string size, but uses the 192 * exact given size. This can be used to share_common part of a larger 193 * buffer or substring. 194 * 195 * @see eina_share_common_add() 196 */ 197 EAPI Eina_Stringshare *eina_stringshare_add_length(const char *str, unsigned int slen) EINA_WARN_UNUSED_RESULT; 198 199 /** 200 * @brief Retrieves an instance of a string for use in a program. 201 * 202 * @param[in] str The NULL-terminated string to retrieve an instance of. 203 * @return A pointer to an instance of the string on success, 204 * @c NULL on failure. 205 * 206 * This function retrieves an instance of @p str. If @p str is 207 * @c NULL, then @c NULL is returned. If @p str is already stored, it 208 * is just returned and its reference counter is increased. Otherwise 209 * a duplicated string of @p str is returned. 210 * 211 * The string @p str must be NULL terminated ('@\0') and its full 212 * length will be used. To use part of the string or non-null 213 * terminated, use eina_stringshare_add_length() instead. 214 * 215 * @see eina_stringshare_add_length() 216 */ 217 EAPI Eina_Stringshare *eina_stringshare_add(const char *str) EINA_WARN_UNUSED_RESULT; 218 219 /** 220 * @brief Retrieves an instance of a string for use in a program 221 * from a format string. 222 * 223 * @param[in] fmt The NULL-terminated format string to retrieve an instance of. 224 * @return A pointer to an instance of the string on success, 225 * @c NULL on failure. 226 * 227 * This function retrieves an instance of @p fmt. If @p fmt is 228 * @c NULL, then @c NULL is returned. If @p fmt is already stored, it 229 * is just returned and its reference counter is increased. Otherwise 230 * a duplicated string is returned. 231 * 232 * The format string @p fmt must be NULL-terminated ('@\0') and its full 233 * length will be used. To use part of the format string or non-null 234 * terminated, use eina_stringshare_nprintf() instead. 235 * 236 * @see eina_stringshare_nprintf() 237 */ 238 EAPI Eina_Stringshare *eina_stringshare_printf(const char *fmt, ...) EINA_WARN_UNUSED_RESULT EINA_PRINTF(1, 2); 239 240 /** 241 * @brief Retrieves an instance of a string for use in a program 242 * from a format string. 243 * 244 * @param[in] fmt The NULL-terminated format string to retrieve an instance of. 245 * @param[in] args The va_args for @p fmt 246 * @return A pointer to an instance of the string on success, 247 * @c NULL on failure. 248 * 249 * This function retrieves an instance of @p fmt with @p args. If @p fmt is 250 * @c NULL, then @c NULL is returned. If @p fmt with @p args is already stored, it 251 * is just returned and its reference counter is increased. Otherwise 252 * a duplicated string is returned. 253 * 254 * The format string @p fmt must be NULL-terminated ('@\0') and its full 255 * length will be used. To use part of the format string or non-null 256 * terminated, use eina_stringshare_nprintf() instead. 257 * 258 * @see eina_stringshare_nprintf() 259 */ 260 EAPI Eina_Stringshare *eina_stringshare_vprintf(const char *fmt, va_list args) EINA_WARN_UNUSED_RESULT; 261 262 /** 263 * @brief Retrieves an instance of a string for use in a program 264 * from a format string with size limitation. 265 * 266 * @param[in] len The length of the format string to use 267 * @param[in] fmt The format string to retrieve an instance of. 268 * @return A pointer to an instance of the string on success, 269 * @c NULL on failure. 270 * 271 * This function retrieves an instance of @p fmt limited by @p len. If @p fmt is 272 * @c NULL or @p len is < 1, then @c NULL is returned. If the resulting string 273 * is already stored, it is returned and its reference counter is increased. 274 * Otherwise a duplicated string is returned. 275 * 276 * @p len length of the format string will be used. To use the 277 * entire format string, use eina_stringshare_printf() instead. 278 * 279 * @see eina_stringshare_printf() 280 */ 281 EAPI Eina_Stringshare *eina_stringshare_nprintf(unsigned int len, const char *fmt, ...) EINA_WARN_UNUSED_RESULT EINA_PRINTF(2, 3); 282 283 /** 284 * Increment references of the given shared string. 285 * 286 * @param[in,out] str The shared string. 287 * @return A pointer to an instance of the string on success, 288 * @c NULL on failure. 289 * 290 * This is similar to eina_share_common_add(), but it's faster since it will 291 * avoid lookups if possible, but on the down side it requires the parameter 292 * to be shared string. In other words, it must be the return of a previous 293 * call to one of the stringshare functions. 294 * 295 * There is no unref since this is the work of eina_share_common_del(). 296 */ 297 EAPI Eina_Stringshare *eina_stringshare_ref(Eina_Stringshare *str); 298 299 /** 300 * @brief Notes that the given string has lost an instance. 301 * 302 * @param[in,out] str String the given string. 303 * 304 * This function decreases the reference counter associated to @p str 305 * if it exists. If that counter reaches 0, the memory associated to 306 * @p str is freed. If @p str is @c NULL, the function returns 307 * immediately. 308 * 309 * @note If the given pointer is not shared, bad things will happen, likely a 310 * segmentation fault. 311 */ 312 EAPI void eina_stringshare_del(Eina_Stringshare *str); 313 314 /** 315 * @brief Notes that the given string @b must be shared. 316 * 317 * @param[in] str The shared string to know the length. It is safe to 318 * give @c NULL, in that case @c 0 is returned. 319 * @return The length of a shared string. 320 * 321 * This function is a cheap way to known the length of a shared 322 * string. 323 * 324 * @note If the given pointer is not shared, bad things will happen, likely a 325 * segmentation fault. If in doubt, try strlen(). 326 */ 327 EAPI int eina_stringshare_strlen(Eina_Stringshare *str) EINA_PURE EINA_WARN_UNUSED_RESULT; 328 329 /** 330 * @brief Dumps the contents of the share_common. 331 * 332 * This function dumps all strings in the share_common to stdout with a 333 * DDD: prefix per line and a memory usage summary. 334 */ 335 EAPI void eina_stringshare_dump(void); 336 337 static inline Eina_Bool eina_stringshare_replace(Eina_Stringshare **p_str, const char *news) EINA_ARG_NONNULL(1); 338 static inline Eina_Bool eina_stringshare_replace_length(Eina_Stringshare **p_str, const char *news, unsigned int slen) EINA_ARG_NONNULL(1); 339 340 static inline Eina_Slice eina_stringshare_slice_get(Eina_Stringshare *str) EINA_PURE EINA_WARN_UNUSED_RESULT; 341 342 #include "eina_inline_stringshare.x" 343 344 /** 345 * @} 346 */ 347 348 /** 349 * @} 350 */ 351 352 #endif /* EINA_STRINGSHARE_H_ */ 353