Alien-SVN
view release on metacpan or search on metacpan
src/subversion/subversion/libsvn_subr/utf.c view on Meta::CPAN
#include <apr_xlate.h>
#include <apr_atomic.h>
#include "svn_hash.h"
#include "svn_string.h"
#include "svn_error.h"
#include "svn_pools.h"
#include "svn_ctype.h"
#include "svn_utf.h"
#include "svn_private_config.h"
#include "win32_xlate.h"
#include "private/svn_utf_private.h"
#include "private/svn_dep_compat.h"
#include "private/svn_string_private.h"
#include "private/svn_mutex.h"
/* Use these static strings to maximize performance on standard conversions.
* Any strings on other locations are still valid, however.
*/
static const char *SVN_UTF_NTOU_XLATE_HANDLE = "svn-utf-ntou-xlate-handle";
static const char *SVN_UTF_UTON_XLATE_HANDLE = "svn-utf-uton-xlate-handle";
static const char *SVN_APR_UTF8_CHARSET = "UTF-8";
static svn_mutex__t *xlate_handle_mutex = NULL;
static svn_boolean_t assume_native_charset_is_utf8 = FALSE;
/* The xlate handle cache is a global hash table with linked lists of xlate
* handles. In multi-threaded environments, a thread "borrows" an xlate
* handle from the cache during a translation and puts it back afterwards.
* This avoids holding a global lock for all translations.
* If there is no handle for a particular key when needed, a new is
* handle is created and put in the cache after use.
* This means that there will be at most N handles open for a key, where N
* is the number of simultanous handles in use for that key. */
typedef struct xlate_handle_node_t {
apr_xlate_t *handle;
/* FALSE if the handle is not valid, since its pool is being
destroyed. */
svn_boolean_t valid;
/* The name of a char encoding or APR_LOCALE_CHARSET. */
const char *frompage, *topage;
struct xlate_handle_node_t *next;
} xlate_handle_node_t;
/* This maps const char * userdata_key strings to xlate_handle_node_t **
handles to the first entry in the linked list of xlate handles. We don't
store the pointer to the list head directly in the hash table, since we
remove/insert entries at the head in the list in the code below, and
we can't use apr_hash_set() in each character translation because that
function allocates memory in each call where the value is non-NULL.
Since these allocations take place in a global pool, this would be a
memory leak. */
static apr_hash_t *xlate_handle_hash = NULL;
/* "1st level cache" to standard conversion maps. We may access these
* using atomic xchange ops, i.e. without further thread synchronization.
* If the respective item is NULL, fallback to hash lookup.
*/
static void * volatile xlat_ntou_static_handle = NULL;
static void * volatile xlat_uton_static_handle = NULL;
/* Clean up the xlate handle cache. */
static apr_status_t
xlate_cleanup(void *arg)
{
/* We set the cache variables to NULL so that translation works in other
cleanup functions, even if it isn't cached then. */
xlate_handle_hash = NULL;
/* ensure no stale objects get accessed */
xlat_ntou_static_handle = NULL;
xlat_uton_static_handle = NULL;
return APR_SUCCESS;
}
/* Set the handle of ARG to NULL. */
static apr_status_t
xlate_handle_node_cleanup(void *arg)
{
xlate_handle_node_t *node = arg;
node->valid = FALSE;
return APR_SUCCESS;
}
void
svn_utf_initialize2(svn_boolean_t assume_native_utf8,
apr_pool_t *pool)
{
if (!xlate_handle_hash)
{
/* We create our own subpool, which we protect with the mutex.
We can't use the pool passed to us by the caller, since we will
use it for xlate handle allocations, possibly in multiple threads,
and pool allocation is not thread-safe. */
apr_pool_t *subpool = svn_pool_create(pool);
svn_mutex__t *mutex;
svn_error_t *err = svn_mutex__init(&mutex, TRUE, subpool);
if (err)
{
svn_error_clear(err);
return;
}
xlate_handle_mutex = mutex;
xlate_handle_hash = apr_hash_make(subpool);
apr_pool_cleanup_register(subpool, NULL, xlate_cleanup,
apr_pool_cleanup_null);
}
if (!assume_native_charset_is_utf8)
assume_native_charset_is_utf8 = assume_native_utf8;
}
( run in 0.490 second using v1.01-cache-2.11-cpan-d7f47b0818f )