Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /* libwapcaplet.h
  2.  *
  3.  * String internment and management tools.
  4.  *
  5.  * Copyright 2009 The NetSurf Browser Project.
  6.  *                Daniel Silverstone <dsilvers@netsurf-browser.org>
  7.  */
  8.  
  9. #ifndef libwapcaplet_h_
  10. #define libwapcaplet_h_
  11.  
  12. #ifdef __cplusplus
  13. extern "C"
  14. {
  15. #endif
  16.  
  17. #include <sys/types.h>
  18. #include <stdbool.h>
  19. #include <stdint.h>
  20.  
  21. /**
  22.  * The type of a reference counter used in libwapcaplet.
  23.  */
  24. typedef uint32_t lwc_refcounter;
  25.        
  26. /**
  27.  * The type of a hash value used in libwapcaplet.
  28.  */
  29. typedef uint32_t lwc_hash;
  30.  
  31. /**
  32.  * An interned string.
  33.  *
  34.  * NOTE: The contents of this struct are considered *PRIVATE* and may
  35.  * change in future revisions.  Do not rely on them whatsoever.
  36.  * They're only here at all so that the ref, unref and matches etc can
  37.  * use them.
  38.  */
  39. typedef struct lwc_string_s {
  40.         struct lwc_string_s **  prevptr;
  41.         struct lwc_string_s *   next;
  42.         size_t          len;
  43.         lwc_hash        hash;
  44.         lwc_refcounter  refcnt;
  45.         struct lwc_string_s *   insensitive;
  46. } lwc_string;
  47.        
  48. /**
  49.  * String iteration function
  50.  *
  51.  * @param str A string which has been interned.
  52.  * @param pw The private pointer for the allocator.
  53.  */
  54. typedef void (*lwc_iteration_callback_fn)(lwc_string *str, void *pw);
  55.  
  56. /**
  57.  * Result codes which libwapcaplet might return.
  58.  */
  59. typedef enum lwc_error_e {
  60.         lwc_error_ok            = 0,    /**< No error. */
  61.         lwc_error_oom           = 1,    /**< Out of memory. */
  62.         lwc_error_range         = 2     /**< Substring internment out of range. */
  63. } lwc_error;
  64.  
  65. /**
  66.  * Intern a string.
  67.  *
  68.  * Take a copy of the string data referred to by \a s and \a slen and
  69.  * intern it.  The resulting ::lwc_string can be used for simple and
  70.  * caseless comparisons by ::lwc_string_isequal and
  71.  * ::lwc_string_caseless_isequal respectively.
  72.  *
  73.  * @param s    Pointer to the start of the string to intern.
  74.  * @param slen Length of the string in characters. (Not including any
  75.  *             terminators)
  76.  * @param ret  Pointer to ::lwc_string pointer to fill out.
  77.  * @return     Result of operation, if not OK then the value pointed
  78.  *             to by \a ret will not be valid.
  79.  *
  80.  * @note The memory pointed to by \a s is not referenced by the result.
  81.  * @note If the string was already present, its reference count is
  82.  * incremented rather than allocating more memory.
  83.  *
  84.  * @note The returned string is currently NULL-terminated but this
  85.  *       will not necessarily be the case in future.  Try not to rely
  86.  *       on it.
  87.  */
  88. extern lwc_error lwc_intern_string(const char *s, size_t slen,
  89.                                    lwc_string **ret);
  90.  
  91. /**
  92.  * Intern a substring.
  93.  *
  94.  * Intern a subsequence of the provided ::lwc_string.
  95.  *
  96.  * @param str      String to acquire substring from.
  97.  * @param ssoffset Substring offset into \a str.
  98.  * @param sslen    Substring length.
  99.  * @param ret      Pointer to pointer to ::lwc_string to fill out.
  100.  * @return         Result of operation, if not OK then the value
  101.  *                 pointed to by \a ret will not be valid.
  102.  */
  103. extern lwc_error lwc_intern_substring(lwc_string *str,
  104.                                       size_t ssoffset, size_t sslen,
  105.                                       lwc_string **ret);
  106.  
  107. /**
  108.  * Increment the reference count on an lwc_string.
  109.  *
  110.  * This increases the reference count on the given string. You should
  111.  * use this when copying a string pointer into a persistent data
  112.  * structure.
  113.  *
  114.  * @verb
  115.  *   myobject->str = lwc_string_ref(myparent->str);
  116.  * @endverb
  117.  *
  118.  * @param str The string to create another reference to.
  119.  * @return    The string pointer to use in your new data structure.
  120.  *
  121.  * @note Use this if copying the string and intending both sides to retain
  122.  * ownership.
  123.  */
  124. #define lwc_string_ref(str) ({lwc_string *__lwc_s = (str); __lwc_s->refcnt++; __lwc_s;})
  125.  
  126. /**
  127.  * Release a reference on an lwc_string.
  128.  *
  129.  * This decreases the reference count on the given ::lwc_string.
  130.  *
  131.  * @param str The string to unref.
  132.  *
  133.  * @note If the reference count reaches zero then the string will be
  134.  *       freed. (Ref count of 1 where string is its own insensitve match
  135.  *       will also result in the string being freed.)
  136.  */
  137. #define lwc_string_unref(str) {                                         \
  138.                 lwc_string *__lwc_s = (str);                                    \
  139.                 __lwc_s->refcnt--;                                              \
  140.                 if ((__lwc_s->refcnt == 0) ||                                   \
  141.                     ((__lwc_s->refcnt == 1) && (__lwc_s->insensitive == __lwc_s)))      \
  142.                         lwc_string_destroy(__lwc_s);                            \
  143.         }
  144.        
  145. /**
  146.  * Destroy an unreffed lwc_string.
  147.  *
  148.  * This destroys an lwc_string whose reference count indicates that it should be.
  149.  *
  150.  * @param str The string to unref.
  151.  */
  152. extern void lwc_string_destroy(lwc_string *str);
  153.  
  154. /**
  155.  * Check if two interned strings are equal.
  156.  *
  157.  * @param str1 The first string in the comparison.
  158.  * @param str2 The second string in the comparison.
  159.  * @param ret  A pointer to a boolean to be filled out with the result.
  160.  * @return     Result of operation, if not ok then value pointed to
  161.  *             by \a ret will not be valid.
  162.  */
  163. #define lwc_string_isequal(str1, str2, ret) \
  164.         ((*(ret) = ((str1) == (str2))), lwc_error_ok)
  165.  
  166. /**
  167.  * Check if two interned strings are case-insensitively equal.
  168.  *
  169.  * @param str1 The first string in the comparison.
  170.  * @param str2 The second string in the comparison.
  171.  * @param ret  A pointer to a boolean to be filled out with the result.
  172.  * @return     Result of operation, if not ok then value pointed to
  173.  *             by \a ret will not be valid.
  174.  */
  175. #define lwc_string_caseless_isequal(_str1,_str2,_ret) ({        \
  176.                         lwc_error __lwc_err = lwc_error_ok;             \
  177.                         lwc_string *__lwc_str1 = (_str1);               \
  178.                         lwc_string *__lwc_str2 = (_str2);               \
  179.                         bool *__lwc_ret = (_ret);                       \
  180.                                                                 \
  181.                         if (__lwc_str1->insensitive == NULL) {          \
  182.                                 __lwc_err = lwc__intern_caseless_string(__lwc_str1); \
  183.                         }                                               \
  184.                         if (__lwc_err == lwc_error_ok && __lwc_str2->insensitive == NULL) {     \
  185.                                 __lwc_err = lwc__intern_caseless_string(__lwc_str2); \
  186.                         }                                               \
  187.                         if (__lwc_err == lwc_error_ok)                  \
  188.                                 *__lwc_ret = (__lwc_str1->insensitive == __lwc_str2->insensitive); \
  189.                         __lwc_err;                                              \
  190.                 })
  191.        
  192. /**
  193.  * Intern a caseless copy of the passed string.
  194.  *
  195.  * @param str The string to intern the caseless copy of.
  196.  *
  197.  * @return    lwc_error_ok if successful, otherwise the
  198.  *            error code describing the issue.,
  199.  *
  200.  * @note This is for "internal" use by the caseless comparison
  201.  *       macro and not for users.
  202.  */    
  203. extern lwc_error
  204. lwc__intern_caseless_string(lwc_string *str);
  205.        
  206. /**
  207.  * Retrieve the data pointer for an interned string.
  208.  *
  209.  * @param str The string to retrieve the data pointer for.
  210.  * @return    The C string data pointer for \a str.
  211.  *
  212.  * @note The data we point at belongs to the string and will
  213.  *       die with the string. Keep a ref if you need it.
  214.  * @note You may not rely on the NULL termination of the strings
  215.  *       in future.  Any code relying on it currently should be
  216.  *       modified to use ::lwc_string_length if possible.
  217.  */
  218. #define lwc_string_data(str) ((const char *)((str)+1))
  219.  
  220. /**
  221.  * Retrieve the data length for an interned string.
  222.  *
  223.  * @param str The string to retrieve the length of.
  224.  * @return    The length of \a str.
  225.  */
  226. #define lwc_string_length(str) ((str)->len)
  227.  
  228. /**
  229.  * Retrieve (or compute if unavailable) a hash value for the content of the string.
  230.  *
  231.  * @param str The string to get the hash for.
  232.  * @return    The 32 bit hash of \a str.
  233.  *
  234.  * @note This API should only be used as a convenient way to retrieve a hash
  235.  *       value for the string. This hash value should not be relied on to be
  236.  *       unique within an invocation of the program, nor should it be relied upon
  237.  *       to be stable between invocations of the program. Never use the hash
  238.  *       value as a way to directly identify the value of the string.
  239.  */
  240. #define lwc_string_hash_value(str) ((str)->hash)
  241.  
  242. /**
  243.  * Iterate the context and return every string in it.
  244.  *
  245.  * @param cb The callback to give the string to.
  246.  * @param pw The private word for the callback.
  247.  */
  248. extern void lwc_iterate_strings(lwc_iteration_callback_fn cb, void *pw);
  249.  
  250. #ifdef __cplusplus
  251. }
  252. #endif
  253.  
  254. #endif /* libwapcaplet_h_ */
  255.