summaryrefslogtreecommitdiff
path: root/sal/rtl
diff options
context:
space:
mode:
Diffstat (limited to 'sal/rtl')
-rw-r--r--sal/rtl/source/alloc.c1541
-rw-r--r--sal/rtl/source/alloc_arena.c1396
-rw-r--r--sal/rtl/source/alloc_arena.h137
-rw-r--r--sal/rtl/source/alloc_cache.c1721
-rw-r--r--sal/rtl/source/alloc_cache.h182
-rw-r--r--sal/rtl/source/alloc_global.c357
-rw-r--r--sal/rtl/source/alloc_impl.h247
-rw-r--r--sal/rtl/source/bootstrap.cxx1059
-rw-r--r--sal/rtl/source/byteseq.c254
-rw-r--r--sal/rtl/source/cipher.c1363
-rw-r--r--sal/rtl/source/cmdargs.cxx109
-rw-r--r--sal/rtl/source/crc.c164
-rw-r--r--sal/rtl/source/debugprint.cxx58
-rw-r--r--sal/rtl/source/digest.c2118
-rw-r--r--sal/rtl/source/gen_makefile.cxx41
-rw-r--r--sal/rtl/source/hash.cxx113
-rw-r--r--sal/rtl/source/hash.h21
-rw-r--r--sal/rtl/source/locale.c362
-rw-r--r--sal/rtl/source/logfile.cxx254
-rw-r--r--sal/rtl/source/macro.hxx110
-rw-r--r--sal/rtl/source/makefile.mk198
-rw-r--r--sal/rtl/source/math.cxx1265
-rw-r--r--sal/rtl/source/memory.c62
-rwxr-xr-xsal/rtl/source/memory_fini.cxx54
-rw-r--r--sal/rtl/source/random.c338
-rw-r--r--sal/rtl/source/rtl_process.c49
-rw-r--r--sal/rtl/source/strbuf.c147
-rw-r--r--sal/rtl/source/strimp.c58
-rw-r--r--sal/rtl/source/strimp.h64
-rw-r--r--sal/rtl/source/string.c320
-rw-r--r--sal/rtl/source/strtmpl.c1567
-rw-r--r--sal/rtl/source/surrogates.h50
-rw-r--r--sal/rtl/source/tres.c686
-rw-r--r--sal/rtl/source/unload.cxx417
-rw-r--r--sal/rtl/source/uri.cxx799
-rw-r--r--sal/rtl/source/ustrbuf.c208
-rw-r--r--sal/rtl/source/ustring.c934
-rw-r--r--sal/rtl/source/uuid.cxx180
38 files changed, 19003 insertions, 0 deletions
diff --git a/sal/rtl/source/alloc.c b/sal/rtl/source/alloc.c
new file mode 100644
index 000000000000..44b37c255004
--- /dev/null
+++ b/sal/rtl/source/alloc.c
@@ -0,0 +1,1541 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifdef PROFILE
+#undef OSL_DEBUG_LEVEL
+#define OSL_DEBUG_LEVEL 0
+#endif /* PROFILE */
+
+#include <sal/types.h>
+#include <osl/diagnose.h>
+#include <rtl/alloc.h>
+
+#ifndef INCLUDED_STDDEF_H
+#include <stddef.h>
+#define INCLUDED_STDDEF_H
+#endif
+
+#ifndef INCLUDED_STDLIB_H
+#include <stdlib.h>
+#define INCLUDED_STDLIB_H
+#endif
+
+#ifndef INCLUDED_STRING_H
+#include <string.h>
+#define INCLUDED_STRING_H
+#endif
+
+#ifndef FORCE_SYSALLOC
+
+/*===========================================================================
+ *
+ * rtl_memory (UNX) internals.
+ *
+ *=========================================================================*/
+#ifdef SAL_UNX
+
+#include <unistd.h>
+#include <pthread.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+
+typedef pthread_mutex_t mutex_type;
+
+#define RTL_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+#define RTL_MUTEX_ACQUIRE(a) pthread_mutex_lock((a))
+#define RTL_MUTEX_RELEASE(a) pthread_mutex_unlock((a))
+
+#if defined(FREEBSD) || defined(NETBSD) || defined(MACOSX)
+static sal_Size __rtl_memory_vmpagesize (void)
+{
+ /* xBSD */
+ return (sal_Size)(getpagesize());
+}
+#elif defined(LINUX) || defined(SOLARIS)
+static sal_Size __rtl_memory_vmpagesize (void)
+{
+ /* POSIX */
+ return (sal_Size)(sysconf(_SC_PAGESIZE));
+}
+#else
+static sal_Size __rtl_memory_vmpagesize (void)
+{
+ /* other */
+ return (sal_Size)(0x2000);
+}
+#endif /* FREEBSD || NETBSD || MACOSX || LINUX || SOLARIS */
+
+#ifndef PROT_HEAP
+#define PROT_HEAP (PROT_READ | PROT_WRITE | PROT_EXEC)
+#endif
+
+/* #95880# building on Solaris 8 provides MAP_ANON, but it
+ is not available on Solaris 7 */
+#if defined (SOLARIS)
+#ifdef MAP_ANON
+#undef MAP_ANON
+#endif
+#endif
+
+#ifndef MAP_ANON
+static void* __rtl_memory_vmalloc (sal_Size n)
+{
+ /* SYSV */
+ int fd = open("/dev/zero", O_RDWR);
+ if (!(fd < 0))
+ {
+ void * p = mmap(NULL, n, PROT_HEAP, MAP_PRIVATE, fd, 0);
+ close(fd);
+ return ((p == MAP_FAILED) ? NULL : p);
+ }
+ return (NULL);
+}
+#else /* MAP_ANON */
+static void* __rtl_memory_vmalloc (sal_Size n)
+{
+ /* xBSD */
+ void * p = mmap(NULL, n, PROT_HEAP, MAP_PRIVATE | MAP_ANON, -1, 0);
+ return ((p == MAP_FAILED) ? NULL : p);
+}
+#endif /* MAP_ANON */
+
+#define RTL_MEMORY_ALLOC(n) __rtl_memory_vmalloc((sal_Size)(n))
+#define RTL_MEMORY_FREE(p, n) munmap((void*)(p), (sal_Size)(n))
+
+#endif /* SAL_UNX */
+
+/*===========================================================================
+ *
+ * rtl_memory (W32) internals.
+ *
+ *=========================================================================*/
+#ifdef SAL_W32
+
+#define WIN32_LEAN_AND_MEAN
+#ifdef _MSC_VER
+#pragma warning(push,1) /* disable warnings within system headers */
+#endif
+#include <windows.h>
+#include <wchar.h>
+
+typedef CRITICAL_SECTION mutex_type;
+
+/* Static initializer (struct declared in WINNT.H). */
+#define RTL_MUTEX_INITIALIZER { NULL, -1, 0, NULL, NULL, 0 }
+
+/*
+ * __rtl_mutex_init (dynamic initialization).
+ *
+ * Static initialization (with DebugInfo == NULL)
+ * leads to Access Violation upon first contention.
+ */
+static void __rtl_mutex_init (LPCRITICAL_SECTION lpCriticalSection)
+{
+ static LONG g_spinlock = 0;
+
+ while (InterlockedExchange (&g_spinlock, 1) == 1)
+ {
+ /* Already locked, spin */
+ Sleep (0);
+ }
+ if (!(lpCriticalSection->DebugInfo))
+ {
+ /* Dynamic initialization */
+ InitializeCriticalSection (lpCriticalSection);
+ }
+ InterlockedExchange (&g_spinlock, 0);
+}
+
+#define RTL_MUTEX_INIT(a) __rtl_mutex_init((LPCRITICAL_SECTION)(a))
+#define RTL_MUTEX_ACQUIRE(a) EnterCriticalSection((a))
+#define RTL_MUTEX_RELEASE(a) LeaveCriticalSection((a))
+
+static sal_Size __rtl_memory_vmpagesize (void)
+{
+ SYSTEM_INFO info;
+ GetSystemInfo (&info);
+ return ((sal_Size)(info.dwPageSize));
+}
+
+#define RTL_MEMORY_ALLOC(n) \
+(void*)(VirtualAlloc (NULL, (SIZE_T)(n), MEM_COMMIT, PAGE_READWRITE))
+
+#define RTL_MEMORY_FREE(p, n) \
+(void)(VirtualFree ((LPVOID)(p), (SIZE_T)(0), MEM_RELEASE))
+
+#endif /* SAL_W32 */
+
+/*===========================================================================
+ *
+ * rtl_memory (OS2) internals.
+ *
+ *=========================================================================*/
+#ifdef SAL_OS2
+
+#define INCL_DOS
+#include <os2.h>
+
+typedef HMTX mutex_type;
+
+/* Static initializer */
+#define RTL_MUTEX_INITIALIZER -1
+
+/*
+ * __rtl_mutex_init (dynamic initialization).
+ *
+ * Static initialization (with DebugInfo == NULL)
+ * leads to Access Violation upon first contention.
+ */
+static void __rtl_mutex_init (mutex_type* mutex)
+{
+ APIRET rc = 0;
+
+ rc = DosCreateMutexSem(NULL,mutex,0,0);
+
+}
+
+static int __rtl_mutex_destroy (mutex_type* mutex)
+{
+ APIRET rc = 0;
+
+
+ do {
+ rc = DosCloseMutexSem(*mutex);
+ if (rc == 301) DosReleaseMutexSem(*mutex);
+ } while (rc == 301);
+
+ *mutex = 0;
+
+ /* Return the completion status: */
+ return (0);
+}
+
+
+static int __rtl_mutex_acquire(mutex_type* mutex)
+{
+ int ret = 0;
+ int status = 0;
+ APIRET rc = 0;
+
+ // initialize static semaphores created with PTHREAD_MUTEX_INITIALIZER state.
+ if (*mutex == -1)
+ __rtl_mutex_init( mutex);
+
+ rc = DosRequestMutexSem(*mutex,SEM_INDEFINITE_WAIT);
+ if (rc)
+ return(1);
+
+ /* Return the completion status: */
+ return (0);
+}
+
+static int __rtl_mutex_release(mutex_type* mutex)
+{
+ int ret = 0;
+ APIRET rc = 0;
+ int status;
+
+
+ // initialize static semaphores created with PTHREAD_MUTEX_INITIALIZER state.
+ if (*mutex == -1)
+ __rtl_mutex_init( mutex);
+
+ rc = DosReleaseMutexSem(*mutex);
+
+ /* Return the completion status: */
+ return (0);
+}
+
+#define RTL_MUTEX_INIT(a) __rtl_mutex_init((mutex_type*)(a))
+#define RTL_MUTEX_ACQUIRE(a) __rtl_mutex_acquire((mutex_type*)(a))
+#define RTL_MUTEX_RELEASE(a) __rtl_mutex_release((mutex_type*)(a))
+
+static sal_Size __rtl_memory_vmpagesize (void)
+{
+ return (sal_Size)(getpagesize());
+}
+
+#define RTL_MEMORY_ALLOC(n) (void*)(malloc(n))
+
+#define RTL_MEMORY_FREE(p, n) (void)(free(p))
+
+#endif /* SAL_OS2 */
+
+/*===========================================================================
+ *
+ * rtl_memory (global) internals.
+ *
+ *=========================================================================*/
+#define __L__ 32
+#define __P__ 24
+#define __N__ ((__L__) + (__P__))
+#define __M__ 0x10000
+
+static const sal_Size __T__ = (__M__) * 2 / 3;
+
+typedef struct __rtl_memory_desc_st memory_type;
+struct __rtl_memory_desc_st
+{
+ sal_Size m_length;
+ sal_Size m_offset;
+ memory_type *m_flink;
+ memory_type *m_blink;
+};
+
+static const int __C__ = 2 * sizeof(sal_Size);
+static const int __Q__ = 2 * sizeof(memory_type*);
+
+typedef struct __rtl_memory_stat_st memory_stat;
+struct __rtl_memory_stat_st
+{
+ sal_uInt64 m_dequeue;
+ sal_uInt64 m_enqueue;
+ sal_Int32 m_delta_q;
+
+ sal_uInt64 m_deqsize;
+ sal_uInt64 m_enqsize;
+ sal_Int32 m_delta_n;
+};
+
+#define RTL_MEMORY_ALIGN(n, m) (((n) + ((m) - 1)) & ~((m) - 1))
+#define RTL_MEMORY_SIZEOF(a) RTL_MEMORY_ALIGN(sizeof(a), sizeof(memory_type))
+
+struct __rtl_memory_global_st
+{
+ sal_Size m_magic;
+ sal_Size m_align;
+
+ union {
+ mutex_type m_lock;
+ char m_data[RTL_MEMORY_SIZEOF(mutex_type)];
+ } m_mutex;
+
+ memory_type m_alloc_head;
+ memory_type m_spare_head;
+ memory_type m_queue_head[__N__];
+
+#if OSL_DEBUG_LEVEL > 0
+ memory_stat m_queue_stat[__N__];
+#endif /* OSL_DEBUG_LEVEL */
+};
+
+static struct __rtl_memory_global_st g_memory =
+{
+ 0, 0, { RTL_MUTEX_INITIALIZER },
+ { 0, 0, NULL, NULL }, { 0, 0, NULL, NULL }, { { 0, 0, NULL, NULL } },
+#if OSL_DEBUG_LEVEL > 0
+ { { 0, 0, 0, 0, 0, 0 } }
+#endif /* OSL_DEBUG_LEVEL */
+};
+
+void SAL_CALL ___rtl_memory_init (void);
+void SAL_CALL ___rtl_memory_fini (void);
+
+#define RTL_MEMORY_ENTER() \
+{ \
+ if (!(g_memory.m_align)) ___rtl_memory_init(); \
+ RTL_MUTEX_ACQUIRE(&(g_memory.m_mutex.m_lock)); \
+}
+
+#define RTL_MEMORY_LEAVE() \
+{ \
+ RTL_MUTEX_RELEASE(&(g_memory.m_mutex.m_lock)); \
+}
+
+/*===========================================================================
+ *
+ * rtl_memory (queue) internals.
+ *
+ *=========================================================================*/
+#if defined(PROFILE) || (OSL_DEBUG_LEVEL > 0)
+static sal_Size queue (sal_Size n)
+{
+ /* k = n div __C__ */
+ register sal_Size k = n / __C__, m = __L__;
+
+ OSL_PRECOND((__L__ == 32),
+ "__rtl_memory_queue(): internal logic error");
+ if (k > m)
+ {
+ /* k = k div __L__ = k div 32 */
+ k >>= 5;
+ while ((k >>= 1) > 0) m++;
+ k = m;
+ }
+
+ OSL_POSTCOND((0 < k) && (k < __N__),
+ "__rtl_memory_queue(): "
+ "internal error: index out of bounds");
+ return (k);
+}
+#else /* PRODUCT */
+#define queue(k, n) \
+{ \
+ (k) = ((n) / __C__); \
+ if ((k) > __L__) \
+ { \
+ register sal_Size m = __L__; \
+ (k) >>= 5; \
+ while (((k) >>= 1) > 0) m++; \
+ (k) = m; \
+ } \
+}
+#endif /* OSL_DEBUG_LEVEL || PRODUCT */
+
+#define queue_start(entry) \
+{ \
+ (entry)->m_flink = (entry); \
+ (entry)->m_blink = (entry); \
+}
+
+#define queue_remove(entry) \
+{ \
+ (entry)->m_blink->m_flink = (entry)->m_flink; \
+ (entry)->m_flink->m_blink = (entry)->m_blink; \
+ queue_start(entry); \
+}
+
+#define queue_insert_head(head, entry) \
+{ \
+ (entry)->m_blink = (head); \
+ (entry)->m_flink = (head)->m_flink; \
+ (head)->m_flink = (entry); \
+ (entry)->m_flink->m_blink = (entry); \
+}
+
+#define queue_insert_tail(head, entry) \
+{ \
+ (entry)->m_flink = (head); \
+ (entry)->m_blink = (head)->m_blink; \
+ (head)->m_blink = (entry); \
+ (entry)->m_blink->m_flink = (entry); \
+}
+
+/*===========================================================================
+ *
+ * rtl_memory (debug) internals.
+ *
+ *=========================================================================*/
+#if OSL_DEBUG_LEVEL > 0
+
+#define __dbg_memory_succ(entry, length) \
+(memory_type*)((char*)((entry)) + ((length) & ~0x1))
+
+#define __dbg_memory_pred(entry, offset) \
+(memory_type*)((char*)((entry)) - ((offset) & ~0x1))
+
+#define __dbg_memory_ensure(entry) (!((sal_Size)(entry) & 0x7))
+
+/*
+ * __dbg_memory_dequeue.
+ */
+static void __dbg_memory_dequeue (sal_Size n)
+{
+ register sal_Size k = queue(n);
+
+ g_memory.m_queue_stat[k].m_dequeue += 1;
+ g_memory.m_queue_stat[k].m_delta_q += 1;
+
+ g_memory.m_queue_stat[k].m_deqsize += n;
+ g_memory.m_queue_stat[k].m_delta_n += n;
+}
+
+/*
+ * __dbg_memory_enqueue.
+ */
+static void __dbg_memory_enqueue (sal_Size n)
+{
+ register sal_Size k = queue(n);
+
+ g_memory.m_queue_stat[k].m_enqueue += 1;
+ g_memory.m_queue_stat[k].m_delta_q -= 1;
+
+ g_memory.m_queue_stat[k].m_enqsize += n;
+ g_memory.m_queue_stat[k].m_delta_n -= n;
+}
+
+/*
+ * __dbg_memory_insert.
+ */
+static void __dbg_memory_insert (memory_type **ppMemory)
+{
+ register memory_type * succ;
+ succ = __dbg_memory_succ (*ppMemory, sizeof(memory_type));
+
+ succ->m_length = (*ppMemory)->m_length - sizeof(memory_type);
+ succ->m_offset = (*ppMemory)->m_offset;
+
+ queue_insert_tail (&(g_memory.m_alloc_head), (*ppMemory));
+ (*ppMemory) = succ;
+}
+
+/*
+ * __dbg_memory_remove.
+ */
+static void __dbg_memory_remove (memory_type **ppMemory)
+{
+ (*ppMemory) = __dbg_memory_pred (*ppMemory, sizeof(memory_type));
+ queue_remove (*ppMemory);
+}
+
+/*
+ * __dbg_memory_verify_chain.
+ */
+static int __dbg_memory_verify_chain (memory_type * x)
+{
+ if (!__dbg_memory_ensure(x))
+ {
+ OSL_ENSURE(0, "__rtl_memory_verify(): invalid pointer alignment.");
+ return (0);
+ }
+ if (!__dbg_memory_ensure(x->m_length & ~0x1))
+ {
+ OSL_ENSURE(0, "__rtl_memory_verify(): dynamic memory corruption");
+ return (0);
+ }
+ if (!__dbg_memory_ensure(x->m_offset & ~0x1))
+ {
+ OSL_ENSURE(0, "__rtl_memory_verify(): dynamic memory corruption");
+ return (0);
+ }
+ if (!(x->m_length & ~0x1))
+ {
+ OSL_ENSURE(0, "__rtl_memory_verify(): dynamic memory corruption");
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * __dbg_memory_verify_queue.
+ */
+static int __dbg_memory_verify_queue (memory_type * x)
+{
+ if (!__dbg_memory_ensure(x))
+ {
+ OSL_ENSURE(0, "__rtl_memory_verify(): invalid pointer alignment.");
+ return (0);
+ }
+ if (!__dbg_memory_ensure(x->m_flink))
+ {
+ OSL_ENSURE(0, "__rtl_memory_verify(): free memory corruption");
+ return (0);
+ }
+ if (!__dbg_memory_ensure(x->m_blink))
+ {
+ OSL_ENSURE(0, "__rtl_memory_verify(): free memory corruption");
+ return (0);
+ }
+ if ((x == x->m_flink) || (x == x->m_blink))
+ {
+ OSL_ENSURE(0, "__rtl_memory_verify(): internal logic error");
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * __dbg_memory_verify_alloc.
+ */
+static int __dbg_memory_verify_alloc (memory_type * x)
+{
+ register memory_type *head, *entry;
+ head = entry = &(g_memory.m_alloc_head);
+
+ if (!__dbg_memory_ensure(x))
+ {
+ OSL_ENSURE(0, "__rtl_memory_verify(): invalid pointer alignment.");
+ return (0);
+ }
+ while (!((entry = entry->m_flink) == head))
+ {
+ if ((entry < x) && (x < __dbg_memory_succ(entry, entry->m_length)))
+ {
+ head = entry = __dbg_memory_succ(entry, sizeof(memory_type));
+ while (!((x == entry) || (entry->m_offset & 0x1)))
+ {
+ /* no match, not last */
+ if (!__dbg_memory_verify_chain (entry))
+ return (0);
+ entry = __dbg_memory_succ(entry, entry->m_length);
+ }
+
+ /* match, or last */
+ if (!__dbg_memory_verify_chain (entry))
+ return (0);
+ break;
+ }
+ }
+ if (!(x == entry))
+ {
+ OSL_ENSURE(0, "__rtl_memory_verify(): memory not allocated.");
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * __dbg_memory_verify.
+ */
+static int __dbg_memory_verify (memory_type * x, int debug)
+{
+ /* dispatch upon 'debug' level */
+ if (debug)
+ {
+ /* verify allocation */
+ if (!__dbg_memory_verify_alloc (x))
+ return (0);
+ }
+ else
+ {
+ /* verify 'chain' fields */
+ if (!__dbg_memory_verify_chain (x))
+ return (0);
+ }
+
+ /* verify 'used' bit */
+ if (!(x->m_length & 0x1))
+ {
+ OSL_ENSURE(0, "__rtl_memory_verify(): memory not used.");
+ return (0);
+ }
+ return (1);
+}
+
+#if OSL_DEBUG_LEVEL > 1
+/*
+ * __dbg_memory_usage_update.
+ */
+static sal_Size __dbg_memory_usage_update (memory_stat * stat, sal_Size length)
+{
+ register sal_Size n = (length & ~0x1), k = queue(n);
+
+ stat[k].m_dequeue += 1;
+ stat[k].m_deqsize += n;
+
+ if (!(length & 0x1))
+ {
+ /* not used */
+ stat[k].m_enqueue += 1;
+ stat[k].m_enqsize += n;
+ return (n);
+ }
+ else
+ {
+ /* used */
+ stat[k].m_delta_q += 1;
+ stat[k].m_delta_n += n;
+ return (0);
+ }
+}
+
+/*
+ * __dbg_memory_usage.
+ */
+static void __dbg_memory_usage (memory_stat * total)
+{
+ register memory_type *head, *entry, *memory;
+ memory_stat stat[__N__];
+
+ memset (stat, 0, __N__ * sizeof(memory_stat));
+
+ head = entry = &(g_memory.m_alloc_head);
+ while (!((entry = entry->m_flink) == head))
+ {
+ register sal_Size k = 0, n = entry->m_length - sizeof(memory_type);
+
+ memory = __dbg_memory_succ(entry, sizeof(memory_type));
+ while (!(memory->m_offset & 0x1))
+ {
+ /* not last */
+ k += __dbg_memory_usage_update (stat, memory->m_length);
+ memory = __dbg_memory_succ(memory, memory->m_length);
+ }
+
+ k += __dbg_memory_usage_update (stat, memory->m_length);
+ OSL_TRACE("%x %10d %10d", (sal_Size)(entry), n, k);
+ }
+
+ if (total)
+ {
+ sal_Size i;
+
+ memset (total, 0, sizeof(memory_stat));
+ for (i = 0; i < __N__; i++)
+ {
+ total->m_dequeue += stat[i].m_dequeue;
+ total->m_enqueue += stat[i].m_enqueue;
+ total->m_delta_q += stat[i].m_delta_q;
+
+ total->m_deqsize += stat[i].m_deqsize;
+ total->m_enqsize += stat[i].m_enqsize;
+ total->m_delta_n += stat[i].m_delta_n;
+ }
+ }
+}
+#endif /* OSL_DEBUG_LEVEL */
+
+#endif /* OSL_DEBUG_LEVEL */
+#if OSL_DEBUG_LEVEL > 0
+
+#define DBG_MEMORY_DEQUEUE(n) __dbg_memory_dequeue((sal_Size)(n) & ~0x1)
+#define DBG_MEMORY_ENQUEUE(n) __dbg_memory_enqueue((sal_Size)(n) & ~0x1)
+
+#define DBG_MEMORY_DEQFILL(entry, offset, length) \
+ memset(((char*)(entry) + (offset)), 0x77777777, (length))
+#define DBG_MEMORY_ENQFILL(entry, offset, length) \
+ memset(((char*)(entry) + (offset)), 0x33333333, (length))
+
+#define DBG_MEMORY_INSERT(entry) __dbg_memory_insert((entry))
+#define DBG_MEMORY_REMOVE(entry) __dbg_memory_remove((entry))
+
+#if OSL_DEBUG_LEVEL > 1
+#define DBG_MEMORY_VERIFY(entry) __dbg_memory_verify((entry), 1)
+#else /* OSL_DEBUG_LEVEL > 0 */
+#define DBG_MEMORY_VERIFY(entry) __dbg_memory_verify((entry), 0)
+#endif /* OSL_DEBUG_LEVEL */
+
+#define DBG_MEMORY_VERIFY_CHAIN(entry) __dbg_memory_verify_chain((entry))
+#define DBG_MEMORY_VERIFY_QUEUE(entry) __dbg_memory_verify_queue((entry))
+
+#else /* PRODUCT */
+
+#define DBG_MEMORY_DEQUEUE(n)
+#define DBG_MEMORY_ENQUEUE(n)
+
+#define DBG_MEMORY_DEQFILL(entry, offset, length)
+#define DBG_MEMORY_ENQFILL(entry, offset, length)
+
+#define DBG_MEMORY_INSERT(entry)
+#define DBG_MEMORY_REMOVE(entry)
+
+#define DBG_MEMORY_VERIFY(entry)
+#define DBG_MEMORY_VERIFY_CHAIN(entry)
+#define DBG_MEMORY_VERIFY_QUEUE(entry)
+
+#endif /* OSL_DEBUG_LEVEL || PRODUCT */
+
+/*===========================================================================
+ *
+ * rtl_memory (manager) internals.
+ *
+ *=========================================================================*/
+#define queue_cast(entry, offset) \
+((memory_type*)((char*)(entry) + (ptrdiff_t)(offset)))
+
+#define __rtl_memory_used(entry) ((entry)->m_length & 0x1)
+#define __rtl_memory_last(entry) ((entry)->m_offset & 0x1)
+#define __rtl_memory_offset(entry) \
+ ((ptrdiff_t)((entry)->m_offset & ~0x1))
+
+/*
+ * ___rtl_memory_init.
+ */
+void SAL_CALL ___rtl_memory_init (void)
+{
+#if defined(RTL_MUTEX_INIT)
+ RTL_MUTEX_INIT (&(g_memory.m_mutex.m_lock));
+#endif /* RTL_MUTEX_INIT */
+
+ RTL_MUTEX_ACQUIRE(&(g_memory.m_mutex.m_lock));
+ if (!(g_memory.m_align))
+ {
+ sal_Size pagesize;
+ int i;
+
+ queue_start (&(g_memory.m_alloc_head));
+ queue_start (&(g_memory.m_spare_head));
+
+ for (i = 0; i < __N__; i++)
+ queue_start (&(g_memory.m_queue_head[i]));
+ for (i = 1; i <= __L__; i++)
+ g_memory.m_queue_head[i].m_length = i * __C__;
+ for (i = __L__ + 1; i < __N__; i++)
+ g_memory.m_queue_head[i].m_length =
+ 2 * g_memory.m_queue_head[i - 1].m_length;
+
+ pagesize = __rtl_memory_vmpagesize();
+ g_memory.m_align = RTL_MEMORY_ALIGN(__M__, pagesize);
+ }
+ RTL_MUTEX_RELEASE(&(g_memory.m_mutex.m_lock));
+}
+
+/*
+ * ___rtl_memory_fini.
+ */
+void SAL_CALL ___rtl_memory_fini (void)
+{
+#if OSL_DEBUG_LEVEL > 1
+
+ memory_stat total;
+
+ __dbg_memory_usage (&total);
+ if (total.m_delta_n > 0)
+ {
+ OSL_TRACE("___rtl_memory_fini(): "
+ "Leak: %10d (Alloc: %10d, Free: %10d)",
+ total.m_delta_n,
+ (sal_uInt32)(total.m_deqsize & 0xffffffff),
+ (sal_uInt32)(total.m_enqsize & 0xffffffff));
+ }
+
+#endif /* OSL_DEBUG_LEVEL */
+}
+
+/*
+ * __rtl_memory_merge.
+ */
+#if defined(PROFILE) || (OSL_DEBUG_LEVEL > 0)
+static void __rtl_memory_merge (memory_type * prev, memory_type * next)
+{
+ /* adjust length */
+ prev->m_length += next->m_length;
+ if (!__rtl_memory_last(next))
+ {
+ /* not last, adjust offset */
+ register memory_type * succ = queue_cast(prev, prev->m_length);
+ DBG_MEMORY_VERIFY_CHAIN (succ);
+ succ->m_offset = prev->m_length | __rtl_memory_last(succ);
+ }
+
+ /* propagate 'last' bit */
+ prev->m_offset |= __rtl_memory_last(next);
+}
+#else /* PRODUCT */
+#define __rtl_memory_merge(prev, next) \
+{ \
+ (prev)->m_length += (next)->m_length; \
+ if (!__rtl_memory_last((next))) \
+ { \
+ register memory_type * succ = queue_cast((prev), (prev)->m_length); \
+ succ->m_offset = (prev)->m_length | __rtl_memory_last(succ); \
+ } \
+ (prev)->m_offset |= __rtl_memory_last((next)); \
+}
+#endif /* OSL_DEBUG_LEVEL || PRODUCT */
+
+/*
+ * __rtl_memory_split.
+ */
+#if defined(PROFILE) || (OSL_DEBUG_LEVEL > 0)
+static void __rtl_memory_split (memory_type * prev, memory_type * next)
+{
+ /* adjust length */
+ prev->m_length -= next->m_length;
+ if (!__rtl_memory_last(prev))
+ {
+ /* not last, adjust offset */
+ register memory_type * succ = queue_cast(next, next->m_length);
+ DBG_MEMORY_VERIFY_CHAIN (succ);
+ succ->m_offset = next->m_length | __rtl_memory_last(succ);
+ }
+
+ /* propagate 'last' bit */
+ next->m_offset |= __rtl_memory_last(prev);
+ prev->m_offset &= ~0x1;
+}
+#else /* PRODUCT */
+#define __rtl_memory_split(prev, next) \
+{ \
+ (prev)->m_length -= (next)->m_length; \
+ if (!__rtl_memory_last((prev))) \
+ { \
+ register memory_type * succ = queue_cast((next), (next)->m_length); \
+ succ->m_offset = (next)->m_length | __rtl_memory_last(succ); \
+ } \
+\
+ (next)->m_offset |= __rtl_memory_last((prev)); \
+ (prev)->m_offset &= ~0x1; \
+}
+#endif /* OSL_DEBUG_LEVEL || PRODUCT */
+
+/*
+ * __rtl_memory_insert.
+ */
+#if defined(PROFILE) || (OSL_DEBUG_LEVEL > 0)
+static void __rtl_memory_insert (memory_type * memory, sal_Size n)
+{
+ /* obtain queue head */
+ register memory_type *head;
+
+ head = &(g_memory.m_queue_head[queue(n)]);
+ DBG_MEMORY_VERIFY_CHAIN (head);
+
+ /* insert at queue tail (first-in first-out) */
+ queue_insert_tail (head, memory);
+}
+#else /* PRODUCT */
+#define __rtl_memory_insert(memory, n) \
+{ \
+ register sal_Size h; \
+\
+ queue(h, (n)); \
+ queue_insert_tail (&(g_memory.m_queue_head[h]), (memory)); \
+}
+#endif /* OSL_DEBUG_LEVEL || PRODUCT */
+
+/*
+ * __rtl_memory_resize.
+ */
+#if defined(PROFILE) || (OSL_DEBUG_LEVEL > 0)
+static void __rtl_memory_resize (memory_type * memory, sal_Size n)
+{
+ register sal_Size k = (memory->m_length - n);
+
+ OSL_ENSURE(!(memory->m_length & 0x1),
+ "__rtl_memory_resize(): "
+ "internal logic error.");
+
+ if ((k >= sizeof(memory_type)) && (n <= __T__))
+ {
+ /* split */
+ register memory_type * remain = queue_cast(memory, n);
+
+ remain->m_length = k; remain->m_offset = n;
+ __rtl_memory_split (memory, remain);
+
+ /* check postcond */
+ if (!__rtl_memory_last(remain))
+ {
+ /* not last, verify used next entry */
+ register memory_type *next;
+
+ next = queue_cast(remain, remain->m_length);
+ DBG_MEMORY_VERIFY_CHAIN (next);
+
+ OSL_POSTCOND(__rtl_memory_used(next),
+ "__rtl_memory_resize(): "
+ "internal logic error.");
+ }
+
+ /* enqueue */
+ __rtl_memory_insert (remain, k);
+ DBG_MEMORY_VERIFY_QUEUE (remain);
+ }
+
+ DBG_MEMORY_DEQUEUE(memory->m_length);
+}
+#else /* PRODUCT */
+#define __rtl_memory_resize(memory, n) \
+{ \
+ register sal_Size kn = ((memory)->m_length - (n)); \
+ if ((kn >= sizeof(memory_type)) && (n <= __T__)) \
+ { \
+ register memory_type * remain = queue_cast((memory), (n)); \
+\
+ remain->m_length = kn; remain->m_offset = (n); \
+ __rtl_memory_split ((memory), remain); \
+\
+ __rtl_memory_insert (remain, kn); \
+ } \
+}
+#endif /* OSL_DEBUG_LEVEL || PRODUCT */
+
+/*
+ * __rtl_memory_dequeue.
+ */
+#if defined(PROFILE) || (OSL_DEBUG_LEVEL > 0)
+static void __rtl_memory_dequeue (memory_type **ppMemory, sal_Size n)
+{
+ register memory_type *head, *entry;
+ register sal_Size k, m = n;
+
+ OSL_PRECOND(!*ppMemory, "__rtl_memory_dequeue(): internal logic error.");
+ for (k = queue(m); k < __N__; k++)
+ {
+ /* first fit (equals best fit w/ ascending insert) */
+ head = &(g_memory.m_queue_head[k]);
+ for (entry = head->m_flink; entry != head; entry = entry->m_flink)
+ {
+ /* queue not empty */
+ DBG_MEMORY_VERIFY_CHAIN (entry);
+ if (entry->m_length >= m)
+ {
+ /* remove entry */
+ DBG_MEMORY_VERIFY_QUEUE (entry);
+ queue_remove (entry);
+
+ /* assign result */
+ *ppMemory = entry;
+ goto dequeue_leave;
+ }
+ }
+ }
+
+ head = &(g_memory.m_spare_head);
+ for (entry = head->m_flink; entry != head; entry = entry->m_flink)
+ {
+ /* queue not empty */
+ DBG_MEMORY_VERIFY_CHAIN (entry);
+ if (entry->m_length >= m)
+ {
+ /* remove entry */
+ DBG_MEMORY_VERIFY_QUEUE (entry);
+ queue_remove (entry);
+
+ /* assign result */
+ *ppMemory = entry;
+ goto dequeue_leave;
+ }
+ }
+
+#if OSL_DEBUG_LEVEL > 0
+ /* adjust for DBG_MEMORY_INSERT() overhead */
+ m += sizeof(memory_type);
+#endif /* OSL_DEBUG_LEVEL */
+
+ k = RTL_MEMORY_ALIGN((m > __M__) ? m : __M__, g_memory.m_align);
+ if (!((entry = RTL_MEMORY_ALLOC(k)) == 0))
+ {
+ entry->m_length = k;
+ entry->m_offset = 0x1; /* set 'last' bit */
+
+ *ppMemory = entry;
+ DBG_MEMORY_INSERT(ppMemory);
+ }
+
+dequeue_leave:
+ OSL_POSTCOND(*ppMemory, "__rtl_memory_dequeue(): out of memory.");
+ if ((entry = *ppMemory) != 0)
+ {
+ /* adjust length */
+ __rtl_memory_resize (entry, n);
+
+ /* fill w/ 'uninitialized' pattern */
+ DBG_MEMORY_DEQFILL (entry, __C__, entry->m_length - __C__);
+ }
+#if OSL_DEBUG_LEVEL > 1
+ if (!entry)
+ {
+ memory_stat total;
+ __dbg_memory_usage (&total);
+ }
+#endif /* OSL_DEBUG_LEVEL */
+}
+#else /* PRODUCT */
+#define __rtl_memory_dequeue(ppMemory, n, label) \
+{ \
+ register memory_type *head, *entry; \
+ register sal_Size h, m = (n); \
+\
+ queue (h, m); \
+ for (; h < __N__; h++) \
+ { \
+ head = &(g_memory.m_queue_head[h]); \
+ for (entry = head->m_flink; entry != head; entry = entry->m_flink) \
+ { \
+ if (entry->m_length >= m) \
+ { \
+ queue_remove (entry); \
+ goto label; \
+ } \
+ } \
+ } \
+\
+ head = &(g_memory.m_spare_head); \
+ for (entry = head->m_flink; entry != head; entry = entry->m_flink) \
+ { \
+ if (entry->m_length >= m) \
+ { \
+ queue_remove (entry); \
+ goto label; \
+ } \
+ } \
+\
+ h = RTL_MEMORY_ALIGN((m > __M__) ? m : __M__, g_memory.m_align); \
+ if (!((entry = RTL_MEMORY_ALLOC(h)) == 0)) \
+ { \
+ entry->m_length = h; \
+ entry->m_offset = 0x1; \
+ } \
+\
+label: \
+ if (entry) \
+ { \
+ __rtl_memory_resize (entry, (n)); \
+ *(ppMemory) = entry; \
+ } \
+}
+#endif /* OSL_DEBUG_LEVEL || PRODUCT */
+
+#if defined(PROFILE) || (OSL_DEBUG_LEVEL > 0)
+#define RTL_MEMORY_DEQUEUE(m, n, l) __rtl_memory_dequeue((m), (n))
+#else /* PRODUCT */
+#define RTL_MEMORY_DEQUEUE(m, n, l) __rtl_memory_dequeue(m, n, l)
+#endif /* OSL_DEBUG_LEVEL || PRODUCT */
+
+/*
+ * __rtl_memory_enqueue.
+ */
+#if defined(PROFILE) || (OSL_DEBUG_LEVEL > 0)
+static void __rtl_memory_enqueue (memory_type **ppMemory)
+{
+ register memory_type *head = *ppMemory;
+
+ OSL_ENSURE(!__rtl_memory_used(head),
+ "__rtl_memory_enqueue(): "
+ "internal logic error.");
+ DBG_MEMORY_ENQUEUE (head->m_length);
+
+ /* fill w/ 'deinitialized' pattern */
+ DBG_MEMORY_ENQFILL (head, __C__, head->m_length - __C__);
+
+ /* try merge w/ next entry */
+ if (!__rtl_memory_last(head))
+ {
+ /* not last, check next in chain */
+ register memory_type * next;
+
+ next = queue_cast(head, head->m_length);
+ DBG_MEMORY_VERIFY_CHAIN (next);
+
+ if (!__rtl_memory_used(next))
+ {
+ /* next not used */
+ DBG_MEMORY_VERIFY_QUEUE (next);
+ queue_remove (next);
+
+ /* merge w/ next */
+ __rtl_memory_merge (head, next);
+ DBG_MEMORY_ENQFILL (next, 0, sizeof(memory_type));
+ }
+ }
+
+ /* try merge w/ prev entry */
+ if (__rtl_memory_offset(head) > 0)
+ {
+ /* not first, check prev in chain */
+ register memory_type * prev;
+
+ prev = queue_cast(head, -(__rtl_memory_offset(head)));
+ DBG_MEMORY_VERIFY_CHAIN (prev);
+
+ if (!__rtl_memory_used(prev))
+ {
+ /* prev not used */
+ DBG_MEMORY_VERIFY_QUEUE (prev);
+ queue_remove (prev);
+
+ /* merge w/ prev */
+ __rtl_memory_merge (prev, head);
+ DBG_MEMORY_ENQFILL (head, 0, sizeof(memory_type));
+ head = prev;
+ }
+ }
+
+ if (!(head->m_offset == 0x1))
+ {
+ /* page still used, enqueue */
+ __rtl_memory_insert (head, head->m_length);
+ head = 0;
+ }
+ else if (head->m_length <= g_memory.m_align)
+ {
+ /* small page unused, check spare page */
+ register memory_type * spare;
+
+ spare = &(g_memory.m_spare_head);
+ if (spare->m_flink == spare)
+ {
+ /* keep as spare page */
+ queue_insert_tail (spare, head);
+ head = 0;
+ }
+ }
+ if ((*ppMemory = head) != 0)
+ {
+ /* page unused, remove */
+ DBG_MEMORY_REMOVE(ppMemory);
+ }
+}
+#else /* PRODUCT */
+#define __rtl_memory_enqueue(ppMemory) \
+{ \
+ register memory_type *head = *(ppMemory); \
+\
+ if (!__rtl_memory_last(head)) \
+ { \
+ register memory_type * next; \
+ next = queue_cast(head, head->m_length); \
+ if (!__rtl_memory_used(next)) \
+ { \
+ queue_remove (next); \
+ __rtl_memory_merge (head, next); \
+ } \
+ } \
+\
+ if (__rtl_memory_offset(head) > 0) \
+ { \
+ register memory_type * prev; \
+ prev = queue_cast(head, -(__rtl_memory_offset(head))); \
+ if (!__rtl_memory_used(prev)) \
+ { \
+ queue_remove (prev); \
+ __rtl_memory_merge (prev, head); \
+ head = prev; \
+ } \
+ } \
+\
+ if (!(head->m_offset == 0x1)) \
+ { \
+ register memory_type * used = head; \
+ __rtl_memory_insert (used, used->m_length); \
+ head = 0; \
+ } \
+ else if (head->m_length <= g_memory.m_align) \
+ { \
+ register memory_type * spare; \
+ spare = &(g_memory.m_spare_head); \
+ if (spare->m_flink == spare) \
+ { \
+ queue_insert_tail (spare, head); \
+ head = 0; \
+ } \
+ } \
+\
+ *(ppMemory) = head; \
+}
+#endif /* OSL_DEBUG_LEVEL || PRODUCT */
+
+#define RTL_MEMORY_ENQUEUE(m) __rtl_memory_enqueue((m))
+
+#endif /* FORCE_SYSALLOC */
+
+/*===========================================================================
+ *
+ * rtl_memory (manager) implementation.
+ *
+ *=========================================================================*/
+/*
+ * rtl_reallocateMemory.
+ */
+#ifndef FORCE_SYSALLOC
+void* SAL_CALL rtl_reallocateMemory (void * p, sal_Size n) SAL_THROW_EXTERN_C()
+{
+ memory_type * memory;
+ if (!(!p || !n))
+ {
+ /* reallocate */
+ register sal_Size datlen;
+
+ memory = queue_cast(p, -(__C__)); p = 0;
+ n = RTL_MEMORY_ALIGN(n, __Q__) + __C__;
+
+ RTL_MEMORY_ENTER();
+ DBG_MEMORY_VERIFY(memory);
+
+ /* clear 'used' bit */
+ DBG_MEMORY_ENQUEUE (memory->m_length);
+ memory->m_length &= ~0x1;
+
+ /* amount of data to be moved or copied */
+ datlen = ((memory->m_length < n) ? memory->m_length : n);
+
+ /* try merge w/ next entry */
+ if (!__rtl_memory_last(memory))
+ {
+ /* not last, check next in chain */
+ register memory_type * next;
+
+ next = queue_cast(memory, memory->m_length);
+ DBG_MEMORY_VERIFY_CHAIN(next);
+
+ if (!__rtl_memory_used(next))
+ {
+ /* next not used */
+ DBG_MEMORY_VERIFY_QUEUE(next);
+ queue_remove (next);
+
+ /* merge w/ next */
+ __rtl_memory_merge (memory, next);
+ }
+ }
+
+ /* try merge w/ prev entry */
+ if (__rtl_memory_offset(memory) > 0)
+ {
+ /* not first, check prev in chain */
+ register memory_type * prev;
+
+ prev = queue_cast(memory, -(__rtl_memory_offset(memory)));
+ DBG_MEMORY_VERIFY_CHAIN (prev);
+
+ if (!__rtl_memory_used(prev))
+ {
+ /* prev not used, try merge, move */
+ if ((memory->m_length + prev->m_length) >= n)
+ {
+ /* prev does fit */
+ DBG_MEMORY_VERIFY_QUEUE (prev);
+ queue_remove (prev);
+
+ /* merge w/ prev */
+ __rtl_memory_merge (prev, memory);
+
+ /* move to prev */
+ memmove (
+ queue_cast(prev, __C__),
+ queue_cast(memory, __C__),
+ datlen - __C__);
+ memory = prev;
+ }
+ }
+ }
+
+ if (memory->m_length >= n)
+ {
+ /* adjust, set 'used' bit */
+ __rtl_memory_resize (memory, n);
+ memory->m_length |= 0x1;
+
+ /* assign result */
+ p = queue_cast(memory, __C__);
+ }
+ else
+ {
+ /* allocate */
+ memory_type * result = 0;
+
+ /* restore 'used' bit */
+ DBG_MEMORY_DEQUEUE (memory->m_length);
+ memory->m_length |= 0x80000000;
+
+ RTL_MEMORY_DEQUEUE (&result, n, realloc_label_1);
+ if (result)
+ {
+ /* set 'used' bit */
+ result->m_length |= 0x1;
+
+ /* copy */
+ memcpy (
+ queue_cast(result, __C__),
+ queue_cast(memory, __C__),
+ datlen - __C__);
+
+ /* clear 'used' bit, enqueue */
+ memory->m_length &= 0x7fffffff;
+ RTL_MEMORY_ENQUEUE (&memory);
+ if (memory)
+ {
+ /* free memory page */
+ RTL_MEMORY_FREE(memory, memory->m_length);
+ }
+
+ /* assign result */
+ p = queue_cast(result, __C__);
+ }
+ }
+ RTL_MEMORY_LEAVE();
+ }
+ else if (!p)
+ {
+ /* allocate */
+ memory = 0;
+ n = RTL_MEMORY_ALIGN(n, __Q__) + __C__;
+
+ RTL_MEMORY_ENTER();
+ RTL_MEMORY_DEQUEUE (&memory, n, realloc_label_2);
+ if (memory)
+ {
+ /* set 'used' bit */
+ memory->m_length |= 0x1;
+
+ /* assign result */
+ p = queue_cast(memory, __C__);
+ }
+ RTL_MEMORY_LEAVE();
+ }
+ else if (!n)
+ {
+ /* free */
+ memory = queue_cast(p, -(__C__)); p = 0;
+
+ RTL_MEMORY_ENTER();
+ DBG_MEMORY_VERIFY(memory);
+
+ /* clear 'used' bit, enqueue */
+ memory->m_length &= ~0x1;
+
+ RTL_MEMORY_ENQUEUE (&memory);
+ if (memory)
+ {
+ /* free memory page */
+ RTL_MEMORY_FREE(memory, memory->m_length);
+ }
+ RTL_MEMORY_LEAVE();
+ }
+ return (p);
+}
+#else /* FORCE_SYSALLOC */
+void* SAL_CALL rtl_reallocateMemory (void * p, sal_Size n) SAL_THROW_EXTERN_C()
+{
+ return realloc(p, (sal_Size)(n));
+}
+#endif /* FORCE_SYSALLOC */
+
+/*
+ * rtl_allocateMemory.
+ */
+#ifndef FORCE_SYSALLOC
+void* SAL_CALL rtl_allocateMemory (sal_Size n) SAL_THROW_EXTERN_C()
+{
+ void * p = 0;
+ if (n > 0)
+ {
+ memory_type * memory = 0;
+ n = RTL_MEMORY_ALIGN(n, __Q__) + __C__;
+
+ RTL_MEMORY_ENTER();
+ RTL_MEMORY_DEQUEUE (&memory, n, alloc_label);
+ if (memory)
+ {
+ /* set 'used' bit */
+ memory->m_length |= 0x1;
+
+ /* assign result */
+ p = queue_cast(memory, __C__);
+ }
+ RTL_MEMORY_LEAVE();
+ }
+ return (p);
+}
+#else /* FORCE_SYSALLOC */
+void* SAL_CALL rtl_allocateMemory (sal_Size n) SAL_THROW_EXTERN_C()
+{
+ return malloc((sal_Size)(n));
+}
+#endif /* FORCE_SYSALLOC */
+
+/*
+ * rtl_freeMemory.
+ */
+#ifndef FORCE_SYSALLOC
+void SAL_CALL rtl_freeMemory (void * p) SAL_THROW_EXTERN_C()
+{
+ if (p)
+ {
+ memory_type * memory = queue_cast(p, -(__C__));
+
+ RTL_MEMORY_ENTER();
+ DBG_MEMORY_VERIFY(memory);
+
+ /* clear 'used' bit, enqueue */
+ memory->m_length &= ~0x1;
+
+ RTL_MEMORY_ENQUEUE (&memory);
+ if (memory)
+ {
+ /* free memory page */
+ RTL_MEMORY_FREE(memory, memory->m_length);
+ }
+ RTL_MEMORY_LEAVE();
+ }
+}
+#else /* FORCE_SYSALLOC */
+void SAL_CALL rtl_freeMemory (void * p) SAL_THROW_EXTERN_C()
+{
+ free(p);
+}
+#endif /* FORCE_SYSALLOC */
+
+/*
+ * rtl_allocateZeroMemory.
+ */
+#ifndef FORCE_SYSALLOC
+void* SAL_CALL rtl_allocateZeroMemory (sal_Size n) SAL_THROW_EXTERN_C()
+{
+ void * p = 0;
+ if (n > 0)
+ {
+ memory_type * memory = 0;
+ n = RTL_MEMORY_ALIGN(n, __Q__) + __C__;
+
+ RTL_MEMORY_ENTER();
+ RTL_MEMORY_DEQUEUE (&memory, n, alloc_label); /* NYI: demand zero */
+ if (memory)
+ {
+ /* zero, set 'used' bit */
+ memset ((char*)memory + __C__, 0, memory->m_length - __C__);
+ memory->m_length |= 0x1;
+
+ /* assign result */
+ p = queue_cast(memory, __C__);
+ }
+ RTL_MEMORY_LEAVE();
+ }
+ return (p);
+}
+#else /* FORCE_SYSALLOC */
+void* SAL_CALL rtl_allocateZeroMemory (sal_Size n) SAL_THROW_EXTERN_C()
+{
+ return calloc((sal_Size)(n), 1);
+}
+#endif /* FORCE_SYSALLOC */
+
+/*
+ * rtl_freeZeroMemory.
+ */
+#ifndef FORCE_SYSALLOC
+void SAL_CALL rtl_freeZeroMemory (void * p, sal_Size n) SAL_THROW_EXTERN_C()
+{
+ (void) n; /* unused */
+ if (p)
+ {
+ memory_type * memory = queue_cast(p, -(__C__));
+
+ RTL_MEMORY_ENTER();
+ DBG_MEMORY_VERIFY(memory);
+
+ /* clear 'used' bit, zero, enqueue */
+ memory->m_length &= ~0x1;
+ memset ((char*)memory + __C__, 0, memory->m_length - __C__);
+
+ RTL_MEMORY_ENQUEUE (&memory); /* NYI: demand zero */
+ if (memory)
+ {
+ /* free memory page */
+ RTL_MEMORY_FREE(memory, memory->m_length);
+ }
+ RTL_MEMORY_LEAVE();
+ }
+}
+#else /* FORCE_SYSALLOC */
+void SAL_CALL rtl_freeZeroMemory (void * p, sal_Size n) SAL_THROW_EXTERN_C()
+{
+ if (p)
+ {
+ memset(p, 0, n);
+ free(p);
+ }
+}
+#endif /* FORCE_SYSALLOC */
+
+/*===========================================================================
+ *
+ * The End.
+ *
+ *=========================================================================*/
diff --git a/sal/rtl/source/alloc_arena.c b/sal/rtl/source/alloc_arena.c
new file mode 100644
index 000000000000..1a74c7e36cae
--- /dev/null
+++ b/sal/rtl/source/alloc_arena.c
@@ -0,0 +1,1396 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#define _BSD_SOURCE /* sys/mman.h: MAP_ANON */
+#include "alloc_arena.h"
+
+#ifndef INCLUDED_RTL_ARENA_IMPL_H
+#include "alloc_impl.h"
+#endif
+#include "internal/once.h"
+#include "sal/macros.h"
+#include "osl/diagnose.h"
+
+#ifndef INCLUDED_STRING_H
+#include <string.h>
+#endif
+
+#ifndef INCLUDED_STDIO_H
+#include <stdio.h>
+#endif
+
+#include "sal/types.h"
+
+#ifdef OS2
+#undef OSL_TRACE
+#define OSL_TRACE 1 ? ((void)0) : _OSL_GLOBAL osl_trace
+#define INCL_DOS
+#include <os2.h>
+#endif
+
+/* ================================================================= *
+ *
+ * arena internals.
+ *
+ * ================================================================= */
+
+/** g_arena_list
+ * @internal
+ */
+struct rtl_arena_list_st
+{
+ rtl_memory_lock_type m_lock;
+ rtl_arena_type m_arena_head;
+};
+
+static struct rtl_arena_list_st g_arena_list;
+
+
+/** gp_arena_arena
+ * provided for arena_type allocations, and hash_table resizing.
+ *
+ * @internal
+ */
+static rtl_arena_type * gp_arena_arena = 0;
+
+
+/** gp_machdep_arena
+ *
+ * Low level virtual memory (pseudo) arena
+ * (platform dependent implementation)
+ *
+ * @internal
+ */
+static rtl_arena_type * gp_machdep_arena = 0;
+
+
+static void *
+SAL_CALL rtl_machdep_alloc (
+ rtl_arena_type * pArena,
+ sal_Size * pSize
+);
+
+static void
+SAL_CALL rtl_machdep_free (
+ rtl_arena_type * pArena,
+ void * pAddr,
+ sal_Size nSize
+);
+
+static sal_Size
+rtl_machdep_pagesize (void);
+
+
+/** gp_default_arena
+ */
+rtl_arena_type * gp_default_arena = 0;
+
+
+/** rtl_arena_init()
+ * @internal
+ */
+static int
+rtl_arena_init (void);
+
+
+/* ================================================================= */
+
+/** rtl_arena_segment_constructor()
+ */
+static int
+rtl_arena_segment_constructor (void * obj)
+{
+ rtl_arena_segment_type * segment = (rtl_arena_segment_type*)(obj);
+
+ QUEUE_START_NAMED(segment, s);
+ QUEUE_START_NAMED(segment, f);
+
+ return (1);
+}
+
+
+/** rtl_arena_segment_destructor()
+ */
+static void
+rtl_arena_segment_destructor (void * obj)
+{
+#if OSL_DEBUG_LEVEL == 0
+ (void) obj; /* unused */
+#else /* OSL_DEBUG_LEVEL */
+ rtl_arena_segment_type * segment = (rtl_arena_segment_type*)(obj);
+
+ OSL_ASSERT(QUEUE_STARTED_NAMED(segment, s));
+ OSL_ASSERT(QUEUE_STARTED_NAMED(segment, f));
+#endif /* OSL_DEBUG_LEVEL */
+}
+
+/* ================================================================= */
+
+/** rtl_arena_segment_populate()
+ *
+ * @precond arena->m_lock acquired.
+ */
+static int
+rtl_arena_segment_populate (
+ rtl_arena_type * arena
+)
+{
+ rtl_arena_segment_type *span;
+ sal_Size size = rtl_machdep_pagesize();
+
+ span = rtl_machdep_alloc(gp_machdep_arena, &size);
+ if (span != 0)
+ {
+ rtl_arena_segment_type *first, *last, *head;
+ sal_Size count = size / sizeof(rtl_arena_segment_type);
+
+ /* insert onto reserve span list */
+ QUEUE_INSERT_TAIL_NAMED(&(arena->m_segment_reserve_span_head), span, s);
+ QUEUE_START_NAMED(span, f);
+ span->m_addr = (sal_uIntPtr)(span);
+ span->m_size = size;
+ span->m_type = RTL_ARENA_SEGMENT_TYPE_SPAN;
+
+ /* insert onto reserve list */
+ head = &(arena->m_segment_reserve_head);
+ for (first = span + 1, last = span + count; first < last; ++first)
+ {
+ QUEUE_INSERT_TAIL_NAMED(head, first, s);
+ QUEUE_START_NAMED(first, f);
+ first->m_addr = 0;
+ first->m_size = 0;
+ first->m_type = 0;
+ }
+ }
+ return (span != 0);
+}
+
+
+/** rtl_arena_segment_get()
+ *
+ * @precond arena->m_lock acquired.
+ * @precond (*ppSegment == 0)
+ */
+static RTL_MEMORY_INLINE void
+rtl_arena_segment_get (
+ rtl_arena_type * arena,
+ rtl_arena_segment_type ** ppSegment
+)
+{
+ rtl_arena_segment_type * head;
+
+ OSL_ASSERT(*ppSegment == 0);
+
+ head = &(arena->m_segment_reserve_head);
+ if ((head->m_snext != head) || rtl_arena_segment_populate (arena))
+ {
+ (*ppSegment) = head->m_snext;
+ QUEUE_REMOVE_NAMED((*ppSegment), s);
+ }
+}
+
+#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+#pragma inline(rtl_arena_segment_get)
+#endif
+
+
+/** rtl_arena_segment_put()
+ *
+ * @precond arena->m_lock acquired.
+ * @postcond (*ppSegment == 0)
+ */
+static RTL_MEMORY_INLINE void
+rtl_arena_segment_put (
+ rtl_arena_type * arena,
+ rtl_arena_segment_type ** ppSegment
+)
+{
+ rtl_arena_segment_type * head;
+
+ OSL_ASSERT(QUEUE_STARTED_NAMED((*ppSegment), s));
+ OSL_ASSERT(QUEUE_STARTED_NAMED((*ppSegment), f));
+
+ (*ppSegment)->m_addr = 0;
+ (*ppSegment)->m_size = 0;
+
+ OSL_ASSERT((*ppSegment)->m_type != RTL_ARENA_SEGMENT_TYPE_HEAD);
+ (*ppSegment)->m_type = 0;
+
+ /* keep as reserve */
+ head = &(arena->m_segment_reserve_head);
+ QUEUE_INSERT_HEAD_NAMED(head, (*ppSegment), s);
+
+ /* clear */
+ (*ppSegment) = 0;
+}
+
+#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+#pragma inline(rtl_arena_segment_put)
+#endif
+
+/* ================================================================= */
+
+/** rtl_arena_freelist_insert()
+ *
+ * @precond arena->m_lock acquired.
+ */
+static RTL_MEMORY_INLINE void
+rtl_arena_freelist_insert (
+ rtl_arena_type * arena,
+ rtl_arena_segment_type * segment
+)
+{
+ rtl_arena_segment_type * head;
+
+ head = &(arena->m_freelist_head[highbit(segment->m_size) - 1]);
+ QUEUE_INSERT_TAIL_NAMED(head, segment, f);
+
+ arena->m_freelist_bitmap |= head->m_size;
+}
+
+#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+#pragma inline(rtl_arena_freelist_insert)
+#endif /* __SUNPRO_C */
+
+
+/** rtl_arena_freelist_remove()
+ *
+ * @precond arena->m_lock acquired.
+ */
+static RTL_MEMORY_INLINE void
+rtl_arena_freelist_remove (
+ rtl_arena_type * arena,
+ rtl_arena_segment_type * segment
+)
+{
+ if ((segment->m_fnext->m_type == RTL_ARENA_SEGMENT_TYPE_HEAD) &&
+ (segment->m_fprev->m_type == RTL_ARENA_SEGMENT_TYPE_HEAD) )
+ {
+ rtl_arena_segment_type * head;
+
+ head = segment->m_fprev;
+ OSL_ASSERT(arena->m_freelist_bitmap & head->m_size);
+ arena->m_freelist_bitmap ^= head->m_size;
+ }
+ QUEUE_REMOVE_NAMED(segment, f);
+}
+
+#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+#pragma inline(rtl_arena_freelist_remove)
+#endif /* __SUNPRO_C */
+
+
+/* ================================================================= */
+
+/** RTL_ARENA_HASH_INDEX()
+ */
+#define RTL_ARENA_HASH_INDEX_IMPL(a, s, q, m) \
+ ((((a) + ((a) >> (s)) + ((a) >> ((s) << 1))) >> (q)) & (m))
+
+#define RTL_ARENA_HASH_INDEX(arena, addr) \
+ RTL_ARENA_HASH_INDEX_IMPL((addr), (arena)->m_hash_shift, (arena)->m_quantum_shift, ((arena)->m_hash_size - 1))
+
+/** rtl_arena_hash_rescale()
+ *
+ * @precond arena->m_lock released.
+ */
+static void
+rtl_arena_hash_rescale (
+ rtl_arena_type * arena,
+ sal_Size new_size
+)
+{
+ rtl_arena_segment_type ** new_table;
+ sal_Size new_bytes;
+
+ new_bytes = new_size * sizeof(rtl_arena_segment_type*);
+ new_table = (rtl_arena_segment_type **)rtl_arena_alloc (gp_arena_arena, &new_bytes);
+
+ if (new_table != 0)
+ {
+ rtl_arena_segment_type ** old_table;
+ sal_Size old_size, i;
+
+ memset (new_table, 0, new_bytes);
+
+ RTL_MEMORY_LOCK_ACQUIRE(&(arena->m_lock));
+
+ old_table = arena->m_hash_table;
+ old_size = arena->m_hash_size;
+
+ OSL_TRACE(
+ "rtl_arena_hash_rescale(\"%s\"): "
+ "nseg: %"PRIu64" (ave: %"PRIu64"), frees: %"PRIu64" "
+ "[old_size: %lu, new_size: %lu]",
+ arena->m_name,
+ arena->m_stats.m_alloc - arena->m_stats.m_free,
+ (arena->m_stats.m_alloc - arena->m_stats.m_free) >> arena->m_hash_shift,
+ arena->m_stats.m_free,
+ old_size, new_size
+ );
+
+#if 0 /* DBG */
+ int i;
+ for (i = 0; i < arena->m_hash_size; i++)
+ {
+ sal_Size k = 0; rtl_arena_segment_type ** segpp = &(arena->m_hash_table[i]);
+ while (*segpp)
+ {
+ k += 1;
+ segpp = &((*segpp)->m_fnext);
+ }
+ fprintf(stdout, "%d, ", k);
+ }
+ fprintf(stdout, "\n");
+#endif /* DBG */
+
+ arena->m_hash_table = new_table;
+ arena->m_hash_size = new_size;
+ arena->m_hash_shift = highbit(arena->m_hash_size) - 1;
+
+ for (i = 0; i < old_size; i++)
+ {
+ rtl_arena_segment_type * curr = old_table[i];
+ while (curr != 0)
+ {
+ rtl_arena_segment_type * next = curr->m_fnext;
+ rtl_arena_segment_type ** head;
+
+ head = &(arena->m_hash_table[RTL_ARENA_HASH_INDEX(arena, curr->m_addr)]);
+ curr->m_fnext = (*head);
+ (*head) = curr;
+
+ curr = next;
+ }
+ old_table[i] = 0;
+ }
+
+ RTL_MEMORY_LOCK_RELEASE(&(arena->m_lock));
+
+ if (old_table != arena->m_hash_table_0)
+ {
+ sal_Size old_bytes = old_size * sizeof(rtl_arena_segment_type*);
+ rtl_arena_free (gp_arena_arena, old_table, old_bytes);
+ }
+ }
+}
+
+
+/** rtl_arena_hash_insert()
+ * ...and update stats.
+ */
+static RTL_MEMORY_INLINE void
+rtl_arena_hash_insert (
+ rtl_arena_type * arena,
+ rtl_arena_segment_type * segment
+)
+{
+ rtl_arena_segment_type ** ppSegment;
+
+ ppSegment = &(arena->m_hash_table[RTL_ARENA_HASH_INDEX(arena, segment->m_addr)]);
+
+ segment->m_fnext = (*ppSegment);
+ (*ppSegment) = segment;
+
+ arena->m_stats.m_alloc += 1;
+ arena->m_stats.m_mem_alloc += segment->m_size;
+}
+
+#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+#pragma inline(rtl_arena_hash_insert)
+#endif /* __SUNPRO_C */
+
+
+/** rtl_arena_hash_remove()
+ * ...and update stats.
+ */
+static rtl_arena_segment_type *
+rtl_arena_hash_remove (
+ rtl_arena_type * arena,
+ sal_uIntPtr addr,
+ sal_Size size
+)
+{
+ rtl_arena_segment_type *segment, **segpp;
+ sal_Size lookups = 0;
+
+#if OSL_DEBUG_LEVEL == 0
+ (void) size; /* unused */
+#endif /* OSL_DEBUG_LEVEL */
+
+ segpp = &(arena->m_hash_table[RTL_ARENA_HASH_INDEX(arena, addr)]);
+ while ((segment = *segpp) != 0)
+ {
+ if (segment->m_addr == addr)
+ {
+ *segpp = segment->m_fnext, segment->m_fnext = segment->m_fprev = segment;
+ break;
+ }
+
+ /* update lookup miss stats */
+ lookups += 1;
+ segpp = &(segment->m_fnext);
+ }
+
+ OSL_POSTCOND(segment != 0, "rtl_arena_hash_remove(): bad free.");
+ if (segment != 0)
+ {
+ OSL_POSTCOND(segment->m_size == size, "rtl_arena_hash_remove(): wrong size.");
+
+ arena->m_stats.m_free += 1;
+ arena->m_stats.m_mem_alloc -= segment->m_size;
+
+ if (lookups > 1)
+ {
+ sal_Size nseg = (sal_Size)(arena->m_stats.m_alloc - arena->m_stats.m_free);
+ if (nseg > 4 * arena->m_hash_size)
+ {
+ if (!(arena->m_flags & RTL_ARENA_FLAG_RESCALE))
+ {
+ sal_Size ave = nseg >> arena->m_hash_shift;
+ sal_Size new_size = arena->m_hash_size << (highbit(ave) - 1);
+
+ arena->m_flags |= RTL_ARENA_FLAG_RESCALE;
+ RTL_MEMORY_LOCK_RELEASE(&(arena->m_lock));
+ rtl_arena_hash_rescale (arena, new_size);
+ RTL_MEMORY_LOCK_ACQUIRE(&(arena->m_lock));
+ arena->m_flags &= ~RTL_ARENA_FLAG_RESCALE;
+ }
+ }
+ }
+ }
+
+ return (segment);
+}
+
+/* ================================================================= */
+
+/** rtl_arena_segment_alloc()
+ * allocate (and remove) segment from freelist
+ *
+ * @precond arena->m_lock acquired
+ * @precond (*ppSegment == 0)
+ */
+static int
+rtl_arena_segment_alloc (
+ rtl_arena_type * arena,
+ sal_Size size,
+ rtl_arena_segment_type ** ppSegment
+)
+{
+ int index = 0;
+
+ OSL_ASSERT(*ppSegment == 0);
+ if (!RTL_MEMORY_ISP2(size))
+ {
+ int msb = highbit(size);
+ if (RTL_ARENA_FREELIST_SIZE == SAL_INT_CAST(size_t, msb))
+ {
+ /* highest possible freelist: fall back to first fit */
+ rtl_arena_segment_type *head, *segment;
+
+ head = &(arena->m_freelist_head[msb - 1]);
+ for (segment = head->m_fnext; segment != head; segment = segment->m_fnext)
+ {
+ if (segment->m_size >= size)
+ {
+ /* allocate first fit segment */
+ (*ppSegment) = segment;
+ break;
+ }
+ }
+ goto dequeue_and_leave;
+ }
+
+ /* roundup to next power of 2 */
+ size = (1UL << msb);
+ }
+
+ index = lowbit(RTL_MEMORY_P2ALIGN(arena->m_freelist_bitmap, size));
+ if (index > 0)
+ {
+ /* instant fit: allocate first free segment */
+ rtl_arena_segment_type *head;
+
+ head = &(arena->m_freelist_head[index - 1]);
+ (*ppSegment) = head->m_fnext;
+ OSL_ASSERT((*ppSegment) != head);
+ }
+
+dequeue_and_leave:
+ if (*ppSegment != 0)
+ {
+ /* remove from freelist */
+ rtl_arena_freelist_remove (arena, (*ppSegment));
+ }
+ return (*ppSegment != 0);
+}
+
+
+/** rtl_arena_segment_create()
+ * import new (span) segment from source arena
+ *
+ * @precond arena->m_lock acquired
+ * @precond (*ppSegment == 0)
+ */
+static int
+rtl_arena_segment_create (
+ rtl_arena_type * arena,
+ sal_Size size,
+ rtl_arena_segment_type ** ppSegment
+)
+{
+ OSL_ASSERT((*ppSegment) == 0);
+ if (arena->m_source_alloc != 0)
+ {
+ rtl_arena_segment_get (arena, ppSegment);
+ if (*ppSegment != 0)
+ {
+ rtl_arena_segment_type * span = 0;
+ rtl_arena_segment_get (arena, &span);
+ if (span != 0)
+ {
+ /* import new span from source arena */
+ RTL_MEMORY_LOCK_RELEASE(&(arena->m_lock));
+
+ span->m_size = size;
+ span->m_addr = (sal_uIntPtr)(arena->m_source_alloc)(
+ arena->m_source_arena, &(span->m_size));
+
+ RTL_MEMORY_LOCK_ACQUIRE(&(arena->m_lock));
+ if (span->m_addr != 0)
+ {
+ /* insert onto segment list, update stats */
+ span->m_type = RTL_ARENA_SEGMENT_TYPE_SPAN;
+ QUEUE_INSERT_HEAD_NAMED(&(arena->m_segment_head), span, s);
+ arena->m_stats.m_mem_total += span->m_size;
+
+ (*ppSegment)->m_addr = span->m_addr;
+ (*ppSegment)->m_size = span->m_size;
+ (*ppSegment)->m_type = RTL_ARENA_SEGMENT_TYPE_FREE;
+ QUEUE_INSERT_HEAD_NAMED(span, (*ppSegment), s);
+
+ /* report success */
+ return (1);
+ }
+ rtl_arena_segment_put (arena, &span);
+ }
+ rtl_arena_segment_put (arena, ppSegment);
+ }
+ }
+ return (0);
+}
+
+
+/** rtl_arena_segment_coalesce()
+ * mark as free and join with adjacent free segment(s)
+ *
+ * @precond arena->m_lock acquired
+ * @precond segment marked 'used'
+ */
+static void
+rtl_arena_segment_coalesce (
+ rtl_arena_type * arena,
+ rtl_arena_segment_type * segment
+)
+{
+ rtl_arena_segment_type *next, *prev;
+
+ /* mark segment free */
+ OSL_ASSERT(segment->m_type == RTL_ARENA_SEGMENT_TYPE_USED);
+ segment->m_type = RTL_ARENA_SEGMENT_TYPE_FREE;
+
+ /* try to merge w/ next segment */
+ next = segment->m_snext;
+ if (next->m_type == RTL_ARENA_SEGMENT_TYPE_FREE)
+ {
+ OSL_ASSERT(segment->m_addr + segment->m_size == next->m_addr);
+ segment->m_size += next->m_size;
+
+ /* remove from freelist */
+ rtl_arena_freelist_remove (arena, next);
+
+ /* remove from segment list */
+ QUEUE_REMOVE_NAMED(next, s);
+
+ /* release segment descriptor */
+ rtl_arena_segment_put (arena, &next);
+ }
+
+ /* try to merge w/ prev segment */
+ prev = segment->m_sprev;
+ if (prev->m_type == RTL_ARENA_SEGMENT_TYPE_FREE)
+ {
+ OSL_ASSERT(prev->m_addr + prev->m_size == segment->m_addr);
+ segment->m_addr = prev->m_addr;
+ segment->m_size += prev->m_size;
+
+ /* remove from freelist */
+ rtl_arena_freelist_remove (arena, prev);
+
+ /* remove from segment list */
+ QUEUE_REMOVE_NAMED(prev, s);
+
+ /* release segment descriptor */
+ rtl_arena_segment_put (arena, &prev);
+ }
+}
+
+/* ================================================================= */
+
+/** rtl_arena_constructor()
+ */
+static void
+rtl_arena_constructor (void * obj)
+{
+ rtl_arena_type * arena = (rtl_arena_type*)(obj);
+ rtl_arena_segment_type * head;
+ size_t i;
+
+ memset (arena, 0, sizeof(rtl_arena_type));
+
+ QUEUE_START_NAMED(arena, arena_);
+
+ (void) RTL_MEMORY_LOCK_INIT(&(arena->m_lock));
+
+ head = &(arena->m_segment_reserve_span_head);
+ rtl_arena_segment_constructor (head);
+ head->m_type = RTL_ARENA_SEGMENT_TYPE_HEAD;
+
+ head = &(arena->m_segment_reserve_head);
+ rtl_arena_segment_constructor (head);
+ head->m_type = RTL_ARENA_SEGMENT_TYPE_HEAD;
+
+ head = &(arena->m_segment_head);
+ rtl_arena_segment_constructor (head);
+ head->m_type = RTL_ARENA_SEGMENT_TYPE_HEAD;
+
+ for (i = 0; i < RTL_ARENA_FREELIST_SIZE; i++)
+ {
+ head = &(arena->m_freelist_head[i]);
+ rtl_arena_segment_constructor (head);
+
+ head->m_size = (1UL << i);
+ head->m_type = RTL_ARENA_SEGMENT_TYPE_HEAD;
+ }
+
+ arena->m_hash_table = arena->m_hash_table_0;
+ arena->m_hash_size = RTL_ARENA_HASH_SIZE;
+ arena->m_hash_shift = highbit(arena->m_hash_size) - 1;
+}
+
+
+/** rtl_arena_destructor()
+ */
+static void
+rtl_arena_destructor (void * obj)
+{
+ rtl_arena_type * arena = (rtl_arena_type*)(obj);
+ rtl_arena_segment_type * head;
+ size_t i;
+
+ OSL_ASSERT(QUEUE_STARTED_NAMED(arena, arena_));
+
+ RTL_MEMORY_LOCK_DESTROY(&(arena->m_lock));
+
+ head = &(arena->m_segment_reserve_span_head);
+ OSL_ASSERT(head->m_type == RTL_ARENA_SEGMENT_TYPE_HEAD);
+ rtl_arena_segment_destructor (head);
+
+ head = &(arena->m_segment_reserve_head);
+ OSL_ASSERT(head->m_type == RTL_ARENA_SEGMENT_TYPE_HEAD);
+ rtl_arena_segment_destructor (head);
+
+ head = &(arena->m_segment_head);
+ OSL_ASSERT(head->m_type == RTL_ARENA_SEGMENT_TYPE_HEAD);
+ rtl_arena_segment_destructor (head);
+
+ for (i = 0; i < RTL_ARENA_FREELIST_SIZE; i++)
+ {
+ head = &(arena->m_freelist_head[i]);
+
+ OSL_ASSERT(head->m_size == (1UL << i));
+ OSL_ASSERT(head->m_type == RTL_ARENA_SEGMENT_TYPE_HEAD);
+
+ rtl_arena_segment_destructor (head);
+ }
+
+ OSL_ASSERT(arena->m_hash_table == arena->m_hash_table_0);
+ OSL_ASSERT(arena->m_hash_size == RTL_ARENA_HASH_SIZE);
+ OSL_ASSERT(
+ arena->m_hash_shift ==
+ SAL_INT_CAST(unsigned, highbit(arena->m_hash_size) - 1));
+}
+
+/* ================================================================= */
+
+/** rtl_arena_activate()
+ */
+static rtl_arena_type *
+rtl_arena_activate (
+ rtl_arena_type * arena,
+ const char * name,
+ sal_Size quantum,
+ sal_Size quantum_cache_max,
+ rtl_arena_type * source_arena,
+ void * (SAL_CALL * source_alloc)(rtl_arena_type *, sal_Size *),
+ void (SAL_CALL * source_free) (rtl_arena_type *, void *, sal_Size)
+)
+{
+ OSL_ASSERT(arena != 0);
+ if (arena != 0)
+ {
+ (void) snprintf (arena->m_name, sizeof(arena->m_name), "%s", name);
+
+ if (!RTL_MEMORY_ISP2(quantum))
+ {
+ /* roundup to next power of 2 */
+ quantum = (1UL << highbit(quantum));
+ }
+ quantum_cache_max = RTL_MEMORY_P2ROUNDUP(quantum_cache_max, quantum);
+
+ arena->m_quantum = quantum;
+ arena->m_quantum_shift = highbit(arena->m_quantum) - 1;
+ arena->m_qcache_max = quantum_cache_max;
+
+ arena->m_source_arena = source_arena;
+ arena->m_source_alloc = source_alloc;
+ arena->m_source_free = source_free;
+
+ if (arena->m_qcache_max > 0)
+ {
+ char name[RTL_ARENA_NAME_LENGTH + 1];
+ int i, n = (arena->m_qcache_max >> arena->m_quantum_shift);
+
+ sal_Size size = n * sizeof(rtl_cache_type*);
+ arena->m_qcache_ptr = (rtl_cache_type**)rtl_arena_alloc (gp_arena_arena, &size);
+ if (!(arena->m_qcache_ptr))
+ {
+ /* out of memory */
+ return (0);
+ }
+ for (i = 1; i <= n; i++)
+ {
+ size = i * arena->m_quantum;
+ (void) snprintf (name, sizeof(name), "%s_%lu", arena->m_name, size);
+ arena->m_qcache_ptr[i - 1] = rtl_cache_create(name, size, 0, NULL, NULL, NULL, NULL, arena, RTL_CACHE_FLAG_QUANTUMCACHE);
+ }
+ }
+
+ /* insert into arena list */
+ RTL_MEMORY_LOCK_ACQUIRE(&(g_arena_list.m_lock));
+ QUEUE_INSERT_TAIL_NAMED(&(g_arena_list.m_arena_head), arena, arena_);
+ RTL_MEMORY_LOCK_RELEASE(&(g_arena_list.m_lock));
+ }
+ return (arena);
+}
+
+/** rtl_arena_deactivate()
+ */
+static void
+rtl_arena_deactivate (
+ rtl_arena_type * arena
+)
+{
+ rtl_arena_segment_type * head, * segment;
+
+ /* remove from arena list */
+ RTL_MEMORY_LOCK_ACQUIRE(&(g_arena_list.m_lock));
+ QUEUE_REMOVE_NAMED(arena, arena_);
+ RTL_MEMORY_LOCK_RELEASE(&(g_arena_list.m_lock));
+
+ /* cleanup quantum cache(s) */
+ if ((arena->m_qcache_max > 0) && (arena->m_qcache_ptr != 0))
+ {
+ int i, n = (arena->m_qcache_max >> arena->m_quantum_shift);
+ for (i = 1; i <= n; i++)
+ {
+ if (arena->m_qcache_ptr[i - 1] != 0)
+ {
+ rtl_cache_destroy (arena->m_qcache_ptr[i - 1]);
+ arena->m_qcache_ptr[i - 1] = 0;
+ }
+ }
+ rtl_arena_free (
+ gp_arena_arena,
+ arena->m_qcache_ptr,
+ n * sizeof(rtl_cache_type*));
+
+ arena->m_qcache_ptr = 0;
+ }
+
+ /* check for leaked segments */
+ OSL_TRACE(
+ "rtl_arena_deactivate(\"%s\"): "
+ "allocs: %"PRIu64", frees: %"PRIu64"; total: %lu, used: %lu",
+ arena->m_name,
+ arena->m_stats.m_alloc, arena->m_stats.m_free,
+ arena->m_stats.m_mem_total, arena->m_stats.m_mem_alloc
+ );
+ if (arena->m_stats.m_alloc > arena->m_stats.m_free)
+ {
+ sal_Size i, n;
+
+ OSL_TRACE(
+ "rtl_arena_deactivate(\"%s\"): "
+ "cleaning up %"PRIu64" leaked segment(s) [%lu bytes]",
+ arena->m_name,
+ arena->m_stats.m_alloc - arena->m_stats.m_free,
+ arena->m_stats.m_mem_alloc
+ );
+
+ /* cleanup still used segment(s) */
+ for (i = 0, n = arena->m_hash_size; i < n; i++)
+ {
+ while ((segment = arena->m_hash_table[i]) != 0)
+ {
+ /* pop from hash table */
+ arena->m_hash_table[i] = segment->m_fnext, segment->m_fnext = segment->m_fprev = segment;
+
+ /* coalesce w/ adjacent free segment(s) */
+ rtl_arena_segment_coalesce (arena, segment);
+
+ /* insert onto freelist */
+ rtl_arena_freelist_insert (arena, segment);
+ }
+ }
+ }
+
+ /* cleanup hash table */
+ if (arena->m_hash_table != arena->m_hash_table_0)
+ {
+ rtl_arena_free (
+ gp_arena_arena,
+ arena->m_hash_table,
+ arena->m_hash_size * sizeof(rtl_arena_segment_type*));
+
+ arena->m_hash_table = arena->m_hash_table_0;
+ arena->m_hash_size = RTL_ARENA_HASH_SIZE;
+ arena->m_hash_shift = highbit(arena->m_hash_size) - 1;
+ }
+
+ /* cleanup segment list */
+ head = &(arena->m_segment_head);
+ for (segment = head->m_snext; segment != head; segment = head->m_snext)
+ {
+ if (segment->m_type == RTL_ARENA_SEGMENT_TYPE_FREE)
+ {
+ /* remove from freelist */
+ rtl_arena_freelist_remove (arena, segment);
+ }
+ else
+ {
+ /* can have only free and span segments here */
+ OSL_ASSERT(segment->m_type == RTL_ARENA_SEGMENT_TYPE_SPAN);
+ }
+
+ /* remove from segment list */
+ QUEUE_REMOVE_NAMED(segment, s);
+
+ /* release segment descriptor */
+ rtl_arena_segment_put (arena, &segment);
+ }
+
+ /* cleanup segment reserve list */
+ head = &(arena->m_segment_reserve_head);
+ for (segment = head->m_snext; segment != head; segment = head->m_snext)
+ {
+ /* remove from segment list */
+ QUEUE_REMOVE_NAMED(segment, s);
+ }
+
+ /* cleanup segment reserve span(s) */
+ head = &(arena->m_segment_reserve_span_head);
+ for (segment = head->m_snext; segment != head; segment = head->m_snext)
+ {
+ /* can have only span segments here */
+ OSL_ASSERT(segment->m_type == RTL_ARENA_SEGMENT_TYPE_SPAN);
+
+ /* remove from segment list */
+ QUEUE_REMOVE_NAMED(segment, s);
+
+ /* return span to g_machdep_arena */
+ rtl_machdep_free (gp_machdep_arena, (void*)(segment->m_addr), segment->m_size);
+ }
+}
+
+/* ================================================================= *
+ *
+ * arena implementation.
+ *
+ * ================================================================= */
+
+/** rtl_arena_create()
+ */
+rtl_arena_type *
+SAL_CALL rtl_arena_create (
+ const char * name,
+ sal_Size quantum,
+ sal_Size quantum_cache_max,
+ rtl_arena_type * source_arena,
+ void * (SAL_CALL * source_alloc)(rtl_arena_type *, sal_Size *),
+ void (SAL_CALL * source_free) (rtl_arena_type *, void *, sal_Size),
+ int flags
+) SAL_THROW_EXTERN_C()
+{
+ rtl_arena_type * result = 0;
+ sal_Size size = sizeof(rtl_arena_type);
+
+ (void) flags; /* unused */
+
+try_alloc:
+ result = (rtl_arena_type*)rtl_arena_alloc (gp_arena_arena, &size);
+ if (result != 0)
+ {
+ rtl_arena_type * arena = result;
+ rtl_arena_constructor (arena);
+
+ if (!source_arena)
+ {
+ OSL_ASSERT(gp_default_arena != 0);
+ source_arena = gp_default_arena;
+ }
+
+ result = rtl_arena_activate (
+ arena,
+ name,
+ quantum,
+ quantum_cache_max,
+ source_arena,
+ source_alloc,
+ source_free
+ );
+
+ if (result == 0)
+ {
+ rtl_arena_deactivate (arena);
+ rtl_arena_destructor (arena);
+ rtl_arena_free (gp_arena_arena, arena, size);
+ }
+ }
+ else if (gp_arena_arena == 0)
+ {
+ if (rtl_arena_init())
+ {
+ /* try again */
+ goto try_alloc;
+ }
+ }
+ return (result);
+}
+
+/** rtl_arena_destroy()
+ */
+void
+SAL_CALL rtl_arena_destroy (
+ rtl_arena_type * arena
+)
+{
+ if (arena != 0)
+ {
+ rtl_arena_deactivate (arena);
+ rtl_arena_destructor (arena);
+ rtl_arena_free (gp_arena_arena, arena, sizeof(rtl_arena_type));
+ }
+}
+
+/** rtl_arena_alloc()
+ */
+void *
+SAL_CALL rtl_arena_alloc (
+ rtl_arena_type * arena,
+ sal_Size * pSize
+) SAL_THROW_EXTERN_C()
+{
+ void * addr = 0;
+
+ if ((arena != 0) && (pSize != 0))
+ {
+ sal_Size size = RTL_MEMORY_ALIGN((*pSize), arena->m_quantum);
+ if (size > arena->m_qcache_max)
+ {
+ /* allocate from segment list */
+ rtl_arena_segment_type *segment = 0;
+
+ RTL_MEMORY_LOCK_ACQUIRE(&(arena->m_lock));
+ if (rtl_arena_segment_alloc (arena, size, &segment) ||
+ rtl_arena_segment_create(arena, size, &segment) )
+ {
+ /* shrink to fit */
+ sal_Size oversize;
+
+ /* mark segment used */
+ OSL_ASSERT(segment->m_type == RTL_ARENA_SEGMENT_TYPE_FREE);
+ segment->m_type = RTL_ARENA_SEGMENT_TYPE_USED;
+
+ /* resize */
+ OSL_ASSERT(segment->m_size >= size);
+ oversize = segment->m_size - size;
+ if (oversize >= SAL_MAX(arena->m_quantum, arena->m_qcache_max))
+ {
+ rtl_arena_segment_type * remainder = 0;
+ rtl_arena_segment_get (arena, &remainder);
+ if (remainder != 0)
+ {
+ segment->m_size = size;
+
+ remainder->m_addr = segment->m_addr + segment->m_size;
+ remainder->m_size = oversize;
+ remainder->m_type = RTL_ARENA_SEGMENT_TYPE_FREE;
+ QUEUE_INSERT_HEAD_NAMED(segment, remainder, s);
+
+ rtl_arena_freelist_insert (arena, remainder);
+ }
+ }
+
+ rtl_arena_hash_insert (arena, segment);
+
+ (*pSize) = segment->m_size;
+ addr = (void*)(segment->m_addr);
+ }
+ RTL_MEMORY_LOCK_RELEASE(&(arena->m_lock));
+ }
+ else if (size > 0)
+ {
+ /* allocate from quantum cache(s) */
+ int index = (size >> arena->m_quantum_shift) - 1;
+ OSL_ASSERT (arena->m_qcache_ptr[index] != 0);
+
+ addr = rtl_cache_alloc (arena->m_qcache_ptr[index]);
+ if (addr != 0)
+ (*pSize) = size;
+ }
+ }
+ return (addr);
+}
+
+/** rtl_arena_free()
+ */
+void
+SAL_CALL rtl_arena_free (
+ rtl_arena_type * arena,
+ void * addr,
+ sal_Size size
+) SAL_THROW_EXTERN_C()
+{
+ if (arena != 0)
+ {
+ size = RTL_MEMORY_ALIGN(size, arena->m_quantum);
+ if (size > arena->m_qcache_max)
+ {
+ /* free to segment list */
+ rtl_arena_segment_type * segment;
+
+ RTL_MEMORY_LOCK_ACQUIRE(&(arena->m_lock));
+
+ segment = rtl_arena_hash_remove (arena, (sal_uIntPtr)(addr), size);
+ if (segment != 0)
+ {
+ rtl_arena_segment_type *next, *prev;
+
+ /* coalesce w/ adjacent free segment(s) */
+ rtl_arena_segment_coalesce (arena, segment);
+
+ /* determine (new) next and prev segment */
+ next = segment->m_snext, prev = segment->m_sprev;
+
+ /* entire span free when prev is a span, and next is either a span or a list head */
+ if (((prev->m_type == RTL_ARENA_SEGMENT_TYPE_SPAN)) &&
+ ((next->m_type == RTL_ARENA_SEGMENT_TYPE_SPAN) ||
+ (next->m_type == RTL_ARENA_SEGMENT_TYPE_HEAD)) )
+ {
+ OSL_ASSERT((prev->m_addr == segment->m_addr) &&
+ (prev->m_size == segment->m_size) );
+
+ if (arena->m_source_free)
+ {
+ addr = (void*)(prev->m_addr);
+ size = prev->m_size;
+
+ /* remove from segment list */
+ QUEUE_REMOVE_NAMED(segment, s);
+
+ /* release segment descriptor */
+ rtl_arena_segment_put (arena, &segment);
+
+ /* remove from segment list */
+ QUEUE_REMOVE_NAMED(prev, s);
+
+ /* release (span) segment descriptor */
+ rtl_arena_segment_put (arena, &prev);
+
+ /* update stats, return span to source arena */
+ arena->m_stats.m_mem_total -= size;
+ RTL_MEMORY_LOCK_RELEASE(&(arena->m_lock));
+
+ (arena->m_source_free)(arena->m_source_arena, addr, size);
+ return;
+ }
+ }
+
+ /* insert onto freelist */
+ rtl_arena_freelist_insert (arena, segment);
+ }
+
+ RTL_MEMORY_LOCK_RELEASE(&(arena->m_lock));
+ }
+ else if (size > 0)
+ {
+ /* free to quantum cache(s) */
+ int index = (size >> arena->m_quantum_shift) - 1;
+ OSL_ASSERT (arena->m_qcache_ptr[index] != 0);
+
+ rtl_cache_free (arena->m_qcache_ptr[index], addr);
+ }
+ }
+}
+
+/* ================================================================= *
+ *
+ * machdep internals.
+ *
+ * ================================================================= */
+
+#if defined(SAL_UNX)
+#include <sys/mman.h>
+#elif defined(SAL_W32) || defined(SAL_OS2)
+#define MAP_FAILED 0
+#endif /* SAL_UNX || SAL_W32 */
+
+/** rtl_machdep_alloc()
+ */
+static void *
+SAL_CALL rtl_machdep_alloc (
+ rtl_arena_type * pArena,
+ sal_Size * pSize
+)
+{
+ void * addr;
+ sal_Size size = (*pSize);
+
+ OSL_PRECOND(pArena == gp_machdep_arena, "rtl_machdep_alloc(): invalid argument");
+
+#if defined(SOLARIS) && defined(SPARC)
+ /* see @ mmap(2) man pages */
+ size += (pArena->m_quantum + pArena->m_quantum); /* "red-zone" pages */
+ if (size > (4 << 20))
+ size = RTL_MEMORY_P2ROUNDUP(size, (4 << 20));
+ else if (size > (512 << 10))
+ size = RTL_MEMORY_P2ROUNDUP(size, (512 << 10));
+ else
+ size = RTL_MEMORY_P2ROUNDUP(size, (64 << 10));
+ size -= (pArena->m_quantum + pArena->m_quantum); /* "red-zone" pages */
+#else
+ /* default allocation granularity */
+ size = RTL_MEMORY_P2ROUNDUP(size, SAL_MAX(pArena->m_quantum, 64 << 10));
+#endif
+
+#if defined(SAL_UNX)
+ addr = mmap (NULL, (size_t)(size), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+#elif defined(SAL_W32)
+ addr = VirtualAlloc (NULL, (SIZE_T)(size), MEM_COMMIT, PAGE_READWRITE);
+#elif defined(SAL_OS2)
+ {
+ APIRET rc;
+ addr = 0;
+ // Use DosAlloc* to get a 4KB page aligned address.
+ rc = DosAllocMem( &addr, size, PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_ANY);
+ if (rc) {
+ fprintf( stderr, "sal3::DosAllocMem failed rc=%d\n", rc);
+ addr = 0;
+ }
+ }
+#endif /* (SAL_UNX || SAL_W32 || SAL_OS2) */
+
+ if (addr != MAP_FAILED)
+ {
+ pArena->m_stats.m_alloc += 1;
+ pArena->m_stats.m_mem_total += size;
+ pArena->m_stats.m_mem_alloc += size;
+
+ (*pSize) = size;
+ return (addr);
+ }
+ return (NULL);
+}
+
+/** rtl_machdep_free()
+ */
+static void
+SAL_CALL rtl_machdep_free (
+ rtl_arena_type * pArena,
+ void * pAddr,
+ sal_Size nSize
+)
+{
+ OSL_PRECOND(pArena == gp_machdep_arena, "rtl_machdep_free(): invalid argument");
+
+ pArena->m_stats.m_free += 1;
+ pArena->m_stats.m_mem_total -= nSize;
+ pArena->m_stats.m_mem_alloc -= nSize;
+
+#if defined(SAL_UNX)
+ (void) munmap(pAddr, nSize);
+#elif defined(SAL_W32)
+ (void) VirtualFree ((LPVOID)(pAddr), (SIZE_T)(0), MEM_RELEASE);
+#elif defined(SAL_OS2)
+ (void) DosFreeMem( pAddr);
+#endif /* (SAL_UNX || SAL_W32) */
+}
+
+/** rtl_machdep_pagesize()
+ */
+static sal_Size
+rtl_machdep_pagesize (void)
+{
+#if defined(SAL_UNX)
+#if defined(FREEBSD) || defined(NETBSD)
+ return ((sal_Size)getpagesize());
+#else /* POSIX */
+ return ((sal_Size)sysconf(_SC_PAGESIZE));
+#endif /* xBSD || POSIX */
+#elif defined(SAL_W32)
+ SYSTEM_INFO info;
+ GetSystemInfo (&info);
+ return ((sal_Size)(info.dwPageSize));
+#elif defined(SAL_OS2)
+ ULONG ulPageSize;
+ DosQuerySysInfo(QSV_PAGE_SIZE, QSV_PAGE_SIZE, &ulPageSize, sizeof(ULONG));
+ return ((sal_Size)ulPageSize);
+#endif /* (SAL_UNX || SAL_W32) */
+}
+
+/* ================================================================= *
+ *
+ * arena initialization.
+ *
+ * ================================================================= */
+
+static void
+rtl_arena_once_init (void)
+{
+ {
+ /* list of arenas */
+ RTL_MEMORY_LOCK_INIT(&(g_arena_list.m_lock));
+ rtl_arena_constructor (&(g_arena_list.m_arena_head));
+ }
+ {
+ /* machdep (pseudo) arena */
+ static rtl_arena_type g_machdep_arena;
+
+ OSL_ASSERT(gp_machdep_arena == 0);
+ rtl_arena_constructor (&g_machdep_arena);
+
+ gp_machdep_arena = rtl_arena_activate (
+ &g_machdep_arena,
+ "rtl_machdep_arena",
+ rtl_machdep_pagesize(),
+ 0, /* no quantum caching */
+ 0, 0, 0 /* no source */
+ );
+ OSL_ASSERT(gp_machdep_arena != 0);
+ }
+ {
+ /* default arena */
+ static rtl_arena_type g_default_arena;
+
+ OSL_ASSERT(gp_default_arena == 0);
+ rtl_arena_constructor (&g_default_arena);
+
+ gp_default_arena = rtl_arena_activate (
+ &g_default_arena,
+ "rtl_default_arena",
+ rtl_machdep_pagesize(),
+ 0, /* no quantum caching */
+ gp_machdep_arena, /* source */
+ rtl_machdep_alloc,
+ rtl_machdep_free
+ );
+ OSL_ASSERT(gp_default_arena != 0);
+ }
+ {
+ /* arena internal arena */
+ static rtl_arena_type g_arena_arena;
+
+ OSL_ASSERT(gp_arena_arena == 0);
+ rtl_arena_constructor (&g_arena_arena);
+
+ gp_arena_arena = rtl_arena_activate (
+ &g_arena_arena,
+ "rtl_arena_internal_arena",
+ 64, /* quantum */
+ 0, /* no quantum caching */
+ gp_default_arena, /* source */
+ rtl_arena_alloc,
+ rtl_arena_free
+ );
+ OSL_ASSERT(gp_arena_arena != 0);
+ }
+}
+
+static int
+rtl_arena_init (void)
+{
+ static sal_once_type g_once = SAL_ONCE_INIT;
+ SAL_ONCE(&g_once, rtl_arena_once_init);
+ return (gp_arena_arena != 0);
+}
+
+/* ================================================================= */
+
+#if defined(__GNUC__)
+static void rtl_arena_fini (void) __attribute__((destructor));
+#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+#pragma fini(rtl_arena_fini)
+static void rtl_arena_fini (void);
+#endif /* __GNUC__ || __SUNPRO_C */
+
+void
+rtl_arena_fini (void)
+{
+ if (gp_arena_arena != 0)
+ {
+ rtl_arena_type * arena, * head;
+
+ RTL_MEMORY_LOCK_ACQUIRE(&(g_arena_list.m_lock));
+ head = &(g_arena_list.m_arena_head);
+
+ for (arena = head->m_arena_next; arena != head; arena = arena->m_arena_next)
+ {
+ OSL_TRACE(
+ "rtl_arena_fini(\"%s\"): "
+ "allocs: %"PRIu64", frees: %"PRIu64"; total: %lu, used: %lu",
+ arena->m_name,
+ arena->m_stats.m_alloc, arena->m_stats.m_free,
+ arena->m_stats.m_mem_total, arena->m_stats.m_mem_alloc
+ );
+ }
+ RTL_MEMORY_LOCK_RELEASE(&(g_arena_list.m_lock));
+ }
+}
+
+/* ================================================================= */
diff --git a/sal/rtl/source/alloc_arena.h b/sal/rtl/source/alloc_arena.h
new file mode 100644
index 000000000000..45907802dba9
--- /dev/null
+++ b/sal/rtl/source/alloc_arena.h
@@ -0,0 +1,137 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_RTL_ALLOC_ARENA_H
+#define INCLUDED_RTL_ALLOC_ARENA_H
+
+#include "sal/types.h"
+#include "rtl/alloc.h"
+#include "alloc_impl.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** rtl_arena_stat_type
+ * @internal
+ */
+typedef struct rtl_arena_stat_st rtl_arena_stat_type;
+struct rtl_arena_stat_st
+{
+ sal_uInt64 m_alloc;
+ sal_uInt64 m_free;
+
+ sal_Size m_mem_total;
+ sal_Size m_mem_alloc;
+};
+
+
+/** rtl_arena_segment_type
+ * @internal
+ */
+#define RTL_ARENA_SEGMENT_TYPE_HEAD ((sal_Size)(0x01))
+#define RTL_ARENA_SEGMENT_TYPE_SPAN ((sal_Size)(0x02))
+#define RTL_ARENA_SEGMENT_TYPE_FREE ((sal_Size)(0x04))
+#define RTL_ARENA_SEGMENT_TYPE_USED ((sal_Size)(0x08))
+
+typedef struct rtl_arena_segment_st rtl_arena_segment_type;
+struct rtl_arena_segment_st
+{
+ /* segment list linkage */
+ rtl_arena_segment_type * m_snext;
+ rtl_arena_segment_type * m_sprev;
+
+ /* free/used list linkage */
+ rtl_arena_segment_type * m_fnext;
+ rtl_arena_segment_type * m_fprev;
+
+ /* segment description */
+ sal_uIntPtr m_addr;
+ sal_Size m_size;
+ sal_Size m_type;
+};
+
+
+/** rtl_arena_type
+ * @internal
+ */
+#define RTL_ARENA_FREELIST_SIZE (sizeof(void*) * 8)
+#define RTL_ARENA_HASH_SIZE 64
+
+#define RTL_ARENA_FLAG_RESCALE 1 /* within hash rescale operation */
+
+struct rtl_arena_st
+{
+ /* linkage */
+ rtl_arena_type * m_arena_next;
+ rtl_arena_type * m_arena_prev;
+
+ /* properties */
+ char m_name[RTL_ARENA_NAME_LENGTH + 1];
+ long m_flags;
+
+ rtl_memory_lock_type m_lock;
+ rtl_arena_stat_type m_stats;
+
+ rtl_arena_type * m_source_arena;
+ void * (SAL_CALL * m_source_alloc)(rtl_arena_type *, sal_Size *);
+ void (SAL_CALL * m_source_free) (rtl_arena_type *, void *, sal_Size);
+
+ sal_Size m_quantum;
+ sal_Size m_quantum_shift; /* log2(m_quantum) */
+
+ rtl_arena_segment_type m_segment_reserve_span_head;
+ rtl_arena_segment_type m_segment_reserve_head;
+
+ rtl_arena_segment_type m_segment_head;
+
+ rtl_arena_segment_type m_freelist_head[RTL_ARENA_FREELIST_SIZE];
+ sal_Size m_freelist_bitmap;
+
+ rtl_arena_segment_type ** m_hash_table;
+ rtl_arena_segment_type * m_hash_table_0[RTL_ARENA_HASH_SIZE];
+ sal_Size m_hash_size; /* m_hash_mask + 1 */
+ sal_Size m_hash_shift; /* log2(m_hash_size) */
+
+ sal_Size m_qcache_max;
+ rtl_cache_type ** m_qcache_ptr;
+};
+
+
+/** gp_default_arena
+ * default arena with pagesize quantum
+ *
+ * @internal
+ */
+extern rtl_arena_type * gp_default_arena;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* INCLUDED_RTL_ALLOC_ARENA_H */
diff --git a/sal/rtl/source/alloc_cache.c b/sal/rtl/source/alloc_cache.c
new file mode 100644
index 000000000000..4e2c030fb3a6
--- /dev/null
+++ b/sal/rtl/source/alloc_cache.c
@@ -0,0 +1,1721 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "alloc_cache.h"
+#include "alloc_impl.h"
+#include "alloc_arena.h"
+#include "internal/once.h"
+#include "sal/macros.h"
+#include "osl/diagnose.h"
+
+#ifndef INCLUDED_STRING_H
+#include <string.h>
+#endif
+
+#ifndef INCLUDED_STDIO_H
+#include <stdio.h>
+#endif
+
+#ifdef OS2
+#undef OSL_TRACE
+#define OSL_TRACE 1 ? ((void)0) : _OSL_GLOBAL osl_trace
+#endif
+
+/* ================================================================= *
+ *
+ * cache internals.
+ *
+ * ================================================================= */
+
+/** g_cache_list
+ * @internal
+ */
+struct rtl_cache_list_st
+{
+ rtl_memory_lock_type m_lock;
+ rtl_cache_type m_cache_head;
+
+#if defined(SAL_UNX) || defined(SAL_OS2)
+ pthread_t m_update_thread;
+ pthread_cond_t m_update_cond;
+#elif defined(SAL_W32)
+ HANDLE m_update_thread;
+ HANDLE m_update_cond;
+#endif /* SAL_UNX || SAL_W32 */
+ int m_update_done;
+};
+
+static struct rtl_cache_list_st g_cache_list;
+
+
+/** gp_cache_arena
+ * provided for cache_type allocations, and hash_table resizing.
+ *
+ * @internal
+ */
+static rtl_arena_type * gp_cache_arena = 0;
+
+
+/** gp_cache_magazine_cache
+ * @internal
+ */
+static rtl_cache_type * gp_cache_magazine_cache = 0;
+
+
+/** gp_cache_slab_cache
+ * @internal
+ */
+static rtl_cache_type * gp_cache_slab_cache = 0;
+
+
+/** gp_cache_bufctl_cache
+ * @internal
+ */
+static rtl_cache_type * gp_cache_bufctl_cache = 0;
+
+
+/** rtl_cache_init()
+ * @internal
+ */
+static int
+rtl_cache_init (void);
+
+
+/* ================================================================= */
+
+/** RTL_CACHE_HASH_INDEX()
+ */
+#define RTL_CACHE_HASH_INDEX_IMPL(a, s, q, m) \
+ ((((a) + ((a) >> (s)) + ((a) >> ((s) << 1))) >> (q)) & (m))
+
+#define RTL_CACHE_HASH_INDEX(cache, addr) \
+ RTL_CACHE_HASH_INDEX_IMPL((addr), (cache)->m_hash_shift, (cache)->m_type_shift, ((cache)->m_hash_size - 1))
+
+
+/** rtl_cache_hash_rescale()
+ */
+static void
+rtl_cache_hash_rescale (
+ rtl_cache_type * cache,
+ sal_Size new_size
+)
+{
+ rtl_cache_bufctl_type ** new_table;
+ sal_Size new_bytes;
+
+ new_bytes = new_size * sizeof(rtl_cache_bufctl_type*);
+ new_table = (rtl_cache_bufctl_type**)rtl_arena_alloc(gp_cache_arena, &new_bytes);
+
+ if (new_table != 0)
+ {
+ rtl_cache_bufctl_type ** old_table;
+ sal_Size old_size, i;
+
+ memset (new_table, 0, new_bytes);
+
+ RTL_MEMORY_LOCK_ACQUIRE(&(cache->m_slab_lock));
+
+ old_table = cache->m_hash_table;
+ old_size = cache->m_hash_size;
+
+ OSL_TRACE(
+ "rtl_cache_hash_rescale(\"%s\"): "
+ "nbuf: % " PRIu64 " (ave: %" PRIu64 "), frees: %" PRIu64 " "
+ "[old_size: %lu, new_size: %lu]",
+ cache->m_name,
+ cache->m_slab_stats.m_alloc - cache->m_slab_stats.m_free,
+ (cache->m_slab_stats.m_alloc - cache->m_slab_stats.m_free) >> cache->m_hash_shift,
+ cache->m_slab_stats.m_free,
+ old_size, new_size);
+
+ cache->m_hash_table = new_table;
+ cache->m_hash_size = new_size;
+ cache->m_hash_shift = highbit(cache->m_hash_size) - 1;
+
+ for (i = 0; i < old_size; i++)
+ {
+ rtl_cache_bufctl_type * curr = old_table[i];
+ while (curr != 0)
+ {
+ rtl_cache_bufctl_type * next = curr->m_next;
+ rtl_cache_bufctl_type ** head;
+
+ head = &(cache->m_hash_table[RTL_CACHE_HASH_INDEX(cache, curr->m_addr)]);
+ curr->m_next = (*head);
+ (*head) = curr;
+
+ curr = next;
+ }
+ old_table[i] = 0;
+ }
+
+ RTL_MEMORY_LOCK_RELEASE(&(cache->m_slab_lock));
+
+ if (old_table != cache->m_hash_table_0)
+ {
+ sal_Size old_bytes = old_size * sizeof(rtl_cache_bufctl_type*);
+ rtl_arena_free (gp_cache_arena, old_table, old_bytes);
+ }
+ }
+}
+
+/** rtl_cache_hash_insert()
+ */
+static RTL_MEMORY_INLINE sal_uIntPtr
+rtl_cache_hash_insert (
+ rtl_cache_type * cache,
+ rtl_cache_bufctl_type * bufctl
+)
+{
+ rtl_cache_bufctl_type ** ppHead;
+
+ ppHead = &(cache->m_hash_table[RTL_CACHE_HASH_INDEX(cache, bufctl->m_addr)]);
+
+ bufctl->m_next = (*ppHead);
+ (*ppHead) = bufctl;
+
+ return (bufctl->m_addr);
+}
+
+#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+#pragma inline(rtl_cache_hash_insert)
+#endif /* __SUNPRO_C */
+
+
+/** rtl_cache_hash_remove()
+ */
+static rtl_cache_bufctl_type *
+rtl_cache_hash_remove (
+ rtl_cache_type * cache,
+ sal_uIntPtr addr
+)
+{
+ rtl_cache_bufctl_type ** ppHead;
+ rtl_cache_bufctl_type * bufctl;
+ sal_Size lookups = 0;
+
+ ppHead = &(cache->m_hash_table[RTL_CACHE_HASH_INDEX(cache, addr)]);
+ while ((bufctl = *ppHead) != 0)
+ {
+ if (bufctl->m_addr == addr)
+ {
+ *ppHead = bufctl->m_next, bufctl->m_next = 0;
+ break;
+ }
+
+ lookups += 1;
+ ppHead = &(bufctl->m_next);
+ }
+
+ OSL_ASSERT (bufctl != 0); /* bad free */
+
+ if (lookups > 1)
+ {
+ sal_Size nbuf = (sal_Size)(cache->m_slab_stats.m_alloc - cache->m_slab_stats.m_free);
+ if (nbuf > 4 * cache->m_hash_size)
+ {
+ if (!(cache->m_features & RTL_CACHE_FEATURE_RESCALE))
+ {
+ sal_Size ave = nbuf >> cache->m_hash_shift;
+ sal_Size new_size = cache->m_hash_size << (highbit(ave) - 1);
+
+ cache->m_features |= RTL_CACHE_FEATURE_RESCALE;
+ RTL_MEMORY_LOCK_RELEASE(&(cache->m_slab_lock));
+ rtl_cache_hash_rescale (cache, new_size);
+ RTL_MEMORY_LOCK_ACQUIRE(&(cache->m_slab_lock));
+ cache->m_features &= ~RTL_CACHE_FEATURE_RESCALE;
+ }
+ }
+ }
+
+ return (bufctl);
+}
+
+/* ================================================================= */
+
+/** RTL_CACHE_SLAB()
+ */
+#define RTL_CACHE_SLAB(addr, size) \
+ (((rtl_cache_slab_type*)(RTL_MEMORY_P2END((sal_uIntPtr)(addr), (size)))) - 1)
+
+
+/** rtl_cache_slab_constructor()
+ */
+static int
+rtl_cache_slab_constructor (void * obj, void * arg)
+{
+ rtl_cache_slab_type * slab = (rtl_cache_slab_type*)(obj);
+
+ (void) arg; /* unused */
+
+ QUEUE_START_NAMED(slab, slab_);
+ slab->m_ntypes = 0;
+
+ return (1);
+}
+
+
+/** rtl_cache_slab_destructor()
+ */
+static void
+rtl_cache_slab_destructor (void * obj, void * arg)
+{
+#if OSL_DEBUG_LEVEL == 0
+ (void) obj; /* unused */
+#else /* OSL_DEBUG_LEVEL */
+ rtl_cache_slab_type * slab = (rtl_cache_slab_type*)(obj);
+
+ /* assure removed from queue(s) */
+ OSL_ASSERT(QUEUE_STARTED_NAMED(slab, slab_));
+
+ /* assure no longer referenced */
+ OSL_ASSERT(slab->m_ntypes == 0);
+#endif /* OSL_DEBUG_LEVEL */
+
+ (void) arg; /* unused */
+}
+
+
+/** rtl_cache_slab_create()
+ *
+ * @precond cache->m_slab_lock released.
+ */
+static rtl_cache_slab_type *
+rtl_cache_slab_create (
+ rtl_cache_type * cache
+)
+{
+ rtl_cache_slab_type * slab = 0;
+ void * addr;
+ sal_Size size;
+
+ size = cache->m_slab_size;
+ addr = rtl_arena_alloc (cache->m_source, &size);
+ if (addr != 0)
+ {
+ OSL_ASSERT(size >= cache->m_slab_size);
+
+ if (cache->m_features & RTL_CACHE_FEATURE_HASH)
+ {
+ /* allocate slab struct from slab cache */
+ OSL_ASSERT (cache != gp_cache_slab_cache);
+ slab = (rtl_cache_slab_type*)rtl_cache_alloc (gp_cache_slab_cache);
+ }
+ else
+ {
+ /* construct embedded slab struct */
+ slab = RTL_CACHE_SLAB(addr, cache->m_slab_size);
+ (void) rtl_cache_slab_constructor (slab, 0);
+ }
+ if (slab != 0)
+ {
+ slab->m_data = (sal_uIntPtr)(addr);
+
+ /* dynamic freelist initialization */
+ slab->m_bp = slab->m_data;
+ slab->m_sp = 0;
+ }
+ else
+ {
+ rtl_arena_free (cache->m_source, addr, size);
+ }
+ }
+ return (slab);
+}
+
+
+/** rtl_cache_slab_destroy()
+ *
+ * @precond cache->m_slab_lock released.
+ */
+static void
+rtl_cache_slab_destroy (
+ rtl_cache_type * cache,
+ rtl_cache_slab_type * slab
+)
+{
+ void * addr = (void*)(slab->m_data);
+ sal_Size refcnt = slab->m_ntypes; slab->m_ntypes = 0;
+
+ if (cache->m_features & RTL_CACHE_FEATURE_HASH)
+ {
+ /* cleanup bufctl(s) for free buffer(s) */
+ sal_Size ntypes = (slab->m_bp - slab->m_data) / cache->m_type_size;
+ for (ntypes -= refcnt; slab->m_sp != 0; ntypes--)
+ {
+ rtl_cache_bufctl_type * bufctl = slab->m_sp;
+
+ /* pop from freelist */
+ slab->m_sp = bufctl->m_next, bufctl->m_next = 0;
+
+ /* return bufctl struct to bufctl cache */
+ rtl_cache_free (gp_cache_bufctl_cache, bufctl);
+ }
+ OSL_ASSERT(ntypes == 0);
+
+ /* return slab struct to slab cache */
+ rtl_cache_free (gp_cache_slab_cache, slab);
+ }
+ else
+ {
+ /* destruct embedded slab struct */
+ rtl_cache_slab_destructor (slab, 0);
+ }
+
+ if ((refcnt == 0) || (cache->m_features & RTL_CACHE_FEATURE_BULKDESTROY))
+ {
+ /* free memory */
+ rtl_arena_free (cache->m_source, addr, cache->m_slab_size);
+ }
+}
+
+
+/** rtl_cache_slab_populate()
+ *
+ * @precond cache->m_slab_lock acquired.
+ */
+static int
+rtl_cache_slab_populate (
+ rtl_cache_type * cache
+)
+{
+ rtl_cache_slab_type * slab;
+
+ RTL_MEMORY_LOCK_RELEASE(&(cache->m_slab_lock));
+ slab = rtl_cache_slab_create (cache);
+ RTL_MEMORY_LOCK_ACQUIRE(&(cache->m_slab_lock));
+ if (slab != 0)
+ {
+ /* update buffer start addr w/ current color */
+ slab->m_bp += cache->m_ncolor;
+
+ /* update color for next slab */
+ cache->m_ncolor += cache->m_type_align;
+ if (cache->m_ncolor > cache->m_ncolor_max)
+ cache->m_ncolor = 0;
+
+ /* update stats */
+ cache->m_slab_stats.m_mem_total += cache->m_slab_size;
+
+ /* insert onto 'free' queue */
+ QUEUE_INSERT_HEAD_NAMED(&(cache->m_free_head), slab, slab_);
+ }
+ return (slab != 0);
+}
+
+/* ================================================================= */
+
+/** rtl_cache_slab_alloc()
+ *
+ * Allocate a buffer from slab layer; used by magazine layer.
+ */
+static void *
+rtl_cache_slab_alloc (
+ rtl_cache_type * cache
+)
+{
+ void * addr = 0;
+ rtl_cache_slab_type * head;
+
+ RTL_MEMORY_LOCK_ACQUIRE(&(cache->m_slab_lock));
+
+ head = &(cache->m_free_head);
+ if ((head->m_slab_next != head) || rtl_cache_slab_populate (cache))
+ {
+ rtl_cache_slab_type * slab;
+ rtl_cache_bufctl_type * bufctl;
+
+ slab = head->m_slab_next;
+ OSL_ASSERT(slab->m_ntypes < cache->m_ntypes);
+
+ if (slab->m_sp == 0)
+ {
+ /* initialize bufctl w/ current 'slab->m_bp' */
+ OSL_ASSERT (slab->m_bp < slab->m_data + cache->m_ntypes * cache->m_type_size + cache->m_ncolor_max);
+ if (cache->m_features & RTL_CACHE_FEATURE_HASH)
+ {
+ /* allocate bufctl */
+ OSL_ASSERT (cache != gp_cache_bufctl_cache);
+ bufctl = (rtl_cache_bufctl_type*)rtl_cache_alloc (gp_cache_bufctl_cache);
+ if (bufctl == 0)
+ {
+ /* out of memory */
+ RTL_MEMORY_LOCK_RELEASE(&(cache->m_slab_lock));
+ return (0);
+ }
+
+ bufctl->m_addr = slab->m_bp;
+ bufctl->m_slab = (sal_uIntPtr)(slab);
+ }
+ else
+ {
+ /* embedded bufctl */
+ bufctl = (rtl_cache_bufctl_type*)(slab->m_bp);
+ }
+ bufctl->m_next = 0;
+
+ /* update 'slab->m_bp' to next free buffer */
+ slab->m_bp += cache->m_type_size;
+
+ /* assign bufctl to freelist */
+ slab->m_sp = bufctl;
+ }
+
+ /* pop front */
+ bufctl = slab->m_sp;
+ slab->m_sp = bufctl->m_next;
+
+ /* increment usage, check for full slab */
+ if ((slab->m_ntypes += 1) == cache->m_ntypes)
+ {
+ /* remove from 'free' queue */
+ QUEUE_REMOVE_NAMED(slab, slab_);
+
+ /* insert onto 'used' queue (tail) */
+ QUEUE_INSERT_TAIL_NAMED(&(cache->m_used_head), slab, slab_);
+ }
+
+ /* update stats */
+ cache->m_slab_stats.m_alloc += 1;
+ cache->m_slab_stats.m_mem_alloc += cache->m_type_size;
+
+ if (cache->m_features & RTL_CACHE_FEATURE_HASH)
+ addr = (void*)rtl_cache_hash_insert (cache, bufctl);
+ else
+ addr = bufctl;
+ }
+
+ RTL_MEMORY_LOCK_RELEASE(&(cache->m_slab_lock));
+ return (addr);
+}
+
+
+/** rtl_cache_slab_free()
+ *
+ * Return a buffer to slab layer; used by magazine layer.
+ */
+static void
+rtl_cache_slab_free (
+ rtl_cache_type * cache,
+ void * addr
+)
+{
+ rtl_cache_bufctl_type * bufctl;
+ rtl_cache_slab_type * slab;
+
+ RTL_MEMORY_LOCK_ACQUIRE(&(cache->m_slab_lock));
+
+ /* determine slab from addr */
+ if (cache->m_features & RTL_CACHE_FEATURE_HASH)
+ {
+ bufctl = rtl_cache_hash_remove (cache, (sal_uIntPtr)(addr));
+ slab = (bufctl != 0) ? (rtl_cache_slab_type*)(bufctl->m_slab) : 0;
+ }
+ else
+ {
+ /* embedded slab struct */
+ bufctl = (rtl_cache_bufctl_type*)(addr);
+ slab = RTL_CACHE_SLAB(addr, cache->m_slab_size);
+ }
+
+ if (slab != 0)
+ {
+ /* check for full slab */
+ if (slab->m_ntypes == cache->m_ntypes)
+ {
+ /* remove from 'used' queue */
+ QUEUE_REMOVE_NAMED(slab, slab_);
+
+ /* insert onto 'free' queue (head) */
+ QUEUE_INSERT_HEAD_NAMED(&(cache->m_free_head), slab, slab_);
+ }
+
+ /* push front */
+ bufctl->m_next = slab->m_sp;
+ slab->m_sp = bufctl;
+
+ /* update stats */
+ cache->m_slab_stats.m_free += 1;
+ cache->m_slab_stats.m_mem_alloc -= cache->m_type_size;
+
+ /* decrement usage, check for empty slab */
+ if ((slab->m_ntypes -= 1) == 0)
+ {
+ /* remove from 'free' queue */
+ QUEUE_REMOVE_NAMED(slab, slab_);
+
+ /* update stats */
+ cache->m_slab_stats.m_mem_total -= cache->m_slab_size;
+
+ /* free 'empty' slab */
+ RTL_MEMORY_LOCK_RELEASE(&(cache->m_slab_lock));
+ rtl_cache_slab_destroy (cache, slab);
+ return;
+ }
+ }
+
+ RTL_MEMORY_LOCK_RELEASE(&(cache->m_slab_lock));
+}
+
+/* ================================================================= */
+
+/** rtl_cache_magazine_constructor()
+ */
+static int
+rtl_cache_magazine_constructor (void * obj, void * arg)
+{
+ rtl_cache_magazine_type * mag = (rtl_cache_magazine_type*)(obj);
+ /* @@@ sal_Size size = (sal_Size)(arg); @@@ */
+
+ (void) arg; /* unused */
+
+ mag->m_mag_next = 0;
+ mag->m_mag_size = RTL_CACHE_MAGAZINE_SIZE;
+ mag->m_mag_used = 0;
+
+ return (1);
+}
+
+
+/** rtl_cache_magazine_destructor()
+ */
+static void
+rtl_cache_magazine_destructor (void * obj, void * arg)
+{
+#if OSL_DEBUG_LEVEL == 0
+ (void) obj; /* unused */
+#else /* OSL_DEBUG_LEVEL */
+ rtl_cache_magazine_type * mag = (rtl_cache_magazine_type*)(obj);
+
+ /* assure removed from queue(s) */
+ OSL_ASSERT(mag->m_mag_next == 0);
+
+ /* assure no longer referenced */
+ OSL_ASSERT(mag->m_mag_used == 0);
+#endif /* OSL_DEBUG_LEVEL */
+
+ (void) arg; /* unused */
+}
+
+
+/** rtl_cache_magazine_clear()
+ */
+static void
+rtl_cache_magazine_clear (
+ rtl_cache_type * cache,
+ rtl_cache_magazine_type * mag
+)
+{
+ for (; mag->m_mag_used > 0; --mag->m_mag_used)
+ {
+ void * obj = mag->m_objects[mag->m_mag_used - 1];
+ mag->m_objects[mag->m_mag_used - 1] = 0;
+
+ if (cache->m_destructor != 0)
+ {
+ /* destruct object */
+ (cache->m_destructor)(obj, cache->m_userarg);
+ }
+
+ /* return buffer to slab layer */
+ rtl_cache_slab_free (cache, obj);
+ }
+}
+
+/* ================================================================= */
+
+/** rtl_cache_depot_enqueue()
+ *
+ * @precond cache->m_depot_lock acquired.
+ */
+static RTL_MEMORY_INLINE void
+rtl_cache_depot_enqueue (
+ rtl_cache_depot_type * depot,
+ rtl_cache_magazine_type * mag
+)
+{
+ /* enqueue empty magazine */
+ mag->m_mag_next = depot->m_mag_next;
+ depot->m_mag_next = mag;
+
+ /* update depot stats */
+ depot->m_mag_count++;
+}
+
+#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+#pragma inline(rtl_cache_depot_enqueue)
+#endif /* __SUNPRO_C */
+
+
+/** rtl_cache_depot_dequeue()
+ *
+ * @precond cache->m_depot_lock acquired.
+ */
+static RTL_MEMORY_INLINE rtl_cache_magazine_type *
+rtl_cache_depot_dequeue (
+ rtl_cache_depot_type * depot
+)
+{
+ rtl_cache_magazine_type * mag = 0;
+ if (depot->m_mag_count > 0)
+ {
+ /* dequeue magazine */
+ OSL_ASSERT(depot->m_mag_next != 0);
+
+ mag = depot->m_mag_next;
+ depot->m_mag_next = mag->m_mag_next;
+ mag->m_mag_next = 0;
+
+ /* update depot stats */
+ depot->m_mag_count--;
+ depot->m_curr_min = SAL_MIN(depot->m_curr_min, depot->m_mag_count);
+ }
+ return (mag);
+}
+
+#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+#pragma inline(rtl_cache_depot_dequeue)
+#endif /* __SUNPRO_C */
+
+
+/** rtl_cache_depot_exchange_alloc()
+ *
+ * @precond cache->m_depot_lock acquired.
+ */
+static RTL_MEMORY_INLINE rtl_cache_magazine_type *
+rtl_cache_depot_exchange_alloc (
+ rtl_cache_type * cache,
+ rtl_cache_magazine_type * empty
+)
+{
+ rtl_cache_magazine_type * full;
+
+ OSL_ASSERT((empty == 0) || (empty->m_mag_used == 0));
+
+ /* dequeue full magazine */
+ full = rtl_cache_depot_dequeue (&(cache->m_depot_full));
+ if ((full != 0) && (empty != 0))
+ {
+ /* enqueue empty magazine */
+ rtl_cache_depot_enqueue (&(cache->m_depot_empty), empty);
+ }
+
+ OSL_ASSERT((full == 0) || (full->m_mag_used > 0));
+
+ return (full);
+}
+
+#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+#pragma inline(rtl_cache_depot_exchange_alloc)
+#endif /* __SUNPRO_C */
+
+
+/** rtl_cache_depot_exchange_free()
+ *
+ * @precond cache->m_depot_lock acquired.
+ */
+static RTL_MEMORY_INLINE rtl_cache_magazine_type *
+rtl_cache_depot_exchange_free (
+ rtl_cache_type * cache,
+ rtl_cache_magazine_type * full
+)
+{
+ rtl_cache_magazine_type * empty;
+
+ OSL_ASSERT((full == 0) || (full->m_mag_used > 0));
+
+ /* dequeue empty magazine */
+ empty = rtl_cache_depot_dequeue (&(cache->m_depot_empty));
+ if ((empty != 0) && (full != 0))
+ {
+ /* enqueue full magazine */
+ rtl_cache_depot_enqueue (&(cache->m_depot_full), full);
+ }
+
+ OSL_ASSERT((empty == 0) || (empty->m_mag_used == 0));
+
+ return (empty);
+}
+
+#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+#pragma inline(rtl_cache_depot_exchange_free)
+#endif /* __SUNPRO_C */
+
+
+/** rtl_cache_depot_populate()
+ *
+ * @precond cache->m_depot_lock acquired.
+ */
+static int
+rtl_cache_depot_populate (
+ rtl_cache_type * cache
+)
+{
+ rtl_cache_magazine_type * empty = 0;
+
+ if (cache->m_magazine_cache != 0)
+ {
+ /* allocate new empty magazine */
+ RTL_MEMORY_LOCK_RELEASE(&(cache->m_depot_lock));
+ empty = (rtl_cache_magazine_type*)rtl_cache_alloc (cache->m_magazine_cache);
+ RTL_MEMORY_LOCK_ACQUIRE(&(cache->m_depot_lock));
+ if (empty != 0)
+ {
+ /* enqueue (new) empty magazine */
+ rtl_cache_depot_enqueue (&(cache->m_depot_empty), empty);
+ }
+ }
+ return (empty != 0);
+}
+
+/* ================================================================= */
+
+/** rtl_cache_constructor()
+ */
+static int
+rtl_cache_constructor (void * obj)
+{
+ rtl_cache_type * cache = (rtl_cache_type*)(obj);
+
+ memset (cache, 0, sizeof(rtl_cache_type));
+
+ /* linkage */
+ QUEUE_START_NAMED(cache, cache_);
+
+ /* slab layer */
+ (void)RTL_MEMORY_LOCK_INIT(&(cache->m_slab_lock));
+
+ QUEUE_START_NAMED(&(cache->m_free_head), slab_);
+ QUEUE_START_NAMED(&(cache->m_used_head), slab_);
+
+ cache->m_hash_table = cache->m_hash_table_0;
+ cache->m_hash_size = RTL_CACHE_HASH_SIZE;
+ cache->m_hash_shift = highbit(cache->m_hash_size) - 1;
+
+ /* depot layer */
+ (void)RTL_MEMORY_LOCK_INIT(&(cache->m_depot_lock));
+
+ return (1);
+}
+
+/** rtl_cache_destructor()
+ */
+static void
+rtl_cache_destructor (void * obj)
+{
+ rtl_cache_type * cache = (rtl_cache_type*)(obj);
+
+ /* linkage */
+ OSL_ASSERT(QUEUE_STARTED_NAMED(cache, cache_));
+
+ /* slab layer */
+ (void)RTL_MEMORY_LOCK_DESTROY(&(cache->m_slab_lock));
+
+ OSL_ASSERT(QUEUE_STARTED_NAMED(&(cache->m_free_head), slab_));
+ OSL_ASSERT(QUEUE_STARTED_NAMED(&(cache->m_used_head), slab_));
+
+ OSL_ASSERT(cache->m_hash_table == cache->m_hash_table_0);
+ OSL_ASSERT(cache->m_hash_size == RTL_CACHE_HASH_SIZE);
+ OSL_ASSERT(cache->m_hash_shift == (sal_Size)(highbit(cache->m_hash_size) - 1));
+
+ /* depot layer */
+ (void)RTL_MEMORY_LOCK_DESTROY(&(cache->m_depot_lock));
+}
+
+/* ================================================================= */
+
+/** rtl_cache_activate()
+ */
+static rtl_cache_type *
+rtl_cache_activate (
+ rtl_cache_type * cache,
+ const char * name,
+ size_t objsize,
+ size_t objalign,
+ int (SAL_CALL * constructor)(void * obj, void * userarg),
+ void (SAL_CALL * destructor) (void * obj, void * userarg),
+ void (SAL_CALL * reclaim) (void * userarg),
+ void * userarg,
+ rtl_arena_type * source,
+ int flags
+)
+{
+ OSL_ASSERT(cache != 0);
+ if (cache != 0)
+ {
+ sal_Size slabsize;
+
+ snprintf (cache->m_name, sizeof(cache->m_name), "%s", name);
+
+ /* ensure minimum size (embedded bufctl linkage) */
+ objsize = SAL_MAX(objsize, sizeof(rtl_cache_bufctl_type*));
+
+ if (objalign == 0)
+ {
+ /* determine default alignment */
+ if (objsize >= RTL_MEMORY_ALIGNMENT_8)
+ objalign = RTL_MEMORY_ALIGNMENT_8;
+ else
+ objalign = RTL_MEMORY_ALIGNMENT_4;
+ }
+ else
+ {
+ /* ensure minimum alignment */
+ objalign = SAL_MAX(objalign, RTL_MEMORY_ALIGNMENT_4);
+ }
+ OSL_ASSERT(RTL_MEMORY_ISP2(objalign));
+
+ cache->m_type_size = objsize = RTL_MEMORY_P2ROUNDUP(objsize, objalign);
+ cache->m_type_align = objalign;
+ cache->m_type_shift = highbit(cache->m_type_size) - 1;
+
+ cache->m_constructor = constructor;
+ cache->m_destructor = destructor;
+ cache->m_reclaim = reclaim;
+ cache->m_userarg = userarg;
+
+ /* slab layer */
+ cache->m_source = source;
+
+ slabsize = source->m_quantum; /* minimum slab size */
+ if (flags & RTL_CACHE_FLAG_QUANTUMCACHE)
+ {
+ /* next power of 2 above 3 * qcache_max */
+ slabsize = SAL_MAX(slabsize, (1UL << highbit(3 * source->m_qcache_max)));
+ }
+ else
+ {
+ /* waste at most 1/8 of slab */
+ slabsize = SAL_MAX(slabsize, cache->m_type_size * 8);
+ }
+
+ slabsize = RTL_MEMORY_P2ROUNDUP(slabsize, source->m_quantum);
+ if (!RTL_MEMORY_ISP2(slabsize))
+ slabsize = 1UL << highbit(slabsize);
+ cache->m_slab_size = slabsize;
+
+ if (cache->m_slab_size > source->m_quantum)
+ {
+ OSL_ASSERT(gp_cache_slab_cache != 0);
+ OSL_ASSERT(gp_cache_bufctl_cache != 0);
+
+ cache->m_features |= RTL_CACHE_FEATURE_HASH;
+ cache->m_ntypes = cache->m_slab_size / cache->m_type_size;
+ cache->m_ncolor_max = cache->m_slab_size % cache->m_type_size;
+ }
+ else
+ {
+ /* embedded slab struct */
+ cache->m_ntypes = (cache->m_slab_size - sizeof(rtl_cache_slab_type)) / cache->m_type_size;
+ cache->m_ncolor_max = (cache->m_slab_size - sizeof(rtl_cache_slab_type)) % cache->m_type_size;
+ }
+
+ OSL_ASSERT(cache->m_ntypes > 0);
+ cache->m_ncolor = 0;
+
+ if (flags & RTL_CACHE_FLAG_BULKDESTROY)
+ {
+ /* allow bulk slab delete upon cache deactivation */
+ cache->m_features |= RTL_CACHE_FEATURE_BULKDESTROY;
+ }
+
+ /* magazine layer */
+ if (!(flags & RTL_CACHE_FLAG_NOMAGAZINE))
+ {
+ OSL_ASSERT(gp_cache_magazine_cache != 0);
+ cache->m_magazine_cache = gp_cache_magazine_cache;
+ }
+
+ /* insert into cache list */
+ RTL_MEMORY_LOCK_ACQUIRE(&(g_cache_list.m_lock));
+ QUEUE_INSERT_TAIL_NAMED(&(g_cache_list.m_cache_head), cache, cache_);
+ RTL_MEMORY_LOCK_RELEASE(&(g_cache_list.m_lock));
+ }
+ return (cache);
+}
+
+/** rtl_cache_deactivate()
+ */
+static void
+rtl_cache_deactivate (
+ rtl_cache_type * cache
+)
+{
+ /* remove from cache list */
+ RTL_MEMORY_LOCK_ACQUIRE(&(g_cache_list.m_lock));
+ QUEUE_REMOVE_NAMED(cache, cache_);
+ RTL_MEMORY_LOCK_RELEASE(&(g_cache_list.m_lock));
+
+ /* cleanup magazine layer */
+ if (cache->m_magazine_cache != 0)
+ {
+ rtl_cache_type * mag_cache;
+ rtl_cache_magazine_type * mag;
+
+ /* prevent recursion */
+ mag_cache = cache->m_magazine_cache, cache->m_magazine_cache = 0;
+
+ /* cleanup cpu layer */
+ if ((mag = cache->m_cpu_curr) != 0)
+ {
+ cache->m_cpu_curr = 0;
+ rtl_cache_magazine_clear (cache, mag);
+ rtl_cache_free (mag_cache, mag);
+ }
+ if ((mag = cache->m_cpu_prev) != 0)
+ {
+ cache->m_cpu_prev = 0;
+ rtl_cache_magazine_clear (cache, mag);
+ rtl_cache_free (mag_cache, mag);
+ }
+
+ /* cleanup depot layer */
+ while ((mag = rtl_cache_depot_dequeue(&(cache->m_depot_full))) != 0)
+ {
+ rtl_cache_magazine_clear (cache, mag);
+ rtl_cache_free (mag_cache, mag);
+ }
+ while ((mag = rtl_cache_depot_dequeue(&(cache->m_depot_empty))) != 0)
+ {
+ rtl_cache_magazine_clear (cache, mag);
+ rtl_cache_free (mag_cache, mag);
+ }
+ }
+
+ OSL_TRACE(
+ "rtl_cache_deactivate(\"%s\"): "
+ "[slab]: allocs: %"PRIu64", frees: %"PRIu64"; total: %lu, used: %lu; "
+ "[cpu]: allocs: %"PRIu64", frees: %"PRIu64"; "
+ "[total]: allocs: %"PRIu64", frees: %"PRIu64"",
+ cache->m_name,
+ cache->m_slab_stats.m_alloc, cache->m_slab_stats.m_free,
+ cache->m_slab_stats.m_mem_total, cache->m_slab_stats.m_mem_alloc,
+ cache->m_cpu_stats.m_alloc, cache->m_cpu_stats.m_free,
+ cache->m_slab_stats.m_alloc + cache->m_cpu_stats.m_alloc,
+ cache->m_slab_stats.m_free + cache->m_cpu_stats.m_free
+ );
+
+ /* cleanup slab layer */
+ if (cache->m_slab_stats.m_alloc > cache->m_slab_stats.m_free)
+ {
+ OSL_TRACE(
+ "rtl_cache_deactivate(\"%s\"): "
+ "cleaning up %"PRIu64" leaked buffer(s) [%lu bytes] [%lu total]",
+ cache->m_name,
+ cache->m_slab_stats.m_alloc - cache->m_slab_stats.m_free,
+ cache->m_slab_stats.m_mem_alloc, cache->m_slab_stats.m_mem_total
+ );
+
+ if (cache->m_features & RTL_CACHE_FEATURE_HASH)
+ {
+ /* cleanup bufctl(s) for leaking buffer(s) */
+ sal_Size i, n = cache->m_hash_size;
+ for (i = 0; i < n; i++)
+ {
+ rtl_cache_bufctl_type * bufctl;
+ while ((bufctl = cache->m_hash_table[i]) != 0)
+ {
+ /* pop from hash table */
+ cache->m_hash_table[i] = bufctl->m_next, bufctl->m_next = 0;
+
+ /* return to bufctl cache */
+ rtl_cache_free (gp_cache_bufctl_cache, bufctl);
+ }
+ }
+ }
+ {
+ /* force cleanup of remaining slabs */
+ rtl_cache_slab_type *head, *slab;
+
+ head = &(cache->m_used_head);
+ for (slab = head->m_slab_next; slab != head; slab = head->m_slab_next)
+ {
+ /* remove from 'used' queue */
+ QUEUE_REMOVE_NAMED(slab, slab_);
+
+ /* update stats */
+ cache->m_slab_stats.m_mem_total -= cache->m_slab_size;
+
+ /* free slab */
+ rtl_cache_slab_destroy (cache, slab);
+ }
+
+ head = &(cache->m_free_head);
+ for (slab = head->m_slab_next; slab != head; slab = head->m_slab_next)
+ {
+ /* remove from 'free' queue */
+ QUEUE_REMOVE_NAMED(slab, slab_);
+
+ /* update stats */
+ cache->m_slab_stats.m_mem_total -= cache->m_slab_size;
+
+ /* free slab */
+ rtl_cache_slab_destroy (cache, slab);
+ }
+ }
+ }
+
+ if (cache->m_hash_table != cache->m_hash_table_0)
+ {
+ rtl_arena_free (
+ gp_cache_arena,
+ cache->m_hash_table,
+ cache->m_hash_size * sizeof(rtl_cache_bufctl_type*));
+
+ cache->m_hash_table = cache->m_hash_table_0;
+ cache->m_hash_size = RTL_CACHE_HASH_SIZE;
+ cache->m_hash_shift = highbit(cache->m_hash_size) - 1;
+ }
+}
+
+/* ================================================================= *
+ *
+ * cache implementation.
+ *
+ * ================================================================= */
+
+/** rtl_cache_create()
+ */
+rtl_cache_type *
+SAL_CALL rtl_cache_create (
+ const char * name,
+ sal_Size objsize,
+ sal_Size objalign,
+ int (SAL_CALL * constructor)(void * obj, void * userarg),
+ void (SAL_CALL * destructor) (void * obj, void * userarg),
+ void (SAL_CALL * reclaim) (void * userarg),
+ void * userarg,
+ rtl_arena_type * source,
+ int flags
+) SAL_THROW_EXTERN_C()
+{
+ rtl_cache_type * result = 0;
+ sal_Size size = sizeof(rtl_cache_type);
+
+try_alloc:
+ result = (rtl_cache_type*)rtl_arena_alloc (gp_cache_arena, &size);
+ if (result != 0)
+ {
+ rtl_cache_type * cache = result;
+ (void) rtl_cache_constructor (cache);
+
+ if (!source)
+ {
+ /* use default arena */
+ OSL_ASSERT(gp_default_arena != 0);
+ source = gp_default_arena;
+ }
+
+ result = rtl_cache_activate (
+ cache,
+ name,
+ objsize,
+ objalign,
+ constructor,
+ destructor,
+ reclaim,
+ userarg,
+ source,
+ flags
+ );
+
+ if (result == 0)
+ {
+ /* activation failed */
+ rtl_cache_deactivate (cache);
+ rtl_cache_destructor (cache);
+ rtl_arena_free (gp_cache_arena, cache, size);
+ }
+ }
+ else if (gp_cache_arena == 0)
+ {
+ if (rtl_cache_init())
+ {
+ /* try again */
+ goto try_alloc;
+ }
+ }
+ return (result);
+}
+
+/** rtl_cache_destroy()
+ */
+void SAL_CALL rtl_cache_destroy (
+ rtl_cache_type * cache
+) SAL_THROW_EXTERN_C()
+{
+ if (cache != 0)
+ {
+ rtl_cache_deactivate (cache);
+ rtl_cache_destructor (cache);
+ rtl_arena_free (gp_cache_arena, cache, sizeof(rtl_cache_type));
+ }
+}
+
+/** rtl_cache_alloc()
+ */
+void *
+SAL_CALL rtl_cache_alloc (
+ rtl_cache_type * cache
+) SAL_THROW_EXTERN_C()
+{
+ void * obj = 0;
+
+ if (cache == 0)
+ return (0);
+
+ if (cache->m_cpu_curr != 0)
+ {
+ RTL_MEMORY_LOCK_ACQUIRE(&(cache->m_depot_lock));
+
+ for (;;)
+ {
+ /* take object from magazine layer */
+ rtl_cache_magazine_type *curr, *prev, *temp;
+
+ curr = cache->m_cpu_curr;
+ if ((curr != 0) && (curr->m_mag_used > 0))
+ {
+ obj = curr->m_objects[--curr->m_mag_used];
+ cache->m_cpu_stats.m_alloc += 1;
+ RTL_MEMORY_LOCK_RELEASE(&(cache->m_depot_lock));
+
+ return (obj);
+ }
+
+ prev = cache->m_cpu_prev;
+ if ((prev != 0) && (prev->m_mag_used > 0))
+ {
+ temp = cache->m_cpu_curr;
+ cache->m_cpu_curr = cache->m_cpu_prev;
+ cache->m_cpu_prev = temp;
+
+ continue;
+ }
+
+ temp = rtl_cache_depot_exchange_alloc (cache, prev);
+ if (temp != 0)
+ {
+ cache->m_cpu_prev = cache->m_cpu_curr;
+ cache->m_cpu_curr = temp;
+
+ continue;
+ }
+
+ /* no full magazine: fall through to slab layer */
+ break;
+ }
+
+ RTL_MEMORY_LOCK_RELEASE(&(cache->m_depot_lock));
+ }
+
+ /* alloc buffer from slab layer */
+ obj = rtl_cache_slab_alloc (cache);
+ if ((obj != 0) && (cache->m_constructor != 0))
+ {
+ /* construct object */
+ if (!((cache->m_constructor)(obj, cache->m_userarg)))
+ {
+ /* construction failure */
+ rtl_cache_slab_free (cache, obj), obj = 0;
+ }
+ }
+
+ return (obj);
+}
+
+/** rtl_cache_free()
+ */
+void
+SAL_CALL rtl_cache_free (
+ rtl_cache_type * cache,
+ void * obj
+) SAL_THROW_EXTERN_C()
+{
+ if ((obj != 0) && (cache != 0))
+ {
+ RTL_MEMORY_LOCK_ACQUIRE(&(cache->m_depot_lock));
+
+ for (;;)
+ {
+ /* return object to magazine layer */
+ rtl_cache_magazine_type *curr, *prev, *temp;
+
+ curr = cache->m_cpu_curr;
+ if ((curr != 0) && (curr->m_mag_used < curr->m_mag_size))
+ {
+ curr->m_objects[curr->m_mag_used++] = obj;
+ cache->m_cpu_stats.m_free += 1;
+ RTL_MEMORY_LOCK_RELEASE(&(cache->m_depot_lock));
+
+ return;
+ }
+
+ prev = cache->m_cpu_prev;
+ if ((prev != 0) && (prev->m_mag_used == 0))
+ {
+ temp = cache->m_cpu_curr;
+ cache->m_cpu_curr = cache->m_cpu_prev;
+ cache->m_cpu_prev = temp;
+
+ continue;
+ }
+
+ temp = rtl_cache_depot_exchange_free (cache, prev);
+ if (temp != 0)
+ {
+ cache->m_cpu_prev = cache->m_cpu_curr;
+ cache->m_cpu_curr = temp;
+
+ continue;
+ }
+
+ if (rtl_cache_depot_populate(cache) != 0)
+ {
+ continue;
+ }
+
+ /* no empty magazine: fall through to slab layer */
+ break;
+ }
+
+ RTL_MEMORY_LOCK_RELEASE(&(cache->m_depot_lock));
+
+ /* no space for constructed object in magazine layer */
+ if (cache->m_destructor != 0)
+ {
+ /* destruct object */
+ (cache->m_destructor)(obj, cache->m_userarg);
+ }
+
+ /* return buffer to slab layer */
+ rtl_cache_slab_free (cache, obj);
+ }
+}
+
+/* ================================================================= *
+ *
+ * cache wsupdate (machdep) internals.
+ *
+ * ================================================================= */
+
+/** rtl_cache_wsupdate_init()
+ *
+ * @precond g_cache_list.m_lock initialized
+ */
+static void
+rtl_cache_wsupdate_init (void);
+
+
+/** rtl_cache_wsupdate_wait()
+ *
+ * @precond g_cache_list.m_lock acquired
+ */
+static void
+rtl_cache_wsupdate_wait (
+ unsigned int seconds
+);
+
+/** rtl_cache_wsupdate_fini()
+ *
+ */
+static void
+rtl_cache_wsupdate_fini (void);
+
+/* ================================================================= */
+
+#if defined(SAL_UNX) || defined(SAL_OS2)
+
+#include <sys/time.h>
+
+static void *
+rtl_cache_wsupdate_all (void * arg);
+
+static void
+rtl_cache_wsupdate_init (void)
+{
+ RTL_MEMORY_LOCK_ACQUIRE(&(g_cache_list.m_lock));
+ g_cache_list.m_update_done = 0;
+ (void) pthread_cond_init (&(g_cache_list.m_update_cond), NULL);
+ if (pthread_create (
+ &(g_cache_list.m_update_thread), NULL, rtl_cache_wsupdate_all, (void*)(10)) != 0)
+ {
+ /* failure */
+ g_cache_list.m_update_thread = (pthread_t)(0);
+ }
+ RTL_MEMORY_LOCK_RELEASE(&(g_cache_list.m_lock));
+}
+
+static void
+rtl_cache_wsupdate_wait (unsigned int seconds)
+{
+ if (seconds > 0)
+ {
+ struct timeval now;
+ struct timespec wakeup;
+
+ gettimeofday(&now, 0);
+ wakeup.tv_sec = now.tv_sec + (seconds);
+ wakeup.tv_nsec = now.tv_usec * 1000;
+
+ (void) pthread_cond_timedwait (
+ &(g_cache_list.m_update_cond),
+ &(g_cache_list.m_lock),
+ &wakeup);
+ }
+}
+
+static void
+rtl_cache_wsupdate_fini (void)
+{
+ RTL_MEMORY_LOCK_ACQUIRE(&(g_cache_list.m_lock));
+ g_cache_list.m_update_done = 1;
+ pthread_cond_signal (&(g_cache_list.m_update_cond));
+ RTL_MEMORY_LOCK_RELEASE(&(g_cache_list.m_lock));
+
+ if (g_cache_list.m_update_thread != (pthread_t)(0))
+ pthread_join (g_cache_list.m_update_thread, NULL);
+}
+
+/* ================================================================= */
+
+#elif defined(SAL_W32)
+
+static DWORD WINAPI
+rtl_cache_wsupdate_all (void * arg);
+
+static void
+rtl_cache_wsupdate_init (void)
+{
+ DWORD dwThreadId;
+
+ RTL_MEMORY_LOCK_ACQUIRE(&(g_cache_list.m_lock));
+ g_cache_list.m_update_done = 0;
+ g_cache_list.m_update_cond = CreateEvent (0, TRUE, FALSE, 0);
+
+ g_cache_list.m_update_thread =
+ CreateThread (NULL, 0, rtl_cache_wsupdate_all, (LPVOID)(10), 0, &dwThreadId);
+ RTL_MEMORY_LOCK_RELEASE(&(g_cache_list.m_lock));
+}
+
+static void
+rtl_cache_wsupdate_wait (unsigned int seconds)
+{
+ if (seconds > 0)
+ {
+ RTL_MEMORY_LOCK_RELEASE(&(g_cache_list.m_lock));
+ WaitForSingleObject (g_cache_list.m_update_cond, (DWORD)(seconds * 1000));
+ RTL_MEMORY_LOCK_ACQUIRE(&(g_cache_list.m_lock));
+ }
+}
+
+static void
+rtl_cache_wsupdate_fini (void)
+{
+ RTL_MEMORY_LOCK_ACQUIRE(&(g_cache_list.m_lock));
+ g_cache_list.m_update_done = 1;
+ SetEvent (g_cache_list.m_update_cond);
+ RTL_MEMORY_LOCK_RELEASE(&(g_cache_list.m_lock));
+
+ WaitForSingleObject (g_cache_list.m_update_thread, INFINITE);
+}
+
+#endif /* SAL_UNX || SAL_W32 */
+
+/* ================================================================= */
+
+/** rtl_cache_depot_wsupdate()
+ * update depot stats and purge excess magazines.
+ *
+ * @precond cache->m_depot_lock acquired
+ */
+static void
+rtl_cache_depot_wsupdate (
+ rtl_cache_type * cache,
+ rtl_cache_depot_type * depot
+)
+{
+ sal_Size npurge;
+
+ depot->m_prev_min = depot->m_curr_min;
+ depot->m_curr_min = depot->m_mag_count;
+
+ npurge = SAL_MIN(depot->m_curr_min, depot->m_prev_min);
+ for (; npurge > 0; npurge--)
+ {
+ rtl_cache_magazine_type * mag = rtl_cache_depot_dequeue (depot);
+ if (mag != 0)
+ {
+ RTL_MEMORY_LOCK_RELEASE(&(cache->m_depot_lock));
+ rtl_cache_magazine_clear (cache, mag);
+ rtl_cache_free (cache->m_magazine_cache, mag);
+ RTL_MEMORY_LOCK_ACQUIRE(&(cache->m_depot_lock));
+ }
+ }
+}
+
+/** rtl_cache_wsupdate()
+ *
+ * @precond cache->m_depot_lock released
+ */
+static void
+rtl_cache_wsupdate (
+ rtl_cache_type * cache
+)
+{
+ if (cache->m_magazine_cache != 0)
+ {
+ RTL_MEMORY_LOCK_ACQUIRE(&(cache->m_depot_lock));
+
+ OSL_TRACE(
+ "rtl_cache_wsupdate(\"%s\") "
+ "[depot: count, curr_min, prev_min] "
+ "full: %lu, %lu, %lu; empty: %lu, %lu, %lu",
+ cache->m_name,
+ cache->m_depot_full.m_mag_count,
+ cache->m_depot_full.m_curr_min,
+ cache->m_depot_full.m_prev_min,
+ cache->m_depot_empty.m_mag_count,
+ cache->m_depot_empty.m_curr_min,
+ cache->m_depot_empty.m_prev_min
+ );
+
+ rtl_cache_depot_wsupdate (cache, &(cache->m_depot_full));
+ rtl_cache_depot_wsupdate (cache, &(cache->m_depot_empty));
+
+ RTL_MEMORY_LOCK_RELEASE(&(cache->m_depot_lock));
+ }
+}
+
+/** rtl_cache_wsupdate_all()
+ *
+ */
+#if defined(SAL_UNX) || defined(SAL_OS2)
+static void *
+#elif defined(SAL_W32)
+static DWORD WINAPI
+#endif /* SAL_UNX || SAL_W32 */
+rtl_cache_wsupdate_all (void * arg)
+{
+ unsigned int seconds = (unsigned int)SAL_INT_CAST(sal_uIntPtr, arg);
+
+ RTL_MEMORY_LOCK_ACQUIRE(&(g_cache_list.m_lock));
+ while (!g_cache_list.m_update_done)
+ {
+ rtl_cache_wsupdate_wait (seconds);
+ if (!g_cache_list.m_update_done)
+ {
+ rtl_cache_type * head, * cache;
+
+ head = &(g_cache_list.m_cache_head);
+ for (cache = head->m_cache_next;
+ cache != head;
+ cache = cache->m_cache_next)
+ {
+ rtl_cache_wsupdate (cache);
+ }
+ }
+ }
+ RTL_MEMORY_LOCK_RELEASE(&(g_cache_list.m_lock));
+
+ return (0);
+}
+
+/* ================================================================= *
+ *
+ * cache initialization.
+ *
+ * ================================================================= */
+
+static void
+rtl_cache_once_init (void)
+{
+ {
+ /* list of caches */
+ RTL_MEMORY_LOCK_INIT(&(g_cache_list.m_lock));
+ (void) rtl_cache_constructor (&(g_cache_list.m_cache_head));
+ }
+ {
+ /* cache: internal arena */
+ OSL_ASSERT(gp_cache_arena == 0);
+
+ gp_cache_arena = rtl_arena_create (
+ "rtl_cache_internal_arena",
+ 64, /* quantum */
+ 0, /* no quantum caching */
+ NULL, /* default source */
+ rtl_arena_alloc,
+ rtl_arena_free,
+ 0 /* flags */
+ );
+ OSL_ASSERT(gp_cache_arena != 0);
+
+ /* check 'gp_default_arena' initialization */
+ OSL_ASSERT(gp_default_arena != 0);
+ }
+ {
+ /* cache: magazine cache */
+ static rtl_cache_type g_cache_magazine_cache;
+
+ OSL_ASSERT(gp_cache_magazine_cache == 0);
+ (void) rtl_cache_constructor (&g_cache_magazine_cache);
+
+ gp_cache_magazine_cache = rtl_cache_activate (
+ &g_cache_magazine_cache,
+ "rtl_cache_magazine_cache",
+ sizeof(rtl_cache_magazine_type), /* objsize */
+ 0, /* objalign */
+ rtl_cache_magazine_constructor,
+ rtl_cache_magazine_destructor,
+ 0, /* reclaim */
+ 0, /* userarg: NYI */
+ gp_default_arena, /* source */
+ RTL_CACHE_FLAG_NOMAGAZINE /* during bootstrap; activated below */
+ );
+ OSL_ASSERT(gp_cache_magazine_cache != 0);
+
+ /* activate magazine layer */
+ g_cache_magazine_cache.m_magazine_cache = gp_cache_magazine_cache;
+ }
+ {
+ /* cache: slab (struct) cache */
+ static rtl_cache_type g_cache_slab_cache;
+
+ OSL_ASSERT(gp_cache_slab_cache == 0);
+ (void) rtl_cache_constructor (&g_cache_slab_cache);
+
+ gp_cache_slab_cache = rtl_cache_activate (
+ &g_cache_slab_cache,
+ "rtl_cache_slab_cache",
+ sizeof(rtl_cache_slab_type), /* objsize */
+ 0, /* objalign */
+ rtl_cache_slab_constructor,
+ rtl_cache_slab_destructor,
+ 0, /* reclaim */
+ 0, /* userarg: none */
+ gp_default_arena, /* source */
+ 0 /* flags: none */
+ );
+ OSL_ASSERT(gp_cache_slab_cache != 0);
+ }
+ {
+ /* cache: bufctl cache */
+ static rtl_cache_type g_cache_bufctl_cache;
+
+ OSL_ASSERT(gp_cache_bufctl_cache == 0);
+ (void) rtl_cache_constructor (&g_cache_bufctl_cache);
+
+ gp_cache_bufctl_cache = rtl_cache_activate (
+ &g_cache_bufctl_cache,
+ "rtl_cache_bufctl_cache",
+ sizeof(rtl_cache_bufctl_type), /* objsize */
+ 0, /* objalign */
+ 0, /* constructor */
+ 0, /* destructor */
+ 0, /* reclaim */
+ 0, /* userarg */
+ gp_default_arena, /* source */
+ 0 /* flags: none */
+ );
+ OSL_ASSERT(gp_cache_bufctl_cache != 0);
+ }
+
+ rtl_cache_wsupdate_init();
+}
+
+static int
+rtl_cache_init (void)
+{
+ static sal_once_type g_once = SAL_ONCE_INIT;
+ SAL_ONCE(&g_once, rtl_cache_once_init);
+ return (gp_cache_arena != 0);
+}
+
+/* ================================================================= */
+
+#if defined(__GNUC__)
+static void rtl_cache_fini (void) __attribute__((destructor));
+#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+#pragma fini(rtl_cache_fini)
+static void rtl_cache_fini (void);
+#endif /* __GNUC__ || __SUNPRO_C */
+
+void
+rtl_cache_fini (void)
+{
+ if (gp_cache_arena != 0)
+ {
+ rtl_cache_type * cache, * head;
+
+ rtl_cache_wsupdate_fini();
+
+ if (gp_cache_bufctl_cache != 0)
+ {
+ cache = gp_cache_bufctl_cache, gp_cache_bufctl_cache = 0;
+ rtl_cache_deactivate (cache);
+ rtl_cache_destructor (cache);
+ }
+ if (gp_cache_slab_cache != 0)
+ {
+ cache = gp_cache_slab_cache, gp_cache_slab_cache = 0;
+ rtl_cache_deactivate (cache);
+ rtl_cache_destructor (cache);
+ }
+ if (gp_cache_magazine_cache != 0)
+ {
+ cache = gp_cache_magazine_cache, gp_cache_magazine_cache = 0;
+ rtl_cache_deactivate (cache);
+ rtl_cache_destructor (cache);
+ }
+ if (gp_cache_arena != 0)
+ {
+ rtl_arena_destroy (gp_cache_arena);
+ gp_cache_arena = 0;
+ }
+
+ RTL_MEMORY_LOCK_ACQUIRE(&(g_cache_list.m_lock));
+ head = &(g_cache_list.m_cache_head);
+ for (cache = head->m_cache_next; cache != head; cache = cache->m_cache_next)
+ {
+ OSL_TRACE(
+ "rtl_cache_fini(\"%s\") "
+ "[slab]: allocs: %"PRIu64", frees: %"PRIu64"; total: %lu, used: %lu; "
+ "[cpu]: allocs: %"PRIu64", frees: %"PRIu64"; "
+ "[total]: allocs: %"PRIu64", frees: %"PRIu64"",
+ cache->m_name,
+ cache->m_slab_stats.m_alloc, cache->m_slab_stats.m_free,
+ cache->m_slab_stats.m_mem_total, cache->m_slab_stats.m_mem_alloc,
+ cache->m_cpu_stats.m_alloc, cache->m_cpu_stats.m_free,
+ cache->m_slab_stats.m_alloc + cache->m_cpu_stats.m_alloc,
+ cache->m_slab_stats.m_free + cache->m_cpu_stats.m_free
+ );
+ }
+ RTL_MEMORY_LOCK_RELEASE(&(g_cache_list.m_lock));
+ }
+}
+
+/* ================================================================= */
diff --git a/sal/rtl/source/alloc_cache.h b/sal/rtl/source/alloc_cache.h
new file mode 100644
index 000000000000..9fed61806fde
--- /dev/null
+++ b/sal/rtl/source/alloc_cache.h
@@ -0,0 +1,182 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_RTL_ALLOC_CACHE_H
+#define INCLUDED_RTL_ALLOC_CACHE_H
+
+#include "sal/types.h"
+#include "rtl/alloc.h"
+#include "alloc_impl.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** rtl_cache_stat_type
+ * @internal
+ */
+typedef struct rtl_cache_stat_st rtl_cache_stat_type;
+struct rtl_cache_stat_st
+{
+ sal_uInt64 m_alloc;
+ sal_uInt64 m_free;
+
+ sal_Size m_mem_total;
+ sal_Size m_mem_alloc;
+};
+
+
+/** rtl_cache_bufctl_type
+ * @internal
+ */
+typedef struct rtl_cache_bufctl_st rtl_cache_bufctl_type;
+struct rtl_cache_bufctl_st
+{
+ rtl_cache_bufctl_type * m_next; /* linkage */
+
+ sal_uIntPtr m_addr; /* buffer address */
+ sal_uIntPtr m_slab; /* parent slab address */
+};
+
+
+/** rtl_cache_slab_type
+ * @internal
+ */
+typedef struct rtl_cache_slab_st rtl_cache_slab_type;
+struct rtl_cache_slab_st
+{
+ rtl_cache_slab_type * m_slab_next; /* slab linkage */
+ rtl_cache_slab_type * m_slab_prev; /* slab linkage */
+
+ sal_Size m_ntypes; /* number of buffers used */
+ sal_uIntPtr m_data; /* buffer start addr */
+
+ sal_uIntPtr m_bp; /* free buffer linkage 'base pointer' */
+ rtl_cache_bufctl_type * m_sp; /* free buffer linkage 'stack pointer' */
+};
+
+
+/** rtl_cache_magazine_type
+ * @internal
+ */
+#define RTL_CACHE_MAGAZINE_SIZE 61
+
+typedef struct rtl_cache_magazine_st rtl_cache_magazine_type;
+struct rtl_cache_magazine_st
+{
+ rtl_cache_magazine_type * m_mag_next; /* depot linkage */
+
+ sal_Size m_mag_size;
+ sal_Size m_mag_used;
+
+ void * m_objects[RTL_CACHE_MAGAZINE_SIZE];
+};
+
+
+/** rtl_cache_depot_type
+ * @internal
+ */
+typedef struct rtl_cache_depot_st rtl_cache_depot_type;
+struct rtl_cache_depot_st
+{
+ /* magazine list */
+ rtl_cache_magazine_type * m_mag_next; /* linkage */
+ sal_Size m_mag_count; /* count */
+
+ /* working set parameters */
+ sal_Size m_curr_min;
+ sal_Size m_prev_min;
+};
+
+
+/** rtl_cache_type
+ * @internal
+ */
+#define RTL_CACHE_HASH_SIZE 8
+
+#define RTL_CACHE_FEATURE_HASH 1
+#define RTL_CACHE_FEATURE_BULKDESTROY 2
+#define RTL_CACHE_FEATURE_RESCALE 4 /* within hash rescale operation */
+
+struct rtl_cache_st
+{
+ /* linkage */
+ rtl_cache_type * m_cache_next;
+ rtl_cache_type * m_cache_prev;
+
+ /* properties */
+ char m_name[RTL_CACHE_NAME_LENGTH + 1];
+ long m_features;
+
+ sal_Size m_type_size; /* const */
+ sal_Size m_type_align; /* const */
+ sal_Size m_type_shift; /* log2(m_type_size); const */
+
+ int (SAL_CALL * m_constructor)(void * obj, void * userarg); /* const */
+ void (SAL_CALL * m_destructor) (void * obj, void * userarg); /* const */
+ void (SAL_CALL * m_reclaim) (void * userarg); /* const */
+ void * m_userarg;
+
+ /* slab layer */
+ rtl_memory_lock_type m_slab_lock;
+ rtl_cache_stat_type m_slab_stats;
+
+ rtl_arena_type * m_source; /* slab supplier; const */
+ sal_Size m_slab_size; /* const */
+ sal_Size m_ntypes; /* number of buffers per slab; const */
+ sal_Size m_ncolor; /* next slab color */
+ sal_Size m_ncolor_max; /* max. slab color */
+
+ rtl_cache_slab_type m_free_head;
+ rtl_cache_slab_type m_used_head;
+
+ rtl_cache_bufctl_type ** m_hash_table;
+ rtl_cache_bufctl_type * m_hash_table_0[RTL_CACHE_HASH_SIZE];
+ sal_Size m_hash_size; /* m_hash_mask + 1 */
+ sal_Size m_hash_shift; /* log2(m_hash_size) */
+
+ /* depot layer */
+ rtl_memory_lock_type m_depot_lock;
+
+ rtl_cache_depot_type m_depot_empty;
+ rtl_cache_depot_type m_depot_full;
+
+ rtl_cache_type * m_magazine_cache; /* magazine supplier; const */
+
+ /* cpu layer */
+ rtl_cache_magazine_type * m_cpu_curr;
+ rtl_cache_magazine_type * m_cpu_prev;
+
+ rtl_cache_stat_type m_cpu_stats;
+};
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* INCLUDED_RTL_ALLOC_CACHE_H */
diff --git a/sal/rtl/source/alloc_global.c b/sal/rtl/source/alloc_global.c
new file mode 100644
index 000000000000..5137f868127d
--- /dev/null
+++ b/sal/rtl/source/alloc_global.c
@@ -0,0 +1,357 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "rtl/alloc.h"
+
+#ifndef INCLUDED_STRING_H
+#include <string.h>
+#define INCLUDED_STRING_H
+#endif
+
+#if !defined(FORCE_SYSALLOC)
+
+/* ================================================================= *
+ *
+ * custom allocator includes.
+ *
+ * ================================================================= */
+
+#ifndef INCLUDED_STDIO_H
+#include <stdio.h>
+#define INCLUDED_STDIO_H
+#endif
+#include "alloc_impl.h"
+#include "internal/once.h"
+#include "sal/macros.h"
+#include "osl/diagnose.h"
+
+/* ================================================================= *
+ *
+ * custom allocator internals.
+ *
+ * ================================================================= */
+
+static const sal_Size g_alloc_sizes[] =
+{
+ /* powers of 2**(1/4) */
+ 4 * 4, 6 * 4,
+ 4 * 8, 5 * 8, 6 * 8, 7 * 8,
+ 4 * 16, 5 * 16, 6 * 16, 7 * 16,
+ 4 * 32, 5 * 32, 6 * 32, 7 * 32,
+ 4 * 64, 5 * 64, 6 * 64, 7 * 64,
+ 4 * 128, 5 * 128, 6 * 128, 7 * 128,
+ 4 * 256, 5 * 256, 6 * 256, 7 * 256,
+ 4 * 512, 5 * 512, 6 * 512, 7 * 512,
+ 4 * 1024, 5 * 1024, 6 * 1024, 7 * 1024,
+ 4 * 2048, 5 * 2048, 6 * 2048, 7 * 2048,
+ 4 * 4096
+};
+
+#define RTL_MEMORY_CACHED_LIMIT 4 * 4096
+#define RTL_MEMORY_CACHED_SIZES (sizeof(g_alloc_sizes) / sizeof(g_alloc_sizes[0]))
+
+static rtl_cache_type * g_alloc_caches[RTL_MEMORY_CACHED_SIZES] =
+{
+ 0,
+};
+
+#define RTL_MEMALIGN 8
+#define RTL_MEMALIGN_SHIFT 3
+
+static rtl_cache_type * g_alloc_table[RTL_MEMORY_CACHED_LIMIT >> RTL_MEMALIGN_SHIFT] =
+{
+ 0,
+};
+
+static rtl_arena_type * gp_alloc_arena = 0;
+
+/* ================================================================= *
+ *
+ * custom allocator initialization / finalization.
+ *
+ * ================================================================= */
+
+static void
+rtl_memory_once_init (void)
+{
+ {
+ /* global memory arena */
+ OSL_ASSERT(gp_alloc_arena == 0);
+
+ gp_alloc_arena = rtl_arena_create (
+ "rtl_alloc_arena",
+ 2048, /* quantum */
+ 0, /* w/o quantum caching */
+ 0, /* default source */
+ rtl_arena_alloc,
+ rtl_arena_free,
+ 0 /* flags */
+ );
+ OSL_ASSERT(gp_alloc_arena != 0);
+ }
+ {
+ sal_Size size;
+ int i, n = RTL_MEMORY_CACHED_SIZES;
+
+ for (i = 0; i < n; i++)
+ {
+ char name[RTL_CACHE_NAME_LENGTH + 1];
+ (void) snprintf (name, sizeof(name), "rtl_alloc_%lu", g_alloc_sizes[i]);
+ g_alloc_caches[i] = rtl_cache_create (name, g_alloc_sizes[i], 0, NULL, NULL, NULL, NULL, NULL, 0);
+ }
+
+ size = RTL_MEMALIGN;
+ for (i = 0; i < n; i++)
+ {
+ while (size <= g_alloc_sizes[i])
+ {
+ g_alloc_table[(size - 1) >> RTL_MEMALIGN_SHIFT] = g_alloc_caches[i];
+ size += RTL_MEMALIGN;
+ }
+ }
+ }
+}
+
+static int
+rtl_memory_init (void)
+{
+ static sal_once_type g_once = SAL_ONCE_INIT;
+ SAL_ONCE(&g_once, rtl_memory_once_init);
+ return (gp_alloc_arena != 0);
+}
+
+/* ================================================================= */
+
+/*
+ Issue http://udk.openoffice.org/issues/show_bug.cgi?id=92388
+
+ Mac OS X does not seem to support "__cxa__atexit", thus leading
+ to the situation that "__attribute__((destructor))__" functions
+ (in particular "rtl_memory_fini") become called _before_ global
+ C++ object d'tors.
+
+ Delegated the call to "rtl_memory_fini" into a dummy C++ object,
+ see memory_fini.cxx .
+*/
+#if defined(__GNUC__) && !defined(MACOSX)
+static void rtl_memory_fini (void) __attribute__((destructor));
+#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+#pragma fini(rtl_memory_fini)
+static void rtl_memory_fini (void);
+#endif /* __GNUC__ || __SUNPRO_C */
+
+void
+rtl_memory_fini (void)
+{
+ int i, n;
+
+ /* clear g_alloc_table */
+ memset (g_alloc_table, 0, sizeof(g_alloc_table));
+
+ /* cleanup g_alloc_caches */
+ for (i = 0, n = RTL_MEMORY_CACHED_SIZES; i < n; i++)
+ {
+ if (g_alloc_caches[i] != 0)
+ {
+ rtl_cache_destroy (g_alloc_caches[i]);
+ g_alloc_caches[i] = 0;
+ }
+ }
+
+ /* cleanup gp_alloc_arena */
+ if (gp_alloc_arena != 0)
+ {
+ rtl_arena_destroy (gp_alloc_arena);
+ gp_alloc_arena = 0;
+ }
+}
+
+/* ================================================================= *
+ *
+ * custom allocator implemenation.
+ *
+ * ================================================================= */
+
+void *
+SAL_CALL rtl_allocateMemory (sal_Size n) SAL_THROW_EXTERN_C()
+{
+ void * p = 0;
+ if (n > 0)
+ {
+ char * addr;
+ sal_Size size = RTL_MEMORY_ALIGN(n + RTL_MEMALIGN, RTL_MEMALIGN);
+
+ OSL_ASSERT(RTL_MEMALIGN >= sizeof(sal_Size));
+ if (n >= SAL_MAX_SIZE - (RTL_MEMALIGN + RTL_MEMALIGN - 1))
+ {
+ /* requested size too large for roundup alignment */
+ return 0;
+ }
+
+try_alloc:
+ if (size <= RTL_MEMORY_CACHED_LIMIT)
+ addr = (char*)rtl_cache_alloc(g_alloc_table[(size - 1) >> RTL_MEMALIGN_SHIFT]);
+ else
+ addr = (char*)rtl_arena_alloc (gp_alloc_arena, &size);
+
+ if (addr != 0)
+ {
+ ((sal_Size*)(addr))[0] = size;
+ p = addr + RTL_MEMALIGN;
+ }
+ else if (gp_alloc_arena == 0)
+ {
+ if (rtl_memory_init())
+ {
+ /* try again */
+ goto try_alloc;
+ }
+ }
+ }
+ return (p);
+}
+
+/* ================================================================= */
+
+void SAL_CALL rtl_freeMemory (void * p) SAL_THROW_EXTERN_C()
+{
+ if (p != 0)
+ {
+ char * addr = (char*)(p) - RTL_MEMALIGN;
+ sal_Size size = ((sal_Size*)(addr))[0];
+
+ if (size <= RTL_MEMORY_CACHED_LIMIT)
+ rtl_cache_free(g_alloc_table[(size - 1) >> RTL_MEMALIGN_SHIFT], addr);
+ else
+ rtl_arena_free (gp_alloc_arena, addr, size);
+ }
+}
+
+/* ================================================================= */
+
+void * SAL_CALL rtl_reallocateMemory (void * p, sal_Size n) SAL_THROW_EXTERN_C()
+{
+ if (n > 0)
+ {
+ if (p != 0)
+ {
+ void * p_old = p;
+ sal_Size n_old = ((sal_Size*)( (char*)(p) - RTL_MEMALIGN ))[0] - RTL_MEMALIGN;
+
+ p = rtl_allocateMemory (n);
+ if (p != 0)
+ {
+ memcpy (p, p_old, SAL_MIN(n, n_old));
+ rtl_freeMemory (p_old);
+ }
+ }
+ else
+ {
+ p = rtl_allocateMemory (n);
+ }
+ }
+ else if (p != 0)
+ {
+ rtl_freeMemory (p), p = 0;
+ }
+ return (p);
+}
+
+#else /* FORCE_SYSALLOC */
+
+/* ================================================================= *
+ *
+ * system allocator includes.
+ *
+ * ================================================================= */
+
+#ifndef INCLUDED_STDLIB_H
+#include <stdlib.h>
+#define INCLUDED_STDLIB_H
+#endif
+
+/* ================================================================= *
+ *
+ * system allocator implemenation.
+ *
+ * ================================================================= */
+
+void * SAL_CALL rtl_allocateMemory (sal_Size n)
+{
+ return malloc (n);
+}
+
+/* ================================================================= */
+
+void SAL_CALL rtl_freeMemory (void * p)
+{
+ free (p);
+}
+
+/* ================================================================= */
+
+void * SAL_CALL rtl_reallocateMemory (void * p, sal_Size n)
+{
+ return realloc (p, n);
+}
+
+/* ================================================================= */
+
+void
+rtl_memory_fini (void)
+{
+ /* nothing to do */
+}
+
+#endif /* FORCE_SYSALLOC */
+
+/* ================================================================= *
+ *
+ * rtl_(allocate|free)ZeroMemory() implemenation.
+ *
+ * ================================================================= */
+
+void * SAL_CALL rtl_allocateZeroMemory (sal_Size n) SAL_THROW_EXTERN_C()
+{
+ void * p = rtl_allocateMemory (n);
+ if (p != 0)
+ memset (p, 0, n);
+ return (p);
+}
+
+/* ================================================================= */
+
+void SAL_CALL rtl_freeZeroMemory (void * p, sal_Size n) SAL_THROW_EXTERN_C()
+{
+ if (p != 0)
+ {
+ memset (p, 0, n);
+ rtl_freeMemory (p);
+ }
+}
+
+/* ================================================================= */
diff --git a/sal/rtl/source/alloc_impl.h b/sal/rtl/source/alloc_impl.h
new file mode 100644
index 000000000000..d3d1924ddf91
--- /dev/null
+++ b/sal/rtl/source/alloc_impl.h
@@ -0,0 +1,247 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_RTL_ALLOC_IMPL_H
+#define INCLUDED_RTL_ALLOC_IMPL_H
+
+#include "sal/types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/** Alignment macros
+ */
+#if SAL_TYPES_ALIGNMENT4 > 1
+#define RTL_MEMORY_ALIGNMENT_4 SAL_TYPES_ALIGNMENT4
+#else
+#define RTL_MEMORY_ALIGNMENT_4 sizeof(int)
+#endif /* SAL_TYPES_ALIGNMENT4 */
+
+#if SAL_TYPES_ALIGNMENT8 > 1
+#define RTL_MEMORY_ALIGNMENT_8 SAL_TYPES_ALIGNMENT8
+#else
+#define RTL_MEMORY_ALIGNMENT_8 sizeof(void*)
+#endif /* SAL_TYPES_ALIGNMENT8 */
+
+#if 0 /* @@@ */
+#define RTL_MEMORY_ALIGNMENT_1 8
+#define RTL_MEMORY_ALIGNMENT_2 (sizeof(void*) * 2)
+#endif /* @@@ */
+
+#define RTL_MEMORY_ALIGN(value, align) (((value) + ((align) - 1)) & ~((align) - 1))
+
+#define RTL_MEMORY_ISP2(value) (((value) & ((value) - 1)) == 0)
+#define RTL_MEMORY_P2ALIGN(value, align) ((value) & -(sal_IntPtr)(align))
+
+#define RTL_MEMORY_P2ROUNDUP(value, align) \
+ (-(-(sal_IntPtr)(value) & -(sal_IntPtr)(align)))
+#define RTL_MEMORY_P2END(value, align) \
+ (-(~(sal_IntPtr)(value) & -(sal_IntPtr)(align)))
+
+
+/** Function inlining macros
+ * (compiler dependent)
+ */
+#ifndef RTL_MEMORY_INLINE
+#if defined(__GNUC__)
+#define RTL_MEMORY_INLINE __inline__
+#elif defined(_MSC_VER)
+#define RTL_MEMORY_INLINE __inline
+#else
+#define RTL_MEMORY_INLINE
+#endif /* __GNUC__ || _MSC_VER */
+#endif /* RTL_MEMORY_INLINE */
+
+
+/** printf() format specifier(s)
+ * (from C90 <sys/int_fmtio.h>)
+ */
+#ifndef PRIu64
+#if defined(_MSC_VER)
+#define PRIu64 "I64u"
+#else /* !_MSC_VER */
+#define PRIu64 "llu"
+#endif /* !_MSC_VER */
+#endif /* PRIu64 */
+
+
+/** highbit(): log2() + 1
+ * (complexity O(1))
+ */
+static RTL_MEMORY_INLINE int
+highbit(sal_Size n)
+{
+ register int k = 1;
+
+ if (n == 0)
+ return (0);
+#if SAL_TYPES_SIZEOFLONG == 8
+ if (n & 0xffffffff00000000ul)
+ k |= 32, n >>= 32;
+#endif
+ if (n & 0xffff0000)
+ k |= 16, n >>= 16;
+ if (n & 0xff00)
+ k |= 8, n >>= 8;
+ if (n & 0xf0)
+ k |= 4, n >>= 4;
+ if (n & 0x0c)
+ k |= 2, n >>= 2;
+ if (n & 0x02)
+ k++;
+
+ return (k);
+}
+
+#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+#pragma inline(highbit)
+#endif /* __SUNPRO_C */
+
+
+/** lowbit(): find first bit set
+ * (complexity O(1))
+ */
+static RTL_MEMORY_INLINE int
+lowbit(sal_Size n)
+{
+ register int k = 1;
+
+ if (n == 0)
+ return (0);
+#if SAL_TYPES_SIZEOFLONG == 8
+ if (!(n & 0xffffffff))
+ k |= 32, n >>= 32;
+#endif
+ if (!(n & 0xffff))
+ k |= 16, n >>= 16;
+ if (!(n & 0xff))
+ k |= 8, n >>= 8;
+ if (!(n & 0xf))
+ k |= 4, n >>= 4;
+ if (!(n & 0x3))
+ k |= 2, n >>= 2;
+ if (!(n & 0x1))
+ k++;
+ return (k);
+}
+
+#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+#pragma inline(lowbit)
+#endif /* __SUNPRO_C */
+
+
+/** Queue manipulation macros
+ * (doubly linked circular list)
+ * (complexity O(1))
+ */
+#define QUEUE_STARTED_NAMED(entry, name) \
+ (((entry)->m_##name##next == (entry)) && ((entry)->m_##name##prev == (entry)))
+
+#define QUEUE_START_NAMED(entry, name) \
+{ \
+ (entry)->m_##name##next = (entry); \
+ (entry)->m_##name##prev = (entry); \
+}
+
+#define QUEUE_REMOVE_NAMED(entry, name) \
+{ \
+ (entry)->m_##name##prev->m_##name##next = (entry)->m_##name##next; \
+ (entry)->m_##name##next->m_##name##prev = (entry)->m_##name##prev; \
+ QUEUE_START_NAMED(entry, name); \
+}
+
+#define QUEUE_INSERT_HEAD_NAMED(head, entry, name) \
+{ \
+ (entry)->m_##name##prev = (head); \
+ (entry)->m_##name##next = (head)->m_##name##next; \
+ (head)->m_##name##next = (entry); \
+ (entry)->m_##name##next->m_##name##prev = (entry); \
+}
+
+#define QUEUE_INSERT_TAIL_NAMED(head, entry, name) \
+{ \
+ (entry)->m_##name##next = (head); \
+ (entry)->m_##name##prev = (head)->m_##name##prev; \
+ (head)->m_##name##prev = (entry); \
+ (entry)->m_##name##prev->m_##name##next = (entry); \
+}
+
+
+/** rtl_memory_lock_type
+ * (platform dependent)
+ */
+#if defined(SAL_UNX) || defined(SAL_OS2)
+
+#include <unistd.h>
+#include <pthread.h>
+
+typedef pthread_mutex_t rtl_memory_lock_type;
+
+#define RTL_MEMORY_LOCK_INIT(lock) pthread_mutex_init((lock), NULL)
+#define RTL_MEMORY_LOCK_DESTROY(lock) pthread_mutex_destroy((lock))
+
+#define RTL_MEMORY_LOCK_ACQUIRE(lock) pthread_mutex_lock((lock))
+#define RTL_MEMORY_LOCK_RELEASE(lock) pthread_mutex_unlock((lock))
+
+#elif defined(SAL_W32)
+
+#define WIN32_LEAN_AND_MEAN
+#ifdef _MSC_VER
+#pragma warning(push,1) /* disable warnings within system headers */
+#endif
+#include <windows.h>
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+typedef CRITICAL_SECTION rtl_memory_lock_type;
+
+#define RTL_MEMORY_LOCK_INIT(lock) InitializeCriticalSection((lock))
+#define RTL_MEMORY_LOCK_DESTROY(lock) DeleteCriticalSection((lock))
+
+#define RTL_MEMORY_LOCK_ACQUIRE(lock) EnterCriticalSection((lock))
+#define RTL_MEMORY_LOCK_RELEASE(lock) LeaveCriticalSection((lock))
+
+#else
+#error Unknown platform
+#endif /* SAL_UNX | SAL_W32 */
+
+
+/** Cache creation flags.
+ * @internal
+ */
+#define RTL_CACHE_FLAG_NOMAGAZINE (1 << 13) /* w/o magazine layer */
+#define RTL_CACHE_FLAG_QUANTUMCACHE (2 << 13) /* used as arena quantum cache */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* INCLUDED_RTL_ALLOC_IMPL_H */
diff --git a/sal/rtl/source/bootstrap.cxx b/sal/rtl/source/bootstrap.cxx
new file mode 100644
index 000000000000..cc7d3336c2d2
--- /dev/null
+++ b/sal/rtl/source/bootstrap.cxx
@@ -0,0 +1,1059 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+
+#include "rtl/bootstrap.h"
+#include "rtl/bootstrap.hxx"
+#include <osl/diagnose.h>
+#include <osl/module.h>
+#include <osl/process.h>
+#include <osl/file.hxx>
+#include <osl/mutex.hxx>
+#include <osl/profile.hxx>
+#include <osl/security.hxx>
+#include <rtl/alloc.h>
+#include <rtl/string.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/ustring.hxx>
+#include <rtl/byteseq.hxx>
+#include <rtl/instance.hxx>
+#include <rtl/malformeduriexception.hxx>
+#include <rtl/uri.hxx>
+#include "rtl/allocator.hxx"
+
+#include "macro.hxx"
+
+#include <hash_map>
+#include <list>
+
+#define MY_STRING_(x) # x
+#define MY_STRING(x) MY_STRING_(x)
+
+//----------------------------------------------------------------------------
+
+using osl::DirectoryItem;
+using osl::FileStatus;
+
+using rtl::OString;
+using rtl::OUString;
+using rtl::OUStringToOString;
+
+struct Bootstrap_Impl;
+
+namespace {
+
+static char const VND_SUN_STAR_PATHNAME[] = "vnd.sun.star.pathname:";
+
+bool isPathnameUrl(rtl::OUString const & url) {
+ return url.matchIgnoreAsciiCaseAsciiL(
+ RTL_CONSTASCII_STRINGPARAM(VND_SUN_STAR_PATHNAME));
+}
+
+bool resolvePathnameUrl(rtl::OUString * url) {
+ OSL_ASSERT(url != NULL);
+ if (!isPathnameUrl(*url) ||
+ (osl::FileBase::getFileURLFromSystemPath(
+ url->copy(RTL_CONSTASCII_LENGTH(VND_SUN_STAR_PATHNAME)), *url) ==
+ osl::FileBase::E_None))
+ {
+ return true;
+ } else {
+ *url = rtl::OUString();
+ return false;
+ }
+}
+
+enum LookupMode {
+ LOOKUP_MODE_NORMAL, LOOKUP_MODE_URE_BOOTSTRAP,
+ LOOKUP_MODE_URE_BOOTSTRAP_EXPANSION };
+
+struct ExpandRequestLink {
+ ExpandRequestLink const * next;
+ Bootstrap_Impl const * file;
+ rtl::OUString key;
+};
+
+rtl::OUString expandMacros(
+ Bootstrap_Impl const * file, rtl::OUString const & text, LookupMode mode,
+ ExpandRequestLink const * requestStack);
+
+rtl::OUString recursivelyExpandMacros(
+ Bootstrap_Impl const * file, rtl::OUString const & text, LookupMode mode,
+ Bootstrap_Impl const * requestFile, rtl::OUString const & requestKey,
+ ExpandRequestLink const * requestStack)
+{
+ for (; requestStack != NULL; requestStack = requestStack->next) {
+ if (requestStack->file == requestFile &&
+ requestStack->key == requestKey)
+ {
+ return rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("***RECURSION DETECTED***"));
+ }
+ }
+ ExpandRequestLink link = { requestStack, requestFile, requestKey };
+ return expandMacros(file, text, mode, &link);
+}
+
+}
+
+//----------------------------------------------------------------------------
+
+struct rtl_bootstrap_NameValue
+{
+ OUString sName;
+ OUString sValue;
+
+ inline rtl_bootstrap_NameValue() SAL_THROW( () )
+ {}
+ inline rtl_bootstrap_NameValue(
+ OUString const & name, OUString const & value ) SAL_THROW( () )
+ : sName( name ),
+ sValue( value )
+ {}
+};
+
+typedef std::list<
+ rtl_bootstrap_NameValue,
+ rtl::Allocator< rtl_bootstrap_NameValue >
+> NameValueList;
+
+bool find(
+ NameValueList const & list, rtl::OUString const & key,
+ rtl::OUString * value)
+{
+ OSL_ASSERT(value != NULL);
+ for (NameValueList::const_iterator i(list.begin()); i != list.end(); ++i) {
+ if (i->sName == key) {
+ *value = i->sValue;
+ return true;
+ }
+ }
+ return false;
+}
+
+namespace {
+ struct rtl_bootstrap_set_list :
+ public rtl::Static< NameValueList, rtl_bootstrap_set_list > {};
+}
+
+//----------------------------------------------------------------------------
+
+static sal_Bool getFromCommandLineArgs(
+ rtl::OUString const & key, rtl::OUString * value )
+{
+ OSL_ASSERT(value != NULL);
+ static NameValueList *pNameValueList = 0;
+ if( ! pNameValueList )
+ {
+ static NameValueList nameValueList;
+
+ sal_Int32 nArgCount = osl_getCommandArgCount();
+ for(sal_Int32 i = 0; i < nArgCount; ++ i)
+ {
+ rtl_uString *pArg = 0;
+ osl_getCommandArg( i, &pArg );
+ if( ('-' == pArg->buffer[0] || '/' == pArg->buffer[0] ) &&
+ 'e' == pArg->buffer[1] &&
+ 'n' == pArg->buffer[2] &&
+ 'v' == pArg->buffer[3] &&
+ ':' == pArg->buffer[4] )
+ {
+ sal_Int32 nIndex = rtl_ustr_indexOfChar( pArg->buffer, '=' );
+ if( nIndex >= 0 )
+ {
+
+ rtl_bootstrap_NameValue nameValue;
+ nameValue.sName = OUString( &(pArg->buffer[5]), nIndex - 5 );
+ nameValue.sValue = OUString( &(pArg->buffer[nIndex+1]) );
+ if( i == nArgCount-1 &&
+ nameValue.sValue.getLength() &&
+ nameValue.sValue[nameValue.sValue.getLength()-1] == 13 )
+ {
+ // avoid the 13 linefeed for the last argument,
+ // when the executable is started from a script,
+ // that was edited on windows
+ nameValue.sValue = nameValue.sValue.copy(0,nameValue.sValue.getLength()-1);
+ }
+ nameValueList.push_back( nameValue );
+ }
+ }
+ rtl_uString_release( pArg );
+ }
+ pNameValueList = &nameValueList;
+ }
+
+ sal_Bool found = sal_False;
+
+ for( NameValueList::iterator ii = pNameValueList->begin() ;
+ ii != pNameValueList->end() ;
+ ++ii )
+ {
+ if( (*ii).sName.equals(key) )
+ {
+ *value = (*ii).sValue;
+ found = sal_True;
+ break;
+ }
+ }
+
+ return found;
+}
+
+//----------------------------------------------------------------------------
+
+extern "C" oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl (
+ rtl_uString ** ppFileURL) SAL_THROW_EXTERN_C();
+
+inline void getExecutableFile_Impl (rtl_uString ** ppFileURL)
+{
+ osl_bootstrap_getExecutableFile_Impl (ppFileURL);
+}
+
+//----------------------------------------------------------------------------
+
+static void getExecutableDirectory_Impl (rtl_uString ** ppDirURL)
+{
+ OUString fileName;
+ getExecutableFile_Impl (&(fileName.pData));
+
+ sal_Int32 nDirEnd = fileName.lastIndexOf('/');
+ OSL_ENSURE(nDirEnd >= 0, "Cannot locate executable directory");
+
+ rtl_uString_newFromStr_WithLength(ppDirURL,fileName.getStr(),nDirEnd);
+}
+
+//----------------------------------------------------------------------------
+
+static OUString & getIniFileName_Impl()
+{
+ static OUString *pStaticName = 0;
+ if( ! pStaticName )
+ {
+ OUString fileName;
+
+ if(getFromCommandLineArgs(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("INIFILENAME")), &fileName))
+ {
+ resolvePathnameUrl(&fileName);
+ }
+ else
+ {
+ getExecutableFile_Impl (&(fileName.pData));
+
+ // get rid of a potential executable extension
+ OUString progExt (RTL_CONSTASCII_USTRINGPARAM(".bin"));
+ if(fileName.getLength() > progExt.getLength()
+ && fileName.copy(fileName.getLength() - progExt.getLength()).equalsIgnoreAsciiCase(progExt))
+ fileName = fileName.copy(0, fileName.getLength() - progExt.getLength());
+
+ progExt = OUString::createFromAscii(".exe");
+ if(fileName.getLength() > progExt.getLength()
+ && fileName.copy(fileName.getLength() - progExt.getLength()).equalsIgnoreAsciiCase(progExt))
+ fileName = fileName.copy(0, fileName.getLength() - progExt.getLength());
+
+ // append config file suffix
+ fileName += OUString(RTL_CONSTASCII_USTRINGPARAM(SAL_CONFIGFILE("")));
+ }
+
+ static OUString theFileName;
+ if(fileName.getLength())
+ theFileName = fileName;
+
+ pStaticName = &theFileName;
+ }
+
+ return *pStaticName;
+}
+
+//----------------------------------------------------------------------------
+
+static inline bool path_exists( OUString const & path )
+{
+ DirectoryItem dirItem;
+ return (DirectoryItem::E_None == DirectoryItem::get( path, dirItem ));
+}
+
+//----------------------------------------------------------------------------
+// #111772#
+// ensure the given file url has no final slash
+
+inline void EnsureNoFinalSlash (rtl::OUString & url)
+{
+ sal_Int32 i = url.getLength();
+ if (i > 0 && url[i - 1] == '/') {
+ url = url.copy(0, i - 1);
+ }
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+struct Bootstrap_Impl
+{
+ sal_Int32 _nRefCount;
+ Bootstrap_Impl * _base_ini;
+
+ NameValueList _nameValueList;
+ OUString _iniName;
+
+ explicit Bootstrap_Impl (OUString const & rIniName);
+ ~Bootstrap_Impl();
+
+ static void * operator new (std::size_t n) SAL_THROW(())
+ { return rtl_allocateMemory (sal_uInt32(n)); }
+ static void operator delete (void * p , std::size_t) SAL_THROW(())
+ { rtl_freeMemory (p); }
+
+ bool getValue(
+ rtl::OUString const & key, rtl_uString ** value,
+ rtl_uString * defaultValue, LookupMode mode, bool override,
+ ExpandRequestLink const * requestStack) const;
+ bool getDirectValue(
+ rtl::OUString const & key, rtl_uString ** value, LookupMode mode,
+ ExpandRequestLink const * requestStack) const;
+ bool getAmbienceValue(
+ rtl::OUString const & key, rtl_uString ** value, LookupMode mode,
+ ExpandRequestLink const * requestStack) const;
+ void expandValue(
+ rtl_uString ** value, rtl::OUString const & text, LookupMode mode,
+ Bootstrap_Impl const * requestFile, rtl::OUString const & requestKey,
+ ExpandRequestLink const * requestStack) const;
+};
+
+//----------------------------------------------------------------------------
+
+Bootstrap_Impl::Bootstrap_Impl( OUString const & rIniName )
+ : _nRefCount( 0 ),
+ _base_ini( 0 ),
+ _iniName (rIniName)
+{
+ OUString base_ini( getIniFileName_Impl() );
+ // normalize path
+ FileStatus status( FileStatusMask_FileURL );
+ DirectoryItem dirItem;
+ if (DirectoryItem::E_None == DirectoryItem::get( base_ini, dirItem ) &&
+ DirectoryItem::E_None == dirItem.getFileStatus( status ))
+ {
+ base_ini = status.getFileURL();
+ if (! rIniName.equals( base_ini ))
+ {
+ _base_ini = static_cast< Bootstrap_Impl * >(
+ rtl_bootstrap_args_open( base_ini.pData ) );
+ }
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ OString sFile = OUStringToOString(_iniName, RTL_TEXTENCODING_ASCII_US);
+ OSL_TRACE(__FILE__" -- Bootstrap_Impl() - %s\n", sFile.getStr());
+#endif /* OSL_DEBUG_LEVEL > 1 */
+
+ oslFileHandle handle;
+ if (_iniName.getLength() &&
+ osl_File_E_None == osl_openFile(_iniName.pData, &handle, osl_File_OpenFlag_Read))
+ {
+ rtl::ByteSequence seq;
+
+ while (osl_File_E_None == osl_readLine(handle , (sal_Sequence **)&seq))
+ {
+ OString line( (const sal_Char *) seq.getConstArray(), seq.getLength() );
+ sal_Int32 nIndex = line.indexOf('=');
+ if (nIndex >= 1)
+ {
+ struct rtl_bootstrap_NameValue nameValue;
+ nameValue.sName = OStringToOUString(
+ line.copy(0,nIndex).trim(), RTL_TEXTENCODING_ASCII_US );
+ nameValue.sValue = OStringToOUString(
+ line.copy(nIndex+1).trim(), RTL_TEXTENCODING_UTF8 );
+
+#if OSL_DEBUG_LEVEL > 1
+ OString name_tmp = OUStringToOString(nameValue.sName, RTL_TEXTENCODING_ASCII_US);
+ OString value_tmp = OUStringToOString(nameValue.sValue, RTL_TEXTENCODING_UTF8);
+ OSL_TRACE(
+ __FILE__" -- pushing: name=%s value=%s\n",
+ name_tmp.getStr(), value_tmp.getStr() );
+#endif /* OSL_DEBUG_LEVEL > 1 */
+
+ _nameValueList.push_back(nameValue);
+ }
+ }
+ osl_closeFile(handle);
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ {
+ OString file_tmp = OUStringToOString(_iniName, RTL_TEXTENCODING_ASCII_US);
+ OSL_TRACE( __FILE__" -- couldn't open file: %s", file_tmp.getStr() );
+ }
+#endif /* OSL_DEBUG_LEVEL > 1 */
+}
+
+//----------------------------------------------------------------------------
+
+Bootstrap_Impl::~Bootstrap_Impl()
+{
+ if (_base_ini != 0)
+ rtl_bootstrap_args_close( _base_ini );
+}
+
+//----------------------------------------------------------------------------
+
+namespace {
+
+Bootstrap_Impl * get_static_bootstrap_handle() SAL_THROW(())
+{
+ osl::MutexGuard guard( osl::Mutex::getGlobalMutex() );
+ static Bootstrap_Impl * s_handle = 0;
+ if (s_handle == 0)
+ {
+ OUString iniName (getIniFileName_Impl());
+ s_handle = static_cast< Bootstrap_Impl * >(
+ rtl_bootstrap_args_open( iniName.pData ) );
+ if (s_handle == 0)
+ {
+ Bootstrap_Impl * that = new Bootstrap_Impl( iniName );
+ ++that->_nRefCount;
+ s_handle = that;
+ }
+ }
+ return s_handle;
+}
+
+struct FundamentalIniData {
+ rtlBootstrapHandle ini;
+
+ FundamentalIniData() {
+ OUString uri;
+ ini =
+ ((static_cast< Bootstrap_Impl * >(get_static_bootstrap_handle())->
+ getValue(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("URE_BOOTSTRAP")),
+ &uri.pData, 0, LOOKUP_MODE_NORMAL, false, 0)) &&
+ resolvePathnameUrl(&uri))
+ ? rtl_bootstrap_args_open(uri.pData) : NULL;
+ }
+
+ ~FundamentalIniData() { rtl_bootstrap_args_close(ini); }
+
+private:
+ FundamentalIniData(FundamentalIniData &); // not defined
+ void operator =(FundamentalIniData &); // not defined
+};
+
+struct FundamentalIni: public rtl::Static< FundamentalIniData, FundamentalIni >
+{};
+
+}
+
+bool Bootstrap_Impl::getValue(
+ rtl::OUString const & key, rtl_uString ** value, rtl_uString * defaultValue,
+ LookupMode mode, bool override, ExpandRequestLink const * requestStack)
+ const
+{
+ if (mode == LOOKUP_MODE_NORMAL &&
+ key.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("URE_BOOTSTRAP")))
+ {
+ mode = LOOKUP_MODE_URE_BOOTSTRAP;
+ }
+ if (override && getDirectValue(key, value, mode, requestStack)) {
+ return true;
+ }
+ if (key.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("_OS"))) {
+ rtl_uString_assign(
+ value, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(THIS_OS)).pData);
+ return true;
+ }
+ if (key.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("_ARCH"))) {
+ rtl_uString_assign(
+ value, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(THIS_ARCH)).pData);
+ return true;
+ }
+ if (key.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("_CPPU_ENV"))) {
+ rtl_uString_assign(
+ value,
+ (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(MY_STRING(CPPU_ENV))).
+ pData));
+ return true;
+ }
+ if (key.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("ORIGIN"))) {
+ rtl_uString_assign(
+ value,
+ _iniName.copy(
+ 0, std::max<sal_Int32>(0, _iniName.lastIndexOf('/'))).pData);
+ return true;
+ }
+ if (getAmbienceValue(key, value, mode, requestStack)) {
+ return true;
+ }
+ if (key.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("SYSUSERCONFIG"))) {
+ rtl::OUString v;
+ bool b = osl::Security().getConfigDir(v);
+ EnsureNoFinalSlash(v);
+ rtl_uString_assign(value, v.pData);
+ return b;
+ }
+ if (key.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("SYSUSERHOME"))) {
+ rtl::OUString v;
+ bool b = osl::Security().getHomeDir(v);
+ EnsureNoFinalSlash(v);
+ rtl_uString_assign(value, v.pData);
+ return b;
+ }
+ if (key.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("SYSBINDIR"))) {
+ getExecutableDirectory_Impl(value);
+ return true;
+ }
+ if (_base_ini != NULL &&
+ _base_ini->getDirectValue(key, value, mode, requestStack))
+ {
+ return true;
+ }
+ if (!override && getDirectValue(key, value, mode, requestStack)) {
+ return true;
+ }
+ if (mode == LOOKUP_MODE_NORMAL) {
+ FundamentalIniData const & d = FundamentalIni::get();
+ Bootstrap_Impl const * b = static_cast<Bootstrap_Impl const *>(d.ini);
+ if (b != NULL && b != this &&
+ b->getDirectValue(key, value, mode, requestStack))
+ {
+ return true;
+ }
+ }
+ if (defaultValue != NULL) {
+ rtl_uString_assign(value, defaultValue);
+ return true;
+ }
+ rtl_uString_new(value);
+ return false;
+}
+
+bool Bootstrap_Impl::getDirectValue(
+ rtl::OUString const & key, rtl_uString ** value, LookupMode mode,
+ ExpandRequestLink const * requestStack) const
+{
+ rtl::OUString v;
+ if (find(_nameValueList, key, &v)) {
+ expandValue(value, v, mode, this, key, requestStack);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool Bootstrap_Impl::getAmbienceValue(
+ rtl::OUString const & key, rtl_uString ** value, LookupMode mode,
+ ExpandRequestLink const * requestStack) const
+{
+ rtl::OUString v;
+ bool f;
+ {
+ osl::MutexGuard g(osl::Mutex::getGlobalMutex());
+ f = find(rtl_bootstrap_set_list::get(), key, &v);
+ }
+ if (f || getFromCommandLineArgs(key, &v) ||
+ osl_getEnvironment(key.pData, &v.pData) == osl_Process_E_None)
+ {
+ expandValue(value, v, mode, NULL, key, requestStack);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void Bootstrap_Impl::expandValue(
+ rtl_uString ** value, rtl::OUString const & text, LookupMode mode,
+ Bootstrap_Impl const * requestFile, rtl::OUString const & requestKey,
+ ExpandRequestLink const * requestStack) const
+{
+ rtl_uString_assign(
+ value,
+ (mode == LOOKUP_MODE_URE_BOOTSTRAP && isPathnameUrl(text) ?
+ text :
+ recursivelyExpandMacros(
+ this, text,
+ (mode == LOOKUP_MODE_URE_BOOTSTRAP ?
+ LOOKUP_MODE_URE_BOOTSTRAP_EXPANSION : mode),
+ requestFile, requestKey, requestStack)).pData);
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace {
+
+struct bootstrap_map {
+ // map<> may be preferred here, but hash_map<> is implemented fully inline,
+ // thus there is no need to link against the stlport:
+ typedef std::hash_map<
+ rtl::OUString, Bootstrap_Impl *,
+ rtl::OUStringHash, std::equal_to< rtl::OUString >,
+ rtl::Allocator< OUString > > t;
+
+ // get and release must only be called properly synchronized via some mutex
+ // (e.g., osl::Mutex::getGlobalMutex()):
+
+ static t * get() {
+ if (m_map == NULL) {
+ m_map = new t;
+ }
+ return m_map;
+ }
+
+ static void release() {
+ if (m_map != NULL && m_map->empty()) {
+ delete m_map;
+ m_map = NULL;
+ }
+ }
+
+private:
+ bootstrap_map(); // not defined
+
+ static t * m_map;
+};
+
+bootstrap_map::t * bootstrap_map::m_map = NULL;
+
+}
+
+//----------------------------------------------------------------------------
+
+rtlBootstrapHandle SAL_CALL rtl_bootstrap_args_open (
+ rtl_uString * pIniName
+) SAL_THROW_EXTERN_C()
+{
+ OUString iniName( pIniName );
+
+ // normalize path
+ FileStatus status( FileStatusMask_FileURL );
+ DirectoryItem dirItem;
+ if (DirectoryItem::E_None != DirectoryItem::get( iniName, dirItem ) ||
+ DirectoryItem::E_None != dirItem.getFileStatus( status ))
+ {
+ return 0;
+ }
+ iniName = status.getFileURL();
+
+ Bootstrap_Impl * that;
+ osl::ResettableMutexGuard guard( osl::Mutex::getGlobalMutex() );
+ bootstrap_map::t* p_bootstrap_map = bootstrap_map::get();
+ bootstrap_map::t::const_iterator iFind( p_bootstrap_map->find( iniName ) );
+ if (iFind == p_bootstrap_map->end())
+ {
+ bootstrap_map::release();
+ guard.clear();
+ that = new Bootstrap_Impl( iniName );
+ guard.reset();
+ p_bootstrap_map = bootstrap_map::get();
+ iFind = p_bootstrap_map->find( iniName );
+ if (iFind == p_bootstrap_map->end())
+ {
+ ++that->_nRefCount;
+ ::std::pair< bootstrap_map::t::iterator, bool > insertion(
+ p_bootstrap_map->insert(
+ bootstrap_map::t::value_type( iniName, that ) ) );
+ OSL_ASSERT( insertion.second );
+ }
+ else
+ {
+ Bootstrap_Impl * obsolete = that;
+ that = iFind->second;
+ ++that->_nRefCount;
+ guard.clear();
+ delete obsolete;
+ }
+ }
+ else
+ {
+ that = iFind->second;
+ ++that->_nRefCount;
+ }
+ return static_cast< rtlBootstrapHandle >( that );
+}
+
+//----------------------------------------------------------------------------
+
+void SAL_CALL rtl_bootstrap_args_close (
+ rtlBootstrapHandle handle
+) SAL_THROW_EXTERN_C()
+{
+ if (handle == 0)
+ return;
+ Bootstrap_Impl * that = static_cast< Bootstrap_Impl * >( handle );
+
+ osl::MutexGuard guard( osl::Mutex::getGlobalMutex() );
+ bootstrap_map::t* p_bootstrap_map = bootstrap_map::get();
+ OSL_ASSERT(
+ p_bootstrap_map->find( that->_iniName )->second == that );
+ --that->_nRefCount;
+ if (that->_nRefCount == 0)
+ {
+ ::std::size_t nLeaking = 8; // only hold up to 8 files statically
+
+#if OSL_DEBUG_LEVEL == 1 // nonpro
+ nLeaking = 0;
+#elif OSL_DEBUG_LEVEL > 1 // debug
+ nLeaking = 1;
+#endif /* OSL_DEBUG_LEVEL */
+
+ if (p_bootstrap_map->size() > nLeaking)
+ {
+ ::std::size_t erased = p_bootstrap_map->erase( that->_iniName );
+ if (erased != 1) {
+ OSL_ASSERT( false );
+ }
+ delete that;
+ }
+ bootstrap_map::release();
+ }
+}
+
+//----------------------------------------------------------------------------
+
+sal_Bool SAL_CALL rtl_bootstrap_get_from_handle(
+ rtlBootstrapHandle handle,
+ rtl_uString * pName,
+ rtl_uString ** ppValue,
+ rtl_uString * pDefault
+) SAL_THROW_EXTERN_C()
+{
+ osl::MutexGuard guard( osl::Mutex::getGlobalMutex() );
+
+ sal_Bool found = sal_False;
+ if(ppValue && pName)
+ {
+ if (handle == 0)
+ handle = get_static_bootstrap_handle();
+ found = static_cast< Bootstrap_Impl * >( handle )->getValue(
+ pName, ppValue, pDefault, LOOKUP_MODE_NORMAL, false, NULL );
+ }
+
+ return found;
+}
+
+//----------------------------------------------------------------------------
+
+void SAL_CALL rtl_bootstrap_get_iniName_from_handle (
+ rtlBootstrapHandle handle,
+ rtl_uString ** ppIniName
+) SAL_THROW_EXTERN_C()
+{
+ if(ppIniName)
+ {
+ if(handle)
+ {
+ Bootstrap_Impl * pImpl = static_cast<Bootstrap_Impl*>(handle);
+ rtl_uString_assign(ppIniName, pImpl->_iniName.pData);
+ }
+ else
+ {
+ const OUString & iniName = getIniFileName_Impl();
+ rtl_uString_assign(ppIniName, iniName.pData);
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+
+void SAL_CALL rtl_bootstrap_setIniFileName (
+ rtl_uString * pName
+) SAL_THROW_EXTERN_C()
+{
+ osl::MutexGuard guard( osl::Mutex::getGlobalMutex() );
+ OUString & file = getIniFileName_Impl();
+ file = pName;
+}
+
+//----------------------------------------------------------------------------
+
+sal_Bool SAL_CALL rtl_bootstrap_get (
+ rtl_uString * pName,
+ rtl_uString ** ppValue,
+ rtl_uString * pDefault
+) SAL_THROW_EXTERN_C()
+{
+ return rtl_bootstrap_get_from_handle(0, pName, ppValue, pDefault);
+}
+
+//----------------------------------------------------------------------------
+
+void SAL_CALL rtl_bootstrap_set (
+ rtl_uString * pName,
+ rtl_uString * pValue
+) SAL_THROW_EXTERN_C()
+{
+ const OUString name( pName );
+ const OUString value( pValue );
+
+ osl::MutexGuard guard( osl::Mutex::getGlobalMutex() );
+
+ NameValueList& r_rtl_bootstrap_set_list = rtl_bootstrap_set_list::get();
+ NameValueList::iterator iPos( r_rtl_bootstrap_set_list.begin() );
+ NameValueList::iterator iEnd( r_rtl_bootstrap_set_list.end() );
+ for ( ; iPos != iEnd; ++iPos )
+ {
+ if (iPos->sName.equals( name ))
+ {
+ iPos->sValue = value;
+ return;
+ }
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ OString cstr_name( OUStringToOString( name, RTL_TEXTENCODING_ASCII_US ) );
+ OString cstr_value( OUStringToOString( value, RTL_TEXTENCODING_ASCII_US ) );
+ OSL_TRACE(
+ "bootstrap.cxx: explicitly setting: name=%s value=%s\n",
+ cstr_name.getStr(), cstr_value.getStr() );
+#endif /* OSL_DEBUG_LEVEL > 1 */
+
+ r_rtl_bootstrap_set_list.push_back( rtl_bootstrap_NameValue( name, value ) );
+}
+
+//----------------------------------------------------------------------------
+
+void SAL_CALL rtl_bootstrap_expandMacros_from_handle (
+ rtlBootstrapHandle handle,
+ rtl_uString ** macro
+) SAL_THROW_EXTERN_C()
+{
+ if (handle == NULL) {
+ handle = get_static_bootstrap_handle();
+ }
+ OUString expanded( expandMacros( static_cast< Bootstrap_Impl * >( handle ),
+ * reinterpret_cast< OUString const * >( macro ),
+ LOOKUP_MODE_NORMAL, NULL ) );
+ rtl_uString_assign( macro, expanded.pData );
+}
+
+//----------------------------------------------------------------------------
+
+void SAL_CALL rtl_bootstrap_expandMacros(
+ rtl_uString ** macro )
+ SAL_THROW_EXTERN_C()
+{
+ rtl_bootstrap_expandMacros_from_handle(NULL, macro);
+}
+
+void rtl_bootstrap_encode( rtl_uString const * value, rtl_uString ** encoded )
+ SAL_THROW_EXTERN_C()
+{
+ OSL_ASSERT(value != NULL);
+ rtl::OUStringBuffer b;
+ for (sal_Int32 i = 0; i < value->length; ++i) {
+ sal_Unicode c = value->buffer[i];
+ if (c == '$' || c == '\\') {
+ b.append(sal_Unicode('\\'));
+ }
+ b.append(c);
+ }
+ rtl_uString_assign(encoded, b.makeStringAndClear().pData);
+}
+
+namespace {
+
+int hex(sal_Unicode c) {
+ return
+ c >= '0' && c <= '9' ? c - '0' :
+ c >= 'A' && c <= 'F' ? c - 'A' + 10 :
+ c >= 'a' && c <= 'f' ? c - 'a' + 10 : -1;
+}
+
+sal_Unicode read(rtl::OUString const & text, sal_Int32 * pos, bool * escaped) {
+ OSL_ASSERT(
+ pos != NULL && *pos >= 0 && *pos < text.getLength() && escaped != NULL);
+ sal_Unicode c = text[(*pos)++];
+ if (c == '\\') {
+ int n1, n2, n3, n4;
+ if (*pos < text.getLength() - 4 && text[*pos] == 'u' &&
+ ((n1 = hex(text[*pos + 1])) >= 0) &&
+ ((n2 = hex(text[*pos + 2])) >= 0) &&
+ ((n3 = hex(text[*pos + 3])) >= 0) &&
+ ((n4 = hex(text[*pos + 4])) >= 0))
+ {
+ *pos += 5;
+ *escaped = true;
+ return static_cast< sal_Unicode >(
+ (n1 << 12) | (n2 << 8) | (n3 << 4) | n4);
+ } else if (*pos < text.getLength()) {
+ *escaped = true;
+ return text[(*pos)++];
+ }
+ }
+ *escaped = false;
+ return c;
+}
+
+rtl::OUString lookup(
+ Bootstrap_Impl const * file, LookupMode mode, bool override,
+ rtl::OUString const & key, ExpandRequestLink const * requestStack)
+{
+ rtl::OUString v;
+ (file == NULL ? get_static_bootstrap_handle() : file)->getValue(
+ key, &v.pData, NULL, mode, override, requestStack);
+ return v;
+}
+
+rtl::OUString expandMacros(
+ Bootstrap_Impl const * file, rtl::OUString const & text, LookupMode mode,
+ ExpandRequestLink const * requestStack)
+{
+ rtl::OUStringBuffer buf;
+ for (sal_Int32 i = 0; i < text.getLength();) {
+ bool escaped;
+ sal_Unicode c = read(text, &i, &escaped);
+ if (escaped || c != '$') {
+ buf.append(c);
+ } else {
+ if (i < text.getLength() && text[i] == '{') {
+ ++i;
+ sal_Int32 p = i;
+ sal_Int32 nesting = 0;
+ rtl::OUString seg[3];
+ int n = 0;
+ while (i < text.getLength()) {
+ sal_Int32 j = i;
+ c = read(text, &i, &escaped);
+ if (!escaped) {
+ switch (c) {
+ case '{':
+ ++nesting;
+ break;
+ case '}':
+ if (nesting == 0) {
+ seg[n++] = text.copy(p, j - p);
+ goto done;
+ } else {
+ --nesting;
+ }
+ break;
+ case ':':
+ if (nesting == 0 && n < 2) {
+ seg[n++] = text.copy(p, j - p);
+ p = i;
+ }
+ break;
+ }
+ }
+ }
+ done:
+ for (int j = 0; j < n; ++j) {
+ seg[j] = expandMacros(file, seg[j], mode, requestStack);
+ }
+ if (n == 3 && seg[1].getLength() == 0) {
+ // For backward compatibility, treat ${file::key} the same
+ // as just ${file:key}:
+ seg[1] = seg[2];
+ n = 2;
+ }
+ if (n == 1) {
+ buf.append(lookup(file, mode, false, seg[0], requestStack));
+ } else if (n == 2) {
+ if (seg[0].equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM(".link")))
+ {
+ osl::File f(seg[1]);
+ rtl::ByteSequence seq;
+ rtl::OUString line;
+ rtl::OUString url;
+ // Silently ignore any errors (is that good?):
+ if (f.open(OpenFlag_Read) == osl::FileBase::E_None &&
+ f.readLine(seq) == osl::FileBase::E_None &&
+ rtl_convertStringToUString(
+ &line.pData,
+ reinterpret_cast< char const * >(
+ seq.getConstArray()),
+ seq.getLength(), RTL_TEXTENCODING_UTF8,
+ (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
+ RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
+ RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)) &&
+ (osl::File::getFileURLFromSystemPath(line, url) ==
+ osl::FileBase::E_None))
+ {
+ try {
+ buf.append(
+ rtl::Uri::convertRelToAbs(seg[1], url));
+ } catch (rtl::MalformedUriException &) {}
+ }
+ } else {
+ buf.append(
+ lookup(
+ static_cast< Bootstrap_Impl * >(
+ rtl::Bootstrap(seg[0]).getHandle()),
+ mode, false, seg[1], requestStack));
+ }
+ } else if (seg[0].equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM(".override")))
+ {
+ rtl::Bootstrap b(seg[1]);
+ Bootstrap_Impl * f = static_cast< Bootstrap_Impl * >(
+ b.getHandle());
+ buf.append(
+ lookup(f, mode, f != NULL, seg[2], requestStack));
+ } else {
+ // Going through osl::Profile, this code erroneously does
+ // not recursively expand macros in the resulting
+ // replacement text (and if it did, it would fail to detect
+ // cycles that pass through here):
+ buf.append(
+ rtl::OStringToOUString(
+ osl::Profile(seg[0]).readString(
+ rtl::OUStringToOString(
+ seg[1], RTL_TEXTENCODING_UTF8),
+ rtl::OUStringToOString(
+ seg[2], RTL_TEXTENCODING_UTF8),
+ rtl::OString()),
+ RTL_TEXTENCODING_UTF8));
+ }
+ } else {
+ rtl::OUStringBuffer kbuf;
+ for (; i < text.getLength();) {
+ sal_Int32 j = i;
+ c = read(text, &j, &escaped);
+ if (!escaped &&
+ (c == ' ' || c == '$' || c == '-' || c == '/' ||
+ c == ';' || c == '\\'))
+ {
+ break;
+ }
+ kbuf.append(c);
+ i = j;
+ }
+ buf.append(
+ lookup(
+ file, mode, false, kbuf.makeStringAndClear(),
+ requestStack));
+ }
+ }
+ }
+ return buf.makeStringAndClear();
+}
+
+}
diff --git a/sal/rtl/source/byteseq.c b/sal/rtl/source/byteseq.c
new file mode 100644
index 000000000000..42b905a8d78f
--- /dev/null
+++ b/sal/rtl/source/byteseq.c
@@ -0,0 +1,254 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <osl/diagnose.h>
+#include <osl/interlck.h>
+
+#include <rtl/byteseq.h>
+#include <rtl/alloc.h>
+#include <rtl/memory.h>
+
+/* static data to be referenced by all empty strings
+ * the refCount is predefined to 1 and must never become 0 !
+ */
+static sal_Sequence aEmpty_rtl_ByteSeq =
+{
+ 1, /* sal_Int32 refCount; */
+ 0, /* sal_Int32 length; */
+ { 0 } /* sal_Unicode buffer[1]; */
+};
+
+//==================================================================================================
+void SAL_CALL rtl_byte_sequence_reference2One(
+ sal_Sequence ** ppSequence )
+{
+ sal_Sequence * pSequence, * pNew;
+ sal_Int32 nElements;
+
+ OSL_ENSURE( ppSequence, "### null ptr!" );
+ pSequence = *ppSequence;
+
+ if (pSequence->nRefCount > 1)
+ {
+ nElements = pSequence->nElements;
+ if (nElements)
+ {
+ pNew = (sal_Sequence *)rtl_allocateMemory( SAL_SEQUENCE_HEADER_SIZE + nElements );
+
+ if ( pNew != 0 )
+ rtl_copyMemory( pNew->elements, pSequence->elements, nElements );
+
+ if (! osl_decrementInterlockedCount( &pSequence->nRefCount ))
+ rtl_freeMemory( pSequence );
+ }
+ else
+ {
+ pNew = (sal_Sequence *)rtl_allocateMemory( SAL_SEQUENCE_HEADER_SIZE );
+ }
+
+ if ( pNew != 0 )
+ {
+ pNew->nRefCount = 1;
+ pNew->nElements = nElements;
+ }
+
+ *ppSequence = pNew;
+ }
+}
+
+//==================================================================================================
+void SAL_CALL rtl_byte_sequence_realloc(
+ sal_Sequence ** ppSequence, sal_Int32 nSize )
+{
+ sal_Sequence * pSequence, * pNew;
+ sal_Int32 nElements;
+
+ OSL_ENSURE( ppSequence, "### null ptr!" );
+ pSequence = *ppSequence;
+ nElements = pSequence->nElements;
+
+ if (nElements == nSize)
+ return;
+
+ if (pSequence->nRefCount > 1) // split
+ {
+ pNew = (sal_Sequence *)rtl_allocateMemory( SAL_SEQUENCE_HEADER_SIZE + nSize );
+
+ if ( pNew != 0 )
+ {
+ if (nSize > nElements)
+ {
+ rtl_copyMemory( pNew->elements, pSequence->elements, nElements );
+ rtl_zeroMemory( pNew->elements + nElements, nSize - nElements );
+ }
+ else
+ {
+ rtl_copyMemory( pNew->elements, pSequence->elements, nSize );
+ }
+ }
+
+ if (! osl_decrementInterlockedCount( &pSequence->nRefCount ))
+ rtl_freeMemory( pSequence );
+ pSequence = pNew;
+ }
+ else
+ {
+ pSequence = (sal_Sequence *)rtl_reallocateMemory(
+ pSequence, SAL_SEQUENCE_HEADER_SIZE + nSize );
+ }
+
+ if ( pSequence != 0 )
+ {
+ pSequence->nRefCount = 1;
+ pSequence->nElements = nSize;
+ }
+
+ *ppSequence = pSequence;
+}
+
+//==================================================================================================
+void SAL_CALL rtl_byte_sequence_acquire( sal_Sequence *pSequence )
+{
+ OSL_ASSERT( pSequence );
+ osl_incrementInterlockedCount( &(pSequence->nRefCount) );
+}
+
+//==================================================================================================
+void SAL_CALL rtl_byte_sequence_release( sal_Sequence *pSequence )
+{
+ if ( pSequence != 0 )
+ {
+ if (! osl_decrementInterlockedCount( &(pSequence->nRefCount )) )
+ {
+ rtl_freeMemory( pSequence );
+ }
+ }
+}
+
+//==================================================================================================
+void SAL_CALL rtl_byte_sequence_construct( sal_Sequence **ppSequence , sal_Int32 nLength )
+{
+ OSL_ASSERT( ppSequence );
+ if( *ppSequence )
+ {
+ rtl_byte_sequence_release( *ppSequence );
+ *ppSequence = 0;
+ }
+
+ if( nLength )
+ {
+ *ppSequence = (sal_Sequence *) rtl_allocateZeroMemory( SAL_SEQUENCE_HEADER_SIZE + nLength );
+
+ if ( *ppSequence != 0 )
+ {
+ (*ppSequence)->nRefCount = 1;
+ (*ppSequence)->nElements = nLength;
+ }
+ }
+ else
+ {
+ *ppSequence = &aEmpty_rtl_ByteSeq;
+ rtl_byte_sequence_acquire( *ppSequence );
+ }
+}
+
+//==================================================================================================
+void SAL_CALL rtl_byte_sequence_constructNoDefault( sal_Sequence **ppSequence , sal_Int32 nLength )
+{
+ OSL_ASSERT( ppSequence );
+ if( *ppSequence )
+ {
+ rtl_byte_sequence_release( *ppSequence );
+ *ppSequence = 0;
+ }
+
+ *ppSequence = (sal_Sequence *) rtl_allocateMemory( SAL_SEQUENCE_HEADER_SIZE + nLength );
+
+ if ( *ppSequence != 0 )
+ {
+ (*ppSequence)->nRefCount = 1;
+ (*ppSequence)->nElements = nLength;
+ }
+}
+
+//==================================================================================================
+void SAL_CALL rtl_byte_sequence_constructFromArray(
+ sal_Sequence **ppSequence, const sal_Int8 *pData , sal_Int32 nLength )
+{
+ rtl_byte_sequence_constructNoDefault( ppSequence , nLength );
+ if ( *ppSequence != 0 )
+ rtl_copyMemory( (*ppSequence)->elements, pData, nLength );
+}
+
+//==================================================================================================
+void SAL_CALL rtl_byte_sequence_assign( sal_Sequence **ppSequence , sal_Sequence *pSequence )
+{
+ if ( *ppSequence != pSequence)
+ {
+ if( *ppSequence )
+ {
+ rtl_byte_sequence_release( *ppSequence );
+ }
+ *ppSequence = pSequence;
+ rtl_byte_sequence_acquire( *ppSequence );
+ }
+// else
+// nothing to do
+
+}
+
+//==================================================================================================
+sal_Bool SAL_CALL rtl_byte_sequence_equals( sal_Sequence *pSequence1 , sal_Sequence *pSequence2 )
+{
+ OSL_ASSERT( pSequence1 );
+ OSL_ASSERT( pSequence2 );
+ if (pSequence1 == pSequence2)
+ {
+ return sal_True;
+ }
+ if (pSequence1->nElements != pSequence2->nElements)
+ {
+ return sal_False;
+ }
+ return (sal_Bool)
+ (rtl_compareMemory(
+ pSequence1->elements, pSequence2->elements, pSequence1->nElements )
+ == 0);
+}
+
+
+//==================================================================================================
+const sal_Int8 *SAL_CALL rtl_byte_sequence_getConstArray( sal_Sequence *pSequence )
+{
+ return ((const sal_Int8*)(pSequence->elements));
+}
+
+//==================================================================================================
+sal_Int32 SAL_CALL rtl_byte_sequence_getLength( sal_Sequence *pSequence )
+{
+ return pSequence->nElements;
+}
diff --git a/sal/rtl/source/cipher.c b/sal/rtl/source/cipher.c
new file mode 100644
index 000000000000..cb11f93cb8e4
--- /dev/null
+++ b/sal/rtl/source/cipher.c
@@ -0,0 +1,1363 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#define _RTL_CIPHER_C_ "$Revision: 1.5 $"
+
+#include <sal/types.h>
+#include <rtl/alloc.h>
+#include <rtl/memory.h>
+#include <rtl/cipher.h>
+
+/*========================================================================
+ *
+ * rtlCipher internals.
+ *
+ *======================================================================*/
+#define RTL_CIPHER_NTOHL(c, l) \
+ ((l) = ((sal_uInt32)(*((c)++))) << 24L, \
+ (l) |= ((sal_uInt32)(*((c)++))) << 16L, \
+ (l) |= ((sal_uInt32)(*((c)++))) << 8L, \
+ (l) |= ((sal_uInt32)(*((c)++))))
+
+#define RTL_CIPHER_HTONL(l, c) \
+ (*((c)++) = (sal_uInt8)(((l) >> 24L) & 0xff), \
+ *((c)++) = (sal_uInt8)(((l) >> 16L) & 0xff), \
+ *((c)++) = (sal_uInt8)(((l) >> 8L) & 0xff), \
+ *((c)++) = (sal_uInt8)(((l) ) & 0xff))
+
+#define RTL_CIPHER_NTOHL64(c, xl, xr, n) \
+{ \
+ (xl) = (xr) = 0; \
+ (c) += (n); \
+ switch ((n)) \
+ { \
+ case 8: (xr) = ((sal_uInt32)(*(--(c)))); \
+ case 7: (xr) |= ((sal_uInt32)(*(--(c)))) << 8L; \
+ case 6: (xr) |= ((sal_uInt32)(*(--(c)))) << 16L; \
+ case 5: (xr) |= ((sal_uInt32)(*(--(c)))) << 24L; \
+ case 4: (xl) = ((sal_uInt32)(*(--(c)))); \
+ case 3: (xl) |= ((sal_uInt32)(*(--(c)))) << 8L; \
+ case 2: (xl) |= ((sal_uInt32)(*(--(c)))) << 16L; \
+ case 1: (xl) |= ((sal_uInt32)(*(--(c)))) << 24L; \
+ } \
+}
+
+#define RTL_CIPHER_HTONL64(xl, xr, c, n) \
+{ \
+ (c) += (n); \
+ switch ((n)) \
+ { \
+ case 8: *(--(c)) = (sal_uInt8)(((xr) ) & 0xff); \
+ case 7: *(--(c)) = (sal_uInt8)(((xr) >> 8L) & 0xff); \
+ case 6: *(--(c)) = (sal_uInt8)(((xr) >> 16L) & 0xff); \
+ case 5: *(--(c)) = (sal_uInt8)(((xr) >> 24L) & 0xff); \
+ case 4: *(--(c)) = (sal_uInt8)(((xl) ) & 0xff); \
+ case 3: *(--(c)) = (sal_uInt8)(((xl) >> 8L) & 0xff); \
+ case 2: *(--(c)) = (sal_uInt8)(((xl) >> 16L) & 0xff); \
+ case 1: *(--(c)) = (sal_uInt8)(((xl) >> 24L) & 0xff); \
+ } \
+}
+
+typedef rtlCipherError (SAL_CALL cipher_init_t) (
+ rtlCipher Cipher,
+ rtlCipherDirection Direction,
+ const sal_uInt8 *pKeyData, sal_Size nKeyLen,
+ const sal_uInt8 *pArgData, sal_Size nArgLen);
+
+typedef rtlCipherError (SAL_CALL cipher_update_t) (
+ rtlCipher Cipher,
+ const void *pData, sal_Size nDatLen,
+ sal_uInt8 *pBuffer, sal_Size nBufLen);
+
+typedef void (SAL_CALL cipher_delete_t) (rtlCipher Cipher);
+
+/** Cipher_Impl.
+ */
+typedef struct cipher_impl_st
+{
+ rtlCipherAlgorithm m_algorithm;
+ rtlCipherDirection m_direction;
+ rtlCipherMode m_mode;
+
+ cipher_init_t *m_init;
+ cipher_update_t *m_encode;
+ cipher_update_t *m_decode;
+ cipher_delete_t *m_delete;
+} Cipher_Impl;
+
+/*========================================================================
+ *
+ * rtlCipher implementation.
+ *
+ *======================================================================*/
+/*
+ * rtl_cipher_create.
+ */
+rtlCipher SAL_CALL rtl_cipher_create (
+ rtlCipherAlgorithm Algorithm,
+ rtlCipherMode Mode)
+{
+ rtlCipher Cipher = (rtlCipher)NULL;
+ switch (Algorithm)
+ {
+ case rtl_Cipher_AlgorithmBF:
+ Cipher = rtl_cipher_createBF (Mode);
+ break;
+
+ case rtl_Cipher_AlgorithmARCFOUR:
+ Cipher = rtl_cipher_createARCFOUR (Mode);
+ break;
+
+ default: /* rtl_Cipher_AlgorithmInvalid */
+ break;
+ }
+ return Cipher;
+}
+
+/*
+ * rtl_cipher_init.
+ */
+rtlCipherError SAL_CALL rtl_cipher_init (
+ rtlCipher Cipher,
+ rtlCipherDirection Direction,
+ const sal_uInt8 *pKeyData, sal_Size nKeyLen,
+ const sal_uInt8 *pArgData, sal_Size nArgLen)
+{
+ Cipher_Impl *pImpl = (Cipher_Impl*)Cipher;
+ if (pImpl == NULL)
+ return rtl_Cipher_E_Argument;
+ if (pImpl->m_init == NULL)
+ return rtl_Cipher_E_Unknown;
+
+ return (pImpl->m_init)(
+ Cipher, Direction, pKeyData, nKeyLen, pArgData, nArgLen);
+}
+
+/*
+ * rtl_cipher_encode.
+ */
+rtlCipherError SAL_CALL rtl_cipher_encode (
+ rtlCipher Cipher,
+ const void *pData, sal_Size nDatLen,
+ sal_uInt8 *pBuffer, sal_Size nBufLen)
+{
+ Cipher_Impl *pImpl = (Cipher_Impl*)Cipher;
+ if (pImpl == NULL)
+ return rtl_Cipher_E_Argument;
+ if (pImpl->m_encode == NULL)
+ return rtl_Cipher_E_Unknown;
+
+ return (pImpl->m_encode)(Cipher, pData, nDatLen, pBuffer, nBufLen);
+}
+
+/*
+ * rtl_cipher_decode.
+ */
+rtlCipherError SAL_CALL rtl_cipher_decode (
+ rtlCipher Cipher,
+ const void *pData, sal_Size nDatLen,
+ sal_uInt8 *pBuffer, sal_Size nBufLen)
+{
+ Cipher_Impl *pImpl = (Cipher_Impl*)Cipher;
+ if (pImpl == NULL)
+ return rtl_Cipher_E_Argument;
+ if (pImpl->m_decode == NULL)
+ return rtl_Cipher_E_Unknown;
+
+ return (pImpl->m_decode)(Cipher, pData, nDatLen, pBuffer, nBufLen);
+}
+
+/*
+ * rtl_cipher_destroy.
+ */
+void SAL_CALL rtl_cipher_destroy (rtlCipher Cipher)
+{
+ Cipher_Impl *pImpl = (Cipher_Impl*)Cipher;
+ if (pImpl && pImpl->m_delete)
+ pImpl->m_delete (Cipher);
+}
+
+/*========================================================================
+ *
+ * rtl_cipherBF (Blowfish) internals.
+ *
+ *======================================================================*/
+#define CIPHER_ROUNDS_BF 16
+
+typedef struct cipherBF_key_st
+{
+ sal_uInt32 m_S[4][256];
+ sal_uInt32 m_P[CIPHER_ROUNDS_BF + 2];
+} CipherKeyBF;
+
+typedef struct cipherBF_context_st
+{
+ CipherKeyBF m_key;
+ union
+ {
+ sal_uInt32 m_long[2];
+ sal_uInt8 m_byte[8];
+ } m_iv;
+ sal_uInt32 m_offset;
+} CipherContextBF;
+
+typedef struct cipherBF_impl_st
+{
+ Cipher_Impl m_cipher;
+ CipherContextBF m_context;
+} CipherBF_Impl;
+
+/** __rtl_cipherBF_init.
+ */
+static rtlCipherError __rtl_cipherBF_init (
+ CipherContextBF *ctx,
+ rtlCipherMode eMode,
+ const sal_uInt8 *pKeyData, sal_Size nKeyLen,
+ const sal_uInt8 *pArgData, sal_Size nArgLen);
+
+/** __rtl_cipherBF_update.
+ */
+static rtlCipherError __rtl_cipherBF_update (
+ CipherContextBF *ctx,
+ rtlCipherMode eMode,
+ rtlCipherDirection eDirection,
+ const sal_uInt8 *pData, sal_Size nDatLen,
+ sal_uInt8 *pBuffer, sal_Size nBufLen);
+
+/** __rtl_cipherBF_updateECB.
+ */
+static void __rtl_cipherBF_updateECB (
+ CipherContextBF *ctx,
+ rtlCipherDirection direction,
+ const sal_uInt8 *pData,
+ sal_uInt8 *pBuffer,
+ sal_Size nLength);
+
+/** __rtl_cipherBF_updateCBC.
+ */
+static void __rtl_cipherBF_updateCBC (
+ CipherContextBF *ctx,
+ rtlCipherDirection direction,
+ const sal_uInt8 *pData,
+ sal_uInt8 *pBuffer,
+ sal_Size nLength);
+
+/** __rtl_cipherBF_updateCFB.
+ */
+static void __rtl_cipherBF_updateCFB (
+ CipherContextBF *ctx,
+ rtlCipherDirection direction,
+ const sal_uInt8 *pData,
+ sal_uInt8 *pBuffer);
+
+/** __rtl_cipher_encode.
+ */
+static void __rtl_cipherBF_encode (
+ CipherKeyBF *key, sal_uInt32 *xl, sal_uInt32 *xr);
+
+/** __rtl_cipherBF_decode.
+ */
+static void __rtl_cipherBF_decode (
+ CipherKeyBF *key, sal_uInt32 *xl, sal_uInt32 *xr);
+
+/** __rtl_cipherBF.
+ */
+static sal_uInt32 __rtl_cipherBF (
+ CipherKeyBF *key, sal_uInt32 x);
+
+/** __rtl_cipherBF_key.
+ */
+static const CipherKeyBF __rtl_cipherBF_key =
+{
+ /* S */
+ {
+ /* S[0] */
+ {
+ /* 0 */
+ 0xD1310BA6L, 0x98DFB5ACL, 0x2FFD72DBL, 0xD01ADFB7L,
+ 0xB8E1AFEDL, 0x6A267E96L, 0xBA7C9045L, 0xF12C7F99L,
+ 0x24A19947L, 0xB3916CF7L, 0x0801F2E2L, 0x858EFC16L,
+ 0x636920D8L, 0x71574E69L, 0xA458FEA3L, 0xF4933D7EL,
+
+ /* 1 */
+ 0x0D95748FL, 0x728EB658L, 0x718BCD58L, 0x82154AEEL,
+ 0x7B54A41DL, 0xC25A59B5L, 0x9C30D539L, 0x2AF26013L,
+ 0xC5D1B023L, 0x286085F0L, 0xCA417918L, 0xB8DB38EFL,
+ 0x8E79DCB0L, 0x603A180EL, 0x6C9E0E8BL, 0xB01E8A3EL,
+
+ /* 2 */
+ 0xD71577C1L, 0xBD314B27L, 0x78AF2FDAL, 0x55605C60L,
+ 0xE65525F3L, 0xAA55AB94L, 0x57489862L, 0x63E81440L,
+ 0x55CA396AL, 0x2AAB10B6L, 0xB4CC5C34L, 0x1141E8CEL,
+ 0xA15486AFL, 0x7C72E993L, 0xB3EE1411L, 0x636FBC2AL,
+
+ /* 3 */
+ 0x2BA9C55DL, 0x741831F6L, 0xCE5C3E16L, 0x9B87931EL,
+ 0xAFD6BA33L, 0x6C24CF5CL, 0x7A325381L, 0x28958677L,
+ 0x3B8F4898L, 0x6B4BB9AFL, 0xC4BFE81BL, 0x66282193L,
+ 0x61D809CCL, 0xFB21A991L, 0x487CAC60L, 0x5DEC8032L,
+
+ /* 4 */
+ 0xEF845D5DL, 0xE98575B1L, 0xDC262302L, 0xEB651B88L,
+ 0x23893E81L, 0xD396ACC5L, 0x0F6D6FF3L, 0x83F44239L,
+ 0x2E0B4482L, 0xA4842004L, 0x69C8F04AL, 0x9E1F9B5EL,
+ 0x21C66842L, 0xF6E96C9AL, 0x670C9C61L, 0xABD388F0L,
+
+ /* 5 */
+ 0x6A51A0D2L, 0xD8542F68L, 0x960FA728L, 0xAB5133A3L,
+ 0x6EEF0B6CL, 0x137A3BE4L, 0xBA3BF050L, 0x7EFB2A98L,
+ 0xA1F1651DL, 0x39AF0176L, 0x66CA593EL, 0x82430E88L,
+ 0x8CEE8619L, 0x456F9FB4L, 0x7D84A5C3L, 0x3B8B5EBEL,
+
+ /* 6 */
+ 0xE06F75D8L, 0x85C12073L, 0x401A449FL, 0x56C16AA6L,
+ 0x4ED3AA62L, 0x363F7706L, 0x1BFEDF72L, 0x429B023DL,
+ 0x37D0D724L, 0xD00A1248L, 0xDB0FEAD3L, 0x49F1C09BL,
+ 0x075372C9L, 0x80991B7BL, 0x25D479D8L, 0xF6E8DEF7L,
+
+ /* 7 */
+ 0xE3FE501AL, 0xB6794C3BL, 0x976CE0BDL, 0x04C006BAL,
+ 0xC1A94FB6L, 0x409F60C4L, 0x5E5C9EC2L, 0x196A2463L,
+ 0x68FB6FAFL, 0x3E6C53B5L, 0x1339B2EBL, 0x3B52EC6FL,
+ 0x6DFC511FL, 0x9B30952CL, 0xCC814544L, 0xAF5EBD09L,
+
+ /* 8 */
+ 0xBEE3D004L, 0xDE334AFDL, 0x660F2807L, 0x192E4BB3L,
+ 0xC0CBA857L, 0x45C8740FL, 0xD20B5F39L, 0xB9D3FBDBL,
+ 0x5579C0BDL, 0x1A60320AL, 0xD6A100C6L, 0x402C7279L,
+ 0x679F25FEL, 0xFB1FA3CCL, 0x8EA5E9F8L, 0xDB3222F8L,
+
+ /* 9 */
+ 0x3C7516DFL, 0xFD616B15L, 0x2F501EC8L, 0xAD0552ABL,
+ 0x323DB5FAL, 0xFD238760L, 0x53317B48L, 0x3E00DF82L,
+ 0x9E5C57BBL, 0xCA6F8CA0L, 0x1A87562EL, 0xDF1769DBL,
+ 0xD542A8F6L, 0x287EFFC3L, 0xAC6732C6L, 0x8C4F5573L,
+
+ /* A */
+ 0x695B27B0L, 0xBBCA58C8L, 0xE1FFA35DL, 0xB8F011A0L,
+ 0x10FA3D98L, 0xFD2183B8L, 0x4AFCB56CL, 0x2DD1D35BL,
+ 0x9A53E479L, 0xB6F84565L, 0xD28E49BCL, 0x4BFB9790L,
+ 0xE1DDF2DAL, 0xA4CB7E33L, 0x62FB1341L, 0xCEE4C6E8L,
+
+ /* B */
+ 0xEF20CADAL, 0x36774C01L, 0xD07E9EFEL, 0x2BF11FB4L,
+ 0x95DBDA4DL, 0xAE909198L, 0xEAAD8E71L, 0x6B93D5A0L,
+ 0xD08ED1D0L, 0xAFC725E0L, 0x8E3C5B2FL, 0x8E7594B7L,
+ 0x8FF6E2FBL, 0xF2122B64L, 0x8888B812L, 0x900DF01CL,
+
+ /* C */
+ 0x4FAD5EA0L, 0x688FC31CL, 0xD1CFF191L, 0xB3A8C1ADL,
+ 0x2F2F2218L, 0xBE0E1777L, 0xEA752DFEL, 0x8B021FA1L,
+ 0xE5A0CC0FL, 0xB56F74E8L, 0x18ACF3D6L, 0xCE89E299L,
+ 0xB4A84FE0L, 0xFD13E0B7L, 0x7CC43B81L, 0xD2ADA8D9L,
+
+ /* D */
+ 0x165FA266L, 0x80957705L, 0x93CC7314L, 0x211A1477L,
+ 0xE6AD2065L, 0x77B5FA86L, 0xC75442F5L, 0xFB9D35CFL,
+ 0xEBCDAF0CL, 0x7B3E89A0L, 0xD6411BD3L, 0xAE1E7E49L,
+ 0x00250E2DL, 0x2071B35EL, 0x226800BBL, 0x57B8E0AFL,
+
+ /* E */
+ 0x2464369BL, 0xF009B91EL, 0x5563911DL, 0x59DFA6AAL,
+ 0x78C14389L, 0xD95A537FL, 0x207D5BA2L, 0x02E5B9C5L,
+ 0x83260376L, 0x6295CFA9L, 0x11C81968L, 0x4E734A41L,
+ 0xB3472DCAL, 0x7B14A94AL, 0x1B510052L, 0x9A532915L,
+
+ /* F */
+ 0xD60F573FL, 0xBC9BC6E4L, 0x2B60A476L, 0x81E67400L,
+ 0x08BA6FB5L, 0x571BE91FL, 0xF296EC6BL, 0x2A0DD915L,
+ 0xB6636521L, 0xE7B9F9B6L, 0xFF34052EL, 0xC5855664L,
+ 0x53B02D5DL, 0xA99F8FA1L, 0x08BA4799L, 0x6E85076AL
+ },
+
+ /* S[1] */
+ {
+ 0x4B7A70E9L, 0xB5B32944L, 0xDB75092EL, 0xC4192623L,
+ 0xAD6EA6B0L, 0x49A7DF7DL, 0x9CEE60B8L, 0x8FEDB266L,
+ 0xECAA8C71L, 0x699A17FFL, 0x5664526CL, 0xC2B19EE1L,
+ 0x193602A5L, 0x75094C29L, 0xA0591340L, 0xE4183A3EL,
+
+ 0x3F54989AL, 0x5B429D65L, 0x6B8FE4D6L, 0x99F73FD6L,
+ 0xA1D29C07L, 0xEFE830F5L, 0x4D2D38E6L, 0xF0255DC1L,
+ 0x4CDD2086L, 0x8470EB26L, 0x6382E9C6L, 0x021ECC5EL,
+ 0x09686B3FL, 0x3EBAEFC9L, 0x3C971814L, 0x6B6A70A1L,
+
+ 0x687F3584L, 0x52A0E286L, 0xB79C5305L, 0xAA500737L,
+ 0x3E07841CL, 0x7FDEAE5CL, 0x8E7D44ECL, 0x5716F2B8L,
+ 0xB03ADA37L, 0xF0500C0DL, 0xF01C1F04L, 0x0200B3FFL,
+ 0xAE0CF51AL, 0x3CB574B2L, 0x25837A58L, 0xDC0921BDL,
+
+ 0xD19113F9L, 0x7CA92FF6L, 0x94324773L, 0x22F54701L,
+ 0x3AE5E581L, 0x37C2DADCL, 0xC8B57634L, 0x9AF3DDA7L,
+ 0xA9446146L, 0x0FD0030EL, 0xECC8C73EL, 0xA4751E41L,
+ 0xE238CD99L, 0x3BEA0E2FL, 0x3280BBA1L, 0x183EB331L,
+
+ 0x4E548B38L, 0x4F6DB908L, 0x6F420D03L, 0xF60A04BFL,
+ 0x2CB81290L, 0x24977C79L, 0x5679B072L, 0xBCAF89AFL,
+ 0xDE9A771FL, 0xD9930810L, 0xB38BAE12L, 0xDCCF3F2EL,
+ 0x5512721FL, 0x2E6B7124L, 0x501ADDE6L, 0x9F84CD87L,
+
+ 0x7A584718L, 0x7408DA17L, 0xBC9F9ABCL, 0xE94B7D8CL,
+ 0xEC7AEC3AL, 0xDB851DFAL, 0x63094366L, 0xC464C3D2L,
+ 0xEF1C1847L, 0x3215D908L, 0xDD433B37L, 0x24C2BA16L,
+ 0x12A14D43L, 0x2A65C451L, 0x50940002L, 0x133AE4DDL,
+
+ 0x71DFF89EL, 0x10314E55L, 0x81AC77D6L, 0x5F11199BL,
+ 0x043556F1L, 0xD7A3C76BL, 0x3C11183BL, 0x5924A509L,
+ 0xF28FE6EDL, 0x97F1FBFAL, 0x9EBABF2CL, 0x1E153C6EL,
+ 0x86E34570L, 0xEAE96FB1L, 0x860E5E0AL, 0x5A3E2AB3L,
+
+ 0x771FE71CL, 0x4E3D06FAL, 0x2965DCB9L, 0x99E71D0FL,
+ 0x803E89D6L, 0x5266C825L, 0x2E4CC978L, 0x9C10B36AL,
+ 0xC6150EBAL, 0x94E2EA78L, 0xA5FC3C53L, 0x1E0A2DF4L,
+ 0xF2F74EA7L, 0x361D2B3DL, 0x1939260FL, 0x19C27960L,
+
+ 0x5223A708L, 0xF71312B6L, 0xEBADFE6EL, 0xEAC31F66L,
+ 0xE3BC4595L, 0xA67BC883L, 0xB17F37D1L, 0x018CFF28L,
+ 0xC332DDEFL, 0xBE6C5AA5L, 0x65582185L, 0x68AB9802L,
+ 0xEECEA50FL, 0xDB2F953BL, 0x2AEF7DADL, 0x5B6E2F84L,
+
+ 0x1521B628L, 0x29076170L, 0xECDD4775L, 0x619F1510L,
+ 0x13CCA830L, 0xEB61BD96L, 0x0334FE1EL, 0xAA0363CFL,
+ 0xB5735C90L, 0x4C70A239L, 0xD59E9E0BL, 0xCBAADE14L,
+ 0xEECC86BCL, 0x60622CA7L, 0x9CAB5CABL, 0xB2F3846EL,
+
+ 0x648B1EAFL, 0x19BDF0CAL, 0xA02369B9L, 0x655ABB50L,
+ 0x40685A32L, 0x3C2AB4B3L, 0x319EE9D5L, 0xC021B8F7L,
+ 0x9B540B19L, 0x875FA099L, 0x95F7997EL, 0x623D7DA8L,
+ 0xF837889AL, 0x97E32D77L, 0x11ED935FL, 0x16681281L,
+
+ 0x0E358829L, 0xC7E61FD6L, 0x96DEDFA1L, 0x7858BA99L,
+ 0x57F584A5L, 0x1B227263L, 0x9B83C3FFL, 0x1AC24696L,
+ 0xCDB30AEBL, 0x532E3054L, 0x8FD948E4L, 0x6DBC3128L,
+ 0x58EBF2EFL, 0x34C6FFEAL, 0xFE28ED61L, 0xEE7C3C73L,
+
+ 0x5D4A14D9L, 0xE864B7E3L, 0x42105D14L, 0x203E13E0L,
+ 0x45EEE2B6L, 0xA3AAABEAL, 0xDB6C4F15L, 0xFACB4FD0L,
+ 0xC742F442L, 0xEF6ABBB5L, 0x654F3B1DL, 0x41CD2105L,
+ 0xD81E799EL, 0x86854DC7L, 0xE44B476AL, 0x3D816250L,
+
+ 0xCF62A1F2L, 0x5B8D2646L, 0xFC8883A0L, 0xC1C7B6A3L,
+ 0x7F1524C3L, 0x69CB7492L, 0x47848A0BL, 0x5692B285L,
+ 0x095BBF00L, 0xAD19489DL, 0x1462B174L, 0x23820E00L,
+ 0x58428D2AL, 0x0C55F5EAL, 0x1DADF43EL, 0x233F7061L,
+
+ 0x3372F092L, 0x8D937E41L, 0xD65FECF1L, 0x6C223BDBL,
+ 0x7CDE3759L, 0xCBEE7460L, 0x4085F2A7L, 0xCE77326EL,
+ 0xA6078084L, 0x19F8509EL, 0xE8EFD855L, 0x61D99735L,
+ 0xA969A7AAL, 0xC50C06C2L, 0x5A04ABFCL, 0x800BCADCL,
+
+ 0x9E447A2EL, 0xC3453484L, 0xFDD56705L, 0x0E1E9EC9L,
+ 0xDB73DBD3L, 0x105588CDL, 0x675FDA79L, 0xE3674340L,
+ 0xC5C43465L, 0x713E38D8L, 0x3D28F89EL, 0xF16DFF20L,
+ 0x153E21E7L, 0x8FB03D4AL, 0xE6E39F2BL, 0xDB83ADF7L
+ },
+
+ /* S[2] */
+ {
+ 0xE93D5A68L, 0x948140F7L, 0xF64C261CL, 0x94692934L,
+ 0x411520F7L, 0x7602D4F7L, 0xBCF46B2EL, 0xD4A20068L,
+ 0xD4082471L, 0x3320F46AL, 0x43B7D4B7L, 0x500061AFL,
+ 0x1E39F62EL, 0x97244546L, 0x14214F74L, 0xBF8B8840L,
+
+ 0x4D95FC1DL, 0x96B591AFL, 0x70F4DDD3L, 0x66A02F45L,
+ 0xBFBC09ECL, 0x03BD9785L, 0x7FAC6DD0L, 0x31CB8504L,
+ 0x96EB27B3L, 0x55FD3941L, 0xDA2547E6L, 0xABCA0A9AL,
+ 0x28507825L, 0x530429F4L, 0x0A2C86DAL, 0xE9B66DFBL,
+
+ 0x68DC1462L, 0xD7486900L, 0x680EC0A4L, 0x27A18DEEL,
+ 0x4F3FFEA2L, 0xE887AD8CL, 0xB58CE006L, 0x7AF4D6B6L,
+ 0xAACE1E7CL, 0xD3375FECL, 0xCE78A399L, 0x406B2A42L,
+ 0x20FE9E35L, 0xD9F385B9L, 0xEE39D7ABL, 0x3B124E8BL,
+
+ 0x1DC9FAF7L, 0x4B6D1856L, 0x26A36631L, 0xEAE397B2L,
+ 0x3A6EFA74L, 0xDD5B4332L, 0x6841E7F7L, 0xCA7820FBL,
+ 0xFB0AF54EL, 0xD8FEB397L, 0x454056ACL, 0xBA489527L,
+ 0x55533A3AL, 0x20838D87L, 0xFE6BA9B7L, 0xD096954BL,
+
+ 0x55A867BCL, 0xA1159A58L, 0xCCA92963L, 0x99E1DB33L,
+ 0xA62A4A56L, 0x3F3125F9L, 0x5EF47E1CL, 0x9029317CL,
+ 0xFDF8E802L, 0x04272F70L, 0x80BB155CL, 0x05282CE3L,
+ 0x95C11548L, 0xE4C66D22L, 0x48C1133FL, 0xC70F86DCL,
+
+ 0x07F9C9EEL, 0x41041F0FL, 0x404779A4L, 0x5D886E17L,
+ 0x325F51EBL, 0xD59BC0D1L, 0xF2BCC18FL, 0x41113564L,
+ 0x257B7834L, 0x602A9C60L, 0xDFF8E8A3L, 0x1F636C1BL,
+ 0x0E12B4C2L, 0x02E1329EL, 0xAF664FD1L, 0xCAD18115L,
+
+ 0x6B2395E0L, 0x333E92E1L, 0x3B240B62L, 0xEEBEB922L,
+ 0x85B2A20EL, 0xE6BA0D99L, 0xDE720C8CL, 0x2DA2F728L,
+ 0xD0127845L, 0x95B794FDL, 0x647D0862L, 0xE7CCF5F0L,
+ 0x5449A36FL, 0x877D48FAL, 0xC39DFD27L, 0xF33E8D1EL,
+
+ 0x0A476341L, 0x992EFF74L, 0x3A6F6EABL, 0xF4F8FD37L,
+ 0xA812DC60L, 0xA1EBDDF8L, 0x991BE14CL, 0xDB6E6B0DL,
+ 0xC67B5510L, 0x6D672C37L, 0x2765D43BL, 0xDCD0E804L,
+ 0xF1290DC7L, 0xCC00FFA3L, 0xB5390F92L, 0x690FED0BL,
+
+ 0x667B9FFBL, 0xCEDB7D9CL, 0xA091CF0BL, 0xD9155EA3L,
+ 0xBB132F88L, 0x515BAD24L, 0x7B9479BFL, 0x763BD6EBL,
+ 0x37392EB3L, 0xCC115979L, 0x8026E297L, 0xF42E312DL,
+ 0x6842ADA7L, 0xC66A2B3BL, 0x12754CCCL, 0x782EF11CL,
+
+ 0x6A124237L, 0xB79251E7L, 0x06A1BBE6L, 0x4BFB6350L,
+ 0x1A6B1018L, 0x11CAEDFAL, 0x3D25BDD8L, 0xE2E1C3C9L,
+ 0x44421659L, 0x0A121386L, 0xD90CEC6EL, 0xD5ABEA2AL,
+ 0x64AF674EL, 0xDA86A85FL, 0xBEBFE988L, 0x64E4C3FEL,
+
+ 0x9DBC8057L, 0xF0F7C086L, 0x60787BF8L, 0x6003604DL,
+ 0xD1FD8346L, 0xF6381FB0L, 0x7745AE04L, 0xD736FCCCL,
+ 0x83426B33L, 0xF01EAB71L, 0xB0804187L, 0x3C005E5FL,
+ 0x77A057BEL, 0xBDE8AE24L, 0x55464299L, 0xBF582E61L,
+
+ 0x4E58F48FL, 0xF2DDFDA2L, 0xF474EF38L, 0x8789BDC2L,
+ 0x5366F9C3L, 0xC8B38E74L, 0xB475F255L, 0x46FCD9B9L,
+ 0x7AEB2661L, 0x8B1DDF84L, 0x846A0E79L, 0x915F95E2L,
+ 0x466E598EL, 0x20B45770L, 0x8CD55591L, 0xC902DE4CL,
+
+ 0xB90BACE1L, 0xBB8205D0L, 0x11A86248L, 0x7574A99EL,
+ 0xB77F19B6L, 0xE0A9DC09L, 0x662D09A1L, 0xC4324633L,
+ 0xE85A1F02L, 0x09F0BE8CL, 0x4A99A025L, 0x1D6EFE10L,
+ 0x1AB93D1DL, 0x0BA5A4DFL, 0xA186F20FL, 0x2868F169L,
+
+ 0xDCB7DA83L, 0x573906FEL, 0xA1E2CE9BL, 0x4FCD7F52L,
+ 0x50115E01L, 0xA70683FAL, 0xA002B5C4L, 0x0DE6D027L,
+ 0x9AF88C27L, 0x773F8641L, 0xC3604C06L, 0x61A806B5L,
+ 0xF0177A28L, 0xC0F586E0L, 0x006058AAL, 0x30DC7D62L,
+
+ 0x11E69ED7L, 0x2338EA63L, 0x53C2DD94L, 0xC2C21634L,
+ 0xBBCBEE56L, 0x90BCB6DEL, 0xEBFC7DA1L, 0xCE591D76L,
+ 0x6F05E409L, 0x4B7C0188L, 0x39720A3DL, 0x7C927C24L,
+ 0x86E3725FL, 0x724D9DB9L, 0x1AC15BB4L, 0xD39EB8FCL,
+
+ 0xED545578L, 0x08FCA5B5L, 0xD83D7CD3L, 0x4DAD0FC4L,
+ 0x1E50EF5EL, 0xB161E6F8L, 0xA28514D9L, 0x6C51133CL,
+ 0x6FD5C7E7L, 0x56E14EC4L, 0x362ABFCEL, 0xDDC6C837L,
+ 0xD79A3234L, 0x92638212L, 0x670EFA8EL, 0x406000E0L
+ },
+
+ /* S[3] */
+ {
+ 0x3A39CE37L, 0xD3FAF5CFL, 0xABC27737L, 0x5AC52D1BL,
+ 0x5CB0679EL, 0x4FA33742L, 0xD3822740L, 0x99BC9BBEL,
+ 0xD5118E9DL, 0xBF0F7315L, 0xD62D1C7EL, 0xC700C47BL,
+ 0xB78C1B6BL, 0x21A19045L, 0xB26EB1BEL, 0x6A366EB4L,
+
+ 0x5748AB2FL, 0xBC946E79L, 0xC6A376D2L, 0x6549C2C8L,
+ 0x530FF8EEL, 0x468DDE7DL, 0xD5730A1DL, 0x4CD04DC6L,
+ 0x2939BBDBL, 0xA9BA4650L, 0xAC9526E8L, 0xBE5EE304L,
+ 0xA1FAD5F0L, 0x6A2D519AL, 0x63EF8CE2L, 0x9A86EE22L,
+
+ 0xC089C2B8L, 0x43242EF6L, 0xA51E03AAL, 0x9CF2D0A4L,
+ 0x83C061BAL, 0x9BE96A4DL, 0x8FE51550L, 0xBA645BD6L,
+ 0x2826A2F9L, 0xA73A3AE1L, 0x4BA99586L, 0xEF5562E9L,
+ 0xC72FEFD3L, 0xF752F7DAL, 0x3F046F69L, 0x77FA0A59L,
+
+ 0x80E4A915L, 0x87B08601L, 0x9B09E6ADL, 0x3B3EE593L,
+ 0xE990FD5AL, 0x9E34D797L, 0x2CF0B7D9L, 0x022B8B51L,
+ 0x96D5AC3AL, 0x017DA67DL, 0xD1CF3ED6L, 0x7C7D2D28L,
+ 0x1F9F25CFL, 0xADF2B89BL, 0x5AD6B472L, 0x5A88F54CL,
+
+ 0xE029AC71L, 0xE019A5E6L, 0x47B0ACFDL, 0xED93FA9BL,
+ 0xE8D3C48DL, 0x283B57CCL, 0xF8D56629L, 0x79132E28L,
+ 0x785F0191L, 0xED756055L, 0xF7960E44L, 0xE3D35E8CL,
+ 0x15056DD4L, 0x88F46DBAL, 0x03A16125L, 0x0564F0BDL,
+
+ 0xC3EB9E15L, 0x3C9057A2L, 0x97271AECL, 0xA93A072AL,
+ 0x1B3F6D9BL, 0x1E6321F5L, 0xF59C66FBL, 0x26DCF319L,
+ 0x7533D928L, 0xB155FDF5L, 0x03563482L, 0x8ABA3CBBL,
+ 0x28517711L, 0xC20AD9F8L, 0xABCC5167L, 0xCCAD925FL,
+
+ 0x4DE81751L, 0x3830DC8EL, 0x379D5862L, 0x9320F991L,
+ 0xEA7A90C2L, 0xFB3E7BCEL, 0x5121CE64L, 0x774FBE32L,
+ 0xA8B6E37EL, 0xC3293D46L, 0x48DE5369L, 0x6413E680L,
+ 0xA2AE0810L, 0xDD6DB224L, 0x69852DFDL, 0x09072166L,
+
+ 0xB39A460AL, 0x6445C0DDL, 0x586CDECFL, 0x1C20C8AEL,
+ 0x5BBEF7DDL, 0x1B588D40L, 0xCCD2017FL, 0x6BB4E3BBL,
+ 0xDDA26A7EL, 0x3A59FF45L, 0x3E350A44L, 0xBCB4CDD5L,
+ 0x72EACEA8L, 0xFA6484BBL, 0x8D6612AEL, 0xBF3C6F47L,
+
+ 0xD29BE463L, 0x542F5D9EL, 0xAEC2771BL, 0xF64E6370L,
+ 0x740E0D8DL, 0xE75B1357L, 0xF8721671L, 0xAF537D5DL,
+ 0x4040CB08L, 0x4EB4E2CCL, 0x34D2466AL, 0x0115AF84L,
+ 0xE1B00428L, 0x95983A1DL, 0x06B89FB4L, 0xCE6EA048L,
+
+ 0x6F3F3B82L, 0x3520AB82L, 0x011A1D4BL, 0x277227F8L,
+ 0x611560B1L, 0xE7933FDCL, 0xBB3A792BL, 0x344525BDL,
+ 0xA08839E1L, 0x51CE794BL, 0x2F32C9B7L, 0xA01FBAC9L,
+ 0xE01CC87EL, 0xBCC7D1F6L, 0xCF0111C3L, 0xA1E8AAC7L,
+
+ 0x1A908749L, 0xD44FBD9AL, 0xD0DADECBL, 0xD50ADA38L,
+ 0x0339C32AL, 0xC6913667L, 0x8DF9317CL, 0xE0B12B4FL,
+ 0xF79E59B7L, 0x43F5BB3AL, 0xF2D519FFL, 0x27D9459CL,
+ 0xBF97222CL, 0x15E6FC2AL, 0x0F91FC71L, 0x9B941525L,
+
+ 0xFAE59361L, 0xCEB69CEBL, 0xC2A86459L, 0x12BAA8D1L,
+ 0xB6C1075EL, 0xE3056A0CL, 0x10D25065L, 0xCB03A442L,
+ 0xE0EC6E0EL, 0x1698DB3BL, 0x4C98A0BEL, 0x3278E964L,
+ 0x9F1F9532L, 0xE0D392DFL, 0xD3A0342BL, 0x8971F21EL,
+
+ 0x1B0A7441L, 0x4BA3348CL, 0xC5BE7120L, 0xC37632D8L,
+ 0xDF359F8DL, 0x9B992F2EL, 0xE60B6F47L, 0x0FE3F11DL,
+ 0xE54CDA54L, 0x1EDAD891L, 0xCE6279CFL, 0xCD3E7E6FL,
+ 0x1618B166L, 0xFD2C1D05L, 0x848FD2C5L, 0xF6FB2299L,
+
+ 0xF523F357L, 0xA6327623L, 0x93A83531L, 0x56CCCD02L,
+ 0xACF08162L, 0x5A75EBB5L, 0x6E163697L, 0x88D273CCL,
+ 0xDE966292L, 0x81B949D0L, 0x4C50901BL, 0x71C65614L,
+ 0xE6C6C7BDL, 0x327A140AL, 0x45E1D006L, 0xC3F27B9AL,
+
+ 0xC9AA53FDL, 0x62A80F00L, 0xBB25BFE2L, 0x35BDD2F6L,
+ 0x71126905L, 0xB2040222L, 0xB6CBCF7CL, 0xCD769C2BL,
+ 0x53113EC0L, 0x1640E3D3L, 0x38ABBD60L, 0x2547ADF0L,
+ 0xBA38209CL, 0xF746CE76L, 0x77AFA1C5L, 0x20756060L,
+
+ 0x85CBFE4EL, 0x8AE88DD8L, 0x7AAAF9B0L, 0x4CF9AA7EL,
+ 0x1948C25CL, 0x02FB8A8CL, 0x01C36AE4L, 0xD6EBE1F9L,
+ 0x90D4F869L, 0xA65CDEA0L, 0x3F09252DL, 0xC208E69FL,
+ 0xB74E6132L, 0xCE77E25BL, 0x578FDFE3L, 0x3AC372E6L
+ }
+ },
+
+ /* P */
+ {
+ 0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L,
+ 0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L,
+ 0x452821E6L, 0x38D01377L, 0xBE5466CFL, 0x34E90C6CL,
+ 0xC0AC29B7L, 0xC97C50DDL, 0x3F84D5B5L, 0xB5470917L,
+ 0x9216D5D9L, 0x8979FB1BL
+ }
+};
+
+/*
+ * __rtl_cipherBF_init.
+ */
+static rtlCipherError __rtl_cipherBF_init (
+ CipherContextBF *ctx,
+ rtlCipherMode eMode,
+ const sal_uInt8 *pKeyData, sal_Size nKeyLen,
+ const sal_uInt8 *pArgData, sal_Size nArgLen)
+{
+ CipherKeyBF *key;
+ sal_uInt32 D, DL, DR;
+ sal_uInt16 i, j, k;
+
+ key = &(ctx->m_key);
+
+ rtl_copyMemory (key, &__rtl_cipherBF_key, sizeof (CipherKeyBF));
+ rtl_zeroMemory (&(ctx->m_iv), sizeof(ctx->m_iv));
+ ctx->m_offset = 0;
+
+ for (i = 0, k = 0; i < CIPHER_ROUNDS_BF + 2; ++i)
+ {
+ D = 0;
+ for (j = 0; j < 4; ++j)
+ {
+ D = ((D << 8) | pKeyData[k]);
+ k++;
+ if (k >= nKeyLen)
+ k = 0;
+ }
+ key->m_P[i] ^= D;
+ }
+
+ DL = 0;
+ DR = 0;
+
+ for (i = 0; i < CIPHER_ROUNDS_BF + 2; i += 2)
+ {
+ __rtl_cipherBF_encode (key, &DL, &DR);
+ key->m_P[i ] = DL;
+ key->m_P[i + 1] = DR;
+ }
+
+ for (i = 0; i < 4; ++i)
+ {
+ for (k = 0; k < 256; k += 2)
+ {
+ __rtl_cipherBF_encode (key, &DL, &DR);
+ key->m_S[i][k ] = DL;
+ key->m_S[i][k + 1] = DR;
+ }
+ }
+
+ if (pArgData && nArgLen)
+ {
+ nArgLen = ((nArgLen < 8) ? nArgLen : 8);
+ if (eMode == rtl_Cipher_ModeStream)
+ {
+ rtl_copyMemory (ctx->m_iv.m_byte, pArgData, nArgLen);
+ }
+ else
+ {
+ RTL_CIPHER_NTOHL64 (pArgData, DL, DR, nArgLen);
+ ctx->m_iv.m_long[0] = DL;
+ ctx->m_iv.m_long[1] = DR;
+ }
+ }
+
+ D = DL = DR = 0;
+ return rtl_Cipher_E_None;
+}
+
+/*
+ * __rtl_cipherBF_update.
+ */
+static rtlCipherError __rtl_cipherBF_update (
+ CipherContextBF *ctx,
+ rtlCipherMode eMode,
+ rtlCipherDirection eDirection,
+ const sal_uInt8 *pData, sal_Size nDatLen,
+ sal_uInt8 *pBuffer, sal_Size nBufLen)
+{
+ /* Check arguments. */
+ if ((pData == NULL) || (pBuffer == NULL))
+ return rtl_Cipher_E_Argument;
+
+ if (!((0 < nDatLen) && (nDatLen <= nBufLen)))
+ return rtl_Cipher_E_BufferSize;
+
+ /* Update. */
+ if (eMode == rtl_Cipher_ModeECB)
+ {
+ /* Block mode. */
+ while (nDatLen > 8)
+ {
+ __rtl_cipherBF_updateECB (ctx, eDirection, pData, pBuffer, 8);
+ nDatLen -= 8;
+ pData += 8;
+ pBuffer += 8;
+ }
+ __rtl_cipherBF_updateECB (ctx, eDirection, pData, pBuffer, nDatLen);
+ }
+ else if (eMode == rtl_Cipher_ModeCBC)
+ {
+ /* Block mode. */
+ while (nDatLen > 8)
+ {
+ __rtl_cipherBF_updateCBC (ctx, eDirection, pData, pBuffer, 8);
+ nDatLen -= 8;
+ pData += 8;
+ pBuffer += 8;
+ }
+ __rtl_cipherBF_updateCBC (ctx, eDirection, pData, pBuffer, nDatLen);
+ }
+ else
+ {
+ /* Stream mode. */
+ while (nDatLen > 0)
+ {
+ __rtl_cipherBF_updateCFB (ctx, eDirection, pData, pBuffer);
+ nDatLen -= 1;
+ pData += 1;
+ pBuffer += 1;
+ }
+ }
+ return rtl_Cipher_E_None;
+}
+
+/*
+ * __rtl_cipherBF_updateECB.
+ */
+static void __rtl_cipherBF_updateECB (
+ CipherContextBF *ctx,
+ rtlCipherDirection direction,
+ const sal_uInt8 *pData,
+ sal_uInt8 *pBuffer,
+ sal_Size nLength)
+{
+ CipherKeyBF *key;
+ sal_uInt32 DL, DR;
+
+ key = &(ctx->m_key);
+ if (direction == rtl_Cipher_DirectionEncode)
+ {
+ RTL_CIPHER_NTOHL64(pData, DL, DR, nLength);
+
+ __rtl_cipherBF_encode (key, &DL, &DR);
+
+ RTL_CIPHER_HTONL(DL, pBuffer);
+ RTL_CIPHER_HTONL(DR, pBuffer);
+ }
+ else
+ {
+ RTL_CIPHER_NTOHL(pData, DL);
+ RTL_CIPHER_NTOHL(pData, DR);
+
+ __rtl_cipherBF_decode (key, &DL, &DR);
+
+ RTL_CIPHER_HTONL64(DL, DR, pBuffer, nLength);
+ }
+ DL = DR = 0;
+}
+
+/*
+ * __rtl_cipherBF_updateCBC.
+ */
+static void __rtl_cipherBF_updateCBC (
+ CipherContextBF *ctx,
+ rtlCipherDirection direction,
+ const sal_uInt8 *pData,
+ sal_uInt8 *pBuffer,
+ sal_Size nLength)
+{
+ CipherKeyBF *key;
+ sal_uInt32 DL, DR;
+
+ key = &(ctx->m_key);
+ if (direction == rtl_Cipher_DirectionEncode)
+ {
+ RTL_CIPHER_NTOHL64(pData, DL, DR, nLength);
+
+ DL ^= ctx->m_iv.m_long[0];
+ DR ^= ctx->m_iv.m_long[1];
+
+ __rtl_cipherBF_encode (key, &DL, &DR);
+
+ ctx->m_iv.m_long[0] = DL;
+ ctx->m_iv.m_long[1] = DR;
+
+ RTL_CIPHER_HTONL(DL, pBuffer);
+ RTL_CIPHER_HTONL(DR, pBuffer);
+ }
+ else
+ {
+ sal_uInt32 IVL, IVR;
+
+ RTL_CIPHER_NTOHL(pData, DL);
+ RTL_CIPHER_NTOHL(pData, DR);
+
+ IVL = DL;
+ IVR = DR;
+
+ __rtl_cipherBF_decode (key, &DL, &DR);
+
+ DL ^= ctx->m_iv.m_long[0];
+ DR ^= ctx->m_iv.m_long[1];
+
+ ctx->m_iv.m_long[0] = IVL;
+ ctx->m_iv.m_long[1] = IVR;
+
+ RTL_CIPHER_HTONL64(DL, DR, pBuffer, nLength);
+ IVL = IVR = 0;
+ }
+ DL = DR = 0;
+}
+
+/*
+ * __rtl_cipherBF_updateCFB.
+ */
+static void __rtl_cipherBF_updateCFB (
+ CipherContextBF *ctx,
+ rtlCipherDirection direction,
+ const sal_uInt8 *pData,
+ sal_uInt8 *pBuffer)
+{
+ sal_uInt8 *iv;
+ sal_uInt32 k;
+
+ iv = ctx->m_iv.m_byte;
+ k = ctx->m_offset;
+
+ if (k == 0)
+ {
+ sal_uInt32 IVL, IVR;
+
+ RTL_CIPHER_NTOHL64(iv, IVL, IVR, 8);
+ __rtl_cipherBF_encode (&(ctx->m_key), &IVL, &IVR);
+ RTL_CIPHER_HTONL64(IVL, IVR, iv, 8);
+
+ IVL = IVR = 0;
+ }
+
+ if (direction == rtl_Cipher_DirectionEncode)
+ {
+ iv[k] ^= *pData;
+ *pBuffer = iv[k];
+ }
+ else
+ {
+ sal_uInt8 c = iv[k];
+ iv[k] = *pData;
+ *pBuffer = *pData ^ c;
+ c = 0;
+ }
+
+ ctx->m_offset = ((k + 1) & 0x07);
+ iv = NULL;
+}
+
+/*
+ * __rtl_cipherBF_encode.
+ */
+static void __rtl_cipherBF_encode (
+ CipherKeyBF *key, sal_uInt32 *xl, sal_uInt32 *xr)
+{
+ sal_uInt32 t, XL, XR;
+ sal_uInt16 i;
+
+ XL = *xl;
+ XR = *xr;
+
+ for (i = 0; i < CIPHER_ROUNDS_BF; ++i)
+ {
+ XL ^= key->m_P[i];
+ XR ^= __rtl_cipherBF (key, XL);
+
+ t = XL;
+ XL = XR;
+ XR = t;
+ }
+
+ t = XL;
+ XL = XR;
+ XR = t;
+
+ XR ^= key->m_P[CIPHER_ROUNDS_BF ];
+ XL ^= key->m_P[CIPHER_ROUNDS_BF + 1];
+
+ *xl = XL;
+ *xr = XR;
+
+ t = XL = XR = 0;
+}
+
+/*
+ * __rtl_cipherBF_decode.
+ */
+static void __rtl_cipherBF_decode (
+ CipherKeyBF *key, sal_uInt32 *xl, sal_uInt32 *xr)
+{
+ sal_uInt32 t, XL, XR;
+ sal_uInt16 i;
+
+ XL = *xl;
+ XR = *xr;
+
+ for (i = CIPHER_ROUNDS_BF + 1; i > 1; --i)
+ {
+ XL ^= key->m_P[i];
+ XR ^= __rtl_cipherBF (key, XL);
+
+ t = XL;
+ XL = XR;
+ XR = t;
+ }
+
+ t = XL;
+ XL = XR;
+ XR = t;
+
+ XR ^= key->m_P[1];
+ XL ^= key->m_P[0];
+
+ *xl = XL;
+ *xr = XR;
+
+ t = XL = XR = 0;
+}
+
+/*
+ * __rtl_cipherBF.
+ */
+static sal_uInt32 __rtl_cipherBF (CipherKeyBF *key, sal_uInt32 x)
+{
+ sal_uInt16 a, b, c, d;
+ sal_uInt32 y;
+
+ d = (sal_uInt16)(x & 0x00ff);
+ x >>= 8;
+ c = (sal_uInt16)(x & 0x00ff);
+ x >>= 8;
+ b = (sal_uInt16)(x & 0x00ff);
+ x >>= 8;
+ a = (sal_uInt16)(x & 0x00ff);
+
+ y = key->m_S[0][a];
+ y += key->m_S[1][b];
+ y ^= key->m_S[2][c];
+ y += key->m_S[3][d];
+
+ return y;
+}
+
+/*========================================================================
+ *
+ * rtl_cipherBF (Blowfish) implementation.
+ *
+ * Reference:
+ * Bruce Schneier: Applied Cryptography, 2nd edition, ch. 14.3
+ *
+ *======================================================================*/
+/*
+ * rtl_cipher_createBF.
+ */
+rtlCipher SAL_CALL rtl_cipher_createBF (rtlCipherMode Mode)
+{
+ CipherBF_Impl *pImpl = (CipherBF_Impl*)NULL;
+
+ if (Mode == rtl_Cipher_ModeInvalid)
+ return ((rtlCipher)NULL);
+
+ pImpl = ((CipherBF_Impl*)rtl_allocateZeroMemory (sizeof (CipherBF_Impl)));
+ if (pImpl)
+ {
+ pImpl->m_cipher.m_algorithm = rtl_Cipher_AlgorithmBF;
+ pImpl->m_cipher.m_direction = rtl_Cipher_DirectionInvalid;
+ pImpl->m_cipher.m_mode = Mode;
+
+ pImpl->m_cipher.m_init = rtl_cipher_initBF;
+ pImpl->m_cipher.m_encode = rtl_cipher_encodeBF;
+ pImpl->m_cipher.m_decode = rtl_cipher_decodeBF;
+ pImpl->m_cipher.m_delete = rtl_cipher_destroyBF;
+ }
+ return ((rtlCipher)pImpl);
+}
+
+/*
+ * rtl_cipher_initBF.
+ */
+rtlCipherError SAL_CALL rtl_cipher_initBF (
+ rtlCipher Cipher,
+ rtlCipherDirection Direction,
+ const sal_uInt8 *pKeyData, sal_Size nKeyLen,
+ const sal_uInt8 *pArgData, sal_Size nArgLen)
+{
+ CipherBF_Impl *pImpl = (CipherBF_Impl*)Cipher;
+
+ if ((pImpl == NULL) || (pKeyData == NULL))
+ return rtl_Cipher_E_Argument;
+
+ if (!(pImpl->m_cipher.m_algorithm == rtl_Cipher_AlgorithmBF))
+ return rtl_Cipher_E_Algorithm;
+
+ if (!(Direction == rtl_Cipher_DirectionInvalid))
+ pImpl->m_cipher.m_direction = Direction;
+ else
+ return rtl_Cipher_E_Direction;
+
+ return __rtl_cipherBF_init (
+ &(pImpl->m_context), pImpl->m_cipher.m_mode,
+ pKeyData, nKeyLen, pArgData, nArgLen);
+}
+
+/*
+ * rtl_cipher_encodeBF.
+ */
+rtlCipherError SAL_CALL rtl_cipher_encodeBF (
+ rtlCipher Cipher,
+ const void *pData, sal_Size nDatLen,
+ sal_uInt8 *pBuffer, sal_Size nBufLen)
+{
+ CipherBF_Impl *pImpl = (CipherBF_Impl*)Cipher;
+ if (pImpl == NULL)
+ return rtl_Cipher_E_Argument;
+
+ if (!(pImpl->m_cipher.m_algorithm == rtl_Cipher_AlgorithmBF))
+ return rtl_Cipher_E_Algorithm;
+
+ if (pImpl->m_cipher.m_direction == rtl_Cipher_DirectionInvalid)
+ return rtl_Cipher_E_Direction;
+ if (pImpl->m_cipher.m_direction == rtl_Cipher_DirectionDecode)
+ return rtl_Cipher_E_Direction;
+
+ return __rtl_cipherBF_update (
+ &(pImpl->m_context), pImpl->m_cipher.m_mode,
+ rtl_Cipher_DirectionEncode,
+ (const sal_uInt8*)pData, nDatLen, pBuffer, nBufLen);
+}
+
+/*
+ * rtl_cipher_decodeBF.
+ */
+rtlCipherError SAL_CALL rtl_cipher_decodeBF (
+ rtlCipher Cipher,
+ const void *pData, sal_Size nDatLen,
+ sal_uInt8 *pBuffer, sal_Size nBufLen)
+{
+ CipherBF_Impl *pImpl = (CipherBF_Impl*)Cipher;
+ if (pImpl == NULL)
+ return rtl_Cipher_E_Argument;
+
+ if (!(pImpl->m_cipher.m_algorithm == rtl_Cipher_AlgorithmBF))
+ return rtl_Cipher_E_Algorithm;
+
+ if (pImpl->m_cipher.m_direction == rtl_Cipher_DirectionInvalid)
+ return rtl_Cipher_E_Direction;
+ if (pImpl->m_cipher.m_direction == rtl_Cipher_DirectionEncode)
+ return rtl_Cipher_E_Direction;
+
+ return __rtl_cipherBF_update (
+ &(pImpl->m_context), pImpl->m_cipher.m_mode,
+ rtl_Cipher_DirectionDecode,
+ (const sal_uInt8*)pData, nDatLen, pBuffer, nBufLen);
+}
+
+/*
+ * rtl_cipher_destroyBF.
+ */
+void SAL_CALL rtl_cipher_destroyBF (rtlCipher Cipher)
+{
+ CipherBF_Impl *pImpl = (CipherBF_Impl*)Cipher;
+ if (pImpl)
+ {
+ if (pImpl->m_cipher.m_algorithm == rtl_Cipher_AlgorithmBF)
+ rtl_freeZeroMemory (pImpl, sizeof (CipherBF_Impl));
+ else
+ rtl_freeMemory (pImpl);
+ }
+}
+
+/*========================================================================
+ *
+ * rtl_cipher_ARCFOUR (RC4) internals.
+ *
+ *======================================================================*/
+#define CIPHER_CBLOCK_ARCFOUR 256
+
+typedef struct cipherARCFOUR_context_st
+{
+ unsigned int m_S[CIPHER_CBLOCK_ARCFOUR];
+ unsigned int m_X, m_Y;
+} ContextARCFOUR_Impl;
+
+typedef struct cipherARCFOUR_impl_st
+{
+ Cipher_Impl m_cipher;
+ ContextARCFOUR_Impl m_context;
+} CipherARCFOUR_Impl;
+
+/** rtl_cipherARCFOUR_update_Impl.
+ */
+static rtlCipherError rtl_cipherARCFOUR_update_Impl (
+ ContextARCFOUR_Impl *ctx,
+ const sal_uInt8 *pData, sal_Size nDatLen,
+ sal_uInt8 *pBuffer, sal_Size nBufLen);
+
+/*
+ * rtl_cipherARCFOUR_init_Impl.
+ */
+static rtlCipherError rtl_cipherARCFOUR_init_Impl (
+ ContextARCFOUR_Impl *ctx,
+ const sal_uInt8 *pKeyData, sal_Size nKeyLen)
+{
+ unsigned int K[CIPHER_CBLOCK_ARCFOUR];
+ unsigned int *L, *S;
+ unsigned int x, y, t;
+ sal_Size n, k;
+
+ S = &(ctx->m_S[0]);
+
+ /* Initialize S linearly. */
+ for (x = 0; x < CIPHER_CBLOCK_ARCFOUR; x++)
+ S[x] = x;
+
+ /* Initialize K with key, repeat key as necessary. */
+ for (L = K, n = CIPHER_CBLOCK_ARCFOUR; n > nKeyLen; n -= nKeyLen)
+ {
+ for (k = 0; k < nKeyLen; k++) L[k] = pKeyData[k];
+ L += nKeyLen;
+ }
+ for (k = 0; k < n; k++) L[k] = pKeyData[k];
+
+ /* Initialize S with K. */
+ for (x = 0, y = 0; x < CIPHER_CBLOCK_ARCFOUR; x++)
+ {
+ y = (y + S[x] + K[x]) % CIPHER_CBLOCK_ARCFOUR;
+ t = S[x], S[x] = S[y], S[y] = t; /* swap S[x] and S[y] */
+ }
+
+ /* Initialize counters X and Y. */
+ ctx->m_X = 0;
+ ctx->m_Y = 0;
+
+ return rtl_Cipher_E_None;
+}
+
+/*
+ * rtl_cipherARCFOUR_update_Impl.
+ */
+static rtlCipherError rtl_cipherARCFOUR_update_Impl (
+ ContextARCFOUR_Impl *ctx,
+ const sal_uInt8 *pData, sal_Size nDatLen,
+ sal_uInt8 *pBuffer, sal_Size nBufLen)
+{
+ register unsigned int *S;
+ register unsigned int x, y, t;
+ sal_Size k;
+
+ /* Check arguments. */
+ if ((pData == NULL) || (pBuffer == NULL))
+ return rtl_Cipher_E_Argument;
+
+ if (!((0 < nDatLen) && (nDatLen <= nBufLen)))
+ return rtl_Cipher_E_BufferSize;
+
+ /* Update. */
+ S = &(ctx->m_S[0]);
+ for (k = 0; k < nDatLen; k++)
+ {
+ /* Update counters X and Y. */
+ x = ctx->m_X;
+ y = ctx->m_Y;
+ x = (x + 1 ) % CIPHER_CBLOCK_ARCFOUR;
+ y = (y + S[x]) % CIPHER_CBLOCK_ARCFOUR;
+ ctx->m_X = x;
+ ctx->m_Y = y;
+
+ /* Swap S[x] and S[y]. */
+ t = S[x], S[x] = S[y], S[y] = t;
+
+ /* Evaluate next key byte S[t]. */
+ t = (S[x] + S[y]) % CIPHER_CBLOCK_ARCFOUR;
+ pBuffer[k] = pData[k] ^ ((sal_uInt8)(S[t] & 0xff));
+ }
+
+ return rtl_Cipher_E_None;
+}
+
+/*========================================================================
+ *
+ * rtl_cipher_ARCFOUR (RC4) implementation.
+ *
+ * Reference:
+ * Bruce Schneier: Applied Cryptography, 2nd edition, ch. 17.1
+ *
+ *======================================================================*/
+/*
+ * rtl_cipher_createARCFOUR.
+ */
+rtlCipher SAL_CALL rtl_cipher_createARCFOUR (rtlCipherMode Mode)
+{
+ CipherARCFOUR_Impl *pImpl = (CipherARCFOUR_Impl*)NULL;
+
+ if (!(Mode == rtl_Cipher_ModeStream))
+ return ((rtlCipher)NULL);
+
+ pImpl = ((CipherARCFOUR_Impl*)rtl_allocateZeroMemory (sizeof (CipherARCFOUR_Impl)));
+ if (pImpl)
+ {
+ pImpl->m_cipher.m_algorithm = rtl_Cipher_AlgorithmARCFOUR;
+ pImpl->m_cipher.m_direction = rtl_Cipher_DirectionInvalid;
+ pImpl->m_cipher.m_mode = rtl_Cipher_ModeStream;
+
+ pImpl->m_cipher.m_init = rtl_cipher_initARCFOUR;
+ pImpl->m_cipher.m_encode = rtl_cipher_encodeARCFOUR;
+ pImpl->m_cipher.m_decode = rtl_cipher_decodeARCFOUR;
+ pImpl->m_cipher.m_delete = rtl_cipher_destroyARCFOUR;
+ }
+ return ((rtlCipher)pImpl);
+}
+
+/*
+ * rtl_cipher_initARCFOUR.
+ */
+rtlCipherError SAL_CALL rtl_cipher_initARCFOUR (
+ rtlCipher Cipher,
+ rtlCipherDirection Direction,
+ const sal_uInt8 *pKeyData, sal_Size nKeyLen,
+ const sal_uInt8 *pArgData, sal_Size nArgLen)
+{
+ CipherARCFOUR_Impl *pImpl = (CipherARCFOUR_Impl*)Cipher;
+ (void) pArgData; // avoid warning
+ (void) nArgLen; // avoid warning
+
+ if ((pImpl == NULL) || (pKeyData == NULL))
+ return rtl_Cipher_E_Argument;
+
+ if (!(pImpl->m_cipher.m_algorithm == rtl_Cipher_AlgorithmARCFOUR))
+ return rtl_Cipher_E_Algorithm;
+
+ if (!(Direction == rtl_Cipher_DirectionInvalid))
+ pImpl->m_cipher.m_direction = Direction;
+ else
+ return rtl_Cipher_E_Direction;
+
+ return rtl_cipherARCFOUR_init_Impl (&(pImpl->m_context), pKeyData, nKeyLen);
+}
+
+/*
+ * rtl_cipher_encodeARCFOUR.
+ */
+rtlCipherError SAL_CALL rtl_cipher_encodeARCFOUR (
+ rtlCipher Cipher,
+ const void *pData, sal_Size nDatLen,
+ sal_uInt8 *pBuffer, sal_Size nBufLen)
+{
+ CipherARCFOUR_Impl *pImpl = (CipherARCFOUR_Impl*)Cipher;
+ if (pImpl == NULL)
+ return rtl_Cipher_E_Argument;
+
+ if (!(pImpl->m_cipher.m_algorithm == rtl_Cipher_AlgorithmARCFOUR))
+ return rtl_Cipher_E_Algorithm;
+
+ if (pImpl->m_cipher.m_direction == rtl_Cipher_DirectionInvalid)
+ return rtl_Cipher_E_Direction;
+
+ return rtl_cipherARCFOUR_update_Impl (
+ &(pImpl->m_context),
+ (const sal_uInt8*)pData, nDatLen, pBuffer, nBufLen);
+}
+
+/*
+ * rtl_cipher_decodeARCFOUR.
+ */
+rtlCipherError SAL_CALL rtl_cipher_decodeARCFOUR (
+ rtlCipher Cipher,
+ const void *pData, sal_Size nDatLen,
+ sal_uInt8 *pBuffer, sal_Size nBufLen)
+{
+ CipherARCFOUR_Impl *pImpl = (CipherARCFOUR_Impl*)Cipher;
+ if (pImpl == NULL)
+ return rtl_Cipher_E_Argument;
+
+ if (!(pImpl->m_cipher.m_algorithm == rtl_Cipher_AlgorithmARCFOUR))
+ return rtl_Cipher_E_Algorithm;
+
+ if (pImpl->m_cipher.m_direction == rtl_Cipher_DirectionInvalid)
+ return rtl_Cipher_E_Direction;
+
+ return rtl_cipherARCFOUR_update_Impl (
+ &(pImpl->m_context),
+ (const sal_uInt8*)pData, nDatLen, pBuffer, nBufLen);
+}
+
+/*
+ * rtl_cipher_destroyARCFOUR.
+ */
+void SAL_CALL rtl_cipher_destroyARCFOUR (rtlCipher Cipher)
+{
+ CipherARCFOUR_Impl *pImpl = (CipherARCFOUR_Impl*)Cipher;
+ if (pImpl)
+ {
+ if (pImpl->m_cipher.m_algorithm == rtl_Cipher_AlgorithmARCFOUR)
+ rtl_freeZeroMemory (pImpl, sizeof (CipherARCFOUR_Impl));
+ else
+ rtl_freeMemory (pImpl);
+ }
+}
diff --git a/sal/rtl/source/cmdargs.cxx b/sal/rtl/source/cmdargs.cxx
new file mode 100644
index 000000000000..dc14cf59d031
--- /dev/null
+++ b/sal/rtl/source/cmdargs.cxx
@@ -0,0 +1,109 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+
+#include <osl/mutex.hxx>
+#include <rtl/process.h>
+#include <rtl/ustring.hxx>
+
+namespace {
+
+rtl_uString ** g_ppCommandArgs = 0;
+sal_uInt32 g_nCommandArgCount = 0;
+
+struct ArgHolder
+{
+ ~ArgHolder();
+};
+
+ArgHolder::~ArgHolder()
+{
+ while (g_nCommandArgCount > 0)
+ rtl_uString_release (g_ppCommandArgs[--g_nCommandArgCount]);
+
+ rtl_freeMemory (g_ppCommandArgs);
+ g_ppCommandArgs = 0;
+}
+
+// The destructor of this static ArgHolder is "activated" by the assignments to
+// g_ppCommandArgs and g_nCommandArgCount in init():
+ArgHolder argHolder;
+
+void init()
+{
+ osl::MutexGuard guard( osl::Mutex::getGlobalMutex() );
+ if (!g_ppCommandArgs)
+ {
+ sal_Int32 i, n = osl_getCommandArgCount();
+
+ g_ppCommandArgs =
+ (rtl_uString**)rtl_allocateZeroMemory (n * sizeof(rtl_uString*));
+ for (i = 0; i < n; i++)
+ {
+ rtl_uString * pArg = 0;
+ osl_getCommandArg (i, &pArg);
+ if (('-' == pArg->buffer[0] || '/' == pArg->buffer[0]) &&
+ 'e' == pArg->buffer[1] &&
+ 'n' == pArg->buffer[2] &&
+ 'v' == pArg->buffer[3] &&
+ ':' == pArg->buffer[4] &&
+ rtl_ustr_indexOfChar (&(pArg->buffer[5]), '=') >= 0 )
+ {
+ // ignore.
+ rtl_uString_release (pArg);
+ }
+ else
+ {
+ // assign.
+ g_ppCommandArgs[g_nCommandArgCount++] = pArg;
+ }
+ }
+ }
+}
+
+}
+
+oslProcessError SAL_CALL rtl_getAppCommandArg (
+ sal_uInt32 nArg, rtl_uString **ppCommandArg)
+{
+ init();
+ oslProcessError result = osl_Process_E_NotFound;
+ if( nArg < g_nCommandArgCount )
+ {
+ rtl_uString_assign( ppCommandArg, g_ppCommandArgs[nArg] );
+ result = osl_Process_E_None;
+ }
+ return (result);
+}
+
+sal_uInt32 SAL_CALL rtl_getAppCommandArgCount (void)
+{
+ init();
+ return g_nCommandArgCount;
+}
diff --git a/sal/rtl/source/crc.c b/sal/rtl/source/crc.c
new file mode 100644
index 000000000000..d8fd53c3b330
--- /dev/null
+++ b/sal/rtl/source/crc.c
@@ -0,0 +1,164 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#define _RTL_CRC_C_ "$Revision: 1.3 $"
+
+#include <sal/types.h>
+#include <rtl/crc.h>
+
+/*========================================================================
+ *
+ * rtl_crc32Table (CRC polynomial 0xEDB88320).
+ *
+ *======================================================================*/
+static const sal_uInt32 rtl_crc32Table[256] =
+{
+ /* 0 */
+ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
+ 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
+ 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
+ 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
+
+ /* 1 */
+ 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
+ 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
+ 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
+
+ /* 2 */
+ 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
+ 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
+ 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
+ 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+
+ /* 3 */
+ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
+ 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
+ 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
+ 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
+
+ /* 4 */
+ 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
+ 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
+ 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
+
+ /* 5 */
+ 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
+ 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
+ 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
+ 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+
+ /* 6 */
+ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
+ 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
+ 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
+ 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
+
+ /* 7 */
+ 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
+ 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
+ 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
+
+ /* 8 */
+ 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
+ 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
+ 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
+ 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+
+ /* 9 */
+ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
+ 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
+ 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
+ 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
+
+ /* A */
+ 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
+ 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
+ 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
+
+ /* B */
+ 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
+ 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
+ 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
+ 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+
+ /* C */
+ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
+ 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
+ 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
+ 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
+
+ /* D */
+ 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
+ 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
+ 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
+
+ /* E */
+ 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
+ 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
+ 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
+ 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+
+ /* F */
+ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
+ 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
+ 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
+ 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
+};
+
+/*========================================================================
+ *
+ * rtl_crc32 implementation.
+ *
+ *======================================================================*/
+#define UPDCRC32(crc, octet) \
+ (rtl_crc32Table[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8))
+
+/*
+ * rtl_crc32.
+ */
+sal_uInt32 SAL_CALL rtl_crc32 (
+ sal_uInt32 Crc,
+ const void *Data, sal_uInt32 DatLen)
+{
+ if (Data)
+ {
+ register const sal_uInt8 *p = (const sal_uInt8 *)Data;
+ register const sal_uInt8 *q = p + DatLen;
+
+ Crc = ~Crc;
+ while (p < q)
+ Crc = UPDCRC32(Crc, *(p++));
+ Crc = ~Crc;
+ }
+ return Crc;
+}
+
diff --git a/sal/rtl/source/debugprint.cxx b/sal/rtl/source/debugprint.cxx
new file mode 100644
index 000000000000..9b86ca077446
--- /dev/null
+++ b/sal/rtl/source/debugprint.cxx
@@ -0,0 +1,58 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+
+#include <rtl/strbuf.hxx>
+#include <rtl/ustring.hxx>
+
+const sal_Char *dbg_dump(const rtl::OString &rStr)
+{
+ static rtl::OStringBuffer aStr;
+
+ aStr = rtl::OStringBuffer(rStr);
+ aStr.append(static_cast<char>(0));
+ return aStr.getStr();
+}
+
+const sal_Char *dbg_dump(const rtl::OUString &rStr)
+{
+ return dbg_dump(rtl::OUStringToOString(rStr, RTL_TEXTENCODING_UTF8));
+}
+
+const sal_Char *dbg_dump(rtl_String *pStr)
+{
+ return dbg_dump(rtl::OString(pStr));
+}
+
+const sal_Char *dbg_dump(rtl_uString *pStr)
+{
+ return dbg_dump(rtl::OUString(pStr));
+}
+
+/* vi:set tabstop=4 shiftwidth=4 expandtab: */
diff --git a/sal/rtl/source/digest.c b/sal/rtl/source/digest.c
new file mode 100644
index 000000000000..1d07fdbdc167
--- /dev/null
+++ b/sal/rtl/source/digest.c
@@ -0,0 +1,2118 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#define _RTL_DIGEST_C_ "$Revision: 1.9 $"
+
+#include <sal/types.h>
+#include <sal/macros.h>
+#include <osl/endian.h>
+#include <rtl/alloc.h>
+#include <rtl/memory.h>
+#include <rtl/digest.h>
+
+/*========================================================================
+ *
+ * rtlDigest internals.
+ *
+ *======================================================================*/
+#define RTL_DIGEST_CREATE(T) ((T*)(rtl_allocateZeroMemory(sizeof(T))))
+
+#define RTL_DIGEST_ROTL(a,n) (((a) << (n)) | ((a) >> (32 - (n))))
+
+#define RTL_DIGEST_HTONL(l,c) \
+ (*((c)++) = (sal_uInt8)(((l) >> 24L) & 0xff), \
+ *((c)++) = (sal_uInt8)(((l) >> 16L) & 0xff), \
+ *((c)++) = (sal_uInt8)(((l) >> 8L) & 0xff), \
+ *((c)++) = (sal_uInt8)(((l) ) & 0xff))
+
+#define RTL_DIGEST_LTOC(l,c) \
+ (*((c)++) = (sal_uInt8)(((l) ) & 0xff), \
+ *((c)++) = (sal_uInt8)(((l) >> 8L) & 0xff), \
+ *((c)++) = (sal_uInt8)(((l) >> 16L) & 0xff), \
+ *((c)++) = (sal_uInt8)(((l) >> 24L) & 0xff))
+
+typedef rtlDigestError (SAL_CALL Digest_init_t) (
+ void *ctx, const sal_uInt8 *Data, sal_uInt32 DatLen);
+
+typedef void (SAL_CALL Digest_delete_t) (void *ctx);
+
+typedef rtlDigestError (SAL_CALL Digest_update_t) (
+ void *ctx, const void *Data, sal_uInt32 DatLen);
+
+typedef rtlDigestError (SAL_CALL Digest_get_t) (
+ void *ctx, sal_uInt8 *Buffer, sal_uInt32 BufLen);
+
+typedef struct digest_impl_st
+{
+ rtlDigestAlgorithm m_algorithm;
+ sal_uInt32 m_length;
+
+ Digest_init_t *m_init;
+ Digest_delete_t *m_delete;
+ Digest_update_t *m_update;
+ Digest_get_t *m_get;
+} Digest_Impl;
+
+/*
+ * __rtl_digest_swapLong.
+ */
+static void __rtl_digest_swapLong (sal_uInt32 *pData, sal_uInt32 nDatLen)
+{
+ register sal_uInt32 *X;
+ register int i, n;
+
+ X = pData;
+ n = nDatLen;
+
+ for (i = 0; i < n; i++)
+ X[i] = OSL_SWAPDWORD(X[i]);
+}
+
+/*========================================================================
+ *
+ * rtlDigest implementation.
+ *
+ *======================================================================*/
+/*
+ * rtl_digest_create.
+ */
+rtlDigest SAL_CALL rtl_digest_create (rtlDigestAlgorithm Algorithm)
+{
+ rtlDigest Digest = (rtlDigest)NULL;
+ switch (Algorithm)
+ {
+ case rtl_Digest_AlgorithmMD2:
+ Digest = rtl_digest_createMD2();
+ break;
+
+ case rtl_Digest_AlgorithmMD5:
+ Digest = rtl_digest_createMD5();
+ break;
+
+ case rtl_Digest_AlgorithmSHA:
+ Digest = rtl_digest_createSHA();
+ break;
+
+ case rtl_Digest_AlgorithmSHA1:
+ Digest = rtl_digest_createSHA1();
+ break;
+
+ case rtl_Digest_AlgorithmHMAC_MD5:
+ Digest = rtl_digest_createHMAC_MD5();
+ break;
+
+ case rtl_Digest_AlgorithmHMAC_SHA1:
+ Digest = rtl_digest_createHMAC_SHA1();
+ break;
+
+ default: /* rtl_Digest_AlgorithmInvalid */
+ break;
+ }
+ return Digest;
+}
+
+/*
+ * rtl_digest_queryAlgorithm.
+ */
+rtlDigestAlgorithm SAL_CALL rtl_digest_queryAlgorithm (rtlDigest Digest)
+{
+ Digest_Impl *pImpl = (Digest_Impl *)Digest;
+ if (pImpl)
+ return pImpl->m_algorithm;
+ else
+ return rtl_Digest_AlgorithmInvalid;
+}
+
+/*
+ * rtl_digest_queryLength.
+ */
+sal_uInt32 SAL_CALL rtl_digest_queryLength (rtlDigest Digest)
+{
+ Digest_Impl *pImpl = (Digest_Impl *)Digest;
+ if (pImpl)
+ return pImpl->m_length;
+ else
+ return 0;
+}
+
+/*
+ * rtl_digest_init.
+ */
+rtlDigestError SAL_CALL rtl_digest_init (
+ rtlDigest Digest, const sal_uInt8 *pData, sal_uInt32 nDatLen)
+{
+ Digest_Impl *pImpl = (Digest_Impl *)Digest;
+ if (pImpl)
+ {
+ if (pImpl->m_init)
+ return pImpl->m_init (Digest, pData, nDatLen);
+ else
+ return rtl_Digest_E_None;
+ }
+ return rtl_Digest_E_Argument;
+}
+
+/*
+ * rtl_digest_update.
+ */
+rtlDigestError SAL_CALL rtl_digest_update (
+ rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
+{
+ Digest_Impl *pImpl = (Digest_Impl *)Digest;
+ if (pImpl && pImpl->m_update)
+ return pImpl->m_update (Digest, pData, nDatLen);
+ else
+ return rtl_Digest_E_Argument;
+}
+
+/*
+ * rtl_digest_get.
+ */
+rtlDigestError SAL_CALL rtl_digest_get (
+ rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
+{
+ Digest_Impl *pImpl = (Digest_Impl *)Digest;
+ if (pImpl && pImpl->m_get)
+ return pImpl->m_get (Digest, pBuffer, nBufLen);
+ else
+ return rtl_Digest_E_Argument;
+}
+
+/*
+ * rtl_digest_destroy.
+ */
+void SAL_CALL rtl_digest_destroy (rtlDigest Digest)
+{
+ Digest_Impl *pImpl = (Digest_Impl *)Digest;
+ if (pImpl && pImpl->m_delete)
+ pImpl->m_delete (Digest);
+}
+
+/*========================================================================
+ *
+ * rtl_digest_MD2 internals.
+ *
+ *======================================================================*/
+#define DIGEST_CBLOCK_MD2 16
+#define DIGEST_LBLOCK_MD2 16
+
+typedef struct digestMD2_context_st
+{
+ sal_uInt32 m_nDatLen;
+ sal_uInt8 m_pData[DIGEST_CBLOCK_MD2];
+ sal_uInt32 m_state[DIGEST_LBLOCK_MD2];
+ sal_uInt32 m_chksum[DIGEST_LBLOCK_MD2];
+} DigestContextMD2;
+
+typedef struct digestMD2_impl_st
+{
+ Digest_Impl m_digest;
+ DigestContextMD2 m_context;
+} DigestMD2_Impl;
+
+static void __rtl_digest_initMD2 (DigestContextMD2 *ctx);
+static void __rtl_digest_updateMD2 (DigestContextMD2 *ctx);
+static void __rtl_digest_endMD2 (DigestContextMD2 *ctx);
+
+static const sal_uInt32 S[256] =
+{
+ 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01,
+ 0x3D, 0x36, 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13,
+ 0x62, 0xA7, 0x05, 0xF3, 0xC0, 0xC7, 0x73, 0x8C,
+ 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, 0x82, 0xCA,
+ 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16,
+ 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12,
+ 0xBE, 0x4E, 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49,
+ 0xA0, 0xFB, 0xF5, 0x8E, 0xBB, 0x2F, 0xEE, 0x7A,
+ 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, 0x07, 0x3F,
+ 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
+ 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27,
+ 0x35, 0x3E, 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03,
+ 0xFF, 0x19, 0x30, 0xB3, 0x48, 0xA5, 0xB5, 0xD1,
+ 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, 0xAA, 0xC6,
+ 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6,
+ 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1,
+ 0x45, 0x9D, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20,
+ 0x86, 0x5B, 0xCF, 0x65, 0xE6, 0x2D, 0xA8, 0x02,
+ 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, 0xB9, 0xF6,
+ 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
+ 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A,
+ 0xC3, 0x5C, 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26,
+ 0x2C, 0x53, 0x0D, 0x6E, 0x85, 0x28, 0x84, 0x09,
+ 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, 0x4D, 0x52,
+ 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA,
+ 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A,
+ 0x78, 0x88, 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D,
+ 0xE9, 0xCB, 0xD5, 0xFE, 0x3B, 0x00, 0x1D, 0x39,
+ 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, 0xD0, 0xE4,
+ 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
+ 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A,
+ 0xDB, 0x99, 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14,
+};
+
+/*
+ * __rtl_digest_MD2.
+ */
+static const Digest_Impl __rtl_digest_MD2 =
+{
+ rtl_Digest_AlgorithmMD2,
+ RTL_DIGEST_LENGTH_MD2,
+
+ NULL,
+ rtl_digest_destroyMD2,
+ rtl_digest_updateMD2,
+ rtl_digest_getMD2
+};
+
+/*
+ * __rtl_digest_initMD2.
+ */
+static void __rtl_digest_initMD2 (DigestContextMD2 *ctx)
+{
+ rtl_zeroMemory (ctx, sizeof (DigestContextMD2));
+}
+
+/*
+ * __rtl_digest_updateMD2.
+ */
+static void __rtl_digest_updateMD2 (DigestContextMD2 *ctx)
+{
+ register sal_uInt8 *X;
+ register sal_uInt32 *sp1, *sp2;
+ register sal_uInt32 i, k, t;
+
+ sal_uInt32 state[48];
+
+ X = ctx->m_pData;
+ sp1 = ctx->m_state;
+ sp2 = ctx->m_chksum;
+
+ k = sp2[DIGEST_LBLOCK_MD2 - 1];
+ for (i = 0; i < 16; i++)
+ {
+ state[i + 0] = sp1[i];
+ state[i + 16] = t = X[i];
+ state[i + 32] = t ^ sp1[i];
+ k = sp2[i] ^= S[t^k];
+ }
+
+ t = 0;
+ for (i = 0; i < 18; i++)
+ {
+ for (k = 0; k < 48; k += 8)
+ {
+ t = state[k + 0] ^= S[t];
+ t = state[k + 1] ^= S[t];
+ t = state[k + 2] ^= S[t];
+ t = state[k + 3] ^= S[t];
+ t = state[k + 4] ^= S[t];
+ t = state[k + 5] ^= S[t];
+ t = state[k + 6] ^= S[t];
+ t = state[k + 7] ^= S[t];
+ }
+ t = ((t + i) & 0xff);
+ }
+
+ rtl_copyMemory (sp1, state, 16 * sizeof(sal_uInt32));
+ rtl_zeroMemory (state, 48 * sizeof(sal_uInt32));
+}
+
+/*
+ * __rtl_digest_endMD2.
+ */
+static void __rtl_digest_endMD2 (DigestContextMD2 *ctx)
+{
+ register sal_uInt8 *X;
+ register sal_uInt32 *C;
+ sal_uInt32 i, n;
+
+ X = ctx->m_pData;
+ C = ctx->m_chksum;
+ n = DIGEST_CBLOCK_MD2 - ctx->m_nDatLen;
+
+ for (i = ctx->m_nDatLen; i < DIGEST_CBLOCK_MD2; i++)
+ X[i] = (sal_uInt8)(n & 0xff);
+ __rtl_digest_updateMD2 (ctx);
+
+ for (i = 0; i < DIGEST_CBLOCK_MD2; i++)
+ X[i] = (sal_uInt8)(C[i] & 0xff);
+ __rtl_digest_updateMD2 (ctx);
+}
+
+/*========================================================================
+ *
+ * rtl_digest_MD2 implementation.
+ *
+ *======================================================================*/
+/*
+ * rtl_digest_MD2.
+ */
+rtlDigestError SAL_CALL rtl_digest_MD2 (
+ const void *pData, sal_uInt32 nDatLen,
+ sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
+{
+ DigestMD2_Impl digest;
+ rtlDigestError result;
+
+ digest.m_digest = __rtl_digest_MD2;
+ __rtl_digest_initMD2 (&(digest.m_context));
+
+ result = rtl_digest_updateMD2 (&digest, pData, nDatLen);
+ if (result == rtl_Digest_E_None)
+ result = rtl_digest_getMD2 (&digest, pBuffer, nBufLen);
+
+ rtl_zeroMemory (&digest, sizeof (digest));
+ return (result);
+}
+
+/*
+ * rtl_digest_createMD2.
+ */
+rtlDigest SAL_CALL rtl_digest_createMD2 (void)
+{
+ DigestMD2_Impl *pImpl = (DigestMD2_Impl*)NULL;
+ pImpl = RTL_DIGEST_CREATE(DigestMD2_Impl);
+ if (pImpl)
+ {
+ pImpl->m_digest = __rtl_digest_MD2;
+ __rtl_digest_initMD2 (&(pImpl->m_context));
+ }
+ return ((rtlDigest)pImpl);
+}
+
+/*
+ * rtl_digest_updateMD2.
+ */
+rtlDigestError SAL_CALL rtl_digest_updateMD2 (
+ rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
+{
+ DigestMD2_Impl *pImpl = (DigestMD2_Impl *)Digest;
+ const sal_uInt8 *d = (const sal_uInt8 *)pData;
+
+ DigestContextMD2 *ctx;
+
+ if ((pImpl == NULL) || (pData == NULL))
+ return rtl_Digest_E_Argument;
+
+ if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmMD2))
+ return rtl_Digest_E_Algorithm;
+
+ if (nDatLen == 0)
+ return rtl_Digest_E_None;
+
+ ctx = &(pImpl->m_context);
+
+ if (ctx->m_nDatLen)
+ {
+ sal_uInt8 *p = ctx->m_pData + ctx->m_nDatLen;
+ sal_uInt32 n = DIGEST_CBLOCK_MD2 - ctx->m_nDatLen;
+
+ if (nDatLen < n)
+ {
+ rtl_copyMemory (p, d, nDatLen);
+ ctx->m_nDatLen += nDatLen;
+
+ return rtl_Digest_E_None;
+ }
+
+ rtl_copyMemory (p, d, n);
+ d += n;
+ nDatLen -= n;
+
+ __rtl_digest_updateMD2 (ctx);
+ ctx->m_nDatLen = 0;
+ }
+
+ while (nDatLen >= DIGEST_CBLOCK_MD2)
+ {
+ rtl_copyMemory (ctx->m_pData, d, DIGEST_CBLOCK_MD2);
+ d += DIGEST_CBLOCK_MD2;
+ nDatLen -= DIGEST_CBLOCK_MD2;
+
+ __rtl_digest_updateMD2 (ctx);
+ }
+
+ rtl_copyMemory (ctx->m_pData, d, nDatLen);
+ ctx->m_nDatLen = nDatLen;
+
+ return rtl_Digest_E_None;
+}
+
+/*
+ * rtl_digest_getMD2.
+ */
+rtlDigestError SAL_CALL rtl_digest_getMD2 (
+ rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
+{
+ DigestMD2_Impl *pImpl = (DigestMD2_Impl *)Digest;
+ sal_uInt32 i;
+
+ DigestContextMD2 *ctx;
+
+ if ((pImpl == NULL) || (pBuffer == NULL))
+ return rtl_Digest_E_Argument;
+
+ if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmMD2))
+ return rtl_Digest_E_Algorithm;
+
+ if (!(pImpl->m_digest.m_length <= nBufLen))
+ return rtl_Digest_E_BufferSize;
+
+ ctx = &(pImpl->m_context);
+
+ __rtl_digest_endMD2 (ctx);
+ for (i = 0; i < DIGEST_CBLOCK_MD2; i++)
+ pBuffer[i] = (sal_uInt8)(ctx->m_state[i] & 0xff);
+ __rtl_digest_initMD2 (ctx);
+
+ return rtl_Digest_E_None;
+}
+
+/*
+ * rtl_digest_destroyMD2.
+ */
+void SAL_CALL rtl_digest_destroyMD2 (rtlDigest Digest)
+{
+ DigestMD2_Impl *pImpl = (DigestMD2_Impl *)Digest;
+ if (pImpl)
+ {
+ if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmMD2)
+ rtl_freeZeroMemory (pImpl, sizeof (DigestMD2_Impl));
+ else
+ rtl_freeMemory (pImpl);
+ }
+}
+
+/*========================================================================
+ *
+ * rtl_digest_MD5 internals.
+ *
+ *======================================================================*/
+#define DIGEST_CBLOCK_MD5 64
+#define DIGEST_LBLOCK_MD5 16
+
+typedef struct digestMD5_context_st
+{
+ sal_uInt32 m_nDatLen;
+ sal_uInt32 m_pData[DIGEST_LBLOCK_MD5];
+ sal_uInt32 m_nA, m_nB, m_nC, m_nD;
+ sal_uInt32 m_nL, m_nH;
+} DigestContextMD5;
+
+typedef struct digestMD5_impl_st
+{
+ Digest_Impl m_digest;
+ DigestContextMD5 m_context;
+} DigestMD5_Impl;
+
+static void __rtl_digest_initMD5 (DigestContextMD5 *ctx);
+static void __rtl_digest_updateMD5 (DigestContextMD5 *ctx);
+static void __rtl_digest_endMD5 (DigestContextMD5 *ctx);
+
+#define F(x,y,z) ((((y) ^ (z)) & (x)) ^ (z))
+#define G(x,y,z) ((((x) ^ (y)) & (z)) ^ (y))
+#define H(x,y,z) ((x) ^ (y) ^ (z))
+#define I(x,y,z) (((x) | (~(z))) ^ (y))
+
+#define R0(a,b,c,d,k,s,t) { \
+ a += ((k) + (t) + F((b), (c), (d))); \
+ a = RTL_DIGEST_ROTL(a, s); \
+ a += b; }
+
+#define R1(a,b,c,d,k,s,t) { \
+ a += ((k) + (t) + G((b), (c), (d))); \
+ a = RTL_DIGEST_ROTL(a, s); \
+ a += b; }
+
+#define R2(a,b,c,d,k,s,t) { \
+ a += ((k) + (t) + H((b), (c), (d))); \
+ a = RTL_DIGEST_ROTL(a, s); \
+ a += b; }
+
+#define R3(a,b,c,d,k,s,t) { \
+ a += ((k) + (t) + I((b), (c), (d))); \
+ a = RTL_DIGEST_ROTL(a, s); \
+ a += b; }
+
+/*
+ * __rtl_digest_MD5.
+ */
+static const Digest_Impl __rtl_digest_MD5 =
+{
+ rtl_Digest_AlgorithmMD5,
+ RTL_DIGEST_LENGTH_MD5,
+
+ NULL,
+ rtl_digest_destroyMD5,
+ rtl_digest_updateMD5,
+ rtl_digest_getMD5
+};
+
+/*
+ * __rtl_digest_initMD5.
+ */
+static void __rtl_digest_initMD5 (DigestContextMD5 *ctx)
+{
+ rtl_zeroMemory (ctx, sizeof (DigestContextMD5));
+
+ ctx->m_nA = (sal_uInt32)0x67452301L;
+ ctx->m_nB = (sal_uInt32)0xefcdab89L;
+ ctx->m_nC = (sal_uInt32)0x98badcfeL;
+ ctx->m_nD = (sal_uInt32)0x10325476L;
+}
+
+/*
+ * __rtl_digest_updateMD5.
+ */
+static void __rtl_digest_updateMD5 (DigestContextMD5 *ctx)
+{
+ register sal_uInt32 A, B, C, D;
+ register sal_uInt32 *X;
+
+ A = ctx->m_nA;
+ B = ctx->m_nB;
+ C = ctx->m_nC;
+ D = ctx->m_nD;
+ X = ctx->m_pData;
+
+ R0 (A, B, C, D, X[ 0], 7, 0xd76aa478L);
+ R0 (D, A, B, C, X[ 1], 12, 0xe8c7b756L);
+ R0 (C, D, A, B, X[ 2], 17, 0x242070dbL);
+ R0 (B, C, D, A, X[ 3], 22, 0xc1bdceeeL);
+ R0 (A, B, C, D, X[ 4], 7, 0xf57c0fafL);
+ R0 (D, A, B, C, X[ 5], 12, 0x4787c62aL);
+ R0 (C, D, A, B, X[ 6], 17, 0xa8304613L);
+ R0 (B, C, D, A, X[ 7], 22, 0xfd469501L);
+ R0 (A, B, C, D, X[ 8], 7, 0x698098d8L);
+ R0 (D, A, B, C, X[ 9], 12, 0x8b44f7afL);
+ R0 (C, D, A, B, X[10], 17, 0xffff5bb1L);
+ R0 (B, C, D, A, X[11], 22, 0x895cd7beL);
+ R0 (A, B, C, D, X[12], 7, 0x6b901122L);
+ R0 (D, A, B, C, X[13], 12, 0xfd987193L);
+ R0 (C, D, A, B, X[14], 17, 0xa679438eL);
+ R0 (B, C, D, A, X[15], 22, 0x49b40821L);
+
+ R1 (A, B, C, D, X[ 1], 5, 0xf61e2562L);
+ R1 (D, A, B, C, X[ 6], 9, 0xc040b340L);
+ R1 (C, D, A, B, X[11], 14, 0x265e5a51L);
+ R1 (B, C, D, A, X[ 0], 20, 0xe9b6c7aaL);
+ R1 (A, B, C, D, X[ 5], 5, 0xd62f105dL);
+ R1 (D, A, B, C, X[10], 9, 0x02441453L);
+ R1 (C, D, A, B, X[15], 14, 0xd8a1e681L);
+ R1 (B, C, D, A, X[ 4], 20, 0xe7d3fbc8L);
+ R1 (A, B, C, D, X[ 9], 5, 0x21e1cde6L);
+ R1 (D, A, B, C, X[14], 9, 0xc33707d6L);
+ R1 (C, D, A, B, X[ 3], 14, 0xf4d50d87L);
+ R1 (B, C, D, A, X[ 8], 20, 0x455a14edL);
+ R1 (A, B, C, D, X[13], 5, 0xa9e3e905L);
+ R1 (D, A, B, C, X[ 2], 9, 0xfcefa3f8L);
+ R1 (C, D, A, B, X[ 7], 14, 0x676f02d9L);
+ R1 (B, C, D, A, X[12], 20, 0x8d2a4c8aL);
+
+ R2 (A, B, C, D, X[ 5], 4, 0xfffa3942L);
+ R2 (D, A, B, C, X[ 8], 11, 0x8771f681L);
+ R2 (C, D, A, B, X[11], 16, 0x6d9d6122L);
+ R2 (B, C, D, A, X[14], 23, 0xfde5380cL);
+ R2 (A, B, C, D, X[ 1], 4, 0xa4beea44L);
+ R2 (D, A, B, C, X[ 4], 11, 0x4bdecfa9L);
+ R2 (C, D, A, B, X[ 7], 16, 0xf6bb4b60L);
+ R2 (B, C, D, A, X[10], 23, 0xbebfbc70L);
+ R2 (A, B, C, D, X[13], 4, 0x289b7ec6L);
+ R2 (D, A, B, C, X[ 0], 11, 0xeaa127faL);
+ R2 (C, D, A, B, X[ 3], 16, 0xd4ef3085L);
+ R2 (B, C, D, A, X[ 6], 23, 0x04881d05L);
+ R2 (A, B, C, D, X[ 9], 4, 0xd9d4d039L);
+ R2 (D, A, B, C, X[12], 11, 0xe6db99e5L);
+ R2 (C, D, A, B, X[15], 16, 0x1fa27cf8L);
+ R2 (B, C, D, A, X[ 2], 23, 0xc4ac5665L);
+
+ R3 (A, B, C, D, X[ 0], 6, 0xf4292244L);
+ R3 (D, A, B, C, X[ 7], 10, 0x432aff97L);
+ R3 (C, D, A, B, X[14], 15, 0xab9423a7L);
+ R3 (B, C, D, A, X[ 5], 21, 0xfc93a039L);
+ R3 (A, B, C, D, X[12], 6, 0x655b59c3L);
+ R3 (D, A, B, C, X[ 3], 10, 0x8f0ccc92L);
+ R3 (C, D, A, B, X[10], 15, 0xffeff47dL);
+ R3 (B, C, D, A, X[ 1], 21, 0x85845dd1L);
+ R3 (A, B, C, D, X[ 8], 6, 0x6fa87e4fL);
+ R3 (D, A, B, C, X[15], 10, 0xfe2ce6e0L);
+ R3 (C, D, A, B, X[ 6], 15, 0xa3014314L);
+ R3 (B, C, D, A, X[13], 21, 0x4e0811a1L);
+ R3 (A, B, C, D, X[ 4], 6, 0xf7537e82L);
+ R3 (D, A, B, C, X[11], 10, 0xbd3af235L);
+ R3 (C, D, A, B, X[ 2], 15, 0x2ad7d2bbL);
+ R3 (B, C, D, A, X[ 9], 21, 0xeb86d391L);
+
+ ctx->m_nA += A;
+ ctx->m_nB += B;
+ ctx->m_nC += C;
+ ctx->m_nD += D;
+}
+
+/*
+ * __rtl_digest_endMD5.
+ */
+static void __rtl_digest_endMD5 (DigestContextMD5 *ctx)
+{
+ static const sal_uInt8 end[4] =
+ {
+ 0x80, 0x00, 0x00, 0x00
+ };
+ register const sal_uInt8 *p = end;
+
+ register sal_uInt32 *X;
+ register int i;
+
+ X = ctx->m_pData;
+ i = (ctx->m_nDatLen >> 2);
+
+#ifdef OSL_BIGENDIAN
+ __rtl_digest_swapLong (X, i + 1);
+#endif /* OSL_BIGENDIAN */
+
+ switch (ctx->m_nDatLen & 0x03)
+ {
+ case 1: X[i] &= 0x000000ff; break;
+ case 2: X[i] &= 0x0000ffff; break;
+ case 3: X[i] &= 0x00ffffff; break;
+ }
+
+ switch (ctx->m_nDatLen & 0x03)
+ {
+ case 0: X[i] = ((sal_uInt32)(*(p++))) << 0L;
+ case 1: X[i] |= ((sal_uInt32)(*(p++))) << 8L;
+ case 2: X[i] |= ((sal_uInt32)(*(p++))) << 16L;
+ case 3: X[i] |= ((sal_uInt32)(*(p++))) << 24L;
+ }
+
+ i += 1;
+
+ if (i >= (DIGEST_LBLOCK_MD5 - 2))
+ {
+ for (; i < DIGEST_LBLOCK_MD5; i++)
+ X[i] = 0;
+ __rtl_digest_updateMD5 (ctx);
+ i = 0;
+ }
+
+ for (; i < (DIGEST_LBLOCK_MD5 - 2); i++)
+ X[i] = 0;
+
+ X[DIGEST_LBLOCK_MD5 - 2] = ctx->m_nL;
+ X[DIGEST_LBLOCK_MD5 - 1] = ctx->m_nH;
+
+ __rtl_digest_updateMD5 (ctx);
+}
+
+/*========================================================================
+ *
+ * rtl_digest_MD5 implementation.
+ *
+ *======================================================================*/
+/*
+ * rtl_digest_MD5.
+ */
+rtlDigestError SAL_CALL rtl_digest_MD5 (
+ const void *pData, sal_uInt32 nDatLen,
+ sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
+{
+ DigestMD5_Impl digest;
+ rtlDigestError result;
+
+ digest.m_digest = __rtl_digest_MD5;
+ __rtl_digest_initMD5 (&(digest.m_context));
+
+ result = rtl_digest_update (&digest, pData, nDatLen);
+ if (result == rtl_Digest_E_None)
+ result = rtl_digest_getMD5 (&digest, pBuffer, nBufLen);
+
+ rtl_zeroMemory (&digest, sizeof (digest));
+ return (result);
+}
+
+/*
+ * rtl_digest_createMD5.
+ */
+rtlDigest SAL_CALL rtl_digest_createMD5 (void)
+{
+ DigestMD5_Impl *pImpl = (DigestMD5_Impl*)NULL;
+ pImpl = RTL_DIGEST_CREATE(DigestMD5_Impl);
+ if (pImpl)
+ {
+ pImpl->m_digest = __rtl_digest_MD5;
+ __rtl_digest_initMD5 (&(pImpl->m_context));
+ }
+ return ((rtlDigest)pImpl);
+}
+
+/*
+ * rtl_digest_updateMD5.
+ */
+rtlDigestError SAL_CALL rtl_digest_updateMD5 (
+ rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
+{
+ DigestMD5_Impl *pImpl = (DigestMD5_Impl *)Digest;
+ const sal_uInt8 *d = (const sal_uInt8 *)pData;
+
+ DigestContextMD5 *ctx;
+ sal_uInt32 len;
+
+ if ((pImpl == NULL) || (pData == NULL))
+ return rtl_Digest_E_Argument;
+
+ if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmMD5))
+ return rtl_Digest_E_Algorithm;
+
+ if (nDatLen == 0)
+ return rtl_Digest_E_None;
+
+ ctx = &(pImpl->m_context);
+
+ len = ctx->m_nL + (nDatLen << 3);
+ if (len < ctx->m_nL) ctx->m_nH += 1;
+ ctx->m_nH += (nDatLen >> 29);
+ ctx->m_nL = len;
+
+ if (ctx->m_nDatLen)
+ {
+ sal_uInt8 *p = (sal_uInt8 *)(ctx->m_pData) + ctx->m_nDatLen;
+ sal_uInt32 n = DIGEST_CBLOCK_MD5 - ctx->m_nDatLen;
+
+ if (nDatLen < n)
+ {
+ rtl_copyMemory (p, d, nDatLen);
+ ctx->m_nDatLen += nDatLen;
+
+ return rtl_Digest_E_None;
+ }
+
+ rtl_copyMemory (p, d, n);
+ d += n;
+ nDatLen -= n;
+
+#ifdef OSL_BIGENDIAN
+ __rtl_digest_swapLong (ctx->m_pData, DIGEST_LBLOCK_MD5);
+#endif /* OSL_BIGENDIAN */
+
+ __rtl_digest_updateMD5 (ctx);
+ ctx->m_nDatLen = 0;
+ }
+
+ while (nDatLen >= DIGEST_CBLOCK_MD5)
+ {
+ rtl_copyMemory (ctx->m_pData, d, DIGEST_CBLOCK_MD5);
+ d += DIGEST_CBLOCK_MD5;
+ nDatLen -= DIGEST_CBLOCK_MD5;
+
+#ifdef OSL_BIGENDIAN
+ __rtl_digest_swapLong (ctx->m_pData, DIGEST_LBLOCK_MD5);
+#endif /* OSL_BIGENDIAN */
+
+ __rtl_digest_updateMD5 (ctx);
+ }
+
+ rtl_copyMemory (ctx->m_pData, d, nDatLen);
+ ctx->m_nDatLen = nDatLen;
+
+ return rtl_Digest_E_None;
+}
+
+/*
+ * rtl_digest_getMD5.
+ */
+rtlDigestError SAL_CALL rtl_digest_getMD5 (
+ rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
+{
+ DigestMD5_Impl *pImpl = (DigestMD5_Impl *)Digest;
+ sal_uInt8 *p = pBuffer;
+
+ DigestContextMD5 *ctx;
+
+ if ((pImpl == NULL) || (pBuffer == NULL))
+ return rtl_Digest_E_Argument;
+
+ if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmMD5))
+ return rtl_Digest_E_Algorithm;
+
+ if (!(pImpl->m_digest.m_length <= nBufLen))
+ return rtl_Digest_E_BufferSize;
+
+ ctx = &(pImpl->m_context);
+
+ __rtl_digest_endMD5 (ctx);
+ RTL_DIGEST_LTOC (ctx->m_nA, p);
+ RTL_DIGEST_LTOC (ctx->m_nB, p);
+ RTL_DIGEST_LTOC (ctx->m_nC, p);
+ RTL_DIGEST_LTOC (ctx->m_nD, p);
+ __rtl_digest_initMD5 (ctx);
+
+ return rtl_Digest_E_None;
+}
+
+/*
+ * rtl_digest_rawMD5.
+ */
+rtlDigestError SAL_CALL rtl_digest_rawMD5 (
+ rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
+{
+ DigestMD5_Impl *pImpl = (DigestMD5_Impl *)Digest;
+ sal_uInt8 *p = pBuffer;
+
+ DigestContextMD5 *ctx;
+
+ if ((pImpl == NULL) || (pBuffer == NULL))
+ return rtl_Digest_E_Argument;
+
+ if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmMD5))
+ return rtl_Digest_E_Algorithm;
+
+ if (!(pImpl->m_digest.m_length <= nBufLen))
+ return rtl_Digest_E_BufferSize;
+
+ ctx = &(pImpl->m_context);
+
+ /* __rtl_digest_endMD5 (ctx); *//* not finalized */
+ RTL_DIGEST_LTOC (ctx->m_nA, p);
+ RTL_DIGEST_LTOC (ctx->m_nB, p);
+ RTL_DIGEST_LTOC (ctx->m_nC, p);
+ RTL_DIGEST_LTOC (ctx->m_nD, p);
+ __rtl_digest_initMD5 (ctx);
+
+ return rtl_Digest_E_None;
+}
+
+/*
+ * rtl_digest_destroyMD5.
+ */
+void SAL_CALL rtl_digest_destroyMD5 (rtlDigest Digest)
+{
+ DigestMD5_Impl *pImpl = (DigestMD5_Impl *)Digest;
+ if (pImpl)
+ {
+ if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmMD5)
+ rtl_freeZeroMemory (pImpl, sizeof (DigestMD5_Impl));
+ else
+ rtl_freeMemory (pImpl);
+ }
+}
+
+/*========================================================================
+ *
+ * rtl_digest_(SHA|SHA1) common internals.
+ *
+ *======================================================================*/
+#define DIGEST_CBLOCK_SHA 64
+#define DIGEST_LBLOCK_SHA 16
+
+typedef sal_uInt32 DigestSHA_update_t (sal_uInt32 x);
+
+static sal_uInt32 __rtl_digest_updateSHA_0 (sal_uInt32 x);
+static sal_uInt32 __rtl_digest_updateSHA_1 (sal_uInt32 x);
+
+typedef struct digestSHA_context_st
+{
+ DigestSHA_update_t *m_update;
+ sal_uInt32 m_nDatLen;
+ sal_uInt32 m_pData[DIGEST_LBLOCK_SHA];
+ sal_uInt32 m_nA, m_nB, m_nC, m_nD, m_nE;
+ sal_uInt32 m_nL, m_nH;
+} DigestContextSHA;
+
+typedef struct digestSHA_impl_st
+{
+ Digest_Impl m_digest;
+ DigestContextSHA m_context;
+} DigestSHA_Impl;
+
+static void __rtl_digest_initSHA (
+ DigestContextSHA *ctx, DigestSHA_update_t *fct);
+
+static void __rtl_digest_updateSHA (DigestContextSHA *ctx);
+static void __rtl_digest_endSHA (DigestContextSHA *ctx);
+
+#define K_00_19 (sal_uInt32)0x5a827999L
+#define K_20_39 (sal_uInt32)0x6ed9eba1L
+#define K_40_59 (sal_uInt32)0x8f1bbcdcL
+#define K_60_79 (sal_uInt32)0xca62c1d6L
+
+#define F_00_19(b,c,d) ((((c) ^ (d)) & (b)) ^ (d))
+#define F_20_39(b,c,d) ((b) ^ (c) ^ (d))
+#define F_40_59(b,c,d) (((b) & (c)) | ((b) & (d)) | ((c) & (d)))
+#define F_60_79(b,c,d) F_20_39(b,c,d)
+
+#define BODY_X(i) \
+ (X[(i)&0x0f] ^ X[((i)+2)&0x0f] ^ X[((i)+8)&0x0f] ^ X[((i)+13)&0x0f])
+
+#define BODY_00_15(u,i,a,b,c,d,e,f) \
+ (f) = X[i]; \
+ (f) += (e) + K_00_19 + RTL_DIGEST_ROTL((a), 5) + F_00_19((b), (c), (d)); \
+ (b) = RTL_DIGEST_ROTL((b), 30);
+
+#define BODY_16_19(u,i,a,b,c,d,e,f) \
+ (f) = BODY_X((i)); \
+ (f) = X[(i)&0x0f] = (u)((f)); \
+ (f) += (e) + K_00_19 + RTL_DIGEST_ROTL((a), 5) + F_00_19((b), (c), (d)); \
+ (b) = RTL_DIGEST_ROTL((b), 30);
+
+#define BODY_20_39(u,i,a,b,c,d,e,f) \
+ (f) = BODY_X((i)); \
+ (f) = X[(i)&0x0f] = (u)((f)); \
+ (f) += (e) + K_20_39 + RTL_DIGEST_ROTL((a), 5) + F_20_39((b), (c), (d)); \
+ (b) = RTL_DIGEST_ROTL((b), 30);
+
+#define BODY_40_59(u,i,a,b,c,d,e,f) \
+ (f) = BODY_X((i)); \
+ (f) = X[(i)&0x0f] = (u)((f)); \
+ (f) += (e) + K_40_59 + RTL_DIGEST_ROTL((a), 5) + F_40_59((b), (c), (d)); \
+ (b) = RTL_DIGEST_ROTL((b), 30);
+
+#define BODY_60_79(u,i,a,b,c,d,e,f) \
+ (f) = BODY_X((i)); \
+ (f) = X[(i)&0x0f] = (u)((f)); \
+ (f) += (e) + K_60_79 + RTL_DIGEST_ROTL((a), 5) + F_60_79((b), (c), (d)); \
+ (b) = RTL_DIGEST_ROTL((b), 30);
+
+/*
+ * __rtl_digest_initSHA.
+ */
+static void __rtl_digest_initSHA (
+ DigestContextSHA *ctx, DigestSHA_update_t *fct)
+{
+ rtl_zeroMemory (ctx, sizeof (DigestContextSHA));
+ ctx->m_update = fct;
+
+ ctx->m_nA = (sal_uInt32)0x67452301L;
+ ctx->m_nB = (sal_uInt32)0xefcdab89L;
+ ctx->m_nC = (sal_uInt32)0x98badcfeL;
+ ctx->m_nD = (sal_uInt32)0x10325476L;
+ ctx->m_nE = (sal_uInt32)0xc3d2e1f0L;
+}
+
+/*
+ * __rtl_digest_updateSHA.
+ */
+static void __rtl_digest_updateSHA (DigestContextSHA *ctx)
+{
+ register sal_uInt32 A, B, C, D, E, T;
+ register sal_uInt32 *X;
+
+ register DigestSHA_update_t *U;
+ U = ctx->m_update;
+
+ A = ctx->m_nA;
+ B = ctx->m_nB;
+ C = ctx->m_nC;
+ D = ctx->m_nD;
+ E = ctx->m_nE;
+ X = ctx->m_pData;
+
+ BODY_00_15 (U, 0, A, B, C, D, E, T);
+ BODY_00_15 (U, 1, T, A, B, C, D, E);
+ BODY_00_15 (U, 2, E, T, A, B, C, D);
+ BODY_00_15 (U, 3, D, E, T, A, B, C);
+ BODY_00_15 (U, 4, C, D, E, T, A, B);
+ BODY_00_15 (U, 5, B, C, D, E, T, A);
+ BODY_00_15 (U, 6, A, B, C, D, E, T);
+ BODY_00_15 (U, 7, T, A, B, C, D, E);
+ BODY_00_15 (U, 8, E, T, A, B, C, D);
+ BODY_00_15 (U, 9, D, E, T, A, B, C);
+ BODY_00_15 (U, 10, C, D, E, T, A, B);
+ BODY_00_15 (U, 11, B, C, D, E, T, A);
+ BODY_00_15 (U, 12, A, B, C, D, E, T);
+ BODY_00_15 (U, 13, T, A, B, C, D, E);
+ BODY_00_15 (U, 14, E, T, A, B, C, D);
+ BODY_00_15 (U, 15, D, E, T, A, B, C);
+ BODY_16_19 (U, 16, C, D, E, T, A, B);
+ BODY_16_19 (U, 17, B, C, D, E, T, A);
+ BODY_16_19 (U, 18, A, B, C, D, E, T);
+ BODY_16_19 (U, 19, T, A, B, C, D, E);
+
+ BODY_20_39 (U, 20, E, T, A, B, C, D);
+ BODY_20_39 (U, 21, D, E, T, A, B, C);
+ BODY_20_39 (U, 22, C, D, E, T, A, B);
+ BODY_20_39 (U, 23, B, C, D, E, T, A);
+ BODY_20_39 (U, 24, A, B, C, D, E, T);
+ BODY_20_39 (U, 25, T, A, B, C, D, E);
+ BODY_20_39 (U, 26, E, T, A, B, C, D);
+ BODY_20_39 (U, 27, D, E, T, A, B, C);
+ BODY_20_39 (U, 28, C, D, E, T, A, B);
+ BODY_20_39 (U, 29, B, C, D, E, T, A);
+ BODY_20_39 (U, 30, A, B, C, D, E, T);
+ BODY_20_39 (U, 31, T, A, B, C, D, E);
+ BODY_20_39 (U, 32, E, T, A, B, C, D);
+ BODY_20_39 (U, 33, D, E, T, A, B, C);
+ BODY_20_39 (U, 34, C, D, E, T, A, B);
+ BODY_20_39 (U, 35, B, C, D, E, T, A);
+ BODY_20_39 (U, 36, A, B, C, D, E, T);
+ BODY_20_39 (U, 37, T, A, B, C, D, E);
+ BODY_20_39 (U, 38, E, T, A, B, C, D);
+ BODY_20_39 (U, 39, D, E, T, A, B, C);
+
+ BODY_40_59 (U, 40, C, D, E, T, A, B);
+ BODY_40_59 (U, 41, B, C, D, E, T, A);
+ BODY_40_59 (U, 42, A, B, C, D, E, T);
+ BODY_40_59 (U, 43, T, A, B, C, D, E);
+ BODY_40_59 (U, 44, E, T, A, B, C, D);
+ BODY_40_59 (U, 45, D, E, T, A, B, C);
+ BODY_40_59 (U, 46, C, D, E, T, A, B);
+ BODY_40_59 (U, 47, B, C, D, E, T, A);
+ BODY_40_59 (U, 48, A, B, C, D, E, T);
+ BODY_40_59 (U, 49, T, A, B, C, D, E);
+ BODY_40_59 (U, 50, E, T, A, B, C, D);
+ BODY_40_59 (U, 51, D, E, T, A, B, C);
+ BODY_40_59 (U, 52, C, D, E, T, A, B);
+ BODY_40_59 (U, 53, B, C, D, E, T, A);
+ BODY_40_59 (U, 54, A, B, C, D, E, T);
+ BODY_40_59 (U, 55, T, A, B, C, D, E);
+ BODY_40_59 (U, 56, E, T, A, B, C, D);
+ BODY_40_59 (U, 57, D, E, T, A, B, C);
+ BODY_40_59 (U, 58, C, D, E, T, A, B);
+ BODY_40_59 (U, 59, B, C, D, E, T, A);
+
+ BODY_60_79 (U, 60, A, B, C, D, E, T);
+ BODY_60_79 (U, 61, T, A, B, C, D, E);
+ BODY_60_79 (U, 62, E, T, A, B, C, D);
+ BODY_60_79 (U, 63, D, E, T, A, B, C);
+ BODY_60_79 (U, 64, C, D, E, T, A, B);
+ BODY_60_79 (U, 65, B, C, D, E, T, A);
+ BODY_60_79 (U, 66, A, B, C, D, E, T);
+ BODY_60_79 (U, 67, T, A, B, C, D, E);
+ BODY_60_79 (U, 68, E, T, A, B, C, D);
+ BODY_60_79 (U, 69, D, E, T, A, B, C);
+ BODY_60_79 (U, 70, C, D, E, T, A, B);
+ BODY_60_79 (U, 71, B, C, D, E, T, A);
+ BODY_60_79 (U, 72, A, B, C, D, E, T);
+ BODY_60_79 (U, 73, T, A, B, C, D, E);
+ BODY_60_79 (U, 74, E, T, A, B, C, D);
+ BODY_60_79 (U, 75, D, E, T, A, B, C);
+ BODY_60_79 (U, 76, C, D, E, T, A, B);
+ BODY_60_79 (U, 77, B, C, D, E, T, A);
+ BODY_60_79 (U, 78, A, B, C, D, E, T);
+ BODY_60_79 (U, 79, T, A, B, C, D, E);
+
+ ctx->m_nA += E;
+ ctx->m_nB += T;
+ ctx->m_nC += A;
+ ctx->m_nD += B;
+ ctx->m_nE += C;
+}
+
+/*
+ * __rtl_digest_endSHA.
+ */
+static void __rtl_digest_endSHA (DigestContextSHA *ctx)
+{
+ static const sal_uInt8 end[4] =
+ {
+ 0x80, 0x00, 0x00, 0x00
+ };
+ register const sal_uInt8 *p = end;
+
+ register sal_uInt32 *X;
+ register int i;
+
+ X = ctx->m_pData;
+ i = (ctx->m_nDatLen >> 2);
+
+#ifdef OSL_BIGENDIAN
+ __rtl_digest_swapLong (X, i + 1);
+#endif /* OSL_BIGENDIAN */
+
+ switch (ctx->m_nDatLen & 0x03)
+ {
+ case 1: X[i] &= 0x000000ff; break;
+ case 2: X[i] &= 0x0000ffff; break;
+ case 3: X[i] &= 0x00ffffff; break;
+ }
+
+ switch (ctx->m_nDatLen & 0x03)
+ {
+ case 0: X[i] = ((sal_uInt32)(*(p++))) << 0L;
+ case 1: X[i] |= ((sal_uInt32)(*(p++))) << 8L;
+ case 2: X[i] |= ((sal_uInt32)(*(p++))) << 16L;
+ case 3: X[i] |= ((sal_uInt32)(*(p++))) << 24L;
+ }
+
+ __rtl_digest_swapLong (X, i + 1);
+
+ i += 1;
+
+ if (i >= (DIGEST_LBLOCK_SHA - 2))
+ {
+ for (; i < DIGEST_LBLOCK_SHA; i++)
+ X[i] = 0;
+ __rtl_digest_updateSHA (ctx);
+ i = 0;
+ }
+
+ for (; i < (DIGEST_LBLOCK_SHA - 2); i++)
+ X[i] = 0;
+
+ X[DIGEST_LBLOCK_SHA - 2] = ctx->m_nH;
+ X[DIGEST_LBLOCK_SHA - 1] = ctx->m_nL;
+
+ __rtl_digest_updateSHA (ctx);
+}
+
+/*========================================================================
+ *
+ * rtl_digest_SHA internals.
+ *
+ *======================================================================*/
+/*
+ * __rtl_digest_SHA_0.
+ */
+static const Digest_Impl __rtl_digest_SHA_0 =
+{
+ rtl_Digest_AlgorithmSHA,
+ RTL_DIGEST_LENGTH_SHA,
+
+ NULL,
+ rtl_digest_destroySHA,
+ rtl_digest_updateSHA,
+ rtl_digest_getSHA
+};
+
+/*
+ * __rtl_digest_updateSHA_0.
+ */
+static sal_uInt32 __rtl_digest_updateSHA_0 (sal_uInt32 x)
+{
+ return x;
+}
+
+/*========================================================================
+ *
+ * rtl_digest_SHA implementation.
+ *
+ *======================================================================*/
+/*
+ * rtl_digest_SHA.
+ */
+rtlDigestError SAL_CALL rtl_digest_SHA (
+ const void *pData, sal_uInt32 nDatLen,
+ sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
+{
+ DigestSHA_Impl digest;
+ rtlDigestError result;
+
+ digest.m_digest = __rtl_digest_SHA_0;
+ __rtl_digest_initSHA (&(digest.m_context), __rtl_digest_updateSHA_0);
+
+ result = rtl_digest_updateSHA (&digest, pData, nDatLen);
+ if (result == rtl_Digest_E_None)
+ result = rtl_digest_getSHA (&digest, pBuffer, nBufLen);
+
+ rtl_zeroMemory (&digest, sizeof (digest));
+ return (result);
+}
+
+/*
+ * rtl_digest_createSHA.
+ */
+rtlDigest SAL_CALL rtl_digest_createSHA (void)
+{
+ DigestSHA_Impl *pImpl = (DigestSHA_Impl*)NULL;
+ pImpl = RTL_DIGEST_CREATE(DigestSHA_Impl);
+ if (pImpl)
+ {
+ pImpl->m_digest = __rtl_digest_SHA_0;
+ __rtl_digest_initSHA (&(pImpl->m_context), __rtl_digest_updateSHA_0);
+ }
+ return ((rtlDigest)pImpl);
+}
+
+/*
+ * rtl_digest_updateSHA.
+ */
+rtlDigestError SAL_CALL rtl_digest_updateSHA (
+ rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
+{
+ DigestSHA_Impl *pImpl = (DigestSHA_Impl *)Digest;
+ const sal_uInt8 *d = (const sal_uInt8 *)pData;
+
+ DigestContextSHA *ctx;
+ sal_uInt32 len;
+
+ if ((pImpl == NULL) || (pData == NULL))
+ return rtl_Digest_E_Argument;
+
+ if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA))
+ return rtl_Digest_E_Algorithm;
+
+ if (nDatLen == 0)
+ return rtl_Digest_E_None;
+
+ ctx = &(pImpl->m_context);
+
+ len = ctx->m_nL + (nDatLen << 3);
+ if (len < ctx->m_nL) ctx->m_nH += 1;
+ ctx->m_nH += (nDatLen >> 29);
+ ctx->m_nL = len;
+
+ if (ctx->m_nDatLen)
+ {
+ sal_uInt8 *p = (sal_uInt8 *)(ctx->m_pData) + ctx->m_nDatLen;
+ sal_uInt32 n = DIGEST_CBLOCK_SHA - ctx->m_nDatLen;
+
+ if (nDatLen < n)
+ {
+ rtl_copyMemory (p, d, nDatLen);
+ ctx->m_nDatLen += nDatLen;
+
+ return rtl_Digest_E_None;
+ }
+
+ rtl_copyMemory (p, d, n);
+ d += n;
+ nDatLen -= n;
+
+#ifndef OSL_BIGENDIAN
+ __rtl_digest_swapLong (ctx->m_pData, DIGEST_LBLOCK_SHA);
+#endif /* OSL_BIGENDIAN */
+
+ __rtl_digest_updateSHA (ctx);
+ ctx->m_nDatLen = 0;
+ }
+
+ while (nDatLen >= DIGEST_CBLOCK_SHA)
+ {
+ rtl_copyMemory (ctx->m_pData, d, DIGEST_CBLOCK_SHA);
+ d += DIGEST_CBLOCK_SHA;
+ nDatLen -= DIGEST_CBLOCK_SHA;
+
+#ifndef OSL_BIGENDIAN
+ __rtl_digest_swapLong (ctx->m_pData, DIGEST_LBLOCK_SHA);
+#endif /* OSL_BIGENDIAN */
+
+ __rtl_digest_updateSHA (ctx);
+ }
+
+ rtl_copyMemory (ctx->m_pData, d, nDatLen);
+ ctx->m_nDatLen = nDatLen;
+
+ return rtl_Digest_E_None;
+}
+
+/*
+ * rtl_digest_getSHA.
+ */
+rtlDigestError SAL_CALL rtl_digest_getSHA (
+ rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
+{
+ DigestSHA_Impl *pImpl = (DigestSHA_Impl *)Digest;
+ sal_uInt8 *p = pBuffer;
+
+ DigestContextSHA *ctx;
+
+ if ((pImpl == NULL) || (pBuffer == NULL))
+ return rtl_Digest_E_Argument;
+
+ if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA))
+ return rtl_Digest_E_Algorithm;
+
+ if (!(pImpl->m_digest.m_length <= nBufLen))
+ return rtl_Digest_E_BufferSize;
+
+ ctx = &(pImpl->m_context);
+
+ __rtl_digest_endSHA (ctx);
+ RTL_DIGEST_HTONL (ctx->m_nA, p);
+ RTL_DIGEST_HTONL (ctx->m_nB, p);
+ RTL_DIGEST_HTONL (ctx->m_nC, p);
+ RTL_DIGEST_HTONL (ctx->m_nD, p);
+ RTL_DIGEST_HTONL (ctx->m_nE, p);
+ __rtl_digest_initSHA (ctx, __rtl_digest_updateSHA_0);
+
+ return rtl_Digest_E_None;
+}
+
+/*
+ * rtl_digest_destroySHA.
+ */
+void SAL_CALL rtl_digest_destroySHA (rtlDigest Digest)
+{
+ DigestSHA_Impl *pImpl = (DigestSHA_Impl *)Digest;
+ if (pImpl)
+ {
+ if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA)
+ rtl_freeZeroMemory (pImpl, sizeof (DigestSHA_Impl));
+ else
+ rtl_freeMemory (pImpl);
+ }
+}
+
+/*========================================================================
+ *
+ * rtl_digest_SHA1 internals.
+ *
+ *======================================================================*/
+/*
+ * __rtl_digest_SHA_1.
+ */
+static const Digest_Impl __rtl_digest_SHA_1 =
+{
+ rtl_Digest_AlgorithmSHA1,
+ RTL_DIGEST_LENGTH_SHA1,
+
+ NULL,
+ rtl_digest_destroySHA1,
+ rtl_digest_updateSHA1,
+ rtl_digest_getSHA1
+};
+
+/*
+ * __rtl_digest_updateSHA_1.
+ */
+static sal_uInt32 __rtl_digest_updateSHA_1 (sal_uInt32 x)
+{
+ return RTL_DIGEST_ROTL (x, 1);
+}
+
+/*========================================================================
+ *
+ * rtl_digest_SHA1 implementation.
+ *
+ *======================================================================*/
+/*
+ * rtl_digest_SHA1.
+ */
+rtlDigestError SAL_CALL rtl_digest_SHA1 (
+ const void *pData, sal_uInt32 nDatLen,
+ sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
+{
+ DigestSHA_Impl digest;
+ rtlDigestError result;
+
+ digest.m_digest = __rtl_digest_SHA_1;
+ __rtl_digest_initSHA (&(digest.m_context), __rtl_digest_updateSHA_1);
+
+ result = rtl_digest_updateSHA1 (&digest, pData, nDatLen);
+ if (result == rtl_Digest_E_None)
+ result = rtl_digest_getSHA1 (&digest, pBuffer, nBufLen);
+
+ rtl_zeroMemory (&digest, sizeof (digest));
+ return (result);
+}
+
+/*
+ * rtl_digest_createSHA1.
+ */
+rtlDigest SAL_CALL rtl_digest_createSHA1 (void)
+{
+ DigestSHA_Impl *pImpl = (DigestSHA_Impl*)NULL;
+ pImpl = RTL_DIGEST_CREATE(DigestSHA_Impl);
+ if (pImpl)
+ {
+ pImpl->m_digest = __rtl_digest_SHA_1;
+ __rtl_digest_initSHA (&(pImpl->m_context), __rtl_digest_updateSHA_1);
+ }
+ return ((rtlDigest)pImpl);
+}
+
+/*
+ * rtl_digest_updateSHA1.
+ */
+rtlDigestError SAL_CALL rtl_digest_updateSHA1 (
+ rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
+{
+ DigestSHA_Impl *pImpl = (DigestSHA_Impl *)Digest;
+ const sal_uInt8 *d = (const sal_uInt8 *)pData;
+
+ DigestContextSHA *ctx;
+ sal_uInt32 len;
+
+ if ((pImpl == NULL) || (pData == NULL))
+ return rtl_Digest_E_Argument;
+
+ if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA1))
+ return rtl_Digest_E_Algorithm;
+
+ if (nDatLen == 0)
+ return rtl_Digest_E_None;
+
+ ctx = &(pImpl->m_context);
+
+ len = ctx->m_nL + (nDatLen << 3);
+ if (len < ctx->m_nL) ctx->m_nH += 1;
+ ctx->m_nH += (nDatLen >> 29);
+ ctx->m_nL = len;
+
+ if (ctx->m_nDatLen)
+ {
+ sal_uInt8 *p = (sal_uInt8 *)(ctx->m_pData) + ctx->m_nDatLen;
+ sal_uInt32 n = DIGEST_CBLOCK_SHA - ctx->m_nDatLen;
+
+ if (nDatLen < n)
+ {
+ rtl_copyMemory (p, d, nDatLen);
+ ctx->m_nDatLen += nDatLen;
+
+ return rtl_Digest_E_None;
+ }
+
+ rtl_copyMemory (p, d, n);
+ d += n;
+ nDatLen -= n;
+
+#ifndef OSL_BIGENDIAN
+ __rtl_digest_swapLong (ctx->m_pData, DIGEST_LBLOCK_SHA);
+#endif /* OSL_BIGENDIAN */
+
+ __rtl_digest_updateSHA (ctx);
+ ctx->m_nDatLen = 0;
+ }
+
+ while (nDatLen >= DIGEST_CBLOCK_SHA)
+ {
+ rtl_copyMemory (ctx->m_pData, d, DIGEST_CBLOCK_SHA);
+ d += DIGEST_CBLOCK_SHA;
+ nDatLen -= DIGEST_CBLOCK_SHA;
+
+#ifndef OSL_BIGENDIAN
+ __rtl_digest_swapLong (ctx->m_pData, DIGEST_LBLOCK_SHA);
+#endif /* OSL_BIGENDIAN */
+
+ __rtl_digest_updateSHA (ctx);
+ }
+
+ rtl_copyMemory (ctx->m_pData, d, nDatLen);
+ ctx->m_nDatLen = nDatLen;
+
+ return rtl_Digest_E_None;
+}
+
+/*
+ * rtl_digest_getSHA1.
+ */
+rtlDigestError SAL_CALL rtl_digest_getSHA1 (
+ rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
+{
+ DigestSHA_Impl *pImpl = (DigestSHA_Impl *)Digest;
+ sal_uInt8 *p = pBuffer;
+
+ DigestContextSHA *ctx;
+
+ if ((pImpl == NULL) || (pBuffer == NULL))
+ return rtl_Digest_E_Argument;
+
+ if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA1))
+ return rtl_Digest_E_Algorithm;
+
+ if (!(pImpl->m_digest.m_length <= nBufLen))
+ return rtl_Digest_E_BufferSize;
+
+ ctx = &(pImpl->m_context);
+
+ __rtl_digest_endSHA (ctx);
+ RTL_DIGEST_HTONL (ctx->m_nA, p);
+ RTL_DIGEST_HTONL (ctx->m_nB, p);
+ RTL_DIGEST_HTONL (ctx->m_nC, p);
+ RTL_DIGEST_HTONL (ctx->m_nD, p);
+ RTL_DIGEST_HTONL (ctx->m_nE, p);
+ __rtl_digest_initSHA (ctx, __rtl_digest_updateSHA_1);
+
+ return rtl_Digest_E_None;
+}
+
+/*
+ * rtl_digest_destroySHA1.
+ */
+void SAL_CALL rtl_digest_destroySHA1 (rtlDigest Digest)
+{
+ DigestSHA_Impl *pImpl = (DigestSHA_Impl *)Digest;
+ if (pImpl)
+ {
+ if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA1)
+ rtl_freeZeroMemory (pImpl, sizeof (DigestSHA_Impl));
+ else
+ rtl_freeMemory (pImpl);
+ }
+}
+
+/*========================================================================
+ *
+ * rtl_digest_HMAC_MD5 internals.
+ *
+ *======================================================================*/
+#define DIGEST_CBLOCK_HMAC_MD5 64
+
+typedef struct _contextHMAC_MD5_st
+{
+ DigestMD5_Impl m_hash;
+ sal_uInt8 m_opad[DIGEST_CBLOCK_HMAC_MD5];
+} ContextHMAC_MD5;
+
+typedef struct _digestHMAC_MD5_impl_st
+{
+ Digest_Impl m_digest;
+ ContextHMAC_MD5 m_context;
+} DigestHMAC_MD5_Impl;
+
+static void __rtl_digest_initHMAC_MD5 (ContextHMAC_MD5 * ctx);
+static void __rtl_digest_ipadHMAC_MD5 (ContextHMAC_MD5 * ctx);
+static void __rtl_digest_opadHMAC_MD5 (ContextHMAC_MD5 * ctx);
+
+/*
+ * __rtl_digest_HMAC_MD5.
+ */
+static const Digest_Impl __rtl_digest_HMAC_MD5 =
+{
+ rtl_Digest_AlgorithmHMAC_MD5,
+ RTL_DIGEST_LENGTH_MD5,
+
+ rtl_digest_initHMAC_MD5,
+ rtl_digest_destroyHMAC_MD5,
+ rtl_digest_updateHMAC_MD5,
+ rtl_digest_getHMAC_MD5
+};
+
+/*
+ * __rtl_digest_initHMAC_MD5.
+ */
+static void __rtl_digest_initHMAC_MD5 (ContextHMAC_MD5 * ctx)
+{
+ DigestMD5_Impl *pImpl = &(ctx->m_hash);
+
+ pImpl->m_digest = __rtl_digest_MD5;
+ __rtl_digest_initMD5 (&(pImpl->m_context));
+
+ rtl_zeroMemory (ctx->m_opad, DIGEST_CBLOCK_HMAC_MD5);
+}
+
+/*
+ * __rtl_digest_ipadHMAC_MD5.
+ */
+static void __rtl_digest_ipadHMAC_MD5 (ContextHMAC_MD5 * ctx)
+{
+ register sal_uInt32 i;
+
+ for (i = 0; i < DIGEST_CBLOCK_HMAC_MD5; i++)
+ ctx->m_opad[i] ^= 0x36;
+ rtl_digest_updateMD5 (
+ &(ctx->m_hash), ctx->m_opad, DIGEST_CBLOCK_HMAC_MD5);
+ for (i = 0; i < DIGEST_CBLOCK_HMAC_MD5; i++)
+ ctx->m_opad[i] ^= 0x36;
+}
+
+/*
+ * __rtl_digest_opadHMAC_MD5.
+ */
+static void __rtl_digest_opadHMAC_MD5 (ContextHMAC_MD5 * ctx)
+{
+ register sal_uInt32 i;
+
+ for (i = 0; i < DIGEST_CBLOCK_HMAC_MD5; i++)
+ ctx->m_opad[i] ^= 0x5c;
+}
+
+/*========================================================================
+ *
+ * rtl_digest_HMAC_MD5 implementation.
+ *
+ *======================================================================*/
+/*
+ * rtl_digest_HMAC_MD5.
+ */
+rtlDigestError SAL_CALL rtl_digest_HMAC_MD5 (
+ const sal_uInt8 *pKeyData, sal_uInt32 nKeyLen,
+ const void *pData, sal_uInt32 nDatLen,
+ sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
+{
+ DigestHMAC_MD5_Impl digest;
+ rtlDigestError result;
+
+ digest.m_digest = __rtl_digest_HMAC_MD5;
+
+ result = rtl_digest_initHMAC_MD5 (&digest, pKeyData, nKeyLen);
+ if (result == rtl_Digest_E_None)
+ {
+ result = rtl_digest_updateHMAC_MD5 (&digest, pData, nDatLen);
+ if (result == rtl_Digest_E_None)
+ result = rtl_digest_getHMAC_MD5 (&digest, pBuffer, nBufLen);
+ }
+
+ rtl_zeroMemory (&digest, sizeof (digest));
+ return (result);
+}
+
+/*
+ * rtl_digest_createHMAC_MD5.
+ */
+rtlDigest SAL_CALL rtl_digest_createHMAC_MD5 (void)
+{
+ DigestHMAC_MD5_Impl *pImpl = (DigestHMAC_MD5_Impl*)NULL;
+ pImpl = RTL_DIGEST_CREATE(DigestHMAC_MD5_Impl);
+ if (pImpl)
+ {
+ pImpl->m_digest = __rtl_digest_HMAC_MD5;
+ __rtl_digest_initHMAC_MD5 (&(pImpl->m_context));
+ }
+ return ((rtlDigest)pImpl);
+}
+
+/*
+ * rtl_digest_initHMAC_MD5.
+ */
+rtlDigestError SAL_CALL rtl_digest_initHMAC_MD5 (
+ rtlDigest Digest, const sal_uInt8 *pKeyData, sal_uInt32 nKeyLen)
+{
+ DigestHMAC_MD5_Impl *pImpl = (DigestHMAC_MD5_Impl*)Digest;
+ ContextHMAC_MD5 *ctx;
+
+ if ((pImpl == NULL) || (pKeyData == NULL))
+ return rtl_Digest_E_Argument;
+
+ if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmHMAC_MD5))
+ return rtl_Digest_E_Algorithm;
+
+ ctx = &(pImpl->m_context);
+ __rtl_digest_initHMAC_MD5 (ctx);
+
+ if (nKeyLen > DIGEST_CBLOCK_HMAC_MD5)
+ {
+ /* Initialize 'opad' with hashed 'KeyData' */
+ rtl_digest_updateMD5 (
+ &(ctx->m_hash), pKeyData, nKeyLen);
+ rtl_digest_getMD5 (
+ &(ctx->m_hash), ctx->m_opad, RTL_DIGEST_LENGTH_MD5);
+ }
+ else
+ {
+ /* Initialize 'opad' with plain 'KeyData' */
+ rtl_copyMemory (ctx->m_opad, pKeyData, nKeyLen);
+ }
+
+ __rtl_digest_ipadHMAC_MD5 (ctx);
+ __rtl_digest_opadHMAC_MD5 (ctx);
+
+ return rtl_Digest_E_None;
+}
+
+/*
+ * rtl_digest_updateHMAC_MD5.
+ */
+rtlDigestError SAL_CALL rtl_digest_updateHMAC_MD5 (
+ rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
+{
+ DigestHMAC_MD5_Impl *pImpl = (DigestHMAC_MD5_Impl*)Digest;
+ ContextHMAC_MD5 *ctx;
+
+ if ((pImpl == NULL) || (pData == NULL))
+ return rtl_Digest_E_Argument;
+
+ if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmHMAC_MD5))
+ return rtl_Digest_E_Algorithm;
+
+ ctx = &(pImpl->m_context);
+ rtl_digest_updateMD5 (&(ctx->m_hash), pData, nDatLen);
+
+ return rtl_Digest_E_None;
+}
+
+/*
+ * rtl_digest_getHMAC_MD5.
+ */
+rtlDigestError SAL_CALL rtl_digest_getHMAC_MD5 (
+ rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
+{
+ DigestHMAC_MD5_Impl *pImpl = (DigestHMAC_MD5_Impl*)Digest;
+ ContextHMAC_MD5 *ctx;
+
+ if ((pImpl == NULL) || (pBuffer == NULL))
+ return rtl_Digest_E_Argument;
+
+ if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmHMAC_MD5))
+ return rtl_Digest_E_Algorithm;
+
+ if (!(pImpl->m_digest.m_length <= nBufLen))
+ return rtl_Digest_E_BufferSize;
+
+ nBufLen = pImpl->m_digest.m_length;
+
+ ctx = &(pImpl->m_context);
+ rtl_digest_getMD5 (&(ctx->m_hash), pBuffer, nBufLen);
+
+ rtl_digest_updateMD5 (&(ctx->m_hash), ctx->m_opad, 64);
+ rtl_digest_updateMD5 (&(ctx->m_hash), pBuffer, nBufLen);
+ rtl_digest_getMD5 (&(ctx->m_hash), pBuffer, nBufLen);
+
+ __rtl_digest_opadHMAC_MD5 (ctx);
+ __rtl_digest_ipadHMAC_MD5 (ctx);
+ __rtl_digest_opadHMAC_MD5 (ctx);
+
+ return rtl_Digest_E_None;
+}
+
+/*
+ * rtl_digest_destroyHMAC_MD5.
+ */
+void SAL_CALL rtl_digest_destroyHMAC_MD5 (rtlDigest Digest)
+{
+ DigestHMAC_MD5_Impl *pImpl = (DigestHMAC_MD5_Impl*)Digest;
+ if (pImpl)
+ {
+ if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmHMAC_MD5)
+ rtl_freeZeroMemory (pImpl, sizeof (DigestHMAC_MD5_Impl));
+ else
+ rtl_freeMemory (pImpl);
+ }
+}
+
+/*========================================================================
+ *
+ * rtl_digest_HMAC_SHA1 internals.
+ *
+ *======================================================================*/
+#define DIGEST_CBLOCK_HMAC_SHA1 64
+
+typedef struct _contextHMAC_SHA1_st
+{
+ DigestSHA_Impl m_hash;
+ sal_uInt8 m_opad[DIGEST_CBLOCK_HMAC_SHA1];
+} ContextHMAC_SHA1;
+
+typedef struct _digestHMAC_SHA1_impl_st
+{
+ Digest_Impl m_digest;
+ ContextHMAC_SHA1 m_context;
+} DigestHMAC_SHA1_Impl;
+
+static void __rtl_digest_initHMAC_SHA1 (ContextHMAC_SHA1 * ctx);
+static void __rtl_digest_ipadHMAC_SHA1 (ContextHMAC_SHA1 * ctx);
+static void __rtl_digest_opadHMAC_SHA1 (ContextHMAC_SHA1 * ctx);
+
+/*
+ * __rtl_digest_HMAC_SHA1.
+ */
+static const Digest_Impl __rtl_digest_HMAC_SHA1 =
+{
+ rtl_Digest_AlgorithmHMAC_SHA1,
+ RTL_DIGEST_LENGTH_SHA1,
+
+ rtl_digest_initHMAC_SHA1,
+ rtl_digest_destroyHMAC_SHA1,
+ rtl_digest_updateHMAC_SHA1,
+ rtl_digest_getHMAC_SHA1
+};
+
+/*
+ * __rtl_digest_initHMAC_SHA1.
+ */
+static void __rtl_digest_initHMAC_SHA1 (ContextHMAC_SHA1 * ctx)
+{
+ DigestSHA_Impl *pImpl = &(ctx->m_hash);
+
+ pImpl->m_digest = __rtl_digest_SHA_1;
+ __rtl_digest_initSHA (&(pImpl->m_context), __rtl_digest_updateSHA_1);
+
+ rtl_zeroMemory (ctx->m_opad, DIGEST_CBLOCK_HMAC_SHA1);
+}
+
+/*
+ * __rtl_digest_ipadHMAC_SHA1.
+ */
+static void __rtl_digest_ipadHMAC_SHA1 (ContextHMAC_SHA1 * ctx)
+{
+ register sal_uInt32 i;
+
+ for (i = 0; i < DIGEST_CBLOCK_HMAC_SHA1; i++)
+ ctx->m_opad[i] ^= 0x36;
+ rtl_digest_updateSHA1 (
+ &(ctx->m_hash), ctx->m_opad, DIGEST_CBLOCK_HMAC_SHA1);
+ for (i = 0; i < DIGEST_CBLOCK_HMAC_SHA1; i++)
+ ctx->m_opad[i] ^= 0x36;
+}
+
+/*
+ * __rtl_digest_opadHMAC_SHA1.
+ */
+static void __rtl_digest_opadHMAC_SHA1 (ContextHMAC_SHA1 * ctx)
+{
+ register sal_uInt32 i;
+
+ for (i = 0; i < DIGEST_CBLOCK_HMAC_SHA1; i++)
+ ctx->m_opad[i] ^= 0x5c;
+}
+
+/*========================================================================
+ *
+ * rtl_digest_HMAC_SHA1 implementation.
+ *
+ *======================================================================*/
+/*
+ * rtl_digest_HMAC_SHA1.
+ */
+rtlDigestError SAL_CALL rtl_digest_HMAC_SHA1 (
+ const sal_uInt8 *pKeyData, sal_uInt32 nKeyLen,
+ const void *pData, sal_uInt32 nDatLen,
+ sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
+{
+ DigestHMAC_SHA1_Impl digest;
+ rtlDigestError result;
+
+ digest.m_digest = __rtl_digest_HMAC_SHA1;
+
+ result = rtl_digest_initHMAC_SHA1 (&digest, pKeyData, nKeyLen);
+ if (result == rtl_Digest_E_None)
+ {
+ result = rtl_digest_updateHMAC_SHA1 (&digest, pData, nDatLen);
+ if (result == rtl_Digest_E_None)
+ result = rtl_digest_getHMAC_SHA1 (&digest, pBuffer, nBufLen);
+ }
+
+ rtl_zeroMemory (&digest, sizeof (digest));
+ return (result);
+}
+
+/*
+ * rtl_digest_createHMAC_SHA1.
+ */
+rtlDigest SAL_CALL rtl_digest_createHMAC_SHA1 (void)
+{
+ DigestHMAC_SHA1_Impl *pImpl = (DigestHMAC_SHA1_Impl*)NULL;
+ pImpl = RTL_DIGEST_CREATE(DigestHMAC_SHA1_Impl);
+ if (pImpl)
+ {
+ pImpl->m_digest = __rtl_digest_HMAC_SHA1;
+ __rtl_digest_initHMAC_SHA1 (&(pImpl->m_context));
+ }
+ return ((rtlDigest)pImpl);
+}
+
+/*
+ * rtl_digest_initHMAC_SHA1.
+ */
+rtlDigestError SAL_CALL rtl_digest_initHMAC_SHA1 (
+ rtlDigest Digest, const sal_uInt8 *pKeyData, sal_uInt32 nKeyLen)
+{
+ DigestHMAC_SHA1_Impl *pImpl = (DigestHMAC_SHA1_Impl*)Digest;
+ ContextHMAC_SHA1 *ctx;
+
+ if ((pImpl == NULL) || (pKeyData == NULL))
+ return rtl_Digest_E_Argument;
+
+ if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmHMAC_SHA1))
+ return rtl_Digest_E_Algorithm;
+
+ ctx = &(pImpl->m_context);
+ __rtl_digest_initHMAC_SHA1 (ctx);
+
+ if (nKeyLen > DIGEST_CBLOCK_HMAC_SHA1)
+ {
+ /* Initialize 'opad' with hashed 'KeyData' */
+ rtl_digest_updateSHA1 (
+ &(ctx->m_hash), pKeyData, nKeyLen);
+ rtl_digest_getSHA1 (
+ &(ctx->m_hash), ctx->m_opad, RTL_DIGEST_LENGTH_SHA1);
+ }
+ else
+ {
+ /* Initialize 'opad' with plain 'KeyData' */
+ rtl_copyMemory (ctx->m_opad, pKeyData, nKeyLen);
+ }
+
+ __rtl_digest_ipadHMAC_SHA1 (ctx);
+ __rtl_digest_opadHMAC_SHA1 (ctx);
+
+ return rtl_Digest_E_None;
+}
+
+/*
+ * rtl_digest_updateHMAC_SHA1.
+ */
+rtlDigestError SAL_CALL rtl_digest_updateHMAC_SHA1 (
+ rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
+{
+ DigestHMAC_SHA1_Impl *pImpl = (DigestHMAC_SHA1_Impl*)Digest;
+ ContextHMAC_SHA1 *ctx;
+
+ if ((pImpl == NULL) || (pData == NULL))
+ return rtl_Digest_E_Argument;
+
+ if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmHMAC_SHA1))
+ return rtl_Digest_E_Algorithm;
+
+ ctx = &(pImpl->m_context);
+ rtl_digest_updateSHA1 (&(ctx->m_hash), pData, nDatLen);
+
+ return rtl_Digest_E_None;
+}
+
+/*
+ * rtl_digest_getHMAC_SHA1.
+ */
+rtlDigestError SAL_CALL rtl_digest_getHMAC_SHA1 (
+ rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
+{
+ DigestHMAC_SHA1_Impl *pImpl = (DigestHMAC_SHA1_Impl*)Digest;
+ ContextHMAC_SHA1 *ctx;
+
+ if ((pImpl == NULL) || (pBuffer == NULL))
+ return rtl_Digest_E_Argument;
+
+ if (!(pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmHMAC_SHA1))
+ return rtl_Digest_E_Algorithm;
+
+ if (!(pImpl->m_digest.m_length <= nBufLen))
+ return rtl_Digest_E_BufferSize;
+
+ nBufLen = pImpl->m_digest.m_length;
+
+ ctx = &(pImpl->m_context);
+ rtl_digest_getSHA1 (&(ctx->m_hash), pBuffer, nBufLen);
+
+ rtl_digest_updateSHA1 (&(ctx->m_hash), ctx->m_opad, sizeof(ctx->m_opad));
+ rtl_digest_updateSHA1 (&(ctx->m_hash), pBuffer, nBufLen);
+ rtl_digest_getSHA1 (&(ctx->m_hash), pBuffer, nBufLen);
+
+ __rtl_digest_opadHMAC_SHA1 (ctx);
+ __rtl_digest_ipadHMAC_SHA1 (ctx);
+ __rtl_digest_opadHMAC_SHA1 (ctx);
+
+ return rtl_Digest_E_None;
+}
+
+/*
+ * rtl_digest_destroyHMAC_SHA1.
+ */
+void SAL_CALL rtl_digest_destroyHMAC_SHA1 (rtlDigest Digest)
+{
+ DigestHMAC_SHA1_Impl *pImpl = (DigestHMAC_SHA1_Impl*)Digest;
+ if (pImpl)
+ {
+ if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmHMAC_SHA1)
+ rtl_freeZeroMemory (pImpl, sizeof (DigestHMAC_SHA1_Impl));
+ else
+ rtl_freeMemory (pImpl);
+ }
+}
+
+/*========================================================================
+ *
+ * rtl_digest_PBKDF2 internals.
+ *
+ *======================================================================*/
+#define DIGEST_CBLOCK_PBKDF2 RTL_DIGEST_LENGTH_HMAC_SHA1
+
+/*
+ * __rtl_digest_updatePBKDF2.
+ */
+static void __rtl_digest_updatePBKDF2 (
+ rtlDigest hDigest,
+ sal_uInt8 T[DIGEST_CBLOCK_PBKDF2],
+ const sal_uInt8 *pSaltData, sal_uInt32 nSaltLen,
+ sal_uInt32 nCount, sal_uInt32 nIndex)
+{
+ /* T_i = F (P, S, c, i) */
+ sal_uInt8 U[DIGEST_CBLOCK_PBKDF2];
+ register sal_uInt32 i, k;
+
+ /* U_(1) = PRF (P, S || INDEX) */
+ rtl_digest_updateHMAC_SHA1 (hDigest, pSaltData, nSaltLen);
+ rtl_digest_updateHMAC_SHA1 (hDigest, &nIndex, sizeof(nIndex));
+ rtl_digest_getHMAC_SHA1 (hDigest, U, DIGEST_CBLOCK_PBKDF2);
+
+ /* T = U_(1) */
+ for (k = 0; k < DIGEST_CBLOCK_PBKDF2; k++) T[k] = U[k];
+
+ /* T ^= U_(2) ^ ... ^ U_(c) */
+ for (i = 1; i < nCount; i++)
+ {
+ /* U_(i) = PRF (P, U_(i-1)) */
+ rtl_digest_updateHMAC_SHA1 (hDigest, U, DIGEST_CBLOCK_PBKDF2);
+ rtl_digest_getHMAC_SHA1 (hDigest, U, DIGEST_CBLOCK_PBKDF2);
+
+ /* T ^= U_(i) */
+ for (k = 0; k < DIGEST_CBLOCK_PBKDF2; k++) T[k] ^= U[k];
+ }
+
+ rtl_zeroMemory (U, DIGEST_CBLOCK_PBKDF2);
+}
+
+/*========================================================================
+ *
+ * rtl_digest_PBKDF2 implementation.
+ *
+ *======================================================================*/
+/*
+ * rtl_digest_PBKDF2.
+ */
+rtlDigestError SAL_CALL rtl_digest_PBKDF2 (
+ sal_uInt8 *pKeyData , sal_uInt32 nKeyLen,
+ const sal_uInt8 *pPassData, sal_uInt32 nPassLen,
+ const sal_uInt8 *pSaltData, sal_uInt32 nSaltLen,
+ sal_uInt32 nCount)
+{
+ DigestHMAC_SHA1_Impl digest;
+ sal_uInt32 i = 1;
+
+ if ((pKeyData == NULL) || (pPassData == NULL) || (pSaltData == NULL))
+ return rtl_Digest_E_Argument;
+
+ digest.m_digest = __rtl_digest_HMAC_SHA1;
+ rtl_digest_initHMAC_SHA1 (&digest, pPassData, nPassLen);
+
+ /* DK = T_(1) || T_(2) || ... || T_(l) */
+ while (nKeyLen >= DIGEST_CBLOCK_PBKDF2)
+ {
+ /* T_(i) = F (P, S, c, i); DK ||= T_(i) */
+ __rtl_digest_updatePBKDF2 (
+ &digest, pKeyData,
+ pSaltData, nSaltLen,
+ nCount, OSL_NETDWORD(i));
+
+ /* Next 'KeyData' block */
+ pKeyData += DIGEST_CBLOCK_PBKDF2;
+ nKeyLen -= DIGEST_CBLOCK_PBKDF2;
+ i += 1;
+ }
+ if (nKeyLen > 0)
+ {
+ /* Last 'KeyData' block */
+ sal_uInt8 T[DIGEST_CBLOCK_PBKDF2];
+
+ /* T_i = F (P, S, c, i) */
+ __rtl_digest_updatePBKDF2 (
+ &digest, T,
+ pSaltData, nSaltLen,
+ nCount, OSL_NETDWORD(i));
+
+ /* DK ||= T_(i) */
+ rtl_copyMemory (pKeyData, T, nKeyLen);
+ rtl_zeroMemory (T, DIGEST_CBLOCK_PBKDF2);
+ }
+
+ rtl_zeroMemory (&digest, sizeof (digest));
+ return rtl_Digest_E_None;
+}
+
+/*========================================================================
+ *
+ * The End.
+ *
+ *======================================================================*/
diff --git a/sal/rtl/source/gen_makefile.cxx b/sal/rtl/source/gen_makefile.cxx
new file mode 100644
index 000000000000..0b11c11d06c9
--- /dev/null
+++ b/sal/rtl/source/gen_makefile.cxx
@@ -0,0 +1,41 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+
+#include "macro.hxx"
+#include <stdio.h>
+
+int main()
+{
+ printf( "RTL_OS:=%s\n", THIS_OS );
+ printf( "RTL_ARCH:=%s\n", THIS_ARCH );
+ return 0;
+}
+
+
diff --git a/sal/rtl/source/hash.cxx b/sal/rtl/source/hash.cxx
new file mode 100644
index 000000000000..7caa2341ca11
--- /dev/null
+++ b/sal/rtl/source/hash.cxx
@@ -0,0 +1,113 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+#include "rtl/allocator.hxx"
+
+#include "hash.h"
+#include "strimp.h"
+
+
+#include <hash_set>
+
+namespace {
+
+struct UStringHash
+{
+ size_t operator()(rtl_uString * const &rString) const
+ { return (size_t)rtl_ustr_hashCode_WithLength( rString->buffer, rString->length ); }
+};
+
+struct UStringEqual
+{
+ sal_Bool operator() ( rtl_uString * const &pStringA,
+ rtl_uString * const &pStringB) const
+ {
+ if (pStringA == pStringB)
+ return true;
+ if (pStringA->length != pStringB->length)
+ return false;
+ return !rtl_ustr_compare_WithLength( pStringA->buffer, pStringA->length,
+ pStringB->buffer, pStringB->length);
+ }
+};
+
+typedef std::hash_set< rtl_uString *, UStringHash, UStringEqual,
+ rtl::Allocator<rtl_uString *> > StringHashTable;
+
+StringHashTable *
+getHashTable ()
+{
+ static StringHashTable *pInternPool = NULL;
+ if (pInternPool == NULL) {
+ static StringHashTable aImpl(1024);
+ pInternPool = &aImpl;
+ }
+ return pInternPool;
+}
+
+}
+
+extern "C" {
+
+rtl_uString *
+rtl_str_hash_intern (rtl_uString *pString,
+ int can_return)
+{
+ StringHashTable *pHash = getHashTable();
+ StringHashTable::iterator aIter;
+ aIter = pHash->find(pString);
+ if (aIter != pHash->end())
+ {
+ rtl_uString *pHashStr = *aIter;
+ rtl_uString_acquire (pHashStr);
+ return pHashStr;
+ }
+ if (!can_return)
+ {
+ rtl_uString *pCopy = NULL;
+ rtl_uString_newFromString( &pCopy, pString );
+ pString = pCopy;
+ if (!pString)
+ return NULL;
+ }
+
+ if (!SAL_STRING_IS_STATIC (pString))
+ pString->refCount |= SAL_STRING_INTERN_FLAG;
+ pHash->insert(pString);
+
+ return pString;
+}
+
+void
+rtl_str_hash_remove (rtl_uString *pString)
+{
+ getHashTable()->erase(pString);
+}
+
+}
diff --git a/sal/rtl/source/hash.h b/sal/rtl/source/hash.h
new file mode 100644
index 000000000000..2aadfb33efcd
--- /dev/null
+++ b/sal/rtl/source/hash.h
@@ -0,0 +1,21 @@
+#ifndef INCLUDED_RTL_SOURCE_HASH_H
+#define INCLUDED_RTL_SOURCE_HASH_H
+
+#include <sal/types.h>
+#include <rtl/ustring.h>
+
+#if defined __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* These functions are not multi-thread safe: */
+
+rtl_uString *rtl_str_hash_intern (rtl_uString *pString,
+ int can_return);
+void rtl_str_hash_remove (rtl_uString *pString);
+
+#if defined __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* INCLUDED_RTL_SOURCE_HASH_H */
diff --git a/sal/rtl/source/locale.c b/sal/rtl/source/locale.c
new file mode 100644
index 000000000000..89a8568f8478
--- /dev/null
+++ b/sal/rtl/source/locale.c
@@ -0,0 +1,362 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "rtl/locale.h"
+
+#include "osl/diagnose.h"
+#include "rtl/alloc.h"
+
+#include "internal/once.h"
+
+static sal_Int32 RTL_HASHTABLE_SIZE[] =
+{
+ 7, 31, 127, 251, 509, 1021, 2039, 4093
+};
+
+typedef struct rtl_hashentry RTL_HASHENTRY;
+
+struct rtl_hashentry
+{
+ rtl_Locale* Entry;
+ RTL_HASHENTRY* Next;
+};
+
+typedef struct rtl_hashtable
+{
+ sal_Int8 iSize;
+ sal_Int32 Size;
+ sal_Int32 Elements;
+ RTL_HASHENTRY** Table;
+} RTL_HASHTABLE;
+
+static RTL_HASHTABLE* g_pLocaleTable = NULL;
+
+static rtl_Locale* g_pDefaultLocale = NULL;
+
+static int rtl_locale_init (void);
+
+/*************************************************************************
+ */
+void rtl_hashentry_destroy(RTL_HASHENTRY* entry)
+{
+ rtl_uString_release(entry->Entry->Language);
+ rtl_uString_release(entry->Entry->Country);
+ rtl_uString_release(entry->Entry->Variant);
+ if (entry->Next)
+ rtl_hashentry_destroy(entry->Next);
+
+ rtl_freeMemory(entry->Entry);
+ rtl_freeMemory(entry);
+}
+
+void rtl_hashtable_destroy(RTL_HASHTABLE* table)
+{
+ sal_Int32 size = 0;
+
+ if (!table)
+ return;
+
+ size = table->Size;
+
+ while (size)
+ {
+ if (table->Table[size - 1])
+ rtl_hashentry_destroy(table->Table[size - 1]);
+ size--;
+ }
+
+ rtl_freeMemory(table->Table);
+ rtl_freeMemory(table);
+}
+
+void rtl_hashtable_init(RTL_HASHTABLE** table, sal_Int8 sizeIndex)
+{
+ sal_Int32 nSize = RTL_HASHTABLE_SIZE[sizeIndex];
+
+ if (*table)
+ rtl_hashtable_destroy(*table);
+
+ *table = (RTL_HASHTABLE*)rtl_allocateMemory( sizeof(RTL_HASHTABLE) );
+
+ (*table)->iSize = sizeIndex;
+ (*table)->Size = nSize;
+ (*table)->Elements = 0;
+ (*table)->Table = (RTL_HASHENTRY**)rtl_allocateMemory( (*table)->Size * sizeof(RTL_HASHENTRY*) );
+
+ while (nSize)
+ {
+ (*table)->Table[nSize - 1] = NULL;
+ nSize--;
+ }
+}
+
+sal_Int32 rtl_hashfunc(RTL_HASHTABLE* table, sal_Int32 key)
+{
+ return ( (sal_uInt32) key % table->Size);
+}
+
+sal_Bool rtl_hashtable_grow(RTL_HASHTABLE** table);
+
+rtl_Locale* rtl_hashtable_add(RTL_HASHTABLE** table, rtl_Locale* value)
+{
+ sal_Int32 key = 0;
+
+ if (!(*table))
+ return NULL;
+
+ if ((*table)->Elements > ((*table)->Size / 2))
+ rtl_hashtable_grow(table);
+
+ key = rtl_hashfunc(*table, value->HashCode);
+
+ if (!(*table)->Table[key])
+ {
+ RTL_HASHENTRY *newEntry = (RTL_HASHENTRY*)rtl_allocateMemory( sizeof(RTL_HASHENTRY) );
+ newEntry->Entry = value;
+ newEntry->Next = NULL;
+ (*table)->Table[key] = newEntry;
+ (*table)->Elements++;
+ return NULL;
+ } else
+ {
+ RTL_HASHENTRY *pEntry = (*table)->Table[key];
+ RTL_HASHENTRY *newEntry = NULL;
+
+ while (pEntry)
+ {
+ if (value->HashCode == pEntry->Entry->HashCode)
+ return pEntry->Entry;
+
+ if (!pEntry->Next)
+ break;
+
+ pEntry = pEntry->Next;
+ }
+
+ newEntry = (RTL_HASHENTRY*)rtl_allocateMemory( sizeof(RTL_HASHENTRY) );
+ newEntry->Entry = value;
+ newEntry->Next = NULL;
+ pEntry->Next = newEntry;
+ (*table)->Elements++;
+ return NULL;
+ }
+}
+
+sal_Bool rtl_hashtable_grow(RTL_HASHTABLE** table)
+{
+ RTL_HASHTABLE* pNewTable = NULL;
+ sal_Int32 i = 0;
+
+ rtl_hashtable_init(&pNewTable, (sal_Int8)((*table)->iSize + 1));
+
+ while (i < (*table)->Size)
+ {
+ if ((*table)->Table[i])
+ {
+ RTL_HASHENTRY *pNext;
+ RTL_HASHENTRY *pEntry = (*table)->Table[i];
+
+ rtl_hashtable_add(&pNewTable, pEntry->Entry);
+
+ while (pEntry->Next)
+ {
+ rtl_hashtable_add(&pNewTable, pEntry->Next->Entry);
+ pNext = pEntry->Next;
+ rtl_freeMemory(pEntry);
+ pEntry = pNext;
+ }
+
+ rtl_freeMemory(pEntry);
+ }
+ i++;
+ }
+
+ rtl_freeMemory((*table)->Table);
+ rtl_freeMemory((*table));
+ (*table) = pNewTable;
+
+ return sal_True;
+}
+
+sal_Bool rtl_hashtable_find(RTL_HASHTABLE * table, sal_Int32 key, sal_Int32 hashCode, rtl_Locale** pValue)
+{
+ if (!table)
+ return sal_False;
+
+ if (table->Table[key])
+ {
+ RTL_HASHENTRY *pEntry = table->Table[key];
+
+ while (pEntry && hashCode != pEntry->Entry->HashCode)
+ pEntry = pEntry->Next;
+
+ if (pEntry)
+ *pValue = pEntry->Entry;
+ else
+ return sal_False;
+ } else
+ return sal_False;
+
+ return sal_True;
+}
+
+/*************************************************************************
+ * rtl_locale_init
+ */
+static void rtl_locale_once_init (void)
+{
+ OSL_ASSERT(g_pLocaleTable == 0);
+ rtl_hashtable_init(&g_pLocaleTable, 1);
+}
+
+static int rtl_locale_init (void)
+{
+ static sal_once_type g_once = SAL_ONCE_INIT;
+ SAL_ONCE(&g_once, rtl_locale_once_init);
+ return (g_pLocaleTable != 0);
+}
+
+/*************************************************************************
+ * rtl_locale_fini
+ */
+#if defined(__GNUC__)
+static void rtl_locale_fini (void) __attribute__((destructor));
+#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+#pragma fini(rtl_locale_fini)
+static void rtl_locale_fini (void);
+#endif /* __GNUC__ || __SUNPRO_C */
+
+void rtl_locale_fini (void)
+{
+ if (g_pLocaleTable != 0)
+ {
+ rtl_hashtable_destroy (g_pLocaleTable);
+ g_pLocaleTable = 0;
+ }
+}
+
+/*************************************************************************
+ * rtl_locale_register
+ */
+rtl_Locale * SAL_CALL rtl_locale_register( const sal_Unicode * language, const sal_Unicode * country, const sal_Unicode * variant )
+{
+ sal_Unicode c = 0;
+ rtl_uString* sLanguage = NULL;
+ rtl_uString* sCountry = NULL;
+ rtl_uString* sVariant = NULL;
+ rtl_Locale *newLocale = NULL;
+ sal_Int32 hashCode = -1;
+ sal_Int32 key = 0;
+
+ if ( !country )
+ country = &c;
+ if ( !variant )
+ variant = &c;
+
+ if (!rtl_locale_init())
+ return NULL;
+
+ hashCode = rtl_ustr_hashCode(language) ^ rtl_ustr_hashCode(country) ^ rtl_ustr_hashCode(variant);
+ key = rtl_hashfunc(g_pLocaleTable, hashCode);
+
+ if (rtl_hashtable_find(g_pLocaleTable, key, hashCode, &newLocale))
+ return newLocale;
+
+ rtl_uString_newFromStr(&sLanguage, language);
+ rtl_uString_newFromStr(&sCountry, country);
+ rtl_uString_newFromStr(&sVariant, variant);
+
+ newLocale = (rtl_Locale*)rtl_allocateMemory( sizeof(rtl_Locale) );
+
+ newLocale->Language = sLanguage;
+ newLocale->Country = sCountry;
+ newLocale->Variant = sVariant;
+ newLocale->HashCode = hashCode;
+
+ rtl_hashtable_add(&g_pLocaleTable, newLocale);
+
+ return newLocale;
+}
+
+/*************************************************************************
+ * rtl_locale_getDefault
+ */
+rtl_Locale * SAL_CALL rtl_locale_getDefault()
+{
+ return g_pDefaultLocale;
+}
+
+/*************************************************************************
+ * rtl_locale_setDefault
+ */
+void SAL_CALL rtl_locale_setDefault( const sal_Unicode * language, const sal_Unicode * country, const sal_Unicode * variant )
+{
+ g_pDefaultLocale = rtl_locale_register(language, country, variant);
+}
+
+/*************************************************************************
+ * rtl_locale_getLanguage
+ */
+rtl_uString * SAL_CALL rtl_locale_getLanguage( rtl_Locale * This )
+{
+ rtl_uString_acquire(This->Language);
+ return This->Language;
+}
+
+/*************************************************************************
+ * rtl_locale_getCountry
+ */
+rtl_uString * SAL_CALL rtl_locale_getCountry( rtl_Locale * This )
+{
+ rtl_uString_acquire(This->Country);
+ return This->Country;
+}
+
+/*************************************************************************
+ * rtl_locale_getVariant
+ */
+rtl_uString * SAL_CALL rtl_locale_getVariant( rtl_Locale * This )
+{
+ rtl_uString_acquire(This->Variant);
+ return This->Variant;
+}
+
+/*************************************************************************
+ * rtl_locale_hashCode
+ */
+sal_Int32 SAL_CALL rtl_locale_hashCode( rtl_Locale * This )
+{
+ return This->HashCode;
+}
+
+/*************************************************************************
+ * rtl_locale_equals
+ */
+sal_Int32 SAL_CALL rtl_locale_equals( rtl_Locale * This, rtl_Locale * obj )
+{
+ return This == obj;
+}
diff --git a/sal/rtl/source/logfile.cxx b/sal/rtl/source/logfile.cxx
new file mode 100644
index 000000000000..56d5e5d5d68e
--- /dev/null
+++ b/sal/rtl/source/logfile.cxx
@@ -0,0 +1,254 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+#include <cstdarg>
+#include <cstdio>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include <rtl/logfile.h>
+#include <osl/process.h>
+#ifndef _OSL_FILE_H_
+#include <osl/time.h>
+#endif
+#include <osl/time.h>
+#include <osl/mutex.hxx>
+#include <rtl/bootstrap.h>
+#include <rtl/ustring.hxx>
+#ifndef _RTL_STRBUF_HXX_
+#include <rtl/ustrbuf.hxx>
+#endif
+#include <rtl/alloc.h>
+#include "osl/thread.h"
+
+#include <algorithm>
+
+#ifdef _MSC_VER
+#define vsnprintf _vsnprintf
+#endif
+
+using namespace rtl;
+using namespace osl;
+using namespace std;
+
+namespace {
+
+static oslFileHandle g_aFile = 0;
+static sal_Bool g_bHasBeenCalled = sal_False;
+static const sal_Int32 g_BUFFERSIZE = 4096;
+static sal_Char *g_buffer = 0;
+
+class LoggerGuard
+{
+public:
+ ~LoggerGuard();
+};
+
+LoggerGuard::~LoggerGuard()
+{
+ if( g_buffer )
+ {
+ sal_Int64 nWritten, nConverted =
+ sprintf( g_buffer, "closing log file at %06" SAL_PRIuUINT32, osl_getGlobalTimer() );
+ if( nConverted > 0 )
+ osl_writeFile( g_aFile, g_buffer, nConverted, (sal_uInt64 *)&nWritten );
+ osl_closeFile( g_aFile );
+ g_aFile = 0;
+
+ rtl_freeMemory( g_buffer );
+ g_buffer = 0;
+ g_bHasBeenCalled = sal_False;
+ }
+}
+
+// The destructor of this static LoggerGuard is "activated" by the assignment to
+// g_buffer in init():
+LoggerGuard loggerGuard;
+
+Mutex & getLogMutex()
+{
+ static Mutex *pMutex = 0;
+ if( !pMutex )
+ {
+ MutexGuard guard( Mutex::getGlobalMutex() );
+ if( ! pMutex )
+ {
+ static Mutex mutex;
+ pMutex = &mutex;
+ }
+ }
+ return *pMutex;
+}
+
+OUString getFileUrl( const OUString &name )
+{
+ OUString aRet;
+ if ( osl_getFileURLFromSystemPath( name.pData, &aRet.pData )
+ != osl_File_E_None )
+ {
+ OSL_ASSERT( false );
+ }
+
+ OUString aWorkingDirectory;
+ osl_getProcessWorkingDir( &(aWorkingDirectory.pData) );
+ osl_getAbsoluteFileURL( aWorkingDirectory.pData, aRet.pData, &(aRet.pData) );
+
+ return aRet;
+}
+
+void init() {
+ if( !g_bHasBeenCalled )
+ {
+ MutexGuard guard( getLogMutex() );
+ if( ! g_bHasBeenCalled )
+ {
+ OUString name( RTL_CONSTASCII_USTRINGPARAM( "RTL_LOGFILE" ) );
+ OUString value;
+ if( rtl_bootstrap_get( name.pData, &value.pData, 0 ) )
+ {
+ // Obtain process id.
+ oslProcessIdentifier aProcessId = 0;
+ oslProcessInfo info;
+ info.Size = sizeof (oslProcessInfo);
+ if (osl_getProcessInfo (0, osl_Process_IDENTIFIER, &info) == osl_Process_E_None)
+ aProcessId = info.Ident;
+
+ // Construct name of log file and open the file.
+ OUStringBuffer buf( 128 );
+ buf.append( value );
+
+ // if the filename ends with .nopid, the incoming filename is not modified
+ if( value.getLength() < 6 /* ".nopid" */ ||
+ rtl_ustr_ascii_compare_WithLength(
+ value.getStr() + (value.getLength()-6) , 6 , ".nopid" ) )
+ {
+ buf.appendAscii( "_" );
+ buf.append( (sal_Int32) aProcessId );
+ buf.appendAscii( ".log" );
+ }
+
+ OUString o = getFileUrl( buf.makeStringAndClear() );
+ oslFileError e = osl_openFile(
+ o.pData, &g_aFile, osl_File_OpenFlag_Write|osl_File_OpenFlag_Create);
+
+ if( osl_File_E_None == e )
+ {
+ TimeValue aCurrentTime;
+ g_buffer = ( sal_Char * ) rtl_allocateMemory( g_BUFFERSIZE );
+ sal_Int64 nConverted = 0;
+ if (osl_getSystemTime (&aCurrentTime))
+ {
+ nConverted = (sal_Int64 ) sprintf (
+ g_buffer,
+ "opening log file %f seconds past January 1st 1970\n"
+ "corresponding to %" SAL_PRIuUINT32 " ms after timer start\n",
+ aCurrentTime.Seconds + 1e-9 * aCurrentTime.Nanosec,
+ osl_getGlobalTimer());
+
+ if( nConverted > 0 )
+ {
+ sal_Int64 nWritten;
+ osl_writeFile( g_aFile, g_buffer, nConverted , (sal_uInt64 *)&nWritten );
+ }
+ }
+
+ nConverted = sprintf (g_buffer, "Process id is %" SAL_PRIuUINT32 "\n", aProcessId);
+ if( nConverted )
+ {
+ sal_Int64 nWritten;
+ osl_writeFile( g_aFile, g_buffer, nConverted, (sal_uInt64 *)&nWritten );
+ }
+ }
+ else
+ {
+ OSL_TRACE( "Couldn't open logfile %s(%d)" , o.getStr(), e );
+ }
+ }
+ g_bHasBeenCalled = sal_True;
+ }
+ }
+}
+
+}
+
+extern "C" void SAL_CALL rtl_logfile_trace ( const char *pszFormat, ... )
+{
+ init();
+ if( g_buffer )
+ {
+ va_list args;
+ va_start(args, pszFormat);
+ {
+ sal_Int64 nConverted, nWritten;
+ MutexGuard guard( getLogMutex() );
+ nConverted = vsnprintf( g_buffer , g_BUFFERSIZE, pszFormat, args );
+ nConverted = (nConverted > g_BUFFERSIZE ? g_BUFFERSIZE : nConverted );
+ if( nConverted > 0 )
+ osl_writeFile( g_aFile, g_buffer, nConverted, (sal_uInt64*)&nWritten );
+ }
+ va_end(args);
+ }
+}
+
+extern "C" void SAL_CALL rtl_logfile_longTrace(char const * format, ...) {
+ init();
+ if (g_buffer != 0) {
+ sal_uInt32 time = osl_getGlobalTimer();
+ oslThreadIdentifier threadId = osl_getThreadIdentifier(0);
+ va_list args;
+ va_start(args, format);
+ {
+ MutexGuard g(getLogMutex());
+ int n1 = snprintf(
+ g_buffer, g_BUFFERSIZE, "%06" SAL_PRIuUINT32 " %" SAL_PRIuUINT32 " ", time, threadId);
+ if (n1 >= 0) {
+ sal_uInt64 n2;
+ osl_writeFile(
+ g_aFile, g_buffer,
+ static_cast< sal_uInt64 >(
+ std::min(n1, static_cast< int >(g_BUFFERSIZE))),
+ &n2);
+ n1 = vsnprintf(g_buffer, g_BUFFERSIZE, format, args);
+ if (n1 > 0) {
+ osl_writeFile(
+ g_aFile, g_buffer,
+ static_cast< sal_uInt64 >(
+ std::min(n1, static_cast< int >(g_BUFFERSIZE))),
+ &n2);
+ }
+ }
+ }
+ va_end(args);
+ }
+}
+
+extern "C" sal_Bool SAL_CALL rtl_logfile_hasLogFile( void ) {
+ init();
+ return g_buffer != 0;
+}
diff --git a/sal/rtl/source/macro.hxx b/sal/rtl/source/macro.hxx
new file mode 100644
index 000000000000..3fa0fbe58f42
--- /dev/null
+++ b/sal/rtl/source/macro.hxx
@@ -0,0 +1,110 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _RTL_MACRO_HXX
+#define _RTL_MACRO_HXX
+
+#include <rtl/bootstrap.h>
+#include <rtl/ustring.hxx>
+#include <osl/endian.h>
+
+#if defined WIN32
+#define THIS_OS "Windows"
+#elif defined OS2
+#define THIS_OS "OS2"
+#elif defined SOLARIS
+#define THIS_OS "Solaris"
+#elif defined LINUX
+#ifdef __FreeBSD_kernel__
+#define THIS_OS "kFreeBSD"
+#else
+#define THIS_OS "Linux"
+#endif
+#elif defined MACOSX
+#define THIS_OS "MacOSX"
+#elif defined NETBSD
+#define THIS_OS "NetBSD"
+#elif defined FREEBSD
+#define THIS_OS "FreeBSD"
+#endif
+
+#if ! defined THIS_OS
+#error "unknown OS -- insert your OS identifier above"
+this is inserted for the case that the preprocessor ignores error
+#endif
+
+#if defined X86_64
+# define THIS_ARCH "X86_64"
+#elif defined INTEL
+# define THIS_ARCH "x86"
+#elif defined POWERPC64
+# define THIS_ARCH "PowerPC_64"
+#elif defined POWERPC
+# define THIS_ARCH "PowerPC"
+#elif defined S390X
+# define THIS_ARCH "S390x"
+#elif defined S390
+# define THIS_ARCH "S390"
+#elif defined SPARC
+#if defined IS_LP64
+# define THIS_ARCH "SPARC64"
+#else
+# define THIS_ARCH "SPARC"
+#endif
+#elif defined MIPS
+# ifdef OSL_BIGENDIAN
+# define THIS_ARCH "MIPS_EB"
+# else
+# define THIS_ARCH "MIPS_EL"
+# endif
+#elif defined ARM
+# ifdef __ARM_EABI__
+# define THIS_ARCH "ARM_EABI"
+# else
+# define THIS_ARCH "ARM_OABI"
+# endif
+#elif defined IA64
+# define THIS_ARCH "IA64"
+#elif defined M68K
+# define THIS_ARCH "M68K"
+#elif defined HPPA
+# define THIS_ARCH "HPPA"
+#elif defined AXP
+# define THIS_ARCH "ALPHA"
+#endif
+
+#if ! defined THIS_ARCH
+#error "unknown ARCH -- insert your ARCH identifier above"
+this is inserted for the case that the preprocessor ignores error
+#endif
+
+#endif
+
+
+
+
+
diff --git a/sal/rtl/source/makefile.mk b/sal/rtl/source/makefile.mk
new file mode 100644
index 000000000000..9968d8992be4
--- /dev/null
+++ b/sal/rtl/source/makefile.mk
@@ -0,0 +1,198 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=sal
+TARGET=cpprtl
+ENABLE_EXCEPTIONS=TRUE
+USE_LDUMP2=TRUE
+
+PROJECTPCH4DLL=TRUE
+PROJECTPCH=cont_pch
+PROJECTPCHSOURCE=cont_pch
+
+.IF "$(GUI)" == "OS2"
+STL_OS2_BUILDING=1
+.ENDIF
+
+TARGETTYPE=CUI
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+.IF "$(ALLOC)" == "SYS_ALLOC" || "$(ALLOC)" == "TCMALLOC" || "$(ALLOC)" == "JEMALLOC"
+CDEFS+= -DFORCE_SYSALLOC
+.ENDIF
+
+CFLAGS+= $(LFS_CFLAGS)
+CXXFLAGS+= $(LFS_CFLAGS)
+
+# --- Files --------------------------------------------------------
+
+# safe that way: gen_makefile doesn't want it,
+# no other link target here
+UWINAPILIB:=
+
+.IF "$(header)" == ""
+
+ALWAYSDBGFILES=$(SLO)$/debugprint.obj
+
+.IF "$(ALWAYSDBGFILES)" != ""
+ALWAYSDBGTARGET=do_it_alwaysdebug
+.ENDIF
+
+SLOFILES= \
+ $(SLO)$/memory.obj \
+ $(SLO)$/cipher.obj \
+ $(SLO)$/crc.obj \
+ $(SLO)$/digest.obj \
+ $(SLO)$/random.obj \
+ $(SLO)$/locale.obj \
+ $(SLO)$/strimp.obj \
+ $(SLO)$/hash.obj \
+ $(SLO)$/string.obj \
+ $(SLO)$/ustring.obj \
+ $(SLO)$/strbuf.obj \
+ $(SLO)$/ustrbuf.obj \
+ $(SLO)$/uuid.obj \
+ $(SLO)$/rtl_process.obj \
+ $(SLO)$/byteseq.obj \
+ $(SLO)$/uri.obj \
+ $(SLO)$/bootstrap.obj \
+ $(SLO)$/cmdargs.obj \
+ $(SLO)$/unload.obj \
+ $(SLO)$/logfile.obj \
+ $(SLO)$/tres.obj \
+ $(SLO)$/debugprint.obj \
+ $(SLO)$/math.obj \
+ $(SLO)$/alloc_global.obj\
+ $(SLO)$/alloc_cache.obj \
+ $(SLO)$/alloc_arena.obj
+
+.IF "$(OS)"=="MACOSX"
+SLOFILES+=$(SLO)$/memory_fini.obj
+.ENDIF
+
+
+#.IF "$(UPDATER)"=="YES"
+OBJFILES= \
+ $(OBJ)$/memory.obj \
+ $(OBJ)$/cipher.obj \
+ $(OBJ)$/crc.obj \
+ $(OBJ)$/digest.obj \
+ $(OBJ)$/random.obj \
+ $(OBJ)$/locale.obj \
+ $(OBJ)$/strimp.obj \
+ $(OBJ)$/hash.obj \
+ $(OBJ)$/string.obj \
+ $(OBJ)$/ustring.obj \
+ $(OBJ)$/strbuf.obj \
+ $(OBJ)$/ustrbuf.obj \
+ $(OBJ)$/uuid.obj \
+ $(OBJ)$/rtl_process.obj \
+ $(OBJ)$/byteseq.obj \
+ $(OBJ)$/uri.obj \
+ $(OBJ)$/bootstrap.obj \
+ $(OBJ)$/cmdargs.obj \
+ $(OBJ)$/unload.obj \
+ $(OBJ)$/logfile.obj \
+ $(OBJ)$/tres.obj \
+ $(OBJ)$/math.obj \
+ $(OBJ)$/alloc_global.obj\
+ $(OBJ)$/alloc_cache.obj \
+ $(OBJ)$/alloc_arena.obj
+
+.IF "$(OS)"=="MACOSX"
+OBJFILES+=$(OBJ)$/memory_fini.obj
+.ENDIF
+
+
+APP1TARGET=gen_makefile
+APP1OBJS=$(SLO)$/gen_makefile.obj
+APP1LIBSALCPPRT=
+APP1RPATH=NONE
+
+# --- Extra objs ----------------------------------------------------
+
+.IF "$(OS)"=="LINUX" || "$(OS)"=="OS2"
+
+#
+# This part builds a second version of alloc.c, with
+# FORCE_SYSALLOC defined. Is later used in util/makefile.mk
+# to build a tiny replacement lib to LD_PRELOAD into the
+# office, enabling e.g. proper valgrinding.
+#
+
+SECOND_BUILD=SYSALLOC
+SYSALLOC_SLOFILES= $(SLO)$/alloc_global.obj
+SYSALLOCCDEFS+=-DFORCE_SYSALLOC
+
+.ENDIF # .IF "$(OS)"=="LINUX"
+
+#.ENDIF
+
+.ENDIF
+
+# --- Makefile snippet --------------------------------------------
+
+# used by e.g. update info file
+BOOTSTRAPMK = $(OUT)$/inc$/rtlbootstrap.mk
+
+# --- Targets ------------------------------------------------------
+
+.IF "$(ALWAYSDBG_FLAG)"==""
+TARGETDEPS+=$(ALWAYSDBGTARGET)
+.ENDIF
+
+.INCLUDE : target.mk
+
+.IF "$(ALWAYSDBGTARGET)" != ""
+.IF "$(ALWAYSDBG_FLAG)" == ""
+# --------------------------------------------------
+# - ALWAYSDBG - files always compiled with debugging
+# --------------------------------------------------
+$(ALWAYSDBGTARGET):
+ @echo --- ALWAYSDBGFILES ---
+ @dmake $(MFLAGS) $(MAKEFILE) debug=true $(ALWAYSDBGFILES) ALWAYSDBG_FLAG=TRUE $(CALLMACROS)
+ @echo --- ALWAYSDBGFILES OVER ---
+
+$(ALWAYSDBGFILES):
+ @echo --- ALWAYSDBG ---
+ @dmake $(MFLAGS) $(MAKEFILE) debug=true ALWAYSDBG_FLAG=TRUE $(CALLMACROS) $@
+ @echo --- ALWAYSDBG OVER ---
+
+.ENDIF
+.ENDIF
+
+
+ALLTAR : $(BOOTSTRAPMK)
+
+$(BOOTSTRAPMK) : $(APP1TARGETN)
+ $(AUGMENT_LIBRARY_PATH) $< > $@
+
diff --git a/sal/rtl/source/math.cxx b/sal/rtl/source/math.cxx
new file mode 100644
index 000000000000..34b940a301c9
--- /dev/null
+++ b/sal/rtl/source/math.cxx
@@ -0,0 +1,1265 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+
+#include "rtl/math.h"
+
+#include "osl/diagnose.h"
+#include "rtl/alloc.h"
+#include "rtl/math.hxx"
+#include "rtl/strbuf.h"
+#include "rtl/string.h"
+#include "rtl/ustrbuf.h"
+#include "rtl/ustring.h"
+#include "sal/mathconf.h"
+#include "sal/types.h"
+
+#include <algorithm>
+#include <float.h>
+#include <limits.h>
+#include <math.h>
+#include <stdlib.h>
+
+
+static int const n10Count = 16;
+static double const n10s[2][n10Count] = {
+ { 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8,
+ 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16 },
+ { 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, 1e-8,
+ 1e-9, 1e-10, 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 1e-16 }
+};
+
+// return pow(10.0,nExp) optimized for exponents in the interval [-16,16]
+static double getN10Exp( int nExp )
+{
+ if ( nExp < 0 )
+ {
+ if ( -nExp <= n10Count )
+ return n10s[1][-nExp-1];
+ else
+ return pow( 10.0, static_cast<double>( nExp ) );
+ }
+ else if ( nExp > 0 )
+ {
+ if ( nExp <= n10Count )
+ return n10s[0][nExp-1];
+ else
+ return pow( 10.0, static_cast<double>( nExp ) );
+ }
+ else // ( nExp == 0 )
+ return 1.0;
+}
+
+/** Approximation algorithm for erf for 0 < x < 0.65. */
+void lcl_Erf0065( double x, double& fVal )
+{
+ static const double pn[] = {
+ 1.12837916709551256,
+ 1.35894887627277916E-1,
+ 4.03259488531795274E-2,
+ 1.20339380863079457E-3,
+ 6.49254556481904354E-5
+ };
+ static const double qn[] = {
+ 1.00000000000000000,
+ 4.53767041780002545E-1,
+ 8.69936222615385890E-2,
+ 8.49717371168693357E-3,
+ 3.64915280629351082E-4
+ };
+ double fPSum = 0.0;
+ double fQSum = 0.0;
+ double fXPow = 1.0;
+ for ( unsigned int i = 0; i <= 4; ++i )
+ {
+ fPSum += pn[i]*fXPow;
+ fQSum += qn[i]*fXPow;
+ fXPow *= x*x;
+ }
+ fVal = x * fPSum / fQSum;
+}
+
+/** Approximation algorithm for erfc for 0.65 < x < 6.0. */
+void lcl_Erfc0600( double x, double& fVal )
+{
+ double fPSum = 0.0;
+ double fQSum = 0.0;
+ double fXPow = 1.0;
+ const double *pn;
+ const double *qn;
+
+ if ( x < 2.2 )
+ {
+ static const double pn22[] = {
+ 9.99999992049799098E-1,
+ 1.33154163936765307,
+ 8.78115804155881782E-1,
+ 3.31899559578213215E-1,
+ 7.14193832506776067E-2,
+ 7.06940843763253131E-3
+ };
+ static const double qn22[] = {
+ 1.00000000000000000,
+ 2.45992070144245533,
+ 2.65383972869775752,
+ 1.61876655543871376,
+ 5.94651311286481502E-1,
+ 1.26579413030177940E-1,
+ 1.25304936549413393E-2
+ };
+ pn = pn22;
+ qn = qn22;
+ }
+ else /* if ( x < 6.0 ) this is true, but the compiler does not know */
+ {
+ static const double pn60[] = {
+ 9.99921140009714409E-1,
+ 1.62356584489366647,
+ 1.26739901455873222,
+ 5.81528574177741135E-1,
+ 1.57289620742838702E-1,
+ 2.25716982919217555E-2
+ };
+ static const double qn60[] = {
+ 1.00000000000000000,
+ 2.75143870676376208,
+ 3.37367334657284535,
+ 2.38574194785344389,
+ 1.05074004614827206,
+ 2.78788439273628983E-1,
+ 4.00072964526861362E-2
+ };
+ pn = pn60;
+ qn = qn60;
+ }
+
+ for ( unsigned int i = 0; i < 6; ++i )
+ {
+ fPSum += pn[i]*fXPow;
+ fQSum += qn[i]*fXPow;
+ fXPow *= x;
+ }
+ fQSum += qn[6]*fXPow;
+ fVal = exp( -1.0*x*x )* fPSum / fQSum;
+}
+
+/** Approximation algorithm for erfc for 6.0 < x < 26.54 (but used for all
+ x > 6.0). */
+void lcl_Erfc2654( double x, double& fVal )
+{
+ static const double pn[] = {
+ 5.64189583547756078E-1,
+ 8.80253746105525775,
+ 3.84683103716117320E1,
+ 4.77209965874436377E1,
+ 8.08040729052301677
+ };
+ static const double qn[] = {
+ 1.00000000000000000,
+ 1.61020914205869003E1,
+ 7.54843505665954743E1,
+ 1.12123870801026015E2,
+ 3.73997570145040850E1
+ };
+
+ double fPSum = 0.0;
+ double fQSum = 0.0;
+ double fXPow = 1.0;
+
+ for ( unsigned int i = 0; i <= 4; ++i )
+ {
+ fPSum += pn[i]*fXPow;
+ fQSum += qn[i]*fXPow;
+ fXPow /= x*x;
+ }
+ fVal = exp(-1.0*x*x)*fPSum / (x*fQSum);
+}
+
+namespace {
+
+double const nKorrVal[] = {
+ 0, 9e-1, 9e-2, 9e-3, 9e-4, 9e-5, 9e-6, 9e-7, 9e-8,
+ 9e-9, 9e-10, 9e-11, 9e-12, 9e-13, 9e-14, 9e-15
+};
+
+struct StringTraits
+{
+ typedef sal_Char Char;
+
+ typedef rtl_String String;
+
+ static inline void createString(rtl_String ** pString,
+ sal_Char const * pChars, sal_Int32 nLen)
+ {
+ rtl_string_newFromStr_WithLength(pString, pChars, nLen);
+ }
+
+ static inline void createBuffer(rtl_String ** pBuffer,
+ sal_Int32 * pCapacity)
+ {
+ rtl_string_new_WithLength(pBuffer, *pCapacity);
+ }
+
+ static inline void appendChar(rtl_String ** pBuffer, sal_Int32 * pCapacity,
+ sal_Int32 * pOffset, sal_Char cChar)
+ {
+ rtl_stringbuffer_insert(pBuffer, pCapacity, *pOffset, &cChar, 1);
+ ++*pOffset;
+ }
+
+ static inline void appendChars(rtl_String ** pBuffer, sal_Int32 * pCapacity,
+ sal_Int32 * pOffset, sal_Char const * pChars,
+ sal_Int32 nLen)
+ {
+ rtl_stringbuffer_insert(pBuffer, pCapacity, *pOffset, pChars, nLen);
+ *pOffset += nLen;
+ }
+
+ static inline void appendAscii(rtl_String ** pBuffer, sal_Int32 * pCapacity,
+ sal_Int32 * pOffset, sal_Char const * pStr,
+ sal_Int32 nLen)
+ {
+ rtl_stringbuffer_insert(pBuffer, pCapacity, *pOffset, pStr, nLen);
+ *pOffset += nLen;
+ }
+};
+
+struct UStringTraits
+{
+ typedef sal_Unicode Char;
+
+ typedef rtl_uString String;
+
+ static inline void createString(rtl_uString ** pString,
+ sal_Unicode const * pChars, sal_Int32 nLen)
+ {
+ rtl_uString_newFromStr_WithLength(pString, pChars, nLen);
+ }
+
+ static inline void createBuffer(rtl_uString ** pBuffer,
+ sal_Int32 * pCapacity)
+ {
+ rtl_uString_new_WithLength(pBuffer, *pCapacity);
+ }
+
+ static inline void appendChar(rtl_uString ** pBuffer, sal_Int32 * pCapacity,
+ sal_Int32 * pOffset, sal_Unicode cChar)
+ {
+ rtl_uStringbuffer_insert(pBuffer, pCapacity, *pOffset, &cChar, 1);
+ ++*pOffset;
+ }
+
+ static inline void appendChars(rtl_uString ** pBuffer,
+ sal_Int32 * pCapacity, sal_Int32 * pOffset,
+ sal_Unicode const * pChars, sal_Int32 nLen)
+ {
+ rtl_uStringbuffer_insert(pBuffer, pCapacity, *pOffset, pChars, nLen);
+ *pOffset += nLen;
+ }
+
+ static inline void appendAscii(rtl_uString ** pBuffer,
+ sal_Int32 * pCapacity, sal_Int32 * pOffset,
+ sal_Char const * pStr, sal_Int32 nLen)
+ {
+ rtl_uStringbuffer_insert_ascii(pBuffer, pCapacity, *pOffset, pStr,
+ nLen);
+ *pOffset += nLen;
+ }
+};
+
+
+// Solaris C++ 5.2 compiler has problems when "StringT ** pResult" is
+// "typename T::String ** pResult" instead:
+template< typename T, typename StringT >
+inline void doubleToString(StringT ** pResult,
+ sal_Int32 * pResultCapacity, sal_Int32 nResultOffset,
+ double fValue, rtl_math_StringFormat eFormat,
+ sal_Int32 nDecPlaces, typename T::Char cDecSeparator,
+ sal_Int32 const * pGroups,
+ typename T::Char cGroupSeparator,
+ bool bEraseTrailingDecZeros)
+{
+ static double const nRoundVal[] = {
+ 5.0e+0, 0.5e+0, 0.5e-1, 0.5e-2, 0.5e-3, 0.5e-4, 0.5e-5, 0.5e-6,
+ 0.5e-7, 0.5e-8, 0.5e-9, 0.5e-10,0.5e-11,0.5e-12,0.5e-13,0.5e-14
+ };
+
+ // sign adjustment, instead of testing for fValue<0.0 this will also fetch
+ // -0.0
+ bool bSign = rtl::math::isSignBitSet( fValue );
+ if( bSign )
+ fValue = -fValue;
+
+ if ( rtl::math::isNan( fValue ) )
+ {
+ // #i112652# XMLSchema-2
+ sal_Int32 nCapacity = RTL_CONSTASCII_LENGTH("NaN");
+ if (pResultCapacity == 0)
+ {
+ pResultCapacity = &nCapacity;
+ T::createBuffer(pResult, pResultCapacity);
+ nResultOffset = 0;
+ }
+ T::appendAscii(pResult, pResultCapacity, &nResultOffset,
+ RTL_CONSTASCII_STRINGPARAM("NaN"));
+
+ return;
+ }
+
+ bool bHuge = fValue == HUGE_VAL; // g++ 3.0.1 requires it this way...
+ if ( bHuge || rtl::math::isInf( fValue ) )
+ {
+ // #i112652# XMLSchema-2
+ sal_Int32 nCapacity = RTL_CONSTASCII_LENGTH("-INF");
+ if (pResultCapacity == 0)
+ {
+ pResultCapacity = &nCapacity;
+ T::createBuffer(pResult, pResultCapacity);
+ nResultOffset = 0;
+ }
+ if ( bSign )
+ T::appendAscii(pResult, pResultCapacity, &nResultOffset,
+ RTL_CONSTASCII_STRINGPARAM("-"));
+ T::appendAscii(pResult, pResultCapacity, &nResultOffset,
+ RTL_CONSTASCII_STRINGPARAM("INF"));
+
+ return;
+ }
+
+ // find the exponent
+ int nExp = 0;
+ if ( fValue > 0.0 )
+ {
+ nExp = static_cast< int >( floor( log10( fValue ) ) );
+ fValue /= getN10Exp( nExp );
+ }
+
+ switch ( eFormat )
+ {
+ case rtl_math_StringFormat_Automatic :
+ { // E or F depending on exponent magnitude
+ int nPrec;
+ if ( nExp <= -15 || nExp >= 15 ) // #58531# was <-16, >16
+ {
+ nPrec = 14;
+ eFormat = rtl_math_StringFormat_E;
+ }
+ else
+ {
+ if ( nExp < 14 )
+ {
+ nPrec = 15 - nExp - 1;
+ eFormat = rtl_math_StringFormat_F;
+ }
+ else
+ {
+ nPrec = 15;
+ eFormat = rtl_math_StringFormat_F;
+ }
+ }
+ if ( nDecPlaces == rtl_math_DecimalPlaces_Max )
+ nDecPlaces = nPrec;
+ }
+ break;
+ case rtl_math_StringFormat_G :
+ { // G-Point, similar to sprintf %G
+ if ( nDecPlaces == rtl_math_DecimalPlaces_DefaultSignificance )
+ nDecPlaces = 6;
+ if ( nExp < -4 || nExp >= nDecPlaces )
+ {
+ nDecPlaces = std::max< sal_Int32 >( 1, nDecPlaces - 1 );
+ eFormat = rtl_math_StringFormat_E;
+ }
+ else
+ {
+ nDecPlaces = std::max< sal_Int32 >( 0, nDecPlaces - nExp - 1 );
+ eFormat = rtl_math_StringFormat_F;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ sal_Int32 nDigits = nDecPlaces + 1;
+
+ if( eFormat == rtl_math_StringFormat_F )
+ nDigits += nExp;
+
+ // Round the number
+ if( nDigits >= 0 )
+ {
+ if( ( fValue += nRoundVal[ nDigits > 15 ? 15 : nDigits ] ) >= 10 )
+ {
+ fValue = 1.0;
+ nExp++;
+ if( eFormat == rtl_math_StringFormat_F )
+ nDigits++;
+ }
+ }
+
+ static sal_Int32 const nBufMax = 256;
+ typename T::Char aBuf[nBufMax];
+ typename T::Char * pBuf;
+ sal_Int32 nBuf = static_cast< sal_Int32 >
+ ( nDigits <= 0 ? std::max< sal_Int32 >( nDecPlaces, abs(nExp) )
+ : nDigits + nDecPlaces ) + 10 + (pGroups ? abs(nDigits) * 2 : 0);
+ if ( nBuf > nBufMax )
+ {
+ pBuf = reinterpret_cast< typename T::Char * >(
+ rtl_allocateMemory(nBuf * sizeof (typename T::Char)));
+ OSL_ENSURE(pBuf != 0, "Out of memory");
+ }
+ else
+ pBuf = aBuf;
+ typename T::Char * p = pBuf;
+ if ( bSign )
+ *p++ = static_cast< typename T::Char >('-');
+
+ bool bHasDec = false;
+
+ int nDecPos;
+ // Check for F format and number < 1
+ if( eFormat == rtl_math_StringFormat_F )
+ {
+ if( nExp < 0 )
+ {
+ *p++ = static_cast< typename T::Char >('0');
+ if ( nDecPlaces > 0 )
+ {
+ *p++ = cDecSeparator;
+ bHasDec = true;
+ }
+ sal_Int32 i = ( nDigits <= 0 ? nDecPlaces : -nExp - 1 );
+ while( (i--) > 0 )
+ *p++ = static_cast< typename T::Char >('0');
+ nDecPos = 0;
+ }
+ else
+ nDecPos = nExp + 1;
+ }
+ else
+ nDecPos = 1;
+
+ int nGrouping = 0, nGroupSelector = 0, nGroupExceed = 0;
+ if ( nDecPos > 1 && pGroups && pGroups[0] && cGroupSeparator )
+ {
+ while ( nGrouping + pGroups[nGroupSelector] < nDecPos )
+ {
+ nGrouping += pGroups[ nGroupSelector ];
+ if ( pGroups[nGroupSelector+1] )
+ {
+ if ( nGrouping + pGroups[nGroupSelector+1] >= nDecPos )
+ break; // while
+ ++nGroupSelector;
+ }
+ else if ( !nGroupExceed )
+ nGroupExceed = nGrouping;
+ }
+ }
+
+ // print the number
+ if( nDigits > 0 )
+ {
+ for ( int i = 0; ; i++ )
+ {
+ if( i < 15 )
+ {
+ int nDigit;
+ if (nDigits-1 == 0 && i > 0 && i < 14)
+ nDigit = static_cast< int >( floor( fValue
+ + nKorrVal[15-i] ) );
+ else
+ nDigit = static_cast< int >( fValue + 1E-15 );
+ if (nDigit >= 10)
+ { // after-treatment of up-rounding to the next decade
+ sal_Int32 sLen = static_cast< long >(p-pBuf)-1;
+ if (sLen == -1)
+ {
+ p = pBuf;
+ if ( eFormat == rtl_math_StringFormat_F )
+ {
+ *p++ = static_cast< typename T::Char >('1');
+ *p++ = static_cast< typename T::Char >('0');
+ }
+ else
+ {
+ *p++ = static_cast< typename T::Char >('1');
+ *p++ = cDecSeparator;
+ *p++ = static_cast< typename T::Char >('0');
+ nExp++;
+ bHasDec = true;
+ }
+ }
+ else
+ {
+ for (sal_Int32 j = sLen; j >= 0; j--)
+ {
+ typename T::Char cS = pBuf[j];
+ if (cS != cDecSeparator)
+ {
+ if ( cS != static_cast< typename T::Char >('9'))
+ {
+ pBuf[j] = ++cS;
+ j = -1; // break loop
+ }
+ else
+ {
+ pBuf[j]
+ = static_cast< typename T::Char >('0');
+ if (j == 0)
+ {
+ if ( eFormat == rtl_math_StringFormat_F)
+ { // insert '1'
+ typename T::Char * px = p++;
+ while ( pBuf < px )
+ {
+ *px = *(px-1);
+ px--;
+ }
+ pBuf[0] = static_cast<
+ typename T::Char >('1');
+ }
+ else
+ {
+ pBuf[j] = static_cast<
+ typename T::Char >('1');
+ nExp++;
+ }
+ }
+ }
+ }
+ }
+ *p++ = static_cast< typename T::Char >('0');
+ }
+ fValue = 0.0;
+ }
+ else
+ {
+ *p++ = static_cast< typename T::Char >(
+ nDigit + static_cast< typename T::Char >('0') );
+ fValue = ( fValue - nDigit ) * 10.0;
+ }
+ }
+ else
+ *p++ = static_cast< typename T::Char >('0');
+ if( !--nDigits )
+ break; // for
+ if( nDecPos )
+ {
+ if( !--nDecPos )
+ {
+ *p++ = cDecSeparator;
+ bHasDec = true;
+ }
+ else if ( nDecPos == nGrouping )
+ {
+ *p++ = cGroupSeparator;
+ nGrouping -= pGroups[ nGroupSelector ];
+ if ( nGroupSelector && nGrouping < nGroupExceed )
+ --nGroupSelector;
+ }
+ }
+ }
+ }
+
+ if ( !bHasDec && eFormat == rtl_math_StringFormat_F )
+ { // nDecPlaces < 0 did round the value
+ while ( --nDecPos > 0 )
+ { // fill before decimal point
+ if ( nDecPos == nGrouping )
+ {
+ *p++ = cGroupSeparator;
+ nGrouping -= pGroups[ nGroupSelector ];
+ if ( nGroupSelector && nGrouping < nGroupExceed )
+ --nGroupSelector;
+ }
+ *p++ = static_cast< typename T::Char >('0');
+ }
+ }
+
+ if ( bEraseTrailingDecZeros && bHasDec && p > pBuf )
+ {
+ while ( *(p-1) == static_cast< typename T::Char >('0') )
+ p--;
+ if ( *(p-1) == cDecSeparator )
+ p--;
+ }
+
+ // Print the exponent ('E', followed by '+' or '-', followed by exactly
+ // three digits). The code in rtl_[u]str_valueOf{Float|Double} relies on
+ // this format.
+ if( eFormat == rtl_math_StringFormat_E )
+ {
+ if ( p == pBuf )
+ *p++ = static_cast< typename T::Char >('1');
+ // maybe no nDigits if nDecPlaces < 0
+ *p++ = static_cast< typename T::Char >('E');
+ if( nExp < 0 )
+ {
+ nExp = -nExp;
+ *p++ = static_cast< typename T::Char >('-');
+ }
+ else
+ *p++ = static_cast< typename T::Char >('+');
+// if (nExp >= 100 )
+ *p++ = static_cast< typename T::Char >(
+ nExp / 100 + static_cast< typename T::Char >('0') );
+ nExp %= 100;
+ *p++ = static_cast< typename T::Char >(
+ nExp / 10 + static_cast< typename T::Char >('0') );
+ *p++ = static_cast< typename T::Char >(
+ nExp % 10 + static_cast< typename T::Char >('0') );
+ }
+
+ if (pResultCapacity == 0)
+ T::createString(pResult, pBuf, p - pBuf);
+ else
+ T::appendChars(pResult, pResultCapacity, &nResultOffset, pBuf,
+ p - pBuf);
+
+ if ( pBuf != &aBuf[0] )
+ rtl_freeMemory(pBuf);
+}
+
+}
+
+void SAL_CALL rtl_math_doubleToString(rtl_String ** pResult,
+ sal_Int32 * pResultCapacity,
+ sal_Int32 nResultOffset, double fValue,
+ rtl_math_StringFormat eFormat,
+ sal_Int32 nDecPlaces,
+ sal_Char cDecSeparator,
+ sal_Int32 const * pGroups,
+ sal_Char cGroupSeparator,
+ sal_Bool bEraseTrailingDecZeros)
+ SAL_THROW_EXTERN_C()
+{
+ doubleToString< StringTraits, StringTraits::String >(
+ pResult, pResultCapacity, nResultOffset, fValue, eFormat, nDecPlaces,
+ cDecSeparator, pGroups, cGroupSeparator, bEraseTrailingDecZeros);
+}
+
+void SAL_CALL rtl_math_doubleToUString(rtl_uString ** pResult,
+ sal_Int32 * pResultCapacity,
+ sal_Int32 nResultOffset, double fValue,
+ rtl_math_StringFormat eFormat,
+ sal_Int32 nDecPlaces,
+ sal_Unicode cDecSeparator,
+ sal_Int32 const * pGroups,
+ sal_Unicode cGroupSeparator,
+ sal_Bool bEraseTrailingDecZeros)
+ SAL_THROW_EXTERN_C()
+{
+ doubleToString< UStringTraits, UStringTraits::String >(
+ pResult, pResultCapacity, nResultOffset, fValue, eFormat, nDecPlaces,
+ cDecSeparator, pGroups, cGroupSeparator, bEraseTrailingDecZeros);
+}
+
+
+namespace {
+
+// if nExp * 10 + nAdd would result in overflow
+inline bool long10Overflow( long& nExp, int nAdd )
+{
+ if ( nExp > (LONG_MAX/10)
+ || (nExp == (LONG_MAX/10) && nAdd > (LONG_MAX%10)) )
+ {
+ nExp = LONG_MAX;
+ return true;
+ }
+ return false;
+}
+
+// We are only concerned about ASCII arabic numerical digits here
+template< typename CharT >
+inline bool isDigit( CharT c )
+{
+ return 0x30 <= c && c <= 0x39;
+}
+
+template< typename CharT >
+inline double stringToDouble(CharT const * pBegin, CharT const * pEnd,
+ CharT cDecSeparator, CharT cGroupSeparator,
+ rtl_math_ConversionStatus * pStatus,
+ CharT const ** pParsedEnd)
+{
+ double fVal = 0.0;
+ rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok;
+
+ CharT const * p0 = pBegin;
+ while (p0 != pEnd && (*p0 == CharT(' ') || *p0 == CharT('\t')))
+ ++p0;
+ bool bSign;
+ if (p0 != pEnd && *p0 == CharT('-'))
+ {
+ bSign = true;
+ ++p0;
+ }
+ else
+ {
+ bSign = false;
+ if (p0 != pEnd && *p0 == CharT('+'))
+ ++p0;
+ }
+ CharT const * p = p0;
+ bool bDone = false;
+
+ // #i112652# XMLSchema-2
+ if (3 >= (pEnd - p))
+ {
+ if ((CharT('N') == p[0]) && (CharT('a') == p[1])
+ && (CharT('N') == p[2]))
+ {
+ p += 3;
+ rtl::math::setNan( &fVal );
+ bDone = true;
+ }
+ else if ((CharT('I') == p[0]) && (CharT('N') == p[1])
+ && (CharT('F') == p[2]))
+ {
+ p += 3;
+ fVal = HUGE_VAL;
+ eStatus = rtl_math_ConversionStatus_OutOfRange;
+ bDone = true;
+ }
+ }
+
+ if (!bDone) // do not recognize e.g. NaN1.23
+ {
+ // leading zeros and group separators may be safely ignored
+ while (p != pEnd && (*p == CharT('0') || *p == cGroupSeparator))
+ ++p;
+
+ long nValExp = 0; // carry along exponent of mantissa
+
+ // integer part of mantissa
+ for (; p != pEnd; ++p)
+ {
+ CharT c = *p;
+ if (isDigit(c))
+ {
+ fVal = fVal * 10.0 + static_cast< double >( c - CharT('0') );
+ ++nValExp;
+ }
+ else if (c != cGroupSeparator)
+ break;
+ }
+
+ // fraction part of mantissa
+ if (p != pEnd && *p == cDecSeparator)
+ {
+ ++p;
+ double fFrac = 0.0;
+ long nFracExp = 0;
+ while (p != pEnd && *p == CharT('0'))
+ {
+ --nFracExp;
+ ++p;
+ }
+ if ( nValExp == 0 )
+ nValExp = nFracExp - 1; // no integer part => fraction exponent
+ // one decimal digit needs ld(10) ~= 3.32 bits
+ static const int nSigs = (DBL_MANT_DIG / 3) + 1;
+ int nDigs = 0;
+ for (; p != pEnd; ++p)
+ {
+ CharT c = *p;
+ if (!isDigit(c))
+ break;
+ if ( nDigs < nSigs )
+ { // further digits (more than nSigs) don't have any
+ // significance
+ fFrac = fFrac * 10.0 + static_cast<double>(c - CharT('0'));
+ --nFracExp;
+ ++nDigs;
+ }
+ }
+ if ( fFrac != 0.0 )
+ fVal += rtl::math::pow10Exp( fFrac, nFracExp );
+ else if ( nValExp < 0 )
+ nValExp = 0; // no digit other than 0 after decimal point
+ }
+
+ if ( nValExp > 0 )
+ --nValExp; // started with offset +1 at the first mantissa digit
+
+ // Exponent
+ if (p != p0 && p != pEnd && (*p == CharT('E') || *p == CharT('e')))
+ {
+ ++p;
+ bool bExpSign;
+ if (p != pEnd && *p == CharT('-'))
+ {
+ bExpSign = true;
+ ++p;
+ }
+ else
+ {
+ bExpSign = false;
+ if (p != pEnd && *p == CharT('+'))
+ ++p;
+ }
+ if ( fVal == 0.0 )
+ { // no matter what follows, zero stays zero, but carry on the
+ // offset
+ while (p != pEnd && isDigit(*p))
+ ++p;
+ }
+ else
+ {
+ bool bOverFlow = false;
+ long nExp = 0;
+ for (; p != pEnd; ++p)
+ {
+ CharT c = *p;
+ if (!isDigit(c))
+ break;
+ int i = c - CharT('0');
+ if ( long10Overflow( nExp, i ) )
+ bOverFlow = true;
+ else
+ nExp = nExp * 10 + i;
+ }
+ if ( nExp )
+ {
+ if ( bExpSign )
+ nExp = -nExp;
+ long nAllExp = ( bOverFlow ? 0 : nExp + nValExp );
+ if ( nAllExp > DBL_MAX_10_EXP || (bOverFlow && !bExpSign) )
+ { // overflow
+ fVal = HUGE_VAL;
+ eStatus = rtl_math_ConversionStatus_OutOfRange;
+ }
+ else if ((nAllExp < DBL_MIN_10_EXP) ||
+ (bOverFlow && bExpSign) )
+ { // underflow
+ fVal = 0.0;
+ eStatus = rtl_math_ConversionStatus_OutOfRange;
+ }
+ else if ( nExp > DBL_MAX_10_EXP || nExp < DBL_MIN_10_EXP )
+ { // compensate exponents
+ fVal = rtl::math::pow10Exp( fVal, -nValExp );
+ fVal = rtl::math::pow10Exp( fVal, nAllExp );
+ }
+ else
+ fVal = rtl::math::pow10Exp( fVal, nExp ); // normal
+ }
+ }
+ }
+ else if (p - p0 == 2 && p != pEnd && p[0] == CharT('#')
+ && p[-1] == cDecSeparator && p[-2] == CharT('1'))
+ {
+ if (pEnd - p >= 4 && p[1] == CharT('I') && p[2] == CharT('N')
+ && p[3] == CharT('F'))
+ {
+ // "1.#INF", "+1.#INF", "-1.#INF"
+ p += 4;
+ fVal = HUGE_VAL;
+ eStatus = rtl_math_ConversionStatus_OutOfRange;
+ // Eat any further digits:
+ while (p != pEnd && isDigit(*p))
+ ++p;
+ }
+ else if (pEnd - p >= 4 && p[1] == CharT('N') && p[2] == CharT('A')
+ && p[3] == CharT('N'))
+ {
+ // "1.#NAN", "+1.#NAN", "-1.#NAN"
+ p += 4;
+ rtl::math::setNan( &fVal );
+ if (bSign)
+ {
+ union {
+ double sd;
+ sal_math_Double md;
+ } m;
+ m.sd = fVal;
+ m.md.w32_parts.msw |= 0x80000000; // create negative NaN
+ fVal = m.sd;
+ bSign = false; // don't negate again
+ }
+ // Eat any further digits:
+ while (p != pEnd && isDigit(*p))
+ ++p;
+ }
+ }
+ }
+
+ // overflow also if more than DBL_MAX_10_EXP digits without decimal
+ // separator, or 0. and more than DBL_MIN_10_EXP digits, ...
+ bool bHuge = fVal == HUGE_VAL; // g++ 3.0.1 requires it this way...
+ if ( bHuge )
+ eStatus = rtl_math_ConversionStatus_OutOfRange;
+
+ if ( bSign )
+ fVal = -fVal;
+
+ if (pStatus != 0)
+ *pStatus = eStatus;
+ if (pParsedEnd != 0)
+ *pParsedEnd = p == p0 ? pBegin : p;
+
+ return fVal;
+}
+
+}
+
+double SAL_CALL rtl_math_stringToDouble(sal_Char const * pBegin,
+ sal_Char const * pEnd,
+ sal_Char cDecSeparator,
+ sal_Char cGroupSeparator,
+ rtl_math_ConversionStatus * pStatus,
+ sal_Char const ** pParsedEnd)
+ SAL_THROW_EXTERN_C()
+{
+ return stringToDouble(pBegin, pEnd, cDecSeparator, cGroupSeparator, pStatus,
+ pParsedEnd);
+}
+
+double SAL_CALL rtl_math_uStringToDouble(sal_Unicode const * pBegin,
+ sal_Unicode const * pEnd,
+ sal_Unicode cDecSeparator,
+ sal_Unicode cGroupSeparator,
+ rtl_math_ConversionStatus * pStatus,
+ sal_Unicode const ** pParsedEnd)
+ SAL_THROW_EXTERN_C()
+{
+ return stringToDouble(pBegin, pEnd, cDecSeparator, cGroupSeparator, pStatus,
+ pParsedEnd);
+}
+
+double SAL_CALL rtl_math_round(double fValue, int nDecPlaces,
+ enum rtl_math_RoundingMode eMode)
+ SAL_THROW_EXTERN_C()
+{
+ OSL_ASSERT(nDecPlaces >= -20 && nDecPlaces <= 20);
+
+ if ( fValue == 0.0 )
+ return fValue;
+
+ // sign adjustment
+ bool bSign = rtl::math::isSignBitSet( fValue );
+ if ( bSign )
+ fValue = -fValue;
+
+ double fFac = 0;
+ if ( nDecPlaces != 0 )
+ {
+ // max 20 decimals, we don't have unlimited precision
+ // #38810# and no overflow on fValue*=fFac
+ if ( nDecPlaces < -20 || 20 < nDecPlaces || fValue > (DBL_MAX / 1e20) )
+ return bSign ? -fValue : fValue;
+
+ fFac = getN10Exp( nDecPlaces );
+ fValue *= fFac;
+ }
+ //else //! uninitialized fFac, not needed
+
+ switch ( eMode )
+ {
+ case rtl_math_RoundingMode_Corrected :
+ {
+ int nExp; // exponent for correction
+ if ( fValue > 0.0 )
+ nExp = static_cast<int>( floor( log10( fValue ) ) );
+ else
+ nExp = 0;
+ int nIndex = 15 - nExp;
+ if ( nIndex > 15 )
+ nIndex = 15;
+ else if ( nIndex <= 1 )
+ nIndex = 0;
+ fValue = floor( fValue + 0.5 + nKorrVal[nIndex] );
+ }
+ break;
+ case rtl_math_RoundingMode_Down :
+ fValue = rtl::math::approxFloor( fValue );
+ break;
+ case rtl_math_RoundingMode_Up :
+ fValue = rtl::math::approxCeil( fValue );
+ break;
+ case rtl_math_RoundingMode_Floor :
+ fValue = bSign ? rtl::math::approxCeil( fValue )
+ : rtl::math::approxFloor( fValue );
+ break;
+ case rtl_math_RoundingMode_Ceiling :
+ fValue = bSign ? rtl::math::approxFloor( fValue )
+ : rtl::math::approxCeil( fValue );
+ break;
+ case rtl_math_RoundingMode_HalfDown :
+ {
+ double f = floor( fValue );
+ fValue = ((fValue - f) <= 0.5) ? f : ceil( fValue );
+ }
+ break;
+ case rtl_math_RoundingMode_HalfUp :
+ {
+ double f = floor( fValue );
+ fValue = ((fValue - f) < 0.5) ? f : ceil( fValue );
+ }
+ break;
+ case rtl_math_RoundingMode_HalfEven :
+#if defined FLT_ROUNDS
+/*
+ Use fast version. FLT_ROUNDS may be defined to a function by some compilers!
+
+ DBL_EPSILON is the smallest fractional number which can be represented,
+ its reciprocal is therefore the smallest number that cannot have a
+ fractional part. Once you add this reciprocal to `x', its fractional part
+ is stripped off. Simply subtracting the reciprocal back out returns `x'
+ without its fractional component.
+ Simple, clever, and elegant - thanks to Ross Cottrell, the original author,
+ who placed it into public domain.
+
+ volatile: prevent compiler from being too smart
+*/
+ if ( FLT_ROUNDS == 1 )
+ {
+ volatile double x = fValue + 1.0 / DBL_EPSILON;
+ fValue = x - 1.0 / DBL_EPSILON;
+ }
+ else
+#endif // FLT_ROUNDS
+ {
+ double f = floor( fValue );
+ if ( (fValue - f) != 0.5 )
+ fValue = floor( fValue + 0.5 );
+ else
+ {
+ double g = f / 2.0;
+ fValue = (g == floor( g )) ? f : (f + 1.0);
+ }
+ }
+ break;
+ default:
+ OSL_ASSERT(false);
+ break;
+ }
+
+ if ( nDecPlaces != 0 )
+ fValue /= fFac;
+
+ return bSign ? -fValue : fValue;
+}
+
+
+double SAL_CALL rtl_math_pow10Exp(double fValue, int nExp) SAL_THROW_EXTERN_C()
+{
+ return fValue * getN10Exp( nExp );
+}
+
+
+double SAL_CALL rtl_math_approxValue( double fValue ) SAL_THROW_EXTERN_C()
+{
+ if (fValue == 0.0 || fValue == HUGE_VAL || !::rtl::math::isFinite( fValue))
+ // We don't handle these conditions. Bail out.
+ return fValue;
+
+ double fOrigValue = fValue;
+
+ bool bSign = ::rtl::math::isSignBitSet( fValue);
+ if (bSign)
+ fValue = -fValue;
+
+ int nExp = static_cast<int>( floor( log10( fValue)));
+ nExp = 14 - nExp;
+ double fExpValue = getN10Exp( nExp);
+
+ fValue *= fExpValue;
+ // If the original value was near DBL_MIN we got an overflow. Restore and
+ // bail out.
+ if (!rtl::math::isFinite( fValue))
+ return fOrigValue;
+ fValue = rtl_math_round( fValue, 0, rtl_math_RoundingMode_Corrected);
+ fValue /= fExpValue;
+ // If the original value was near DBL_MAX we got an overflow. Restore and
+ // bail out.
+ if (!rtl::math::isFinite( fValue))
+ return fOrigValue;
+
+ return bSign ? -fValue : fValue;
+}
+
+
+double SAL_CALL rtl_math_expm1( double fValue ) SAL_THROW_EXTERN_C()
+{
+ double fe = exp( fValue );
+ if (fe == 1.0)
+ return fValue;
+ if (fe-1.0 == -1.0)
+ return -1.0;
+ return (fe-1.0) * fValue / log(fe);
+}
+
+
+double SAL_CALL rtl_math_log1p( double fValue ) SAL_THROW_EXTERN_C()
+{
+ // Use volatile because a compiler may be too smart "optimizing" the
+ // condition such that in certain cases the else path was called even if
+ // (fp==1.0) was true, where the term (fp-1.0) then resulted in 0.0 and
+ // hence the entire expression resulted in NaN.
+ // Happened with g++ 3.4.1 and an input value of 9.87E-18
+ volatile double fp = 1.0 + fValue;
+ if (fp == 1.0)
+ return fValue;
+ else
+ return log(fp) * fValue / (fp-1.0);
+}
+
+
+double SAL_CALL rtl_math_atanh( double fValue ) SAL_THROW_EXTERN_C()
+{
+ return 0.5 * rtl_math_log1p( 2.0 * fValue / (1.0-fValue) );
+}
+
+
+/** Parent error function (erf) that calls different algorithms based on the
+ value of x. It takes care of cases where x is negative as erf is an odd
+ function i.e. erf(-x) = -erf(x).
+
+ Kramer, W., and Blomquist, F., 2000, Algorithms with Guaranteed Error Bounds
+ for the Error Function and the Complementary Error Function
+
+ http://www.math.uni-wuppertal.de/wrswt/literatur_en.html
+
+ @author Kohei Yoshida <kohei@openoffice.org>
+
+ @see #i55735#
+ */
+double SAL_CALL rtl_math_erf( double x ) SAL_THROW_EXTERN_C()
+{
+ if( x == 0.0 )
+ return 0.0;
+
+ bool bNegative = false;
+ if ( x < 0.0 )
+ {
+ x = fabs( x );
+ bNegative = true;
+ }
+
+ double fErf = 1.0;
+ if ( x < 1.0e-10 )
+ fErf = (double) (x*1.1283791670955125738961589031215452L);
+ else if ( x < 0.65 )
+ lcl_Erf0065( x, fErf );
+ else
+ fErf = 1.0 - rtl_math_erfc( x );
+
+ if ( bNegative )
+ fErf *= -1.0;
+
+ return fErf;
+}
+
+
+/** Parent complementary error function (erfc) that calls different algorithms
+ based on the value of x. It takes care of cases where x is negative as erfc
+ satisfies relationship erfc(-x) = 2 - erfc(x). See the comment for Erf(x)
+ for the source publication.
+
+ @author Kohei Yoshida <kohei@openoffice.org>
+
+ @see #i55735#, moved from module scaddins (#i97091#)
+
+ */
+double SAL_CALL rtl_math_erfc( double x ) SAL_THROW_EXTERN_C()
+{
+ if ( x == 0.0 )
+ return 1.0;
+
+ bool bNegative = false;
+ if ( x < 0.0 )
+ {
+ x = fabs( x );
+ bNegative = true;
+ }
+
+ double fErfc = 0.0;
+ if ( x >= 0.65 )
+ {
+ if ( x < 6.0 )
+ lcl_Erfc0600( x, fErfc );
+ else
+ lcl_Erfc2654( x, fErfc );
+ }
+ else
+ fErfc = 1.0 - rtl_math_erf( x );
+
+ if ( bNegative )
+ fErfc = 2.0 - fErfc;
+
+ return fErfc;
+}
+
+/** improved accuracy of asinh for |x| large and for x near zero
+ @see #i97605#
+ */
+double SAL_CALL rtl_math_asinh( double fX ) SAL_THROW_EXTERN_C()
+{
+ double fSign = 1.0;
+ if ( fX == 0.0 )
+ return 0.0;
+ else
+ {
+ if ( fX < 0.0 )
+ {
+ fX = - fX;
+ fSign = -1.0;
+ }
+ if ( fX < 0.125 )
+ return fSign * rtl_math_log1p( fX + fX*fX / (1.0 + sqrt( 1.0 + fX*fX)));
+ else if ( fX < 1.25e7 )
+ return fSign * log( fX + sqrt( 1.0 + fX*fX));
+ else
+ return fSign * log( 2.0*fX);
+ }
+}
+
+/** improved accuracy of acosh for x large and for x near 1
+ @see #i97605#
+ */
+double SAL_CALL rtl_math_acosh( double fX ) SAL_THROW_EXTERN_C()
+{
+ volatile double fZ = fX - 1.0;
+ if ( fX < 1.0 )
+ {
+ double fResult;
+ ::rtl::math::setNan( &fResult );
+ return fResult;
+ }
+ else if ( fX == 1.0 )
+ return 0.0;
+ else if ( fX < 1.1 )
+ return rtl_math_log1p( fZ + sqrt( fZ*fZ + 2.0*fZ));
+ else if ( fX < 1.25e7 )
+ return log( fX + sqrt( fX*fX - 1.0));
+ else
+ return log( 2.0*fX);
+}
diff --git a/sal/rtl/source/memory.c b/sal/rtl/source/memory.c
new file mode 100644
index 000000000000..a92d4201bd32
--- /dev/null
+++ b/sal/rtl/source/memory.c
@@ -0,0 +1,62 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+#include <string.h>
+#include <rtl/memory.h>
+
+void SAL_CALL rtl_zeroMemory(void *Ptr, sal_Size Bytes)
+{
+ memset(Ptr, 0, Bytes);
+}
+
+void SAL_CALL rtl_fillMemory(void *Ptr, sal_Size Bytes, sal_uInt8 Fill)
+{
+ memset(Ptr, Fill, Bytes);
+}
+
+void SAL_CALL rtl_copyMemory(void *Dst, const void *Src, sal_Size Bytes)
+{
+ memcpy(Dst, Src, Bytes);
+}
+
+void SAL_CALL rtl_moveMemory(void *Dst, const void *Src, sal_Size Bytes)
+{
+ memmove(Dst, Src, Bytes);
+}
+
+sal_Int32 SAL_CALL rtl_compareMemory(const void *MemA, const void *MemB, sal_Size Bytes)
+{
+ return memcmp(MemA, MemB, Bytes);
+}
+
+void* SAL_CALL rtl_findInMemory(const void *MemA, sal_uInt8 ch, sal_Size Bytes)
+{
+ return memchr(MemA, ch, Bytes);
+}
+
+
diff --git a/sal/rtl/source/memory_fini.cxx b/sal/rtl/source/memory_fini.cxx
new file mode 100755
index 000000000000..f88f09887595
--- /dev/null
+++ b/sal/rtl/source/memory_fini.cxx
@@ -0,0 +1,54 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+/*
+ Issue http://udk.openoffice.org/issues/show_bug.cgi?id=92388
+
+ Mac OS X does not seem to support "__cxa__atexit", thus leading
+ to the situation that "__attribute__((destructor))__" functions
+ (in particular "rtl_memory_fini") become called _before_ global
+ C++ object d'tors.
+
+ Using a C++ dummy object instead.
+*/
+
+#include <stdio.h>
+
+extern "C" void rtl_memory_fini (void);
+
+
+struct RTL_Memory_Fini {
+ ~RTL_Memory_Fini() ;
+};
+
+RTL_Memory_Fini::~RTL_Memory_Fini() {
+ rtl_memory_fini();
+}
+
+
+static RTL_Memory_Fini rtl_Memory_Fini;
diff --git a/sal/rtl/source/random.c b/sal/rtl/source/random.c
new file mode 100644
index 000000000000..3ee911942684
--- /dev/null
+++ b/sal/rtl/source/random.c
@@ -0,0 +1,338 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#define _RTL_RANDOM_C_ "$Revision: 1.6 $"
+
+#include <sal/types.h>
+#include <osl/thread.h>
+#include <osl/time.h>
+#include <rtl/alloc.h>
+#include <rtl/digest.h>
+#include <rtl/random.h>
+#include <osl/time.h>
+
+/*========================================================================
+ *
+ * rtlRandom internals.
+ *
+ *======================================================================*/
+#define RTL_RANDOM_RNG_1(a) ((a) * 16807L)
+#define RTL_RANDOM_RNG_2(a) ((a) * 65539L)
+
+#define RTL_RANDOM_RNG(x, y, z) \
+{ \
+ (x) = 170 * ((x) % 178) - 63 * ((x) / 178); \
+ if ((x) < 0) (x) += 30328L; \
+ \
+ (y) = 171 * ((y) % 177) - 2 * ((y) / 177); \
+ if ((y) < 0) (y) += 30269L; \
+ \
+ (z) = 172 * ((z) % 176) - 35 * ((z) / 176); \
+ if ((z) < 0) (z) += 30307L; \
+}
+
+/** RandomData_Impl.
+ */
+typedef struct random_data_impl_st
+{
+ sal_Int16 m_nX;
+ sal_Int16 m_nY;
+ sal_Int16 m_nZ;
+} RandomData_Impl;
+
+/** __rtl_random_data.
+ */
+static double __rtl_random_data (RandomData_Impl *pImpl);
+
+/** RandomPool_Impl.
+ */
+#define RTL_RANDOM_DIGEST rtl_Digest_AlgorithmMD5
+#define RTL_RANDOM_SIZE_DIGEST RTL_DIGEST_LENGTH_MD5
+#define RTL_RANDOM_SIZE_POOL 1023
+
+typedef struct random_pool_impl_st
+{
+ rtlDigest m_hDigest;
+ sal_uInt8 m_pDigest[RTL_RANDOM_SIZE_DIGEST];
+ sal_uInt8 m_pData[RTL_RANDOM_SIZE_POOL + 1];
+ sal_uInt32 m_nData;
+ sal_uInt32 m_nIndex;
+ sal_uInt32 m_nCount;
+} RandomPool_Impl;
+
+/** __rtl_random_initPool.
+ */
+static sal_Bool __rtl_random_initPool (
+ RandomPool_Impl *pImpl);
+
+/** __rtl_random_seedPool.
+ */
+static void __rtl_random_seedPool (
+ RandomPool_Impl *pImpl, const sal_uInt8 *pBuffer, sal_Size nBufLen);
+
+/** __rtl_random_readPool.
+ */
+static void __rtl_random_readPool (
+ RandomPool_Impl *pImpl, sal_uInt8 *pBuffer, sal_Size nBufLen);
+
+/*
+ * __rtl_random_data.
+ */
+static double __rtl_random_data (RandomData_Impl *pImpl)
+{
+ register double random;
+
+ RTL_RANDOM_RNG (pImpl->m_nX, pImpl->m_nY, pImpl->m_nZ);
+ random = (((double)(pImpl->m_nX) / 30328.0) +
+ ((double)(pImpl->m_nY) / 30269.0) +
+ ((double)(pImpl->m_nZ) / 30307.0) );
+
+ random -= ((double)((sal_uInt32)(random)));
+ return (random);
+}
+
+/*
+ * __rtl_random_initPool.
+ */
+static sal_Bool __rtl_random_initPool (RandomPool_Impl *pImpl)
+{
+ pImpl->m_hDigest = rtl_digest_create (RTL_RANDOM_DIGEST);
+ if (pImpl->m_hDigest)
+ {
+ oslThreadIdentifier id;
+ TimeValue tv;
+ RandomData_Impl rd;
+ double seed;
+
+ /* The use of uninitialized stack variables as a way to
+ * enhance the entropy of the random pool triggers
+ * memory checkers like purify and valgrind.
+ */
+
+ /*
+ __rtl_random_seedPool (pImpl, (sal_uInt8*)&id, sizeof(id));
+ __rtl_random_seedPool (pImpl, (sal_uInt8*)&tv, sizeof(tv));
+ __rtl_random_seedPool (pImpl, (sal_uInt8*)&rd, sizeof(rd));
+ */
+
+ id = osl_getThreadIdentifier (NULL);
+ id = RTL_RANDOM_RNG_2(RTL_RANDOM_RNG_1(id));
+ __rtl_random_seedPool (pImpl, (sal_uInt8*)&id, sizeof(id));
+
+ osl_getSystemTime (&tv);
+ tv.Seconds = RTL_RANDOM_RNG_2(tv.Seconds);
+ tv.Nanosec = RTL_RANDOM_RNG_2(tv.Nanosec);
+ __rtl_random_seedPool (pImpl, (sal_uInt8*)&tv, sizeof(tv));
+
+ rd.m_nX = (sal_Int16)(((id >> 1) << 1) + 1);
+ rd.m_nY = (sal_Int16)(((tv.Seconds >> 1) << 1) + 1);
+ rd.m_nZ = (sal_Int16)(((tv.Nanosec >> 1) << 1) + 1);
+ __rtl_random_seedPool (pImpl, (sal_uInt8*)&rd, sizeof(rd));
+
+ while (pImpl->m_nData < RTL_RANDOM_SIZE_POOL)
+ {
+ seed = __rtl_random_data (&rd);
+ __rtl_random_seedPool (pImpl, (sal_uInt8*)&seed, sizeof(seed));
+ }
+ return sal_True;
+ }
+ return sal_False;
+}
+
+/*
+ * __rtl_random_seedPool.
+ */
+static void __rtl_random_seedPool (
+ RandomPool_Impl *pImpl, const sal_uInt8 *pBuffer, sal_Size nBufLen)
+{
+ sal_Size i;
+ sal_sSize j, k;
+
+ for (i = 0; i < nBufLen; i += RTL_RANDOM_SIZE_DIGEST)
+ {
+ j = nBufLen - i;
+ if (j > RTL_RANDOM_SIZE_DIGEST)
+ j = RTL_RANDOM_SIZE_DIGEST;
+
+ rtl_digest_update (
+ pImpl->m_hDigest, pImpl->m_pDigest, RTL_RANDOM_SIZE_DIGEST);
+
+ k = (pImpl->m_nIndex + j) - RTL_RANDOM_SIZE_POOL;
+ if (k > 0)
+ {
+ rtl_digest_update (
+ pImpl->m_hDigest, &(pImpl->m_pData[pImpl->m_nIndex]), j - k);
+ rtl_digest_update (
+ pImpl->m_hDigest, &(pImpl->m_pData[0]), k);
+ }
+ else
+ {
+ rtl_digest_update (
+ pImpl->m_hDigest, &(pImpl->m_pData[pImpl->m_nIndex]), j);
+ }
+
+ rtl_digest_update (pImpl->m_hDigest, pBuffer, j);
+ pBuffer += j;
+
+ rtl_digest_get (
+ pImpl->m_hDigest, pImpl->m_pDigest, RTL_RANDOM_SIZE_DIGEST);
+ for (k = 0; k < j; k++)
+ {
+ pImpl->m_pData[pImpl->m_nIndex++] ^= pImpl->m_pDigest[k];
+ if (pImpl->m_nIndex >= RTL_RANDOM_SIZE_POOL)
+ {
+ pImpl->m_nData = RTL_RANDOM_SIZE_POOL;
+ pImpl->m_nIndex = 0;
+ }
+ }
+ }
+
+ if (pImpl->m_nIndex > pImpl->m_nData)
+ pImpl->m_nData = pImpl->m_nIndex;
+}
+
+/*
+ * __rtl_random_readPool.
+ */
+static void __rtl_random_readPool (
+ RandomPool_Impl *pImpl, sal_uInt8 *pBuffer, sal_Size nBufLen)
+{
+ sal_Int32 j, k;
+
+ while (nBufLen > 0)
+ {
+ j = nBufLen;
+ if (j > RTL_RANDOM_SIZE_DIGEST/2)
+ j = RTL_RANDOM_SIZE_DIGEST/2;
+ nBufLen -= j;
+
+ rtl_digest_update (
+ pImpl->m_hDigest,
+ &(pImpl->m_pDigest[RTL_RANDOM_SIZE_DIGEST/2]),
+ RTL_RANDOM_SIZE_DIGEST/2);
+
+ k = (pImpl->m_nIndex + j) - pImpl->m_nData;
+ if (k > 0)
+ {
+ rtl_digest_update (
+ pImpl->m_hDigest, &(pImpl->m_pData[pImpl->m_nIndex]), j - k);
+ rtl_digest_update (
+ pImpl->m_hDigest, &(pImpl->m_pData[0]), k);
+ }
+ else
+ {
+ rtl_digest_update (
+ pImpl->m_hDigest, &(pImpl->m_pData[pImpl->m_nIndex]), j);
+ }
+
+ rtl_digest_get (
+ pImpl->m_hDigest, pImpl->m_pDigest, RTL_RANDOM_SIZE_DIGEST);
+ for (k = 0; k < j; k++)
+ {
+ if (pImpl->m_nIndex >= pImpl->m_nData) pImpl->m_nIndex = 0;
+ pImpl->m_pData[pImpl->m_nIndex++] ^= pImpl->m_pDigest[k];
+ *pBuffer++ = pImpl->m_pDigest[k + RTL_RANDOM_SIZE_DIGEST/2];
+ }
+ }
+
+ pImpl->m_nCount++;
+ rtl_digest_update (
+ pImpl->m_hDigest, &(pImpl->m_nCount), sizeof(pImpl->m_nCount));
+ rtl_digest_update (
+ pImpl->m_hDigest, pImpl->m_pDigest, RTL_RANDOM_SIZE_DIGEST);
+ rtl_digest_get (
+ pImpl->m_hDigest, pImpl->m_pDigest, RTL_RANDOM_SIZE_DIGEST);
+}
+
+/*========================================================================
+ *
+ * rtlRandom implementation.
+ *
+ *======================================================================*/
+/*
+ * rtl_random_createPool.
+ */
+rtlRandomPool SAL_CALL rtl_random_createPool (void)
+{
+ RandomPool_Impl *pImpl = (RandomPool_Impl*)NULL;
+ pImpl = (RandomPool_Impl*)rtl_allocateZeroMemory (sizeof(RandomPool_Impl));
+ if (pImpl)
+ {
+ if (!__rtl_random_initPool (pImpl))
+ {
+ rtl_freeZeroMemory (pImpl, sizeof(RandomPool_Impl));
+ pImpl = (RandomPool_Impl*)NULL;
+ }
+ }
+ return ((rtlRandomPool)pImpl);
+}
+
+/*
+ * rtl_random_destroyPool.
+ */
+void SAL_CALL rtl_random_destroyPool (rtlRandomPool Pool)
+{
+ RandomPool_Impl *pImpl = (RandomPool_Impl *)Pool;
+ if (pImpl)
+ {
+ rtl_digest_destroy (pImpl->m_hDigest);
+ rtl_freeZeroMemory (pImpl, sizeof (RandomPool_Impl));
+ }
+}
+
+/*
+ * rtl_random_addBytes.
+ */
+rtlRandomError SAL_CALL rtl_random_addBytes (
+ rtlRandomPool Pool, const void *Buffer, sal_Size Bytes)
+{
+ RandomPool_Impl *pImpl = (RandomPool_Impl *)Pool;
+ const sal_uInt8 *pBuffer = (const sal_uInt8 *)Buffer;
+
+ if ((pImpl == NULL) || (pBuffer == NULL))
+ return rtl_Random_E_Argument;
+
+ __rtl_random_seedPool (pImpl, pBuffer, Bytes);
+ return rtl_Random_E_None;
+}
+
+/*
+ * rtl_random_getBytes.
+ */
+rtlRandomError SAL_CALL rtl_random_getBytes (
+ rtlRandomPool Pool, void *Buffer, sal_Size Bytes)
+{
+ RandomPool_Impl *pImpl = (RandomPool_Impl *)Pool;
+ sal_uInt8 *pBuffer = (sal_uInt8 *)Buffer;
+
+ if ((pImpl == NULL) || (pBuffer == NULL))
+ return rtl_Random_E_Argument;
+
+ __rtl_random_readPool (pImpl, pBuffer, Bytes);
+ return rtl_Random_E_None;
+}
+
diff --git a/sal/rtl/source/rtl_process.c b/sal/rtl/source/rtl_process.c
new file mode 100644
index 000000000000..d70c92c17cee
--- /dev/null
+++ b/sal/rtl/source/rtl_process.c
@@ -0,0 +1,49 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#include <string.h>
+#include <osl/mutex.h>
+#include <rtl/uuid.h>
+
+/* rtl_getCommandArg, rtl_getCommandArgCount see cmdargs.cxx */
+
+void SAL_CALL rtl_getGlobalProcessId( sal_uInt8 *pTargetUUID )
+{
+ static sal_uInt8 *pUuid = 0;
+ if( ! pUuid )
+ {
+ osl_acquireMutex( * osl_getGlobalMutex() );
+ if( ! pUuid )
+ {
+ static sal_uInt8 aUuid[16];
+ rtl_createUuid( aUuid , 0 , sal_False );
+ pUuid = aUuid;
+ }
+ osl_releaseMutex( * osl_getGlobalMutex() );
+ }
+ memcpy( pTargetUUID , pUuid , 16 );
+}
+
diff --git a/sal/rtl/source/strbuf.c b/sal/rtl/source/strbuf.c
new file mode 100644
index 000000000000..09dd83f8b32f
--- /dev/null
+++ b/sal/rtl/source/strbuf.c
@@ -0,0 +1,147 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <osl/interlck.h>
+
+#ifndef _RTL_STRING_HXX_
+#include <rtl/strbuf.hxx>
+#endif
+#include <rtl/memory.h>
+
+/*
+#include <rtl/alloc.h>
+*/
+
+
+
+/*************************************************************************
+ * rtl_stringbuffer_newFromStr_WithLength
+ */
+void SAL_CALL rtl_stringbuffer_newFromStr_WithLength( rtl_String ** newStr,
+ const sal_Char * value,
+ sal_Int32 count )
+{
+ if (!value)
+ {
+ rtl_string_new_WithLength( newStr, 16 );
+ return;
+ }
+
+ rtl_string_new_WithLength( newStr, count + 16 );
+ (*newStr)->length = count;
+ rtl_copyMemory( (*newStr)->buffer, value, count );
+ return;
+}
+
+/*************************************************************************
+ * rtl_stringbuffer_newFromStringBuffer
+ */
+sal_Int32 SAL_CALL rtl_stringbuffer_newFromStringBuffer( rtl_String ** newStr,
+ sal_Int32 capacity,
+ rtl_String * oldStr )
+{
+ sal_Int32 newCapacity = capacity;
+
+ if (newCapacity < oldStr->length)
+ newCapacity = oldStr->length;
+
+ rtl_string_new_WithLength( newStr, newCapacity );
+ if (oldStr->length > 0) {
+ (*newStr)->length = oldStr->length;
+ rtl_copyMemory( (*newStr)->buffer, oldStr->buffer, oldStr->length );
+ }
+ return newCapacity;
+}
+
+/*************************************************************************
+ * rtl_stringbuffer_ensureCapacity
+ */
+void SAL_CALL rtl_stringbuffer_ensureCapacity
+ (rtl_String ** This, sal_Int32* capacity, sal_Int32 minimumCapacity)
+{
+ if (minimumCapacity > *capacity)
+ {
+ rtl_String * pTmp = *This;
+ rtl_String * pNew = NULL;
+ *capacity = ((*This)->length + 1) * 2;
+ if (minimumCapacity > *capacity)
+ /* still lower, set to the minimum capacity */
+ *capacity = minimumCapacity;
+
+ rtl_string_new_WithLength(&pNew, *capacity);
+ pNew->length = (*This)->length;
+ *This = pNew;
+
+ rtl_copyMemory( (*This)->buffer, pTmp->buffer, pTmp->length );
+ rtl_string_release( pTmp );
+ }
+}
+
+/*************************************************************************
+ * rtl_stringbuffer_insert
+ */
+void SAL_CALL rtl_stringbuffer_insert( rtl_String ** This,
+ sal_Int32 * capacity,
+ sal_Int32 offset,
+ const sal_Char * str,
+ sal_Int32 len )
+{
+ sal_Int32 nOldLen;
+ sal_Char * pBuf;
+ sal_Int32 n;
+ if( len != 0 )
+ {
+ if (*capacity < (*This)->length + len)
+ rtl_stringbuffer_ensureCapacity( This, capacity, (*This)->length + len );
+
+ /*
+ if( len == 1 )
+ This->buffer
+ */
+ nOldLen = (*This)->length;
+ pBuf = (*This)->buffer;
+
+ /* copy the tail */
+ n = (nOldLen - offset);
+ if( n == 1 )
+ /* optimized for 1 character */
+ pBuf[offset + len] = pBuf[offset];
+ else if( n > 1 )
+ rtl_moveMemory( pBuf + offset + len, pBuf + offset, n * sizeof(sal_Char) );
+
+ /* insert the new characters */
+ n = len;
+ if( len == 1 )
+ /* optimized for 1 character */
+ pBuf[offset] = *str;
+ else if( n > 1 )
+ rtl_copyMemory( pBuf + offset, str, len * sizeof(sal_Char) );
+ (*This)->length = nOldLen + len;
+ pBuf[ nOldLen + len ] = 0;
+ }
+}
+
diff --git a/sal/rtl/source/strimp.c b/sal/rtl/source/strimp.c
new file mode 100644
index 000000000000..993969700a88
--- /dev/null
+++ b/sal/rtl/source/strimp.c
@@ -0,0 +1,58 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "strimp.h"
+
+sal_Int16 rtl_ImplGetDigit( sal_Unicode ch, sal_Int16 nRadix )
+{
+ sal_Int16 n = -1;
+ if ( (ch >= '0') && (ch <= '9') )
+ n = ch-'0';
+ else if ( (ch >= 'a') && (ch <= 'z') )
+ n = ch-'a'+10;
+ else if ( (ch >= 'A') && (ch <= 'Z') )
+ n = ch-'A'+10;
+ return (n < nRadix) ? n : -1;
+}
+
+sal_Bool rtl_ImplIsWhitespace( sal_Unicode c )
+{
+ /* Space or Control character? */
+ if ( (c <= 32) && c )
+ return sal_True;
+
+ /* Only in the General Punctuation area Space or Control characters are included? */
+ if ( (c < 0x2000) || (c > 0x206F) )
+ return sal_False;
+
+ if ( ((c >= 0x2000) && (c <= 0x200B)) || /* All Spaces */
+ (c == 0x2028) || /* LINE SEPARATOR */
+ (c == 0x2029) ) /* PARAGRAPH SEPARATOR */
+ return sal_True;
+
+ return sal_False;
+}
diff --git a/sal/rtl/source/strimp.h b/sal/rtl/source/strimp.h
new file mode 100644
index 000000000000..533b7087a652
--- /dev/null
+++ b/sal/rtl/source/strimp.h
@@ -0,0 +1,64 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_RTL_SOURCE_STRIMP_H
+#define INCLUDED_RTL_SOURCE_STRIMP_H
+
+#include <osl/interlck.h>
+
+#include "sal/types.h"
+
+/* ======================================================================= */
+/* Help functions for String and UString */
+/* ======================================================================= */
+
+#if defined __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * refCount is opaqueincludes 2 bit-fields;
+ * MSB: 'interned' - is stored in the intern hash
+ * MSB-1: 'static' - is a const / static string,
+ * do no ref counting
+ */
+#define SAL_STRING_INTERN_FLAG 0x80000000
+#define SAL_STRING_STATIC_FLAG 0x40000000
+#define SAL_STRING_REFCOUNT(a) ((a) & 0x3fffffff)
+
+#define SAL_STRING_IS_INTERN(a) ((a)->refCount & SAL_STRING_INTERN_FLAG)
+#define SAL_STRING_IS_STATIC(a) ((a)->refCount & SAL_STRING_STATIC_FLAG)
+
+sal_Int16 rtl_ImplGetDigit( sal_Unicode ch, sal_Int16 nRadix );
+
+sal_Bool rtl_ImplIsWhitespace( sal_Unicode c );
+
+#if defined __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* INCLUDED_RTL_SOURCE_STRIMP_H */
diff --git a/sal/rtl/source/string.c b/sal/rtl/source/string.c
new file mode 100644
index 000000000000..c0f9a33c218b
--- /dev/null
+++ b/sal/rtl/source/string.c
@@ -0,0 +1,320 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+#pragma warning(disable:4738) // storing 32-bit float result in memory, possible loss of performance
+#endif
+
+#include <rtl/memory.h>
+#include <osl/interlck.h>
+#include <rtl/alloc.h>
+#include <osl/diagnose.h>
+#include <rtl/tencinfo.h>
+
+#include "strimp.h"
+#include "surrogates.h"
+#include <rtl/string.h>
+
+#include "rtl/math.h"
+#include "rtl/tencinfo.h"
+
+/* ======================================================================= */
+
+/* static data to be referenced by all empty strings
+ * the refCount is predefined to 1 and must never become 0 !
+ */
+static rtl_String const aImplEmpty_rtl_String =
+{
+ SAL_STRING_STATIC_FLAG|1,
+ /* sal_Int32 refCount; */
+ 0, /* sal_Int32 length; */
+ { 0 } /* sal_Char buffer[1]; */
+};
+
+/* ======================================================================= */
+
+#define IMPL_RTL_STRCODE sal_Char
+#define IMPL_RTL_USTRCODE( c ) ((unsigned char)c)
+#define IMPL_RTL_STRNAME( n ) rtl_str_ ## n
+
+#define IMPL_RTL_STRINGNAME( n ) rtl_string_ ## n
+#define IMPL_RTL_STRINGDATA rtl_String
+#define IMPL_RTL_EMPTYSTRING aImplEmpty_rtl_String
+
+/* ======================================================================= */
+
+/* Include String/UString template code */
+
+#include "strtmpl.c"
+
+sal_Int32 SAL_CALL rtl_str_valueOfFloat(sal_Char * pStr, float f)
+{
+ rtl_String * pResult = NULL;
+ sal_Int32 nLen;
+ rtl_math_doubleToString(
+ &pResult, 0, 0, f, rtl_math_StringFormat_G,
+ RTL_STR_MAX_VALUEOFFLOAT - RTL_CONSTASCII_LENGTH("-x.E-xxx"), '.', 0, 0,
+ sal_True);
+ nLen = pResult->length;
+ OSL_ASSERT(nLen < RTL_STR_MAX_VALUEOFFLOAT);
+ rtl_copyMemory(pStr, pResult->buffer, (nLen + 1) * sizeof(sal_Char));
+ rtl_string_release(pResult);
+ return nLen;
+}
+
+sal_Int32 SAL_CALL rtl_str_valueOfDouble(sal_Char * pStr, double d)
+{
+ rtl_String * pResult = NULL;
+ sal_Int32 nLen;
+ rtl_math_doubleToString(
+ &pResult, 0, 0, d, rtl_math_StringFormat_G,
+ RTL_STR_MAX_VALUEOFDOUBLE - RTL_CONSTASCII_LENGTH("-x.E-xxx"), '.', 0,
+ 0, sal_True);
+ nLen = pResult->length;
+ OSL_ASSERT(nLen < RTL_STR_MAX_VALUEOFDOUBLE);
+ rtl_copyMemory(pStr, pResult->buffer, (nLen + 1) * sizeof(sal_Char));
+ rtl_string_release(pResult);
+ return nLen;
+}
+
+float SAL_CALL rtl_str_toFloat(sal_Char const * pStr)
+{
+ return (float) rtl_math_stringToDouble(pStr, pStr + rtl_str_getLength(pStr),
+ '.', 0, 0, 0);
+}
+
+double SAL_CALL rtl_str_toDouble(sal_Char const * pStr)
+{
+ return rtl_math_stringToDouble(pStr, pStr + rtl_str_getLength(pStr), '.', 0,
+ 0, 0);
+}
+
+/* ======================================================================= */
+
+static int rtl_ImplGetFastUTF8ByteLen( const sal_Unicode* pStr, sal_Int32 nLen )
+{
+ int n;
+ sal_Unicode c;
+ sal_uInt32 nUCS4Char;
+ const sal_Unicode* pEndStr;
+
+ n = 0;
+ pEndStr = pStr+nLen;
+ while ( pStr < pEndStr )
+ {
+ c = *pStr;
+
+ if ( c < 0x80 )
+ n++;
+ else if ( c < 0x800 )
+ n += 2;
+ else
+ {
+ if ( !SAL_RTL_IS_HIGH_SURROGATE(c) )
+ n += 3;
+ else
+ {
+ nUCS4Char = c;
+
+ if ( pStr+1 < pEndStr )
+ {
+ c = *(pStr+1);
+ if ( SAL_RTL_IS_LOW_SURROGATE(c) )
+ {
+ nUCS4Char = SAL_RTL_COMBINE_SURROGATES(nUCS4Char, c);
+ pStr++;
+ }
+ }
+
+ if ( nUCS4Char < 0x10000 )
+ n += 3;
+ else if ( nUCS4Char < 0x200000 )
+ n += 4;
+ else if ( nUCS4Char < 0x4000000 )
+ n += 5;
+ else
+ n += 6;
+ }
+ }
+
+ pStr++;
+ }
+
+ return n;
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Bool SAL_CALL rtl_impl_convertUStringToString(rtl_String ** pTarget,
+ sal_Unicode const * pSource,
+ sal_Int32 nLength,
+ rtl_TextEncoding nEncoding,
+ sal_uInt32 nFlags,
+ sal_Bool bCheckErrors)
+{
+ OSL_ASSERT(pTarget != NULL
+ && (pSource != NULL || nLength == 0)
+ && nLength >= 0
+ && rtl_isOctetTextEncoding(nEncoding));
+
+ if ( !nLength )
+ rtl_string_new( pTarget );
+ else
+ {
+ rtl_String* pTemp;
+ rtl_UnicodeToTextConverter hConverter;
+ sal_uInt32 nInfo;
+ sal_Size nSrcChars;
+ sal_Size nDestBytes;
+ sal_Size nNewLen;
+ sal_Size nNotConvertedChars;
+ sal_Size nMaxCharLen;
+
+ /* Optimization for UTF-8 - we try to calculate the exact length */
+ /* For all other encoding we try an good estimation */
+ if ( nEncoding == RTL_TEXTENCODING_UTF8 )
+ {
+ nNewLen = rtl_ImplGetFastUTF8ByteLen( pSource, nLength );
+ /* Includes the string only ASCII, then we could copy
+ the buffer faster */
+ if ( nNewLen == (sal_Size)nLength )
+ {
+ IMPL_RTL_STRCODE* pBuffer;
+ if ( *pTarget )
+ IMPL_RTL_STRINGNAME( release )( *pTarget );
+ *pTarget = IMPL_RTL_STRINGNAME( ImplAlloc )( nLength );
+ OSL_ASSERT(*pTarget != NULL);
+ pBuffer = (*pTarget)->buffer;
+ do
+ {
+ /* Check ASCII range */
+ OSL_ENSURE( *pSource <= 127,
+ "rtl_uString2String() - UTF8 test is encoding is wrong" );
+
+ *pBuffer = (IMPL_RTL_STRCODE)(unsigned char)*pSource;
+ pBuffer++;
+ pSource++;
+ nLength--;
+ }
+ while ( nLength );
+ return sal_True;
+ }
+
+ nMaxCharLen = 4;
+ }
+ else
+ {
+ rtl_TextEncodingInfo aTextEncInfo;
+ aTextEncInfo.StructSize = sizeof( aTextEncInfo );
+ if ( !rtl_getTextEncodingInfo( nEncoding, &aTextEncInfo ) )
+ {
+ aTextEncInfo.AverageCharSize = 1;
+ aTextEncInfo.MaximumCharSize = 8;
+ }
+
+ nNewLen = nLength*aTextEncInfo.AverageCharSize;
+ nMaxCharLen = aTextEncInfo.MaximumCharSize;
+ }
+
+ nFlags |= RTL_UNICODETOTEXT_FLAGS_FLUSH;
+ hConverter = rtl_createUnicodeToTextConverter( nEncoding );
+
+ for (;;)
+ {
+ pTemp = IMPL_RTL_STRINGNAME( ImplAlloc )( nNewLen );
+ OSL_ASSERT(pTemp != NULL);
+ nDestBytes = rtl_convertUnicodeToText( hConverter, 0,
+ pSource, nLength,
+ pTemp->buffer, nNewLen,
+ nFlags,
+ &nInfo, &nSrcChars );
+ if (bCheckErrors && (nInfo & RTL_UNICODETOTEXT_INFO_ERROR) != 0)
+ {
+ rtl_freeMemory(pTemp);
+ rtl_destroyUnicodeToTextConverter(hConverter);
+ return sal_False;
+ }
+
+ if ((nInfo & RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL) == 0)
+ break;
+
+ /* Buffer not big enough, try again with enough space */
+ rtl_freeMemory( pTemp );
+
+ /* Try with the max. count of characters with
+ additional overhead for replacing functionality */
+ nNotConvertedChars = nLength-nSrcChars;
+ nNewLen = nDestBytes+(nNotConvertedChars*nMaxCharLen)+nNotConvertedChars+4;
+ }
+
+ /* Set the buffer to the correct size or is there to
+ much overhead, reallocate to the correct size */
+ if ( nNewLen > nDestBytes+8 )
+ {
+ rtl_String* pTemp2 = IMPL_RTL_STRINGNAME( ImplAlloc )( nDestBytes );
+ OSL_ASSERT(pTemp2 != NULL);
+ rtl_str_ImplCopy( pTemp2->buffer, pTemp->buffer, nDestBytes );
+ rtl_freeMemory( pTemp );
+ pTemp = pTemp2;
+ }
+ else
+ {
+ pTemp->length = nDestBytes;
+ pTemp->buffer[nDestBytes] = 0;
+ }
+
+ rtl_destroyUnicodeToTextConverter( hConverter );
+ if ( *pTarget )
+ IMPL_RTL_STRINGNAME( release )( *pTarget );
+ *pTarget = pTemp;
+
+ /* Results the conversion in an empty buffer -
+ create an empty string */
+ if ( pTemp && !nDestBytes )
+ rtl_string_new( pTarget );
+ }
+ return sal_True;
+}
+
+void SAL_CALL rtl_uString2String( rtl_String** ppThis,
+ const sal_Unicode* pUStr,
+ sal_Int32 nULen,
+ rtl_TextEncoding eTextEncoding,
+ sal_uInt32 nCvtFlags )
+{
+ rtl_impl_convertUStringToString(ppThis, pUStr, nULen, eTextEncoding,
+ nCvtFlags, sal_False);
+}
+
+sal_Bool SAL_CALL rtl_convertUStringToString(rtl_String ** pTarget,
+ sal_Unicode const * pSource,
+ sal_Int32 nLength,
+ rtl_TextEncoding nEncoding,
+ sal_uInt32 nFlags)
+{
+ return rtl_impl_convertUStringToString(pTarget, pSource, nLength, nEncoding,
+ nFlags, sal_True);
+}
diff --git a/sal/rtl/source/strtmpl.c b/sal/rtl/source/strtmpl.c
new file mode 100644
index 000000000000..8c60583b14cc
--- /dev/null
+++ b/sal/rtl/source/strtmpl.c
@@ -0,0 +1,1567 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+/* ======================================================================= */
+/* Internal C-String help functions which could be used without the */
+/* String-Class */
+/* ======================================================================= */
+
+/*
+inline void rtl_str_ImplCopy( IMPL_RTL_STRCODE* pDest,
+ const IMPL_RTL_STRCODE* pSrc,
+ sal_Int32 nCount )
+{
+ while ( nCount > 0 )
+ {
+ *pDest = *pSrc;
+ pDest++;
+ pSrc++;
+ nCount--;
+ }
+}
+*/
+
+#define rtl_str_ImplCopy( _pDest, _pSrc, _nCount ) \
+{ \
+ IMPL_RTL_STRCODE* __mm_pDest = _pDest; \
+ const IMPL_RTL_STRCODE* __mm_pSrc = _pSrc; \
+ sal_Int32 __mm_nCount = _nCount; \
+ while ( __mm_nCount > 0 ) \
+ { \
+ *__mm_pDest = *__mm_pSrc; \
+ __mm_pDest++; \
+ __mm_pSrc++; \
+ __mm_nCount--; \
+ } \
+}
+
+/* ======================================================================= */
+/* C-String functions which could be used without the String-Class */
+/* ======================================================================= */
+
+sal_Int32 SAL_CALL IMPL_RTL_STRNAME( getLength )( const IMPL_RTL_STRCODE* pStr )
+{
+ const IMPL_RTL_STRCODE* pTempStr = pStr;
+ while( *pTempStr )
+ pTempStr++;
+ return pTempStr-pStr;
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL IMPL_RTL_STRNAME( compare )( const IMPL_RTL_STRCODE* pStr1,
+ const IMPL_RTL_STRCODE* pStr2 )
+{
+ sal_Int32 nRet;
+ while ( ((nRet = ((sal_Int32)(IMPL_RTL_USTRCODE(*pStr1)))-
+ ((sal_Int32)(IMPL_RTL_USTRCODE(*pStr2)))) == 0) &&
+ *pStr2 )
+ {
+ pStr1++;
+ pStr2++;
+ }
+
+ return nRet;
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL IMPL_RTL_STRNAME( compare_WithLength )( const IMPL_RTL_STRCODE* pStr1,
+ sal_Int32 nStr1Len,
+ const IMPL_RTL_STRCODE* pStr2,
+ sal_Int32 nStr2Len )
+{
+ sal_Int32 nRet = nStr1Len - nStr2Len;
+ int nCount = (nRet <= 0) ? nStr1Len : nStr2Len;
+
+ --pStr1;
+ --pStr2;
+ while( (--nCount >= 0) && (*++pStr1 == *++pStr2) );
+
+ if( nCount >= 0 )
+ nRet = ((sal_Int32)(IMPL_RTL_USTRCODE( *pStr1 )))
+ - ((sal_Int32)(IMPL_RTL_USTRCODE( *pStr2 )));
+
+ return nRet;
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL IMPL_RTL_STRNAME( shortenedCompare_WithLength )( const IMPL_RTL_STRCODE* pStr1,
+ sal_Int32 nStr1Len,
+ const IMPL_RTL_STRCODE* pStr2,
+ sal_Int32 nStr2Len,
+ sal_Int32 nShortenedLength )
+{
+ const IMPL_RTL_STRCODE* pStr1End = pStr1 + nStr1Len;
+ const IMPL_RTL_STRCODE* pStr2End = pStr2 + nStr2Len;
+ sal_Int32 nRet;
+ while ( (nShortenedLength > 0) &&
+ (pStr1 < pStr1End) && (pStr2 < pStr2End) )
+ {
+ nRet = ((sal_Int32)(IMPL_RTL_USTRCODE( *pStr1 )))-
+ ((sal_Int32)(IMPL_RTL_USTRCODE( *pStr2 )));
+ if ( nRet )
+ return nRet;
+
+ nShortenedLength--;
+ pStr1++;
+ pStr2++;
+ }
+
+ if ( nShortenedLength <= 0 )
+ return 0;
+ return nStr1Len - nStr2Len;
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL IMPL_RTL_STRNAME( reverseCompare_WithLength )( const IMPL_RTL_STRCODE* pStr1,
+ sal_Int32 nStr1Len,
+ const IMPL_RTL_STRCODE* pStr2,
+ sal_Int32 nStr2Len )
+{
+ const IMPL_RTL_STRCODE* pStr1Run = pStr1+nStr1Len;
+ const IMPL_RTL_STRCODE* pStr2Run = pStr2+nStr2Len;
+ sal_Int32 nRet;
+ while ( (pStr1 < pStr1Run) && (pStr2 < pStr2Run) )
+ {
+ pStr1Run--;
+ pStr2Run--;
+ nRet = ((sal_Int32)(IMPL_RTL_USTRCODE( *pStr1Run )))-
+ ((sal_Int32)(IMPL_RTL_USTRCODE( *pStr2Run )));
+ if ( nRet )
+ return nRet;
+ }
+
+ return nStr1Len - nStr2Len;
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL IMPL_RTL_STRNAME( compareIgnoreAsciiCase )( const IMPL_RTL_STRCODE* pStr1,
+ const IMPL_RTL_STRCODE* pStr2 )
+{
+ sal_Int32 nRet;
+ sal_Int32 c1;
+ sal_Int32 c2;
+ do
+ {
+ /* If character between 'A' and 'Z', than convert it to lowercase */
+ c1 = (sal_Int32)IMPL_RTL_USTRCODE( *pStr1 );
+ c2 = (sal_Int32)IMPL_RTL_USTRCODE( *pStr2 );
+ if ( (c1 >= 65) && (c1 <= 90) )
+ c1 += 32;
+ if ( (c2 >= 65) && (c2 <= 90) )
+ c2 += 32;
+ nRet = c1-c2;
+ if ( nRet != 0 )
+ return nRet;
+
+ pStr1++;
+ pStr2++;
+ }
+ while ( c2 );
+
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL IMPL_RTL_STRNAME( compareIgnoreAsciiCase_WithLength )( const IMPL_RTL_STRCODE* pStr1,
+ sal_Int32 nStr1Len,
+ const IMPL_RTL_STRCODE* pStr2,
+ sal_Int32 nStr2Len )
+{
+ const IMPL_RTL_STRCODE* pStr1End = pStr1 + nStr1Len;
+ const IMPL_RTL_STRCODE* pStr2End = pStr2 + nStr2Len;
+ sal_Int32 nRet;
+ sal_Int32 c1;
+ sal_Int32 c2;
+ while ( (pStr1 < pStr1End) && (pStr2 < pStr2End) )
+ {
+ /* If character between 'A' and 'Z', than convert it to lowercase */
+ c1 = (sal_Int32)IMPL_RTL_USTRCODE( *pStr1 );
+ c2 = (sal_Int32)IMPL_RTL_USTRCODE( *pStr2 );
+ if ( (c1 >= 65) && (c1 <= 90) )
+ c1 += 32;
+ if ( (c2 >= 65) && (c2 <= 90) )
+ c2 += 32;
+ nRet = c1-c2;
+ if ( nRet != 0 )
+ return nRet;
+
+ pStr1++;
+ pStr2++;
+ }
+
+ return nStr1Len - nStr2Len;
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL IMPL_RTL_STRNAME( shortenedCompareIgnoreAsciiCase_WithLength )( const IMPL_RTL_STRCODE* pStr1,
+ sal_Int32 nStr1Len,
+ const IMPL_RTL_STRCODE* pStr2,
+ sal_Int32 nStr2Len,
+ sal_Int32 nShortenedLength )
+{
+ const IMPL_RTL_STRCODE* pStr1End = pStr1 + nStr1Len;
+ const IMPL_RTL_STRCODE* pStr2End = pStr2 + nStr2Len;
+ sal_Int32 nRet;
+ sal_Int32 c1;
+ sal_Int32 c2;
+ while ( (nShortenedLength > 0) &&
+ (pStr1 < pStr1End) && (pStr2 < pStr2End) )
+ {
+ /* If character between 'A' and 'Z', than convert it to lowercase */
+ c1 = (sal_Int32)IMPL_RTL_USTRCODE( *pStr1 );
+ c2 = (sal_Int32)IMPL_RTL_USTRCODE( *pStr2 );
+ if ( (c1 >= 65) && (c1 <= 90) )
+ c1 += 32;
+ if ( (c2 >= 65) && (c2 <= 90) )
+ c2 += 32;
+ nRet = c1-c2;
+ if ( nRet != 0 )
+ return nRet;
+
+ nShortenedLength--;
+ pStr1++;
+ pStr2++;
+ }
+
+ if ( nShortenedLength <= 0 )
+ return 0;
+ return nStr1Len - nStr2Len;
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL IMPL_RTL_STRNAME( hashCode )( const IMPL_RTL_STRCODE* pStr )
+{
+ return IMPL_RTL_STRNAME( hashCode_WithLength )( pStr, IMPL_RTL_STRNAME( getLength )( pStr ) );
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL IMPL_RTL_STRNAME( hashCode_WithLength )( const IMPL_RTL_STRCODE* pStr,
+ sal_Int32 nLen )
+{
+ sal_Int32 h = nLen;
+
+ if ( nLen < 256 )
+ {
+ while ( nLen > 0 )
+ {
+ h = (h*37) + IMPL_RTL_USTRCODE( *pStr );
+ pStr++;
+ nLen--;
+ }
+ }
+ else
+ {
+ sal_Int32 nSkip;
+ const IMPL_RTL_STRCODE* pEndStr = pStr+nLen-5;
+
+ /* only sample some characters */
+ /* the first 3, some characters between, and the last 5 */
+ h = (h*39) + IMPL_RTL_USTRCODE( *pStr );
+ pStr++;
+ h = (h*39) + IMPL_RTL_USTRCODE( *pStr );
+ pStr++;
+ h = (h*39) + IMPL_RTL_USTRCODE( *pStr );
+ pStr++;
+
+ if ( nLen < 32 )
+ nSkip = nLen / 4;
+ else
+ nSkip = nLen / 8;
+ nLen -= 8;
+ while ( nLen > 0 )
+ {
+ h = (h*39) + IMPL_RTL_USTRCODE( *pStr );
+ pStr += nSkip;
+ nLen -= nSkip;
+ }
+
+ h = (h*39) + IMPL_RTL_USTRCODE( *pEndStr );
+ pEndStr++;
+ h = (h*39) + IMPL_RTL_USTRCODE( *pEndStr );
+ pEndStr++;
+ h = (h*39) + IMPL_RTL_USTRCODE( *pEndStr );
+ pEndStr++;
+ h = (h*39) + IMPL_RTL_USTRCODE( *pEndStr );
+ pEndStr++;
+ h = (h*39) + IMPL_RTL_USTRCODE( *pEndStr );
+ }
+
+ return h;
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL IMPL_RTL_STRNAME( indexOfChar )( const IMPL_RTL_STRCODE* pStr,
+ IMPL_RTL_STRCODE c )
+{
+ const IMPL_RTL_STRCODE* pTempStr = pStr;
+ while ( *pTempStr )
+ {
+ if ( *pTempStr == c )
+ return pTempStr-pStr;
+
+ pTempStr++;
+ }
+
+ return -1;
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL IMPL_RTL_STRNAME( indexOfChar_WithLength )( const IMPL_RTL_STRCODE* pStr,
+ sal_Int32 nLen,
+ IMPL_RTL_STRCODE c )
+{
+ const IMPL_RTL_STRCODE* pTempStr = pStr;
+ while ( nLen > 0 )
+ {
+ if ( *pTempStr == c )
+ return pTempStr-pStr;
+
+ pTempStr++;
+ nLen--;
+ }
+
+ return -1;
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL IMPL_RTL_STRNAME( lastIndexOfChar )( const IMPL_RTL_STRCODE* pStr,
+ IMPL_RTL_STRCODE c )
+{
+ return IMPL_RTL_STRNAME( lastIndexOfChar_WithLength )( pStr, IMPL_RTL_STRNAME( getLength )( pStr ), c );
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL IMPL_RTL_STRNAME( lastIndexOfChar_WithLength )( const IMPL_RTL_STRCODE* pStr,
+ sal_Int32 nLen,
+ IMPL_RTL_STRCODE c )
+{
+ pStr += nLen;
+ while ( nLen > 0 )
+ {
+ nLen--;
+ pStr--;
+
+ if ( *pStr == c )
+ return nLen;
+ }
+
+ return -1;
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL IMPL_RTL_STRNAME( indexOfStr )( const IMPL_RTL_STRCODE* pStr,
+ const IMPL_RTL_STRCODE* pSubStr )
+{
+ return IMPL_RTL_STRNAME( indexOfStr_WithLength )( pStr, IMPL_RTL_STRNAME( getLength )( pStr ),
+ pSubStr, IMPL_RTL_STRNAME( getLength )( pSubStr ) );
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL IMPL_RTL_STRNAME( indexOfStr_WithLength )( const IMPL_RTL_STRCODE* pStr,
+ sal_Int32 nStrLen,
+ const IMPL_RTL_STRCODE* pSubStr,
+ sal_Int32 nSubLen )
+{
+ /* faster search for a single character */
+ if ( nSubLen < 2 )
+ {
+ /* an empty SubString is always not foundable */
+ if ( nSubLen == 1 )
+ {
+ IMPL_RTL_STRCODE c = *pSubStr;
+ const IMPL_RTL_STRCODE* pTempStr = pStr;
+ while ( nStrLen > 0 )
+ {
+ if ( *pTempStr == c )
+ return pTempStr-pStr;
+
+ pTempStr++;
+ nStrLen--;
+ }
+ }
+ }
+ else
+ {
+ const IMPL_RTL_STRCODE* pTempStr = pStr;
+ while ( nStrLen > 0 )
+ {
+ if ( *pTempStr == *pSubStr )
+ {
+ /* Compare SubString */
+ if ( nSubLen <= nStrLen )
+ {
+ const IMPL_RTL_STRCODE* pTempStr1 = pTempStr;
+ const IMPL_RTL_STRCODE* pTempStr2 = pSubStr;
+ sal_Int32 nTempLen = nSubLen;
+ while ( nTempLen )
+ {
+ if ( *pTempStr1 != *pTempStr2 )
+ break;
+
+ pTempStr1++;
+ pTempStr2++;
+ nTempLen--;
+ }
+
+ if ( !nTempLen )
+ return pTempStr-pStr;
+ }
+ else
+ break;
+ }
+
+ nStrLen--;
+ pTempStr++;
+ }
+ }
+
+ return -1;
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL IMPL_RTL_STRNAME( lastIndexOfStr )( const IMPL_RTL_STRCODE* pStr,
+ const IMPL_RTL_STRCODE* pSubStr )
+{
+ return IMPL_RTL_STRNAME( lastIndexOfStr_WithLength )( pStr, IMPL_RTL_STRNAME( getLength )( pStr ),
+ pSubStr, IMPL_RTL_STRNAME( getLength )( pSubStr ) );
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL IMPL_RTL_STRNAME( lastIndexOfStr_WithLength )( const IMPL_RTL_STRCODE* pStr,
+ sal_Int32 nStrLen,
+ const IMPL_RTL_STRCODE* pSubStr,
+ sal_Int32 nSubLen )
+{
+ /* faster search for a single character */
+ if ( nSubLen < 2 )
+ {
+ /* an empty SubString is always not foundable */
+ if ( nSubLen == 1 )
+ {
+ IMPL_RTL_STRCODE c = *pSubStr;
+ pStr += nStrLen;
+ while ( nStrLen > 0 )
+ {
+ nStrLen--;
+ pStr--;
+
+ if ( *pStr == c )
+ return nStrLen;
+ }
+ }
+ }
+ else
+ {
+ pStr += nStrLen;
+ nStrLen -= nSubLen;
+ pStr -= nSubLen;
+ while ( nStrLen >= 0 )
+ {
+ const IMPL_RTL_STRCODE* pTempStr1 = pStr;
+ const IMPL_RTL_STRCODE* pTempStr2 = pSubStr;
+ sal_Int32 nTempLen = nSubLen;
+ while ( nTempLen )
+ {
+ if ( *pTempStr1 != *pTempStr2 )
+ break;
+
+ pTempStr1++;
+ pTempStr2++;
+ nTempLen--;
+ }
+
+ if ( !nTempLen )
+ return nStrLen;
+
+ nStrLen--;
+ pStr--;
+ }
+ }
+
+ return -1;
+}
+
+/* ----------------------------------------------------------------------- */
+
+void SAL_CALL IMPL_RTL_STRNAME( replaceChar )( IMPL_RTL_STRCODE* pStr,
+ IMPL_RTL_STRCODE cOld,
+ IMPL_RTL_STRCODE cNew )
+{
+ while ( *pStr )
+ {
+ if ( *pStr == cOld )
+ *pStr = cNew;
+
+ pStr++;
+ }
+}
+
+/* ----------------------------------------------------------------------- */
+
+void SAL_CALL IMPL_RTL_STRNAME( replaceChar_WithLength )( IMPL_RTL_STRCODE* pStr,
+ sal_Int32 nLen,
+ IMPL_RTL_STRCODE cOld,
+ IMPL_RTL_STRCODE cNew )
+{
+ while ( nLen > 0 )
+ {
+ if ( *pStr == cOld )
+ *pStr = cNew;
+
+ pStr++;
+ nLen--;
+ }
+}
+
+/* ----------------------------------------------------------------------- */
+
+void SAL_CALL IMPL_RTL_STRNAME( toAsciiLowerCase )( IMPL_RTL_STRCODE* pStr )
+{
+ while ( *pStr )
+ {
+ /* Between A-Z (65-90), than to lowercase (+32) */
+ if ( (*pStr >= 65) && (*pStr <= 90) )
+ *pStr += 32;
+
+ pStr++;
+ }
+}
+
+/* ----------------------------------------------------------------------- */
+
+void SAL_CALL IMPL_RTL_STRNAME( toAsciiLowerCase_WithLength )( IMPL_RTL_STRCODE* pStr,
+ sal_Int32 nLen )
+{
+ while ( nLen > 0 )
+ {
+ /* Between A-Z (65-90), than to lowercase (+32) */
+ if ( (*pStr >= 65) && (*pStr <= 90) )
+ *pStr += 32;
+
+ pStr++;
+ nLen--;
+ }
+}
+
+/* ----------------------------------------------------------------------- */
+
+void SAL_CALL IMPL_RTL_STRNAME( toAsciiUpperCase )( IMPL_RTL_STRCODE* pStr )
+{
+ while ( *pStr )
+ {
+ /* Between a-z (97-122), than to uppercase (-32) */
+ if ( (*pStr >= 97) && (*pStr <= 122) )
+ *pStr -= 32;
+
+ pStr++;
+ }
+}
+
+/* ----------------------------------------------------------------------- */
+
+void SAL_CALL IMPL_RTL_STRNAME( toAsciiUpperCase_WithLength )( IMPL_RTL_STRCODE* pStr,
+ sal_Int32 nLen )
+{
+ while ( nLen > 0 )
+ {
+ /* Between a-z (97-122), than to uppercase (-32) */
+ if ( (*pStr >= 97) && (*pStr <= 122) )
+ *pStr -= 32;
+
+ pStr++;
+ nLen--;
+ }
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL IMPL_RTL_STRNAME( trim )( IMPL_RTL_STRCODE* pStr )
+{
+ return IMPL_RTL_STRNAME( trim_WithLength )( pStr, IMPL_RTL_STRNAME( getLength )( pStr ) );
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL IMPL_RTL_STRNAME( trim_WithLength )( IMPL_RTL_STRCODE* pStr, sal_Int32 nLen )
+{
+ sal_Int32 nPreSpaces = 0;
+ sal_Int32 nPostSpaces = 0;
+ sal_Int32 nIndex = nLen-1;
+
+ while ( (nPreSpaces < nLen) && rtl_ImplIsWhitespace( IMPL_RTL_USTRCODE(*(pStr+nPreSpaces)) ) )
+ nPreSpaces++;
+
+ while ( (nIndex > nPreSpaces) && rtl_ImplIsWhitespace( IMPL_RTL_USTRCODE(*(pStr+nIndex)) ) )
+ {
+ nPostSpaces++;
+ nIndex--;
+ }
+
+ if ( nPostSpaces )
+ {
+ nLen -= nPostSpaces;
+ *(pStr+nLen) = 0;
+ }
+
+ if ( nPreSpaces )
+ {
+ IMPL_RTL_STRCODE* pNewStr = pStr+nPreSpaces;
+
+ nLen -= nPreSpaces;
+ nIndex = nLen;
+
+ while ( nIndex )
+ {
+ *pStr = *pNewStr;
+ pStr++;
+ pNewStr++;
+ nIndex--;
+ }
+ *pStr = 0;
+ }
+
+ return nLen;
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL IMPL_RTL_STRNAME( valueOfBoolean )( IMPL_RTL_STRCODE* pStr, sal_Bool b )
+{
+ if ( b )
+ {
+ *pStr = 't';
+ pStr++;
+ *pStr = 'r';
+ pStr++;
+ *pStr = 'u';
+ pStr++;
+ *pStr = 'e';
+ pStr++;
+ *pStr = 0;
+ return 4;
+ }
+ else
+ {
+ *pStr = 'f';
+ pStr++;
+ *pStr = 'a';
+ pStr++;
+ *pStr = 'l';
+ pStr++;
+ *pStr = 's';
+ pStr++;
+ *pStr = 'e';
+ pStr++;
+ *pStr = 0;
+ return 5;
+ }
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL IMPL_RTL_STRNAME( valueOfChar )( IMPL_RTL_STRCODE* pStr,
+ IMPL_RTL_STRCODE c )
+{
+ *pStr++ = c;
+ *pStr = 0;
+ return 1;
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL IMPL_RTL_STRNAME( valueOfInt32 )( IMPL_RTL_STRCODE* pStr,
+ sal_Int32 n,
+ sal_Int16 nRadix )
+{
+ sal_Char aBuf[RTL_STR_MAX_VALUEOFINT32];
+ sal_Char* pBuf = aBuf;
+ sal_Int32 nLen = 0;
+ sal_uInt32 nValue;
+
+ /* Radix must be valid */
+ if ( (nRadix < RTL_STR_MIN_RADIX) || (nRadix > RTL_STR_MAX_RADIX) )
+ nRadix = 10;
+
+ /* is value negativ */
+ if ( n < 0 )
+ {
+ *pStr = '-';
+ pStr++;
+ nLen++;
+ nValue = -n; /* FIXME this code is not portable for n == -2147483648
+ (smallest negative value for sal_Int32) */
+ }
+ else
+ nValue = n;
+
+ /* create a recursive buffer with all values, except the last one */
+ do
+ {
+ sal_Char nDigit = (sal_Char)(nValue % nRadix);
+ nValue /= nRadix;
+ if ( nDigit > 9 )
+ *pBuf = (nDigit-10) + 'a';
+ else
+ *pBuf = (nDigit + '0' );
+ pBuf++;
+ }
+ while ( nValue > 0 );
+
+ /* copy the values in the right direction into the destination buffer */
+ do
+ {
+ pBuf--;
+ *pStr = *pBuf;
+ pStr++;
+ nLen++;
+ }
+ while ( pBuf != aBuf );
+ *pStr = 0;
+
+ return nLen;
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL IMPL_RTL_STRNAME( valueOfInt64 )( IMPL_RTL_STRCODE* pStr,
+ sal_Int64 n,
+ sal_Int16 nRadix )
+{
+ sal_Char aBuf[RTL_STR_MAX_VALUEOFINT64];
+ sal_Char* pBuf = aBuf;
+ sal_Int32 nLen = 0;
+ sal_uInt64 nValue;
+
+ /* Radix must be valid */
+ if ( (nRadix < RTL_STR_MIN_RADIX) || (nRadix > RTL_STR_MAX_RADIX) )
+ nRadix = 10;
+
+ /* is value negativ */
+ if ( n < 0 )
+ {
+ *pStr = '-';
+ pStr++;
+ nLen++;
+ nValue = -n; /* FIXME this code is not portable for
+ n == -9223372036854775808 (smallest negative value for
+ sal_Int64) */
+ }
+ else
+ nValue = n;
+
+ /* create a recursive buffer with all values, except the last one */
+ do
+ {
+ sal_Char nDigit = (sal_Char)(nValue % nRadix);
+ nValue /= nRadix;
+ if ( nDigit > 9 )
+ *pBuf = (nDigit-10) + 'a';
+ else
+ *pBuf = (nDigit + '0' );
+ pBuf++;
+ }
+ while ( nValue > 0 );
+
+ /* copy the values in the right direction into the destination buffer */
+ do
+ {
+ pBuf--;
+ *pStr = *pBuf;
+ pStr++;
+ nLen++;
+ }
+ while ( pBuf != aBuf );
+ *pStr = 0;
+
+ return nLen;
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Bool SAL_CALL IMPL_RTL_STRNAME( toBoolean )( const IMPL_RTL_STRCODE* pStr )
+{
+ if ( *pStr == '1' )
+ return sal_True;
+
+ if ( (*pStr == 'T') || (*pStr == 't') )
+ {
+ pStr++;
+ if ( (*pStr == 'R') || (*pStr == 'r') )
+ {
+ pStr++;
+ if ( (*pStr == 'U') || (*pStr == 'u') )
+ {
+ pStr++;
+ if ( (*pStr == 'E') || (*pStr == 'e') )
+ return sal_True;
+ }
+ }
+ }
+
+ return sal_False;
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL IMPL_RTL_STRNAME( toInt32 )( const IMPL_RTL_STRCODE* pStr,
+ sal_Int16 nRadix )
+{
+ sal_Bool bNeg;
+ sal_Int16 nDigit;
+ sal_Int32 n = 0;
+
+ if ( (nRadix < RTL_STR_MIN_RADIX) || (nRadix > RTL_STR_MAX_RADIX) )
+ nRadix = 10;
+
+ /* Skip whitespaces */
+ while ( *pStr && rtl_ImplIsWhitespace( IMPL_RTL_USTRCODE( *pStr ) ) )
+ pStr++;
+
+ if ( *pStr == '-' )
+ {
+ bNeg = sal_True;
+ pStr++;
+ }
+ else
+ {
+ if ( *pStr == '+' )
+ pStr++;
+ bNeg = sal_False;
+ }
+
+ while ( *pStr )
+ {
+ nDigit = rtl_ImplGetDigit( IMPL_RTL_USTRCODE( *pStr ), nRadix );
+ if ( nDigit < 0 )
+ break;
+
+ n *= nRadix;
+ n += nDigit;
+
+ pStr++;
+ }
+
+ if ( bNeg )
+ return -n;
+ else
+ return n;
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int64 SAL_CALL IMPL_RTL_STRNAME( toInt64 )( const IMPL_RTL_STRCODE* pStr,
+ sal_Int16 nRadix )
+{
+ sal_Bool bNeg;
+ sal_Int16 nDigit;
+ sal_Int64 n = 0;
+
+ if ( (nRadix < RTL_STR_MIN_RADIX) || (nRadix > RTL_STR_MAX_RADIX) )
+ nRadix = 10;
+
+ /* Skip whitespaces */
+ while ( *pStr && rtl_ImplIsWhitespace( IMPL_RTL_USTRCODE( *pStr ) ) )
+ pStr++;
+
+ if ( *pStr == '-' )
+ {
+ bNeg = sal_True;
+ pStr++;
+ }
+ else
+ {
+ if ( *pStr == '+' )
+ pStr++;
+ bNeg = sal_False;
+ }
+
+ while ( *pStr )
+ {
+ nDigit = rtl_ImplGetDigit( IMPL_RTL_USTRCODE( *pStr ), nRadix );
+ if ( nDigit < 0 )
+ break;
+
+ n *= nRadix;
+ n += nDigit;
+
+ pStr++;
+ }
+
+ if ( bNeg )
+ return -n;
+ else
+ return n;
+}
+
+/* ======================================================================= */
+/* Internal String-Class help functions */
+/* ======================================================================= */
+
+static IMPL_RTL_STRINGDATA* IMPL_RTL_STRINGNAME( ImplAlloc )( sal_Int32 nLen )
+{
+ IMPL_RTL_STRINGDATA * pData
+ = (SAL_INT_CAST(sal_uInt32, nLen)
+ <= ((SAL_MAX_UINT32 - sizeof (IMPL_RTL_STRINGDATA))
+ / sizeof (IMPL_RTL_STRCODE)))
+ ? (IMPL_RTL_STRINGDATA *) rtl_allocateMemory(
+ sizeof (IMPL_RTL_STRINGDATA) + nLen * sizeof (IMPL_RTL_STRCODE))
+ : NULL;
+ if (pData != NULL) {
+ pData->refCount = 1;
+ pData->length = nLen;
+ pData->buffer[nLen] = 0;
+ }
+ return pData;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static IMPL_RTL_STRCODE* IMPL_RTL_STRINGNAME( ImplNewCopy )( IMPL_RTL_STRINGDATA** ppThis,
+ IMPL_RTL_STRINGDATA* pStr,
+ sal_Int32 nCount )
+{
+ IMPL_RTL_STRCODE* pDest;
+ const IMPL_RTL_STRCODE* pSrc;
+ IMPL_RTL_STRINGDATA* pData = IMPL_RTL_STRINGNAME( ImplAlloc )( pStr->length );
+ OSL_ASSERT(pData != NULL);
+
+ pDest = pData->buffer;
+ pSrc = pStr->buffer;
+ while ( nCount > 0 )
+ {
+ *pDest = *pSrc;
+ pDest++;
+ pSrc++;
+ nCount--;
+ }
+
+ *ppThis = pData;
+ return pDest;
+}
+
+/* ======================================================================= */
+/* String-Class functions */
+/* ======================================================================= */
+
+#define IMPL_RTL_AQUIRE( pThis ) \
+{ \
+ if (!SAL_STRING_IS_STATIC (pThis)) \
+ osl_incrementInterlockedCount( &((pThis)->refCount) ); \
+}
+
+/* ----------------------------------------------------------------------- */
+
+void SAL_CALL IMPL_RTL_STRINGNAME( acquire )( IMPL_RTL_STRINGDATA* pThis )
+{
+ IMPL_RTL_AQUIRE( pThis );
+}
+
+/* ----------------------------------------------------------------------- */
+
+void SAL_CALL IMPL_RTL_STRINGNAME( release )( IMPL_RTL_STRINGDATA* pThis )
+{
+ if (SAL_STRING_IS_STATIC (pThis))
+ return;
+
+/* OString doesn't have an 'intern' */
+#ifdef IMPL_RTL_INTERN
+ if (SAL_STRING_IS_INTERN (pThis))
+ {
+ internRelease (pThis);
+ return;
+ }
+#endif
+
+ if ( pThis->refCount == 1 ||
+ !osl_decrementInterlockedCount( &(pThis->refCount) ) )
+ {
+ rtl_freeMemory( pThis );
+ }
+}
+
+/* ----------------------------------------------------------------------- */
+
+void SAL_CALL IMPL_RTL_STRINGNAME( new )( IMPL_RTL_STRINGDATA** ppThis )
+{
+ if ( *ppThis)
+ IMPL_RTL_STRINGNAME( release )( *ppThis );
+
+ *ppThis = (IMPL_RTL_STRINGDATA*) (&IMPL_RTL_EMPTYSTRING);
+ IMPL_RTL_AQUIRE( *ppThis );
+}
+
+/* ----------------------------------------------------------------------- */
+
+void SAL_CALL IMPL_RTL_STRINGNAME( new_WithLength )( IMPL_RTL_STRINGDATA** ppThis, sal_Int32 nLen )
+{
+ if ( nLen <= 0 )
+ IMPL_RTL_STRINGNAME( new )( ppThis );
+ else
+ {
+ if ( *ppThis)
+ IMPL_RTL_STRINGNAME( release )( *ppThis );
+
+ *ppThis = IMPL_RTL_STRINGNAME( ImplAlloc )( nLen );
+ OSL_ASSERT(*ppThis != NULL);
+ (*ppThis)->length = 0;
+
+ {
+ IMPL_RTL_STRCODE* pTempStr = (*ppThis)->buffer;
+ while ( nLen >= 0 )
+ {
+ *pTempStr = 0;
+ pTempStr++;
+ nLen--;
+ }
+ }
+ }
+}
+
+/* ----------------------------------------------------------------------- */
+
+void SAL_CALL IMPL_RTL_STRINGNAME( newFromString )( IMPL_RTL_STRINGDATA** ppThis,
+ const IMPL_RTL_STRINGDATA* pStr )
+{
+ IMPL_RTL_STRINGDATA* pOrg;
+
+ if ( !pStr->length )
+ {
+ IMPL_RTL_STRINGNAME( new )( ppThis );
+ return;
+ }
+
+ pOrg = *ppThis;
+ *ppThis = IMPL_RTL_STRINGNAME( ImplAlloc )( pStr->length );
+ OSL_ASSERT(*ppThis != NULL);
+ rtl_str_ImplCopy( (*ppThis)->buffer, pStr->buffer, pStr->length );
+
+ /* must be done at least, if pStr == *ppThis */
+ if ( pOrg )
+ IMPL_RTL_STRINGNAME( release )( pOrg );
+}
+
+/* ----------------------------------------------------------------------- */
+
+void SAL_CALL IMPL_RTL_STRINGNAME( newFromStr )( IMPL_RTL_STRINGDATA** ppThis,
+ const IMPL_RTL_STRCODE* pCharStr )
+{
+ IMPL_RTL_STRCODE* pBuffer;
+ IMPL_RTL_STRINGDATA* pOrg;
+ sal_Int32 nLen;
+
+ if ( pCharStr )
+ {
+ const IMPL_RTL_STRCODE* pTempStr = pCharStr;
+ while( *pTempStr )
+ pTempStr++;
+ nLen = pTempStr-pCharStr;
+ }
+ else
+ nLen = 0;
+
+ if ( !nLen )
+ {
+ IMPL_RTL_STRINGNAME( new )( ppThis );
+ return;
+ }
+
+ pOrg = *ppThis;
+ *ppThis = IMPL_RTL_STRINGNAME( ImplAlloc )( nLen );
+ OSL_ASSERT(*ppThis != NULL);
+ pBuffer = (*ppThis)->buffer;
+ do
+ {
+ *pBuffer = *pCharStr;
+ pBuffer++;
+ pCharStr++;
+ }
+ while ( *pCharStr );
+
+ /* must be done at least, if pCharStr == *ppThis */
+ if ( pOrg )
+ IMPL_RTL_STRINGNAME( release )( pOrg );
+}
+
+/* ----------------------------------------------------------------------- */
+
+void SAL_CALL IMPL_RTL_STRINGNAME( newFromStr_WithLength )( IMPL_RTL_STRINGDATA** ppThis,
+ const IMPL_RTL_STRCODE* pCharStr,
+ sal_Int32 nLen )
+{
+ IMPL_RTL_STRINGDATA* pOrg;
+
+ if ( !pCharStr || (nLen <= 0) )
+ {
+ IMPL_RTL_STRINGNAME( new )( ppThis );
+ return;
+ }
+
+ pOrg = *ppThis;
+ *ppThis = IMPL_RTL_STRINGNAME( ImplAlloc )( nLen );
+ OSL_ASSERT(*ppThis != NULL);
+ rtl_str_ImplCopy( (*ppThis)->buffer, pCharStr, nLen );
+
+ /* must be done at least, if pCharStr == *ppThis */
+ if ( pOrg )
+ IMPL_RTL_STRINGNAME( release )( pOrg );
+}
+
+/* ----------------------------------------------------------------------- */
+
+void SAL_CALL IMPL_RTL_STRINGNAME( assign )( IMPL_RTL_STRINGDATA** ppThis,
+ IMPL_RTL_STRINGDATA* pStr )
+{
+ /* must be done at first, if pStr == *ppThis */
+ IMPL_RTL_AQUIRE( pStr );
+
+ if ( *ppThis )
+ IMPL_RTL_STRINGNAME( release )( *ppThis );
+
+ *ppThis = pStr;
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL IMPL_RTL_STRINGNAME( getLength )( const IMPL_RTL_STRINGDATA* pThis )
+{
+ return pThis->length;
+}
+
+/* ----------------------------------------------------------------------- */
+
+IMPL_RTL_STRCODE* SAL_CALL IMPL_RTL_STRINGNAME( getStr )( IMPL_RTL_STRINGDATA * pThis )
+{
+ return pThis->buffer;
+}
+
+/* ----------------------------------------------------------------------- */
+
+void SAL_CALL IMPL_RTL_STRINGNAME( newConcat )( IMPL_RTL_STRINGDATA** ppThis,
+ IMPL_RTL_STRINGDATA* pLeft,
+ IMPL_RTL_STRINGDATA* pRight )
+{
+ IMPL_RTL_STRINGDATA* pOrg = *ppThis;
+
+ /* Test for 0-Pointer - if not, change newReplaceStrAt! */
+ if ( !pRight || !pRight->length )
+ {
+ *ppThis = pLeft;
+ IMPL_RTL_AQUIRE( pLeft );
+ }
+ else if ( !pLeft || !pLeft->length )
+ {
+ *ppThis = pRight;
+ IMPL_RTL_AQUIRE( pRight );
+ }
+ else
+ {
+ IMPL_RTL_STRINGDATA* pTempStr = IMPL_RTL_STRINGNAME( ImplAlloc )( pLeft->length + pRight->length );
+ OSL_ASSERT(pTempStr != NULL);
+ rtl_str_ImplCopy( pTempStr->buffer, pLeft->buffer, pLeft->length );
+ rtl_str_ImplCopy( pTempStr->buffer+pLeft->length, pRight->buffer, pRight->length );
+ *ppThis = pTempStr;
+ }
+
+ /* must be done at least, if left or right == *ppThis */
+ if ( pOrg )
+ IMPL_RTL_STRINGNAME( release )( pOrg );
+}
+
+/* ----------------------------------------------------------------------- */
+
+void SAL_CALL IMPL_RTL_STRINGNAME( newReplaceStrAt )( IMPL_RTL_STRINGDATA** ppThis,
+ IMPL_RTL_STRINGDATA* pStr,
+ sal_Int32 nIndex,
+ sal_Int32 nCount,
+ IMPL_RTL_STRINGDATA* pNewSubStr )
+{
+ /* Append? */
+ if ( nIndex >= pStr->length )
+ {
+ /* newConcat test, if pNewSubStr is 0 */
+ IMPL_RTL_STRINGNAME( newConcat )( ppThis, pStr, pNewSubStr );
+ return;
+ }
+
+ /* negativ index? */
+ if ( nIndex < 0 )
+ {
+ nCount -= nIndex;
+ nIndex = 0;
+ }
+
+ /* not more than the String length could be deleted */
+ if ( nCount >= pStr->length-nIndex )
+ {
+ nCount = pStr->length-nIndex;
+
+ /* Assign of NewSubStr? */
+ if ( !nIndex && (nCount >= pStr->length) )
+ {
+ if ( !pNewSubStr )
+ IMPL_RTL_STRINGNAME( new )( ppThis );
+ else
+ IMPL_RTL_STRINGNAME( assign )( ppThis, pNewSubStr );
+ return;
+ }
+ }
+
+ /* Assign of Str? */
+ if ( !nCount && (!pNewSubStr || !pNewSubStr->length) )
+ {
+ IMPL_RTL_STRINGNAME( assign )( ppThis, pStr );
+ return;
+ }
+
+ {
+ IMPL_RTL_STRINGDATA* pOrg = *ppThis;
+ IMPL_RTL_STRCODE* pBuffer;
+ sal_Int32 nNewLen;
+
+ /* Calculate length of the new string */
+ nNewLen = pStr->length-nCount;
+ if ( pNewSubStr )
+ nNewLen += pNewSubStr->length;
+
+ /* Alloc New Buffer */
+ *ppThis = IMPL_RTL_STRINGNAME( ImplAlloc )( nNewLen );
+ OSL_ASSERT(*ppThis != NULL);
+ pBuffer = (*ppThis)->buffer;
+ if ( nIndex )
+ {
+ rtl_str_ImplCopy( pBuffer, pStr->buffer, nIndex );
+ pBuffer += nIndex;
+ }
+ if ( pNewSubStr && pNewSubStr->length )
+ {
+ rtl_str_ImplCopy( pBuffer, pNewSubStr->buffer, pNewSubStr->length );
+ pBuffer += pNewSubStr->length;
+ }
+ rtl_str_ImplCopy( pBuffer, pStr->buffer+nIndex+nCount, pStr->length-nIndex-nCount );
+
+ /* must be done at least, if pStr or pNewSubStr == *ppThis */
+ if ( pOrg )
+ IMPL_RTL_STRINGNAME( release )( pOrg );
+ }
+}
+
+/* ----------------------------------------------------------------------- */
+
+void SAL_CALL IMPL_RTL_STRINGNAME( newReplace )( IMPL_RTL_STRINGDATA** ppThis,
+ IMPL_RTL_STRINGDATA* pStr,
+ IMPL_RTL_STRCODE cOld,
+ IMPL_RTL_STRCODE cNew )
+{
+ IMPL_RTL_STRINGDATA* pOrg = *ppThis;
+ int bChanged = 0;
+ sal_Int32 nLen = pStr->length;
+ const IMPL_RTL_STRCODE* pCharStr = pStr->buffer;
+
+ while ( nLen > 0 )
+ {
+ if ( *pCharStr == cOld )
+ {
+ /* Copy String */
+ IMPL_RTL_STRCODE* pNewCharStr = IMPL_RTL_STRINGNAME( ImplNewCopy )( ppThis, pStr, pCharStr-pStr->buffer );
+
+ /* replace/copy rest of the string */
+ if ( pNewCharStr )
+ {
+ *pNewCharStr = cNew;
+ pNewCharStr++;
+ pCharStr++;
+ nLen--;
+
+ while ( nLen > 0 )
+ {
+ if ( *pCharStr == cOld )
+ *pNewCharStr = cNew;
+ else
+ *pNewCharStr = *pCharStr;
+
+ pNewCharStr++;
+ pCharStr++;
+ nLen--;
+ }
+ }
+
+ bChanged = 1;
+ break;
+ }
+
+ pCharStr++;
+ nLen--;
+ }
+
+ if ( !bChanged )
+ {
+ *ppThis = pStr;
+ IMPL_RTL_AQUIRE( pStr );
+ }
+
+ /* must be done at least, if pStr == *ppThis */
+ if ( pOrg )
+ IMPL_RTL_STRINGNAME( release )( pOrg );
+}
+
+/* ----------------------------------------------------------------------- */
+
+void SAL_CALL IMPL_RTL_STRINGNAME( newToAsciiLowerCase )( IMPL_RTL_STRINGDATA** ppThis,
+ IMPL_RTL_STRINGDATA* pStr )
+{
+ IMPL_RTL_STRINGDATA* pOrg = *ppThis;
+ int bChanged = 0;
+ sal_Int32 nLen = pStr->length;
+ const IMPL_RTL_STRCODE* pCharStr = pStr->buffer;
+
+ while ( nLen > 0 )
+ {
+ /* Between A-Z (65-90), than to lowercase (+32) */
+ if ( (*pCharStr >= 65) && (*pCharStr <= 90) )
+ {
+ /* Copy String */
+ IMPL_RTL_STRCODE* pNewCharStr = IMPL_RTL_STRINGNAME( ImplNewCopy )( ppThis, pStr, pCharStr-pStr->buffer );
+
+ /* replace/copy rest of the string */
+ if ( pNewCharStr )
+ {
+ /* to lowercase (+32) */
+ *pNewCharStr = *pCharStr+32;
+ pNewCharStr++;
+ pCharStr++;
+ nLen--;
+
+ while ( nLen > 0 )
+ {
+ /* Between A-Z (65-90), than to lowercase (+32) */
+ if ( (*pCharStr >= 65) && (*pCharStr <= 90) )
+ *pNewCharStr = *pCharStr+32;
+ else
+ *pNewCharStr = *pCharStr;
+
+ pNewCharStr++;
+ pCharStr++;
+ nLen--;
+ }
+ }
+
+ bChanged = 1;
+ break;
+ }
+
+ pCharStr++;
+ nLen--;
+ }
+
+ if ( !bChanged )
+ {
+ *ppThis = pStr;
+ IMPL_RTL_AQUIRE( pStr );
+ }
+
+ /* must be done at least, if pStr == *ppThis */
+ if ( pOrg )
+ IMPL_RTL_STRINGNAME( release )( pOrg );
+}
+
+/* ----------------------------------------------------------------------- */
+
+void SAL_CALL IMPL_RTL_STRINGNAME( newToAsciiUpperCase )( IMPL_RTL_STRINGDATA** ppThis,
+ IMPL_RTL_STRINGDATA* pStr )
+{
+ IMPL_RTL_STRINGDATA* pOrg = *ppThis;
+ int bChanged = 0;
+ sal_Int32 nLen = pStr->length;
+ const IMPL_RTL_STRCODE* pCharStr = pStr->buffer;
+
+ while ( nLen > 0 )
+ {
+ /* Between a-z (97-122), than to uppercase (-32) */
+ if ( (*pCharStr >= 97) && (*pCharStr <= 122) )
+ {
+ /* Copy String */
+ IMPL_RTL_STRCODE* pNewCharStr = IMPL_RTL_STRINGNAME( ImplNewCopy )( ppThis, pStr, pCharStr-pStr->buffer );
+
+ /* replace/copy rest of the string */
+ if ( pNewCharStr )
+ {
+ /* to uppercase (-32) */
+ *pNewCharStr = *pCharStr-32;
+ pNewCharStr++;
+ pCharStr++;
+ nLen--;
+
+ while ( nLen > 0 )
+ {
+ /* Between a-z (97-122), than to uppercase (-32) */
+ if ( (*pCharStr >= 97) && (*pCharStr <= 122) )
+ *pNewCharStr = *pCharStr-32;
+ else
+ *pNewCharStr = *pCharStr;
+
+ pNewCharStr++;
+ pCharStr++;
+ nLen--;
+ }
+ }
+
+ bChanged = 1;
+ break;
+ }
+
+ pCharStr++;
+ nLen--;
+ }
+
+ if ( !bChanged )
+ {
+ *ppThis = pStr;
+ IMPL_RTL_AQUIRE( pStr );
+ }
+
+ /* must be done at least, if pStr == *ppThis */
+ if ( pOrg )
+ IMPL_RTL_STRINGNAME( release )( pOrg );
+}
+
+/* ----------------------------------------------------------------------- */
+
+void SAL_CALL IMPL_RTL_STRINGNAME( newTrim )( IMPL_RTL_STRINGDATA** ppThis,
+ IMPL_RTL_STRINGDATA* pStr )
+{
+ IMPL_RTL_STRINGDATA* pOrg = *ppThis;
+ const IMPL_RTL_STRCODE* pCharStr = pStr->buffer;
+ sal_Int32 nPreSpaces = 0;
+ sal_Int32 nPostSpaces = 0;
+ sal_Int32 nLen = pStr->length;
+ sal_Int32 nIndex = nLen-1;
+
+ while ( (nPreSpaces < nLen) && rtl_ImplIsWhitespace( IMPL_RTL_USTRCODE(*(pCharStr+nPreSpaces)) ) )
+ nPreSpaces++;
+
+ while ( (nIndex > nPreSpaces) && rtl_ImplIsWhitespace( IMPL_RTL_USTRCODE(*(pCharStr+nIndex)) ) )
+ {
+ nPostSpaces++;
+ nIndex--;
+ }
+
+ if ( !nPreSpaces && !nPostSpaces )
+ {
+ *ppThis = pStr;
+ IMPL_RTL_AQUIRE( pStr );
+ }
+ else
+ {
+ nLen -= nPostSpaces+nPreSpaces;
+ *ppThis = IMPL_RTL_STRINGNAME( ImplAlloc )( nLen );
+ OSL_ASSERT(*ppThis != NULL);
+ if ( *ppThis )
+ rtl_str_ImplCopy( (*ppThis)->buffer, pStr->buffer+nPreSpaces, nLen );
+ }
+
+ /* must be done at least, if pStr == *ppThis */
+ if ( pOrg )
+ IMPL_RTL_STRINGNAME( release )( pOrg );
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL IMPL_RTL_STRINGNAME( getToken )( IMPL_RTL_STRINGDATA** ppThis,
+ IMPL_RTL_STRINGDATA* pStr,
+ sal_Int32 nToken,
+ IMPL_RTL_STRCODE cTok,
+ sal_Int32 nIndex )
+{
+ const IMPL_RTL_STRCODE* pCharStr = pStr->buffer;
+ const IMPL_RTL_STRCODE* pCharStrStart;
+ const IMPL_RTL_STRCODE* pOrgCharStr;
+ sal_Int32 nLen = pStr->length-nIndex;
+ sal_Int32 nTokCount = 0;
+
+ // Set ppThis to an empty string and return -1 if either nToken or nIndex is
+ // negative:
+ if (nIndex < 0) {
+ nToken = -1;
+ }
+
+ pCharStr += nIndex;
+ pOrgCharStr = pCharStr;
+ pCharStrStart = pCharStr;
+ while ( nLen > 0 )
+ {
+ if ( *pCharStr == cTok )
+ {
+ nTokCount++;
+
+ if ( nTokCount == nToken )
+ pCharStrStart = pCharStr+1;
+ else
+ {
+ if ( nTokCount > nToken )
+ break;
+ }
+ }
+
+ pCharStr++;
+ nLen--;
+ }
+
+ if ( (nToken < 0) || (nTokCount < nToken) || (pCharStr == pCharStrStart) )
+ {
+ IMPL_RTL_STRINGNAME( new )( ppThis );
+ if( (nToken < 0) || (nTokCount < nToken ) )
+ return -1;
+ else if( nLen > 0 )
+ return nIndex+(pCharStr-pOrgCharStr)+1;
+ else return -1;
+ }
+ else
+ {
+ IMPL_RTL_STRINGNAME( newFromStr_WithLength )( ppThis, pCharStrStart, pCharStr-pCharStrStart );
+ if ( nLen )
+ return nIndex+(pCharStr-pOrgCharStr)+1;
+ else
+ return -1;
+ }
+}
diff --git a/sal/rtl/source/surrogates.h b/sal/rtl/source/surrogates.h
new file mode 100644
index 000000000000..48fe4182ad46
--- /dev/null
+++ b/sal/rtl/source/surrogates.h
@@ -0,0 +1,50 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SAL_RTL_SOURCE_SURROGATES_H
+#define INCLUDED_SAL_RTL_SOURCE_SURROGATES_H
+
+#include "sal/config.h"
+
+#define SAL_RTL_FIRST_HIGH_SURROGATE 0xD800
+#define SAL_RTL_LAST_HIGH_SURROGATE 0xDBFF
+#define SAL_RTL_FIRST_LOW_SURROGATE 0xDC00
+#define SAL_RTL_LAST_LOW_SURROGATE 0xDFFF
+
+#define SAL_RTL_IS_HIGH_SURROGATE(utf16) \
+ ((utf16) >= SAL_RTL_FIRST_HIGH_SURROGATE && \
+ (utf16) <= SAL_RTL_LAST_HIGH_SURROGATE)
+
+#define SAL_RTL_IS_LOW_SURROGATE(utf16) \
+ ((utf16) >= SAL_RTL_FIRST_LOW_SURROGATE && \
+ (utf16) <= SAL_RTL_LAST_LOW_SURROGATE)
+
+#define SAL_RTL_COMBINE_SURROGATES(high, low) \
+ ((((high) - SAL_RTL_FIRST_HIGH_SURROGATE) << 10) + \
+ ((low) - SAL_RTL_FIRST_LOW_SURROGATE) + 0x10000)
+
+#endif
diff --git a/sal/rtl/source/tres.c b/sal/rtl/source/tres.c
new file mode 100644
index 000000000000..85e5c4367066
--- /dev/null
+++ b/sal/rtl/source/tres.c
@@ -0,0 +1,686 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <stdio.h>
+#include <rtl/tres.h>
+#include <osl/diagnose.h>
+#include <osl/time.h>
+
+ /* force an assertion on false state */
+#define TST_BOOM(c, m) OSL_ENSURE(c, m)
+
+
+typedef struct _rtl_CmpState
+{
+ struct _rtl_CmpState* m_next;
+ struct _rtl_CmpState* m_prev;
+
+ sal_Bool m_stat;
+ rtl_String* m_msg;
+
+} rtl_CmpState;
+
+typedef struct _rtl_FuncState
+{
+ struct _rtl_FuncState* m_next;
+ struct _rtl_FuncState* m_prev;
+ rtl_String* m_name;
+ sal_uInt32 m_flags;
+ sal_uInt32 m_start;
+ sal_uInt32 m_stop;
+ struct _rtl_CmpState* m_cmp;
+
+} rtl_FuncState;
+
+
+
+typedef struct _rtl_TestResult_Data
+{
+ rtl_TestResult_vtable* m_funcs;
+ void* m_externaldata;
+
+ rtl_FuncState* m_state;
+
+} rtl_TestResult_Data;
+
+
+ /**
+ * internal helper functions
+ */
+
+ /* ...to create, link, unlink and destroy allocated memory */
+rtl_FuncState* SAL_CALL rtl_tres_create_funcstate( const sal_Char* meth );
+rtl_FuncState* SAL_CALL rtl_tres_link_funcstate( rtl_FuncState* ptr,
+ rtl_FuncState* plink );
+rtl_FuncState* SAL_CALL rtl_tres_unlink_funcstate( rtl_FuncState* plink );
+rtl_CmpState* SAL_CALL rtl_tres_create_cmpstate(
+ sal_Bool state,
+ const sal_Char* msg
+ );
+rtl_CmpState* SAL_CALL rtl_tres_link_cmpstate( rtl_CmpState* ptr,
+ rtl_CmpState* plink );
+rtl_CmpState* SAL_CALL rtl_tres_unlink_cmpstate( rtl_CmpState* plink );
+sal_uInt32 SAL_CALL rtl_tres_timer();
+void SAL_CALL rtl_tres_destroy_funcstate( rtl_FuncState* pState_ );
+void SAL_CALL rtl_tres_destroy_funcstates( rtl_FuncState* pState_ );
+void SAL_CALL rtl_tres_destroy_cmpstates( rtl_CmpState* pState_ );
+void SAL_CALL rtl_tres_destroy_cmpstate( rtl_CmpState* pState_ );
+
+
+ /* set and clear single bits */
+static void SAL_CALL rtl_tres_setbit( rtl_FuncState* pState_,
+ sal_uInt32 flag );
+static void SAL_CALL rtl_tres_clearbit( rtl_FuncState* pState_,
+ sal_uInt32 flag );
+
+ /**
+ * forward declarations of concrete function implementations overloadable
+ * and accessible via vtable
+ */
+static sal_Bool SAL_CALL rtl_tres_state(
+ rtl_TestResult* pThis_,
+ sal_Bool state,
+ const sal_Char* msg,
+ const sal_Char* sub,
+ sal_Bool v
+ );
+
+static void SAL_CALL rtl_tres_end( rtl_TestResult* pThis_,
+ const sal_Char* msg );
+
+static rtl_funcstate SAL_CALL rtl_tres_funcstate( rtl_TestResult* pThis_ );
+
+static sal_Bool SAL_CALL rtl_tres_ispassed( rtl_TestResult* pThis_ );
+static sal_Bool SAL_CALL rtl_tres_isok( rtl_TestResult* pThis_ );
+
+static sal_Bool SAL_CALL rtl_tres_isbit( rtl_TestResult* pThis_,
+ sal_uInt32 flag );
+
+static rtl_funcstate SAL_CALL rtl_tres_getnextfuncstate( rtl_funcstate );
+static rtl_funcstate SAL_CALL rtl_tres_getprevfuncstate( rtl_funcstate );
+static sal_uInt32 SAL_CALL rtl_tres_getflags( rtl_funcstate );
+sal_uInt32 SAL_CALL rtl_tres_getstarttime( rtl_funcstate );
+sal_uInt32 SAL_CALL rtl_tres_getstoptime( rtl_funcstate );
+static rtl_cmpstate SAL_CALL rtl_tres_getcmpstate( rtl_funcstate );
+
+static sal_Bool SAL_CALL rtl_tres_getstat( rtl_cmpstate );
+rtl_String* SAL_CALL rtl_tres_getname( rtl_funcstate );
+rtl_String* SAL_CALL rtl_tres_getmsg( rtl_cmpstate );
+static rtl_cmpstate SAL_CALL rtl_tres_getnextcmpstate( rtl_cmpstate );
+
+
+ /**
+ * initialize vtable with function pointers
+ */
+static rtl_TestResult_vtable trVTable =
+{
+ sizeof(rtl_TestResult_vtable),
+ rtl_tres_state,
+ rtl_tres_end,
+ rtl_tres_ispassed,
+ rtl_tres_isok,
+ rtl_tres_funcstate,
+ rtl_tres_isbit,
+ rtl_tres_getnextfuncstate,
+ rtl_tres_getprevfuncstate,
+ rtl_tres_getflags,
+ rtl_tres_getname,
+ rtl_tres_getstarttime,
+ rtl_tres_getstoptime,
+ rtl_tres_getcmpstate,
+ rtl_tres_getstat,
+ rtl_tres_getmsg,
+ rtl_tres_getnextcmpstate
+};
+
+ /**
+ * rtl_tres_create
+ * create and initialize data struct for TestResult
+ *
+ * @param const sal_Char* meth = name of the method (entryname)
+ * @param sal_uInt32 flags = bitmap of comandline and status flags
+ *
+ * @return rtl_TestResult* = pointer to a new allocated testresult struct
+ */
+rtl_TestResult* rtl_tres_create( const sal_Char* meth, sal_uInt32 flags )
+{
+ /* allocate memory for testresult data structure */
+ rtl_TestResult_Data* pData = (rtl_TestResult_Data*) malloc( sizeof(
+ rtl_TestResult_Data ) );
+ /* initialize members... */
+ pData->m_funcs = &trVTable; /* ...vtableptr to vtbladr */
+ pData->m_externaldata = 0; /* ...external data pointer */
+
+ /* allocate memory for state structure and initialize members */
+ pData->m_state = rtl_tres_create_funcstate( meth );
+ pData->m_state->m_flags = flags; /* ...option Bitmap */
+
+ /* set OK flag initial */
+ rtl_tres_setbit( pData->m_state, rtl_tres_Flag_OK );
+
+ return (rtl_TestResult*)pData ;
+}
+
+/**
+ * rtl_tres_create_funcstate
+ * allocates and initializes a structure to represent the status of a test
+ * entry or its substates
+ *
+ * @param const sal_Char* meth = the name of the method (entry or sub entry)
+ *
+ * @return rtl_FuncState* = pointer to a new allocated funcstate struct
+ */
+rtl_FuncState* SAL_CALL rtl_tres_create_funcstate( const sal_Char* meth )
+{
+ rtl_FuncState* pStat = 0; /* status structure */
+
+ /* allocate memory for status structure */
+ pStat = (rtl_FuncState*) malloc( sizeof( struct _rtl_FuncState ) );
+
+ if ( pStat )
+ {
+ pStat->m_next = pStat; /* init ptr to next struct */
+ pStat->m_prev = pStat; /* init ptr to prev struct */
+
+ pStat->m_name = 0; /* init name */
+ pStat->m_flags = 0; /* init flags */
+ pStat->m_start = rtl_tres_timer(); /* init start milliseconds */
+ pStat->m_stop = 0; /* init stop milliseconds */
+ pStat->m_cmp = 0; /* init ptr to msg struct */
+ rtl_string_newFromStr( &pStat->m_name, meth );/* copy meth to name */
+
+ /* set ok flag initially */
+ rtl_tres_setbit(pStat, rtl_tres_Flag_OK);
+ }
+
+ return ( pStat );
+}
+ /**
+ * rtl_tres_link_funcstate
+ * link initialized funcstate structure to a circular double linked list
+ *
+ * @param rtl_FuncState* ptr = pointer to a funcstate where to link in new
+ * @param rtl_FuncState* plink = pointer to a funcstate to link in list
+ *
+ * @return rtl_FuncState* = pointer to structure linked in new
+ */
+rtl_FuncState* SAL_CALL rtl_tres_link_funcstate( rtl_FuncState* ptr,
+ rtl_FuncState* plink )
+{
+ ptr->m_next->m_prev = plink;
+ ptr->m_next->m_prev->m_next = ptr->m_next;
+ ptr->m_next->m_prev->m_prev = ptr;
+ ptr->m_next = plink;
+ return ( plink );
+}
+
+ /**
+ * rtl_tres_unlink_funcstate
+ * unlink funcstate structure from a circular double linked list
+ *
+ * @param rtl_FuncState* plink = pointer to a funcstate to unlink from list
+ *
+ * @return rtl_FuncState* = pointer to funcstate struct unlinked from
+ * list
+ */
+rtl_FuncState* SAL_CALL rtl_tres_unlink_funcstate( rtl_FuncState* plink )
+{
+ plink->m_next->m_prev = plink->m_prev;
+ plink->m_prev->m_next = plink->m_next;
+ plink->m_next = plink;
+ plink->m_prev = plink;
+ return ( plink );
+}
+
+ /**
+ * rtl_tres_link_cmpstate
+ * link initialized cmpstate structure to a circular double linked list
+ *
+ * @param rtl_CmpState* ptr = pointer to a cmpstate where to link in new
+ * @param rtl_CmpState* plink = pointer to a cmpstate to link in list
+ *
+ * @return rtl_CmpState* = pointer to cmpstate struct linked in new
+ */
+rtl_CmpState* SAL_CALL rtl_tres_link_cmpstate( rtl_CmpState* ptr,
+ rtl_CmpState* plink )
+{
+ ptr->m_next->m_prev = plink;
+ ptr->m_next->m_prev->m_next = ptr->m_next;
+ ptr->m_next->m_prev->m_prev = ptr;
+ ptr->m_next = plink;
+ return ( plink );
+}
+ /**
+ * rtl_tres_unlink_cmpstate
+ * unlink cmpstate structure from a circular double linked list
+ *
+ * @param rtl_CmpState* plink = pointer to a cmpstate to unlink from list
+ *
+ * @return rtl_CmpState* = pointer to cmpstate struct unlinked from list
+ */
+rtl_CmpState* SAL_CALL rtl_tres_unlink_cmpstate( rtl_CmpState* plink )
+{
+ plink->m_next->m_prev = plink->m_prev;
+ plink->m_prev->m_next = plink->m_next;
+ plink->m_next = plink;
+ plink->m_prev = plink;
+ return ( plink );
+}
+
+ /**
+ * rtl_tres_create_cmpstate
+ * allocates and initializes a structure to represent the status of a test
+ * comparison
+ *
+ * @param sal_Bool state = compare state
+ * @param sal_Char* msg = message for logging and debug purposes
+ *
+ * @return rtl_CmpState* = pointer to the new allocated struct
+ */
+rtl_CmpState* SAL_CALL rtl_tres_create_cmpstate(
+ sal_Bool state,
+ const sal_Char* msg
+ )
+{
+ /* allocate memory for cmpstate struct */
+ rtl_CmpState* pStat = (rtl_CmpState*) malloc( sizeof( rtl_CmpState ) );
+
+ /* initialize if memory could be allocated */
+ if ( pStat )
+ {
+ pStat->m_next = pStat; /* init next with this */
+ pStat->m_prev = pStat; /* init prev with this */
+ pStat->m_msg = 0;
+ pStat->m_stat = state; /* boolean state */
+ rtl_string_newFromStr( &pStat->m_msg, msg ); /* copy message */
+ }
+ return ( pStat );
+}
+
+ /**
+ * rtl_tres_destroy
+ * free allocated memory of testresult data struct
+ *
+ * @param rtl_TestResult* pThis_ = ponter to a valid testresult struct
+ */
+void SAL_CALL rtl_tres_destroy( rtl_TestResult* pThis_ )
+{
+ /* cast to implementation representation structure */
+ rtl_TestResult_Data* pData = (rtl_TestResult_Data*) pThis_;
+
+ /* destroy all funcstates */
+ if ( pData->m_state )
+ rtl_tres_destroy_funcstates( pData->m_state );
+
+ /* free allocted memory and reinitialize to zero */
+ /* to be able to prevent dangling pointer access*/
+ free( pData ); pData = 0;
+}
+
+ /**
+ * rtl_tres_destroy_funcstates
+ * free allocated memory occupied by the list of funcstate data structs
+ * (iterates through next pointers)
+ *
+ * @param rtl_FuncState* pState_ = pointer to a valid funcstate struct
+ */
+void SAL_CALL rtl_tres_destroy_funcstates( rtl_FuncState* pState_ )
+{
+ rtl_FuncState* plink = pState_->m_next;
+ while ( plink != plink->m_next )
+ {
+ rtl_tres_destroy_funcstate( rtl_tres_unlink_funcstate( plink ) );
+ plink = pState_->m_next;
+ }
+ rtl_tres_destroy_funcstate( plink );
+}
+
+ /**
+ * rtl_tres_destroy_cmpstates
+ * free allocated memory occupied by the list of cmpstate data structs
+ * (iterates through next pointers)
+ *
+ * @param rtl_CmpState* pState_ = pointer to a valid cmpstate struct
+ */
+void SAL_CALL rtl_tres_destroy_cmpstates( rtl_CmpState* pState_ )
+{
+ rtl_CmpState* plink = pState_->m_next;
+ while ( plink != plink->m_next )
+ {
+ rtl_tres_destroy_cmpstate( rtl_tres_unlink_cmpstate( plink ) );
+ plink = pState_->m_next;
+ }
+ rtl_tres_destroy_cmpstate( plink );
+}
+
+
+ /**
+ * rtl_tres_destroy_funcstate
+ * free allocated memory occupied by one funcstate and it's list
+ * of cmpstate data structs
+ *
+ * @param rtl_FuncState* pState_ = pointer to a valid funcstate struct
+ */
+void SAL_CALL rtl_tres_destroy_funcstate( rtl_FuncState* pState_ )
+{
+ rtl_FuncState* plink = pState_;
+
+ if ( plink->m_cmp )
+ rtl_tres_destroy_cmpstates( plink->m_cmp );
+
+ if ( plink->m_name )
+ {
+ rtl_string_release( plink->m_name );
+ plink->m_name = 0;
+ }
+ plink->m_flags = 0;
+ free( plink );
+ plink = 0;
+}
+
+ /**
+ * rtl_tres_destroy_cmpstate
+ * free allocated memory of a cmpstate data struct
+ *
+ * @param rtl_CmpState* pState_ = pointer to cmpstate struct to destroy
+ */
+void SAL_CALL rtl_tres_destroy_cmpstate( rtl_CmpState* pState_ )
+{
+
+ rtl_CmpState* plink = pState_;
+
+ if ( plink->m_msg )
+ {
+ rtl_string_release( plink->m_msg );
+ plink->m_msg = 0;
+ }
+ free( plink );
+ plink = 0;
+}
+ /**
+ * central function to call in tests
+ *
+ * @param rtl_TestResult* pThis_ = self pointer to TestResult structure
+ * @param sal_Bool state = boolean result of statement comparison
+ * @param const sal_Char* msg = message for actual statementcomparison
+ * @param const sal_Char* sub = name of sub testfunction
+ * @param sal_Bool v = boolean verbose parameter
+ *
+ * @return sal_Bool = determines if statement comparison
+ * was positive or not
+ */
+static sal_Bool SAL_CALL rtl_tres_state(
+ rtl_TestResult* pThis_,
+ sal_Bool state,
+ const sal_Char* msg,
+ const sal_Char* sub,
+ sal_Bool v
+ )
+{
+
+ /* cast pointer to testresult data implementation struct*/
+ rtl_TestResult_Data* pData = (rtl_TestResult_Data*)pThis_;
+
+ /* initialize funcstate pointer with masterstate */
+ rtl_FuncState* pFunc = pData->m_state;
+
+ /* if substate required */
+ if ( sub )
+ {
+ /* link new created function state to last item */
+ pFunc = rtl_tres_link_funcstate( pFunc->m_prev,
+ rtl_tres_create_funcstate( sub ) );
+
+ /* indicate this state as substate */
+ rtl_tres_setbit( pFunc, rtl_tres_Flag_SUB );
+
+ /* indicate prvious state as passed if no masterstate */
+ if ( pFunc->m_prev != pData->m_state )
+ rtl_tres_setbit( pFunc->m_prev, rtl_tres_Flag_PASSED );
+ }
+
+
+ /* test failed */
+ if( ! state )
+ {
+ /* determine if assertion should be thrown */
+ if ( rtl_tres_isbit( pThis_, rtl_tres_Flag_BOOM ) )
+ {
+ /* if message available */
+ if ( msg )
+ TST_BOOM( state, msg );
+ else
+ TST_BOOM( state, "no msg available" );
+ }
+
+ /* clear this state ok flag and masterstate ok flag */
+ rtl_tres_clearbit( pFunc, rtl_tres_Flag_OK );
+ rtl_tres_clearbit( pData->m_state, rtl_tres_Flag_OK );
+ }
+ /* message available */
+ if( msg )
+ {
+ /* append a new comparison state */
+ if (! pFunc->m_cmp )
+ pFunc->m_cmp = rtl_tres_create_cmpstate( state, msg );
+ else
+ rtl_tres_link_cmpstate( pFunc->m_cmp,
+ rtl_tres_create_cmpstate(state, msg ) );
+
+ /* message to stderr required ? */
+ if ( v || ( pFunc->m_next->m_flags & rtl_tres_Flag_VERBOSE ) )
+ fprintf( stderr, "%s\n", msg );
+ }
+
+ pFunc->m_stop = rtl_tres_timer();
+ return ( state );
+}
+
+ /**
+ * rtl_tres_timer
+ * function to get actual timevalue
+ * this has to be replaced by a high resolution timer
+ */
+sal_uInt32 SAL_CALL rtl_tres_timer()
+{
+ sal_uInt32 val = 0;
+ TimeValue* tmv = (TimeValue*)malloc( sizeof( TimeValue ) );
+ osl_getSystemTime( tmv );
+ val = tmv->Nanosec/1000L;
+ free( tmv );
+ return ( val );
+}
+
+
+static void SAL_CALL rtl_tres_end( rtl_TestResult* pThis_,
+ const sal_Char* msg )
+{
+ rtl_TestResult_Data* pData = (rtl_TestResult_Data*) pThis_;
+
+ if( msg )
+ {
+ if (! pData->m_state->m_cmp )
+ pData->m_state->m_cmp = rtl_tres_create_cmpstate( sal_True, msg );
+ else
+ rtl_tres_link_cmpstate( pData->m_state->m_cmp,
+ rtl_tres_create_cmpstate( sal_True, msg ) );
+ }
+ pData->m_state->m_prev->m_flags |= rtl_tres_Flag_PASSED;
+ pData->m_state->m_flags |= rtl_tres_Flag_PASSED;
+ pData->m_state->m_stop = rtl_tres_timer();
+}
+
+
+static sal_Bool SAL_CALL rtl_tres_ispassed( rtl_TestResult* pThis_ )
+{
+ return rtl_tres_isbit( pThis_, rtl_tres_Flag_PASSED );
+}
+
+static sal_Bool SAL_CALL rtl_tres_isok( rtl_TestResult* pThis_ )
+{
+ return rtl_tres_isbit( pThis_, rtl_tres_Flag_OK );
+}
+ /**
+ * return pointer to funcstate structure
+ */
+static rtl_funcstate SAL_CALL rtl_tres_funcstate( rtl_TestResult* pThis_ )
+{
+
+ rtl_TestResult_Data* pThis = (rtl_TestResult_Data*) pThis_;
+ return (rtl_funcstate)pThis->m_state;
+}
+
+ /**
+ * determine if a flag is set or not
+ */
+static sal_Bool SAL_CALL rtl_tres_isbit( rtl_TestResult* pThis_,
+ sal_uInt32 flag )
+{
+ return (sal_Bool)
+ ((((rtl_TestResult_Data *) pThis_)->m_state->m_flags & flag) == flag);
+}
+ /**
+ * set one single bit
+ */
+static void SAL_CALL rtl_tres_setbit( rtl_FuncState* pState_,
+ sal_uInt32 flag )
+{
+ pState_->m_flags |= flag;
+}
+ /**
+ * clear one single bit
+ */
+static void SAL_CALL rtl_tres_clearbit( rtl_FuncState* pState_,
+ sal_uInt32 flag )
+{
+ pState_->m_flags = pState_->m_flags & ( ~flag );
+}
+
+ /**
+ * returns next pointer of passed funcstate structure
+ */
+rtl_funcstate SAL_CALL rtl_tres_getnextfuncstate( rtl_funcstate fstate )
+{
+ rtl_FuncState* fs = (rtl_FuncState*)fstate;
+ return( (rtl_funcstate)fs->m_next );
+
+}
+ /**
+ * returns previous pointer of passed funcstate structure
+ */
+rtl_funcstate SAL_CALL rtl_tres_getprevfuncstate( rtl_funcstate fstate )
+{
+ rtl_FuncState* fs = (rtl_FuncState*)fstate;
+ return( (rtl_funcstate)fs->m_prev );
+
+}
+ /**
+ * returns flag value of passed funcstate structure
+ */
+sal_uInt32 SAL_CALL rtl_tres_getflags( rtl_funcstate fstate )
+{
+ rtl_FuncState* fs = (rtl_FuncState*)fstate;
+ return( fs->m_flags );
+}
+ /**
+ * returns name of passed funcstate structure
+ */
+rtl_String* SAL_CALL rtl_tres_getname( rtl_funcstate fstate )
+{
+ rtl_FuncState* fs = (rtl_FuncState*)fstate;
+ return( fs->m_name );
+}
+ /**
+ * returns starttime of passed funcstate structure
+ */
+sal_uInt32 SAL_CALL rtl_tres_getstarttime( rtl_funcstate fstate )
+{
+ rtl_FuncState* fs = (rtl_FuncState*)fstate;
+ return( fs->m_start );
+}
+
+ /**
+ * returns stoptime of passed funcstate structure
+ */
+sal_uInt32 SAL_CALL rtl_tres_getstoptime( rtl_funcstate fstate )
+{
+ rtl_FuncState* fs = (rtl_FuncState*)fstate;
+ return( fs->m_stop );
+}
+
+ /**
+ * returns pointer to cmpstate of passed funcstate structure
+ */
+rtl_cmpstate SAL_CALL rtl_tres_getcmpstate( rtl_funcstate fstate)
+{
+ rtl_FuncState* fs = (rtl_FuncState*)fstate;
+ return( (rtl_cmpstate)fs->m_cmp );
+
+}
+ /**
+ * returns boolean state of passed cmpstate structure
+ */
+sal_Bool SAL_CALL rtl_tres_getstat( rtl_cmpstate cstate)
+{
+ rtl_CmpState* cs = (rtl_CmpState*)cstate;
+ return( cs->m_stat );
+}
+ /**
+ * returns message of passed cmpstate structure
+ */
+rtl_String* SAL_CALL rtl_tres_getmsg( rtl_cmpstate cstate)
+{
+ rtl_CmpState* cs = (rtl_CmpState*)cstate;
+ return( cs->m_msg );
+}
+ /**
+ * returns next pointer of passed cmpstate structure
+ */
+rtl_cmpstate SAL_CALL rtl_tres_getnextcmpstate( rtl_cmpstate cstate)
+{
+ rtl_CmpState* cs = (rtl_CmpState*)cstate;
+ return( (rtl_cmpstate)cs->m_next );
+}
+
+/*
+// <method_logPrintf>
+//inline void logPrintf ( const sal_Bool bTestCaseState,
+// const char *pFormatStr, ...
+// )
+//{
+// if( m_pFunctions && m_pFunctions->pLogPrintf )
+// {
+// va_list vArgumentList;
+// va_start ( vArgumentList, pFormatStr );
+
+// m_pFunctions->pLogPrintf( this, bTestCaseState, pFormatStr, vArgumentList );
+
+// va_end ( vArgumentList );
+// }
+//} // </method_logPrintf>
+ */
+
diff --git a/sal/rtl/source/unload.cxx b/sal/rtl/source/unload.cxx
new file mode 100644
index 000000000000..ba31bd9c86f9
--- /dev/null
+++ b/sal/rtl/source/unload.cxx
@@ -0,0 +1,417 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+#include <rtl/unload.h>
+#include <rtl/alloc.h>
+#include <rtl/ustring.hxx>
+#include <osl/mutex.hxx>
+#include <hash_map>
+#include "rtl/allocator.hxx"
+
+#include <functional>
+#include <list>
+#include <deque>
+
+using osl::MutexGuard;
+
+//----------------------------------------------------------------------------
+
+static void rtl_notifyUnloadingListeners();
+
+static sal_Bool isEqualTimeValue ( const TimeValue* time1, const TimeValue* time2)
+{
+ if( time1->Seconds == time2->Seconds &&
+ time1->Nanosec == time2->Nanosec)
+ return sal_True;
+ else
+ return sal_False;
+}
+
+static sal_Bool isGreaterTimeValue( const TimeValue* time1, const TimeValue* time2)
+{
+ sal_Bool retval= sal_False;
+ if ( time1->Seconds > time2->Seconds)
+ retval= sal_True;
+ else if ( time1->Seconds == time2->Seconds)
+ {
+ if( time1->Nanosec > time2->Nanosec)
+ retval= sal_True;
+ }
+ return retval;
+}
+
+static sal_Bool isGreaterEqualTimeValue( const TimeValue* time1, const TimeValue* time2)
+{
+ if( isEqualTimeValue( time1, time2) )
+ return sal_True;
+ else if( isGreaterTimeValue( time1, time2))
+ return sal_True;
+ else
+ return sal_False;
+}
+
+static void addTimeValue( const TimeValue* value1, const TimeValue* value2, TimeValue* result)
+{
+ sal_uInt64 sum;
+ result->Nanosec=0;
+ result->Seconds=0;
+
+ sum= value1->Nanosec + value2->Nanosec;
+ if( sum >= 1000000000 )
+ {
+ result->Seconds=1;
+ sum -= 1000000000;
+ }
+ result->Nanosec= (sal_uInt32)sum;
+ result->Seconds += value1->Seconds + value2->Seconds;
+}
+
+
+static sal_Bool hasEnoughTimePassed( const TimeValue* unusedSince, const TimeValue* timespan)
+{
+ sal_Bool retval= sal_False;
+ TimeValue currentTime;
+ if( osl_getSystemTime( &currentTime))
+ {
+ TimeValue addedTime;
+ addTimeValue( unusedSince, timespan, &addedTime);
+ if( isGreaterEqualTimeValue( &currentTime, &addedTime))
+ retval= sal_True;
+ }
+
+ return retval;
+}
+
+static osl::Mutex* getUnloadingMutex()
+{
+ static osl::Mutex * g_pMutex= NULL;
+ if (!g_pMutex)
+ {
+ MutexGuard guard( osl::Mutex::getGlobalMutex() );
+ if (!g_pMutex)
+ {
+ static osl::Mutex g_aMutex;
+ g_pMutex= &g_aMutex;
+ }
+ }
+ return g_pMutex;
+}
+
+extern "C" void rtl_moduleCount_acquire(rtl_ModuleCount * that )
+{
+ rtl_StandardModuleCount* pMod= (rtl_StandardModuleCount*)that;
+ osl_incrementInterlockedCount( &pMod->counter);
+}
+
+extern "C" void rtl_moduleCount_release( rtl_ModuleCount * that )
+{
+ rtl_StandardModuleCount* pMod= (rtl_StandardModuleCount*)that;
+ OSL_ENSURE( pMod->counter >0 , "library counter incorrect" );
+ osl_decrementInterlockedCount( &pMod->counter);
+ if( pMod->counter == 0)
+ {
+ MutexGuard guard( getUnloadingMutex());
+
+ if( sal_False == osl_getSystemTime( &pMod->unusedSince) )
+ {
+ // set the time to 0 if we could not get the time
+ pMod->unusedSince.Seconds= 0;
+ pMod->unusedSince.Nanosec= 0;
+ }
+ }
+}
+
+
+struct hashModule
+{
+ size_t operator()( const oslModule& rkey) const
+ {
+ return (size_t)rkey;
+ }
+};
+
+typedef std::hash_map<
+ oslModule,
+ std::pair<sal_uInt32, component_canUnloadFunc>,
+ hashModule,
+ std::equal_to<oslModule>,
+ rtl::Allocator<oslModule>
+> ModuleMap;
+
+typedef ModuleMap::iterator Mod_IT;
+
+static ModuleMap& getModuleMap()
+{
+ static ModuleMap * g_pMap= NULL;
+ if (!g_pMap)
+ {
+ MutexGuard guard( getUnloadingMutex() );
+ if (!g_pMap)
+ {
+ static ModuleMap g_aModuleMap;
+ g_pMap= &g_aModuleMap;
+ }
+ }
+ return *g_pMap;
+}
+
+extern "C" sal_Bool rtl_moduleCount_canUnload( rtl_StandardModuleCount * that, TimeValue * libUnused)
+{
+ if (that->counter == 0)
+ {
+ MutexGuard guard( getUnloadingMutex());
+ if (libUnused && (that->counter == 0))
+ {
+ rtl_copyMemory(libUnused, &that->unusedSince, sizeof(TimeValue));
+ }
+ }
+ return (that->counter == 0);
+}
+
+
+extern "C" sal_Bool SAL_CALL rtl_registerModuleForUnloading( oslModule module)
+{
+ MutexGuard guard( getUnloadingMutex());
+ ModuleMap& moduleMap= getModuleMap();
+ sal_Bool ret= sal_True;
+
+ // If the module has been registered before, then find it and increment
+ // its reference cout
+ Mod_IT it= moduleMap.find( module);
+ if( it != moduleMap.end())
+ {
+ //module already registered, increment ref count
+ it->second.first++;
+ }
+ else
+ {
+ // Test if the module supports unloading (exports component_canUnload)
+ rtl::OUString name(RTL_CONSTASCII_USTRINGPARAM( COMPONENT_CANUNLOAD));
+ component_canUnloadFunc pFunc=
+ (component_canUnloadFunc)osl_getFunctionSymbol( module, name.pData);
+ if (pFunc)
+ {
+ //register module for the first time, set ref count to 1
+ moduleMap[module]= std::make_pair((sal_uInt32)1, pFunc);
+ }
+ else
+ ret= sal_False;
+ }
+ return ret;
+}
+
+extern "C" void SAL_CALL rtl_unregisterModuleForUnloading( oslModule module)
+{
+ MutexGuard guard( getUnloadingMutex());
+
+ ModuleMap& moduleMap= getModuleMap();
+ Mod_IT it= moduleMap.find( module);
+ if( it != moduleMap.end() )
+ {
+ // The module is registered, decrement ref count.
+ it->second.first --;
+
+ // If the refcount == 0 then remove the module from the map
+ if( it->second.first == 0)
+ moduleMap.erase( it);
+ }
+}
+
+extern "C" void SAL_CALL rtl_unloadUnusedModules( TimeValue* libUnused)
+{
+ MutexGuard guard( getUnloadingMutex());
+
+ typedef std::list< oslModule, rtl::Allocator<oslModule> > list_type;
+ list_type unloadedModulesList;
+
+ ModuleMap& moduleMap= getModuleMap();
+ Mod_IT it_e= moduleMap.end();
+
+ // notify all listeners
+ rtl_notifyUnloadingListeners();
+
+ // prepare default TimeValue if argumetn is NULL
+ TimeValue nullTime={0,0};
+ TimeValue* pLibUnused= libUnused? libUnused : &nullTime;
+
+ Mod_IT it= moduleMap.begin();
+ for (; it != it_e; ++it)
+ {
+ //can the module be unloaded?
+ component_canUnloadFunc func= it->second.second;
+ TimeValue unusedSince= {0, 0};
+
+ if( func( &unusedSince) )
+ {
+ // module can be unloaded if it has not been used at least for the time
+ // specified by the argument libUnused
+ if( hasEnoughTimePassed( &unusedSince, pLibUnused))
+ {
+ // get the reference count and unload the module as many times
+ sal_uInt32 refCount= it->second.first;
+
+ for ( sal_uInt32 i=0; i < refCount; i++)
+ osl_unloadModule( it->first);
+
+ // mark the module for later removal
+ unloadedModulesList.push_front( it->first);
+ }
+ }
+ }
+
+ // remove all entries containing invalid (unloaded) modules
+ list_type::const_iterator un_it= unloadedModulesList.begin();
+ for (; un_it != unloadedModulesList.end(); ++un_it)
+ {
+ moduleMap.erase( *un_it);
+ }
+}
+
+
+// ==============================================================================
+// Unloading Listener Administration
+//===============================================================================
+struct hashListener
+{
+ size_t operator()( const sal_Int32& rkey) const
+ {
+ return (size_t)rkey;
+ }
+};
+
+typedef std::hash_map<
+ sal_Int32,
+ std::pair<rtl_unloadingListenerFunc, void*>,
+ hashListener,
+ std::equal_to<sal_Int32>,
+ rtl::Allocator<sal_Int32>
+> ListenerMap;
+
+typedef ListenerMap::iterator Lis_IT;
+
+static ListenerMap& getListenerMap()
+{
+ static ListenerMap * g_pListeners= NULL;
+ if (!g_pListeners)
+ {
+ MutexGuard guard( getUnloadingMutex() );
+ if (!g_pListeners)
+ {
+ static ListenerMap g_aListenerMap;
+ g_pListeners= &g_aListenerMap;
+ }
+ }
+ return *g_pListeners;
+}
+
+
+// This queue contains cookies which have been passed out by rtl_addUnloadingListener and
+// which have been regainded by rtl_removeUnloadingListener. When rtl_addUnloadingListener
+// is called then a cookie has to be returned. First we look into the set if there is one
+// availabe. Otherwise a new cookie will be provided.
+// not a new value is returned.
+
+typedef std::deque<
+ sal_Int32,
+ rtl::Allocator<sal_Int32>
+> queue_type;
+
+static queue_type& getCookieQueue()
+{
+ static queue_type * g_pCookies= NULL;
+ if (!g_pCookies)
+ {
+ MutexGuard guard( getUnloadingMutex() );
+ if (!g_pCookies)
+ {
+ static queue_type g_aCookieQueue;
+ g_pCookies= &g_aCookieQueue;
+ }
+ }
+ return *g_pCookies;
+}
+
+static sal_Int32 getCookie()
+{
+ static sal_Int32 cookieValue= 1;
+
+ sal_Int32 retval;
+ queue_type& regainedCookies= getCookieQueue();
+ if( regainedCookies.empty() )
+ retval= cookieValue++;
+ else
+ {
+ retval= regainedCookies.front();
+ regainedCookies.pop_front();
+ }
+ return retval;
+}
+
+static inline void recycleCookie( sal_Int32 i)
+{
+ getCookieQueue().push_back(i);
+}
+
+
+// calling the function twice with the same arguments will return tow different cookies.
+// The listener will then notified twice.
+
+extern "C"
+sal_Int32 SAL_CALL rtl_addUnloadingListener( rtl_unloadingListenerFunc callback, void* _this)
+{
+ MutexGuard guard( getUnloadingMutex());
+
+ sal_Int32 cookie= getCookie();
+ ListenerMap& listenerMap= getListenerMap();
+ listenerMap[ cookie]= std::make_pair( callback, _this);
+ return cookie;
+}
+
+
+extern "C"
+void SAL_CALL rtl_removeUnloadingListener( sal_Int32 cookie )
+{
+ MutexGuard guard( getUnloadingMutex());
+
+ ListenerMap& listenerMap= getListenerMap();
+ size_t removedElements= listenerMap.erase( cookie);
+ if( removedElements )
+ recycleCookie( cookie);
+}
+
+
+static void rtl_notifyUnloadingListeners()
+{
+ ListenerMap& listenerMap= getListenerMap();
+ for( Lis_IT it= listenerMap.begin(); it != listenerMap.end(); ++it)
+ {
+ rtl_unloadingListenerFunc callbackFunc= it->second.first;
+ callbackFunc( it->second.second);
+ }
+}
diff --git a/sal/rtl/source/uri.cxx b/sal/rtl/source/uri.cxx
new file mode 100644
index 000000000000..551c4f199251
--- /dev/null
+++ b/sal/rtl/source/uri.cxx
@@ -0,0 +1,799 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+
+#include "rtl/uri.h"
+
+#include "surrogates.h"
+
+#include "osl/diagnose.h"
+#include "rtl/strbuf.hxx"
+#include "rtl/textenc.h"
+#include "rtl/textcvt.h"
+#include "rtl/uri.h"
+#include "rtl/ustrbuf.h"
+#include "rtl/ustrbuf.hxx"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+
+#include <cstddef>
+
+namespace {
+
+std::size_t const nCharClassSize = 128;
+
+sal_Unicode const cEscapePrefix = 0x25; // '%'
+
+inline bool isDigit(sal_uInt32 nUtf32)
+{
+ return nUtf32 >= 0x30 && nUtf32 <= 0x39; // '0'--'9'
+}
+
+inline bool isAlpha(sal_uInt32 nUtf32)
+{
+ // 'A'--'Z', 'a'--'z'
+ return (
+ (nUtf32 >= 0x41 && nUtf32 <= 0x5A) ||
+ (nUtf32 >= 0x61 && nUtf32 <= 0x7A)
+ );
+}
+
+inline bool isHighSurrogate(sal_uInt32 nUtf16)
+{
+ return SAL_RTL_IS_HIGH_SURROGATE(nUtf16);
+}
+
+inline bool isLowSurrogate(sal_uInt32 nUtf16)
+{
+ return SAL_RTL_IS_LOW_SURROGATE(nUtf16);
+}
+
+inline sal_uInt32 combineSurrogates(sal_uInt32 high, sal_uInt32 low)
+{
+ return SAL_RTL_COMBINE_SURROGATES(high, low);
+}
+
+inline int getHexWeight(sal_uInt32 nUtf32)
+{
+ return nUtf32 >= 0x30 && nUtf32 <= 0x39 ? // '0'--'9'
+ static_cast< int >(nUtf32 - 0x30) :
+ nUtf32 >= 0x41 && nUtf32 <= 0x46 ? // 'A'--'F'
+ static_cast< int >(nUtf32 - 0x41 + 10) :
+ nUtf32 >= 0x61 && nUtf32 <= 0x66 ? // 'a'--'f'
+ static_cast< int >(nUtf32 - 0x61 + 10) :
+ -1; // not a hex digit
+}
+
+inline bool isValid(sal_Bool const * pCharClass, sal_uInt32 nUtf32)
+{
+ return nUtf32 < nCharClassSize && pCharClass[nUtf32];
+}
+
+inline void writeUnicode(rtl_uString ** pBuffer, sal_Int32 * pCapacity,
+ sal_Unicode cChar)
+{
+ rtl_uStringbuffer_insert(pBuffer, pCapacity, (*pBuffer)->length, &cChar, 1);
+}
+
+enum EscapeType
+{
+ EscapeNo,
+ EscapeChar,
+ EscapeOctet
+};
+
+/* Read any of the following:
+
+ - sequence of escape sequences representing character from eCharset,
+ translated to single UCS4 character; or
+
+ - pair of UTF-16 surrogates, translated to single UCS4 character; or
+
+ _ single UTF-16 character, extended to UCS4 character.
+ */
+sal_uInt32 readUcs4(sal_Unicode const ** pBegin, sal_Unicode const * pEnd,
+ bool bEncoded, rtl_TextEncoding eCharset,
+ EscapeType * pType)
+{
+ sal_uInt32 nChar = *(*pBegin)++;
+ int nWeight1;
+ int nWeight2;
+ if (nChar == cEscapePrefix && bEncoded && pEnd - *pBegin >= 2
+ && (nWeight1 = getHexWeight((*pBegin)[0])) >= 0
+ && (nWeight2 = getHexWeight((*pBegin)[1])) >= 0)
+ {
+ *pBegin += 2;
+ nChar = static_cast< sal_uInt32 >(nWeight1 << 4 | nWeight2);
+ if (nChar <= 0x7F)
+ *pType = EscapeChar;
+ else if (eCharset == RTL_TEXTENCODING_UTF8)
+ {
+ if (nChar >= 0xC0 && nChar <= 0xF4)
+ {
+ sal_uInt32 nEncoded;
+ int nShift;
+ sal_uInt32 nMin;
+ if (nChar <= 0xDF)
+ {
+ nEncoded = (nChar & 0x1F) << 6;
+ nShift = 0;
+ nMin = 0x80;
+ }
+ else if (nChar <= 0xEF)
+ {
+ nEncoded = (nChar & 0x0F) << 12;
+ nShift = 6;
+ nMin = 0x800;
+ }
+ else
+ {
+ nEncoded = (nChar & 0x07) << 18;
+ nShift = 12;
+ nMin = 0x10000;
+ }
+ sal_Unicode const * p = *pBegin;
+ bool bUTF8 = true;
+ for (; nShift >= 0; nShift -= 6)
+ {
+ if (pEnd - p < 3 || p[0] != cEscapePrefix
+ || (nWeight1 = getHexWeight(p[1])) < 8
+ || nWeight1 > 11
+ || (nWeight2 = getHexWeight(p[2])) < 0)
+ {
+ bUTF8 = sal_False;
+ break;
+ }
+ p += 3;
+ nEncoded |= ((nWeight1 & 3) << 4 | nWeight2) << nShift;
+ }
+ if (bUTF8 && nEncoded >= nMin && !isHighSurrogate(nEncoded)
+ && !isLowSurrogate(nEncoded) && nEncoded <= 0x10FFFF)
+ {
+ *pBegin = p;
+ *pType = EscapeChar;
+ return nEncoded;
+ }
+ }
+ *pType = EscapeOctet;
+ }
+ else
+ {
+ rtl::OStringBuffer aBuf;
+ aBuf.append(static_cast< char >(nChar));
+ rtl_TextToUnicodeConverter aConverter
+ = rtl_createTextToUnicodeConverter(eCharset);
+ sal_Unicode const * p = *pBegin;
+ for (;;)
+ {
+ sal_Unicode aDst[2];
+ sal_uInt32 nInfo;
+ sal_Size nConverted;
+ sal_Size nDstSize = rtl_convertTextToUnicode(
+ aConverter, 0, aBuf.getStr(), aBuf.getLength(), aDst,
+ sizeof aDst / sizeof aDst[0],
+ (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
+ | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
+ | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR),
+ &nInfo, &nConverted);
+ if (nInfo == 0)
+ {
+ OSL_ASSERT(
+ nConverted
+ == sal::static_int_cast< sal_uInt32 >(
+ aBuf.getLength()));
+ rtl_destroyTextToUnicodeConverter(aConverter);
+ *pBegin = p;
+ *pType = EscapeChar;
+ OSL_ASSERT(
+ nDstSize == 1
+ || (nDstSize == 2 && isHighSurrogate(aDst[0])
+ && isLowSurrogate(aDst[1])));
+ return nDstSize == 1
+ ? aDst[0] : combineSurrogates(aDst[0], aDst[1]);
+ }
+ else if (nInfo == RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL
+ && pEnd - p >= 3 && p[0] == cEscapePrefix
+ && (nWeight1 = getHexWeight(p[1])) >= 0
+ && (nWeight2 = getHexWeight(p[2])) >= 0)
+ {
+ p += 3;
+ aBuf.append(static_cast< char >(nWeight1 << 4 | nWeight2));
+ }
+ else if (nInfo == RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL
+ && p != pEnd && *p <= 0x7F)
+ {
+ aBuf.append(static_cast< char >(*p++));
+ }
+ else
+ {
+ OSL_ASSERT(
+ (nInfo & RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL)
+ == 0);
+ break;
+ }
+ }
+ rtl_destroyTextToUnicodeConverter(aConverter);
+ *pType = EscapeOctet;
+ }
+ return nChar;
+ }
+ else
+ {
+ *pType = EscapeNo;
+ return isHighSurrogate(nChar) && *pBegin < pEnd
+ && isLowSurrogate(**pBegin) ?
+ combineSurrogates(nChar, *(*pBegin)++) : nChar;
+ }
+}
+
+void writeUcs4(rtl_uString ** pBuffer, sal_Int32 * pCapacity, sal_uInt32 nUtf32)
+{
+ OSL_ENSURE(nUtf32 <= 0x10FFFF, "bad UTF-32 char");
+ if (nUtf32 <= 0xFFFF) {
+ writeUnicode(
+ pBuffer, pCapacity, static_cast< sal_Unicode >(nUtf32));
+ } else {
+ nUtf32 -= 0x10000;
+ writeUnicode(
+ pBuffer, pCapacity,
+ static_cast< sal_Unicode >(nUtf32 >> 10 | 0xD800));
+ writeUnicode(
+ pBuffer, pCapacity,
+ static_cast< sal_Unicode >((nUtf32 & 0x3FF) | 0xDC00));
+ }
+}
+
+void writeEscapeOctet(rtl_uString ** pBuffer, sal_Int32 * pCapacity,
+ sal_uInt32 nOctet)
+{
+ OSL_ENSURE(nOctet <= 0xFF, "bad octet");
+
+ static sal_Unicode const aHex[16]
+ = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }; /* '0'--'9', 'A'--'F' */
+
+ writeUnicode(pBuffer, pCapacity, cEscapePrefix);
+ writeUnicode(pBuffer, pCapacity, aHex[nOctet >> 4]);
+ writeUnicode(pBuffer, pCapacity, aHex[nOctet & 15]);
+}
+
+bool writeEscapeChar(rtl_uString ** pBuffer, sal_Int32 * pCapacity,
+ sal_uInt32 nUtf32, rtl_TextEncoding eCharset, bool bStrict)
+{
+ OSL_ENSURE(nUtf32 <= 0x10FFFF, "bad UTF-32 char");
+ if (eCharset == RTL_TEXTENCODING_UTF8) {
+ if (nUtf32 < 0x80)
+ writeEscapeOctet(pBuffer, pCapacity, nUtf32);
+ else if (nUtf32 < 0x800)
+ {
+ writeEscapeOctet(pBuffer, pCapacity, nUtf32 >> 6 | 0xC0);
+ writeEscapeOctet(pBuffer, pCapacity, (nUtf32 & 0x3F) | 0x80);
+ }
+ else if (nUtf32 < 0x10000)
+ {
+ writeEscapeOctet(pBuffer, pCapacity, nUtf32 >> 12 | 0xE0);
+ writeEscapeOctet(pBuffer, pCapacity, (nUtf32 >> 6 & 0x3F) | 0x80);
+ writeEscapeOctet(pBuffer, pCapacity, (nUtf32 & 0x3F) | 0x80);
+ }
+ else
+ {
+ writeEscapeOctet(pBuffer, pCapacity, nUtf32 >> 18 | 0xF0);
+ writeEscapeOctet(pBuffer, pCapacity, (nUtf32 >> 12 & 0x3F) | 0x80);
+ writeEscapeOctet(pBuffer, pCapacity, (nUtf32 >> 6 & 0x3F) | 0x80);
+ writeEscapeOctet(pBuffer, pCapacity, (nUtf32 & 0x3F) | 0x80);
+ }
+ } else {
+ rtl_UnicodeToTextConverter aConverter
+ = rtl_createUnicodeToTextConverter(eCharset);
+ sal_Unicode aSrc[2];
+ sal_Size nSrcSize;
+ if (nUtf32 <= 0xFFFF)
+ {
+ aSrc[0] = static_cast< sal_Unicode >(nUtf32);
+ nSrcSize = 1;
+ }
+ else
+ {
+ aSrc[0] = static_cast< sal_Unicode >(
+ ((nUtf32 - 0x10000) >> 10) | 0xD800);
+ aSrc[1] = static_cast< sal_Unicode >(
+ ((nUtf32 - 0x10000) & 0x3FF) | 0xDC00);
+ nSrcSize = 2;
+ }
+ sal_Char aDst[32]; // FIXME random value
+ sal_uInt32 nInfo;
+ sal_Size nConverted;
+ sal_Size nDstSize = rtl_convertUnicodeToText(
+ aConverter, 0, aSrc, nSrcSize, aDst, sizeof aDst,
+ RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
+ | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
+ | RTL_UNICODETOTEXT_FLAGS_FLUSH,
+ &nInfo, &nConverted);
+ OSL_ASSERT((nInfo & RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL) == 0);
+ rtl_destroyUnicodeToTextConverter(aConverter);
+ if (nInfo == 0) {
+ OSL_ENSURE(nConverted == nSrcSize, "bad rtl_convertUnicodeToText");
+ for (sal_Size i = 0; i < nDstSize; ++i)
+ writeEscapeOctet(pBuffer, pCapacity,
+ static_cast< unsigned char >(aDst[i]));
+ // FIXME all octets are escaped, even if there is no need
+ } else {
+ if (bStrict) {
+ return false;
+ } else {
+ writeUcs4(pBuffer, pCapacity, nUtf32);
+ }
+ }
+ }
+ return true;
+}
+
+struct Component
+{
+ sal_Unicode const * pBegin;
+ sal_Unicode const * pEnd;
+
+ inline Component(): pBegin(0) {}
+
+ inline bool isPresent() const { return pBegin != 0; }
+
+ inline sal_Int32 getLength() const;
+};
+
+inline sal_Int32 Component::getLength() const
+{
+ OSL_ENSURE(isPresent(), "taking length of non-present component");
+ return static_cast< sal_Int32 >(pEnd - pBegin);
+}
+
+struct Components
+{
+ Component aScheme;
+ Component aAuthority;
+ Component aPath;
+ Component aQuery;
+ Component aFragment;
+};
+
+void parseUriRef(rtl_uString const * pUriRef, Components * pComponents)
+{
+ // This algorithm is liberal and accepts various forms of illegal input.
+
+ sal_Unicode const * pBegin = pUriRef->buffer;
+ sal_Unicode const * pEnd = pBegin + pUriRef->length;
+ sal_Unicode const * pPos = pBegin;
+
+ if (pPos != pEnd && isAlpha(*pPos))
+ for (sal_Unicode const * p = pPos + 1; p != pEnd; ++p)
+ if (*p == ':')
+ {
+ pComponents->aScheme.pBegin = pBegin;
+ pComponents->aScheme.pEnd = ++p;
+ pPos = p;
+ break;
+ }
+ else if (!isAlpha(*p) && !isDigit(*p) && *p != '+' && *p != '-'
+ && *p != '.')
+ break;
+
+ if (pEnd - pPos >= 2 && pPos[0] == '/' && pPos[1] == '/')
+ {
+ pComponents->aAuthority.pBegin = pPos;
+ pPos += 2;
+ while (pPos != pEnd && *pPos != '/' && *pPos != '?' && *pPos != '#')
+ ++pPos;
+ pComponents->aAuthority.pEnd = pPos;
+ }
+
+ pComponents->aPath.pBegin = pPos;
+ while (pPos != pEnd && *pPos != '?' && * pPos != '#')
+ ++pPos;
+ pComponents->aPath.pEnd = pPos;
+
+ if (pPos != pEnd && *pPos == '?')
+ {
+ pComponents->aQuery.pBegin = pPos++;
+ while (pPos != pEnd && * pPos != '#')
+ ++pPos;
+ pComponents->aQuery.pEnd = pPos;
+ }
+
+ if (pPos != pEnd)
+ {
+ OSL_ASSERT(*pPos == '#');
+ pComponents->aFragment.pBegin = pPos;
+ pComponents->aFragment.pEnd = pEnd;
+ }
+}
+
+rtl::OUString joinPaths(Component const & rBasePath, Component const & rRelPath)
+{
+ OSL_ASSERT(rBasePath.isPresent() && *rBasePath.pBegin == '/');
+ OSL_ASSERT(rRelPath.isPresent());
+
+ // The invariant of aBuffer is that it always starts and ends with a slash
+ // (until probably right at the end of the algorithm, when the last segment
+ // of rRelPath is added, which does not necessarily end in a slash):
+ rtl::OUStringBuffer aBuffer(rBasePath.getLength() + rRelPath.getLength());
+ // XXX numeric overflow
+
+ // Segments "." and ".." within rBasePath are not conisdered special (but
+ // are also not removed by ".." segments within rRelPath), RFC 2396 seems a
+ // bit unclear about this point:
+ sal_Int32 nFixed = 1;
+ sal_Unicode const * p = rBasePath.pBegin + 1;
+ for (sal_Unicode const * q = p; q != rBasePath.pEnd; ++q)
+ if (*q == '/')
+ {
+ if (
+ (q - p == 1 && p[0] == '.') ||
+ (q - p == 2 && p[0] == '.' && p[1] == '.')
+ )
+ {
+ nFixed = q + 1 - rBasePath.pBegin;
+ }
+ p = q + 1;
+ }
+ aBuffer.append(rBasePath.pBegin, p - rBasePath.pBegin);
+
+ p = rRelPath.pBegin;
+ if (p != rRelPath.pEnd)
+ for (;;)
+ {
+ sal_Unicode const * q = p;
+ sal_Unicode const * r;
+ for (;;)
+ {
+ if (q == rRelPath.pEnd)
+ {
+ r = q;
+ break;
+ }
+ if (*q == '/')
+ {
+ r = q + 1;
+ break;
+ }
+ ++q;
+ }
+ if (q - p == 2 && p[0] == '.' && p[1] == '.')
+ {
+ // Erroneous excess segments ".." within rRelPath are left
+ // intact, as the examples in RFC 2396, section C.2, suggest:
+ sal_Int32 i = aBuffer.getLength() - 1;
+ if (i < nFixed)
+ {
+ aBuffer.append(p, r - p);
+ nFixed += 3;
+ }
+ else
+ {
+ while (aBuffer.charAt(i - 1) != '/')
+ --i;
+ aBuffer.setLength(i);
+ }
+ }
+ else if (q - p != 1 || *p != '.')
+ aBuffer.append(p, r - p);
+ if (q == rRelPath.pEnd)
+ break;
+ p = q + 1;
+ }
+
+ return aBuffer.makeStringAndClear();
+}
+
+}
+
+sal_Bool const * SAL_CALL rtl_getUriCharClass(rtl_UriCharClass eCharClass)
+ SAL_THROW_EXTERN_C()
+{
+ static sal_Bool const aCharClass[][nCharClassSize]
+ = {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* None */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* !"#$%&'()*+,-./*/
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*0123456789:;<=>?*/
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*@ABCDEFGHIJKLMNO*/
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*PQRSTUVWXYZ[\]^_*/
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*`abcdefghijklmno*/
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /*pqrstuvwxyz{|}~ */
+ },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Uric */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* !"#$%&'()*+,-./*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, /*0123456789:;<=>?*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*@ABCDEFGHIJKLMNO*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, /*PQRSTUVWXYZ[\]^_*/
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*`abcdefghijklmno*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0 /*pqrstuvwxyz{|}~ */
+ },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* UricNoSlash */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* !"#$%&'()*+,-./*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, /*0123456789:;<=>?*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*@ABCDEFGHIJKLMNO*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /*PQRSTUVWXYZ[\]^_*/
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*`abcdefghijklmno*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0 /*pqrstuvwxyz{|}~ */
+ },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* RelSegment */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* !"#$%&'()*+,-./*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, /*0123456789:;<=>?*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*@ABCDEFGHIJKLMNO*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /*PQRSTUVWXYZ[\]^_*/
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*`abcdefghijklmno*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0 /*pqrstuvwxyz{|}~ */
+ },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* RegName */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* !"#$%&'()*+,-./*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, /*0123456789:;<=>?*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*@ABCDEFGHIJKLMNO*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /*PQRSTUVWXYZ[\]^_*/
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*`abcdefghijklmno*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0 /*pqrstuvwxyz{|}~ */
+ },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Userinfo */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* !"#$%&'()*+,-./*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, /*0123456789:;<=>?*/
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*@ABCDEFGHIJKLMNO*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /*PQRSTUVWXYZ[\]^_*/
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*`abcdefghijklmno*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0 /*pqrstuvwxyz{|}~ */
+ },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Pchar */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* !"#$%&'()*+,-./*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, /*0123456789:;<=>?*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*@ABCDEFGHIJKLMNO*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /*PQRSTUVWXYZ[\]^_*/
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*`abcdefghijklmno*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0 /*pqrstuvwxyz{|}~ */
+ },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* UnoParamValue */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, /* !"#$%&'()*+,-./*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /*0123456789:;<=>?*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*@ABCDEFGHIJKLMNO*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /*PQRSTUVWXYZ[\]^_*/
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*`abcdefghijklmno*/
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0 /*pqrstuvwxyz{|}~ */
+ }};
+ OSL_ENSURE(
+ (eCharClass >= 0
+ && (sal::static_int_cast< std::size_t >(eCharClass)
+ < sizeof aCharClass / sizeof aCharClass[0])),
+ "bad eCharClass");
+ return aCharClass[eCharClass];
+}
+
+void SAL_CALL rtl_uriEncode(rtl_uString * pText, sal_Bool const * pCharClass,
+ rtl_UriEncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset, rtl_uString ** pResult)
+ SAL_THROW_EXTERN_C()
+{
+ OSL_ENSURE(!pCharClass[0x25], "bad pCharClass");
+ // make sure the percent sign is encoded...
+
+ sal_Unicode const * p = pText->buffer;
+ sal_Unicode const * pEnd = p + pText->length;
+ sal_Int32 nCapacity = 0;
+ rtl_uString_new(pResult);
+ while (p < pEnd)
+ {
+ EscapeType eType;
+ sal_uInt32 nUtf32 = readUcs4(
+ &p, pEnd,
+ (eMechanism == rtl_UriEncodeKeepEscapes
+ || eMechanism == rtl_UriEncodeCheckEscapes
+ || eMechanism == rtl_UriEncodeStrictKeepEscapes),
+ eCharset, &eType);
+ switch (eType)
+ {
+ case EscapeNo:
+ if (isValid(pCharClass, nUtf32)) // implies nUtf32 <= 0x7F
+ writeUnicode(pResult, &nCapacity,
+ static_cast< sal_Unicode >(nUtf32));
+ else if (!writeEscapeChar(
+ pResult, &nCapacity, nUtf32, eCharset,
+ (eMechanism == rtl_UriEncodeStrict
+ || eMechanism == rtl_UriEncodeStrictKeepEscapes)))
+ {
+ rtl_uString_new(pResult);
+ return;
+ }
+ break;
+
+ case EscapeChar:
+ if (eMechanism == rtl_UriEncodeCheckEscapes
+ && isValid(pCharClass, nUtf32)) // implies nUtf32 <= 0x7F
+ writeUnicode(pResult, &nCapacity,
+ static_cast< sal_Unicode >(nUtf32));
+ else if (!writeEscapeChar(
+ pResult, &nCapacity, nUtf32, eCharset,
+ (eMechanism == rtl_UriEncodeStrict
+ || eMechanism == rtl_UriEncodeStrictKeepEscapes)))
+ {
+ rtl_uString_new(pResult);
+ return;
+ }
+ break;
+
+ case EscapeOctet:
+ writeEscapeOctet(pResult, &nCapacity, nUtf32);
+ break;
+ }
+ }
+}
+
+void SAL_CALL rtl_uriDecode(rtl_uString * pText,
+ rtl_UriDecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset, rtl_uString ** pResult)
+ SAL_THROW_EXTERN_C()
+{
+ switch (eMechanism)
+ {
+ case rtl_UriDecodeNone:
+ rtl_uString_assign(pResult, pText);
+ break;
+
+ case rtl_UriDecodeToIuri:
+ eCharset = RTL_TEXTENCODING_UTF8;
+ default: // rtl_UriDecodeWithCharset, rtl_UriDecodeStrict
+ {
+ sal_Unicode const * p = pText->buffer;
+ sal_Unicode const * pEnd = p + pText->length;
+ sal_Int32 nCapacity = 0;
+ rtl_uString_new(pResult);
+ while (p < pEnd)
+ {
+ EscapeType eType;
+ sal_uInt32 nUtf32 = readUcs4(&p, pEnd, true, eCharset, &eType);
+ switch (eType)
+ {
+ case EscapeChar:
+ if (nUtf32 <= 0x7F && eMechanism == rtl_UriDecodeToIuri)
+ {
+ writeEscapeOctet(pResult, &nCapacity, nUtf32);
+ break;
+ }
+ case EscapeNo:
+ writeUcs4(pResult, &nCapacity, nUtf32);
+ break;
+
+ case EscapeOctet:
+ if (eMechanism == rtl_UriDecodeStrict) {
+ rtl_uString_new(pResult);
+ return;
+ }
+ writeEscapeOctet(pResult, &nCapacity, nUtf32);
+ break;
+ }
+ }
+ }
+ break;
+ }
+}
+
+sal_Bool SAL_CALL rtl_uriConvertRelToAbs(rtl_uString * pBaseUriRef,
+ rtl_uString * pRelUriRef,
+ rtl_uString ** pResult,
+ rtl_uString ** pException)
+ SAL_THROW_EXTERN_C()
+{
+ // If pRelUriRef starts with a scheme component it is an absolute URI
+ // reference, and we are done (i.e., this algorithm does not support
+ // backwards-compatible relative URIs starting with a scheme component, see
+ // RFC 2396, section 5.2, step 3):
+ Components aRelComponents;
+ parseUriRef(pRelUriRef, &aRelComponents);
+ if (aRelComponents.aScheme.isPresent())
+ {
+ rtl_uString_assign(pResult, pRelUriRef);
+ return true;
+ }
+
+ // Parse pBaseUriRef; if the scheme component is not present or not valid,
+ // or the path component is not empty and starts with anything but a slash,
+ // an exception is raised:
+ Components aBaseComponents;
+ parseUriRef(pBaseUriRef, &aBaseComponents);
+ if (!aBaseComponents.aScheme.isPresent())
+ {
+ rtl::OUString aMessage(pBaseUriRef);
+ aMessage += rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ " does not start with a scheme component"));
+ rtl_uString_assign(pException,
+ const_cast< rtl::OUString & >(aMessage).pData);
+ return false;
+ }
+ if (aBaseComponents.aPath.pBegin != aBaseComponents.aPath.pEnd
+ && *aBaseComponents.aPath.pBegin != '/')
+ {
+ rtl::OUString aMessage(pBaseUriRef);
+ aMessage += rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "path component does not start with slash"));
+ rtl_uString_assign(pException, aMessage.pData);
+ return false;
+ }
+
+ // Use the algorithm from RFC 2396, section 5.2, to turn the relative URI
+ // into an absolute one (if the relative URI is a reference to the "current
+ // document," the "current document" is here taken to be the base URI):
+ rtl::OUStringBuffer aBuffer;
+ aBuffer.append(aBaseComponents.aScheme.pBegin,
+ aBaseComponents.aScheme.getLength());
+ if (aRelComponents.aAuthority.isPresent())
+ {
+ aBuffer.append(aRelComponents.aAuthority.pBegin,
+ aRelComponents.aAuthority.getLength());
+ aBuffer.append(aRelComponents.aPath.pBegin,
+ aRelComponents.aPath.getLength());
+ if (aRelComponents.aQuery.isPresent())
+ aBuffer.append(aRelComponents.aQuery.pBegin,
+ aRelComponents.aQuery.getLength());
+ }
+ else
+ {
+ if (aBaseComponents.aAuthority.isPresent())
+ aBuffer.append(aBaseComponents.aAuthority.pBegin,
+ aBaseComponents.aAuthority.getLength());
+ if (aRelComponents.aPath.pBegin == aRelComponents.aPath.pEnd
+ && !aRelComponents.aQuery.isPresent())
+ {
+ aBuffer.append(aBaseComponents.aPath.pBegin,
+ aBaseComponents.aPath.getLength());
+ if (aBaseComponents.aQuery.isPresent())
+ aBuffer.append(aBaseComponents.aQuery.pBegin,
+ aBaseComponents.aQuery.getLength());
+ }
+ else
+ {
+ if (*aRelComponents.aPath.pBegin == '/')
+ aBuffer.append(aRelComponents.aPath.pBegin,
+ aRelComponents.aPath.getLength());
+ else
+ aBuffer.append(joinPaths(aBaseComponents.aPath,
+ aRelComponents.aPath));
+ if (aRelComponents.aQuery.isPresent())
+ aBuffer.append(aRelComponents.aQuery.pBegin,
+ aRelComponents.aQuery.getLength());
+ }
+ }
+ if (aRelComponents.aFragment.isPresent())
+ aBuffer.append(aRelComponents.aFragment.pBegin,
+ aRelComponents.aFragment.getLength());
+ rtl_uString_assign(pResult, aBuffer.makeStringAndClear().pData);
+ return true;
+}
diff --git a/sal/rtl/source/ustrbuf.c b/sal/rtl/source/ustrbuf.c
new file mode 100644
index 000000000000..d9fdb9983fb1
--- /dev/null
+++ b/sal/rtl/source/ustrbuf.c
@@ -0,0 +1,208 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <osl/interlck.h>
+
+#ifndef _RTL_STRING_HXX_
+#include <rtl/ustrbuf.hxx>
+#endif
+#include <rtl/memory.h>
+
+/*
+#include <rtl/alloc.h>
+*/
+
+
+
+/*************************************************************************
+ * rtl_uStringbuffer_newFromStr_WithLength
+ */
+void SAL_CALL rtl_uStringbuffer_newFromStr_WithLength( rtl_uString ** newStr,
+ const sal_Unicode * value,
+ sal_Int32 count)
+{
+ if (!value)
+ {
+ rtl_uString_new_WithLength( newStr, 16 );
+ return;
+ }
+
+ rtl_uString_new_WithLength( newStr, count + 16 );
+ (*newStr)->length = count;
+ rtl_copyMemory( (*newStr)->buffer, value, count * sizeof(sal_Unicode));
+ return;
+}
+
+/*************************************************************************
+ * rtl_uStringbuffer_newFromStringBuffer
+ */
+sal_Int32 SAL_CALL rtl_uStringbuffer_newFromStringBuffer( rtl_uString ** newStr,
+ sal_Int32 capacity,
+ rtl_uString * oldStr )
+{
+ sal_Int32 newCapacity = capacity;
+
+ if (newCapacity < oldStr->length)
+ newCapacity = oldStr->length;
+
+ rtl_uString_new_WithLength( newStr, newCapacity );
+
+ if (oldStr->length > 0) {
+ (*newStr)->length = oldStr->length;
+ rtl_copyMemory( (*newStr)->buffer, oldStr->buffer, oldStr->length * sizeof(sal_Unicode));
+ }
+ return newCapacity;
+}
+
+/*************************************************************************
+ * rtl_uStringbuffer_ensureCapacity
+ */
+void SAL_CALL rtl_uStringbuffer_ensureCapacity
+ (rtl_uString ** This, sal_Int32* capacity, sal_Int32 minimumCapacity)
+{
+ if (minimumCapacity > *capacity)
+ {
+ rtl_uString * pTmp = *This;
+ rtl_uString * pNew = NULL;
+ *capacity = ((*This)->length + 1) * 2;
+ if (minimumCapacity > *capacity)
+ /* still lower, set to the minimum capacity */
+ *capacity = minimumCapacity;
+
+ rtl_uString_new_WithLength(&pNew, *capacity);
+ pNew->length = (*This)->length;
+ *This = pNew;
+
+ rtl_copyMemory( (*This)->buffer, pTmp->buffer, pTmp->length * sizeof(sal_Unicode) );
+ rtl_uString_release( pTmp );
+ }
+}
+
+/*************************************************************************
+ * rtl_uStringbuffer_insert
+ */
+void SAL_CALL rtl_uStringbuffer_insert( rtl_uString ** This,
+ sal_Int32 * capacity,
+ sal_Int32 offset,
+ const sal_Unicode * str,
+ sal_Int32 len)
+{
+ sal_Int32 nOldLen;
+ sal_Unicode * pBuf;
+ sal_Int32 n;
+ if( len != 0 )
+ {
+ if (*capacity < (*This)->length + len)
+ rtl_uStringbuffer_ensureCapacity( This, capacity, (*This)->length + len );
+
+ /*
+ if( len == 1 )
+ This->buffer
+ */
+ nOldLen = (*This)->length;
+ pBuf = (*This)->buffer;
+
+ /* copy the tail */
+ n = (nOldLen - offset);
+ if( n == 1 )
+ /* optimized for 1 character */
+ pBuf[offset + len] = pBuf[offset];
+ else if( n > 1 )
+ rtl_moveMemory( pBuf + offset + len, pBuf + offset, n * sizeof(sal_Unicode) );
+
+ /* insert the new characters */
+ if( len == 1 )
+ /* optimized for 1 character */
+ pBuf[offset] = *str;
+ else if( len > 1 )
+ rtl_copyMemory( pBuf + offset, str, len * sizeof(sal_Unicode) );
+ (*This)->length = nOldLen + len;
+ pBuf[ nOldLen + len ] = 0;
+ }
+}
+
+void rtl_uStringbuffer_insertUtf32(
+ rtl_uString ** pThis, sal_Int32 * capacity, sal_Int32 offset, sal_uInt32 c)
+{
+ sal_Unicode buf[2];
+ sal_Int32 len;
+ OSL_ASSERT(c <= 0x10FFFF && !(c >= 0xD800 && c <= 0xDFFF));
+ if (c <= 0xFFFF) {
+ buf[0] = (sal_Unicode) c;
+ len = 1;
+ } else {
+ c -= 0x10000;
+ buf[0] = (sal_Unicode) ((c >> 10) | 0xD800);
+ buf[1] = (sal_Unicode) ((c & 0x3FF) | 0xDC00);
+ len = 2;
+ }
+ rtl_uStringbuffer_insert(pThis, capacity, offset, buf, len);
+}
+
+/*************************************************************************
+ * rtl_uStringbuffer_insert_ascii
+ */
+void SAL_CALL rtl_uStringbuffer_insert_ascii( /*inout*/rtl_uString ** This,
+ /*inout*/sal_Int32 * capacity,
+ sal_Int32 offset,
+ const sal_Char * str,
+ sal_Int32 len)
+{
+ sal_Int32 nOldLen;
+ sal_Unicode * pBuf;
+ sal_Int32 n;
+ if( len != 0 )
+ {
+ if (*capacity < (*This)->length + len)
+ rtl_uStringbuffer_ensureCapacity( This, capacity, (*This)->length + len );
+
+ nOldLen = (*This)->length;
+ pBuf = (*This)->buffer;
+
+ /* copy the tail */
+ n = (nOldLen - offset);
+ if( n == 1 )
+ /* optimized for 1 character */
+ pBuf[offset + len] = pBuf[offset];
+ else if( n > 1 )
+ rtl_moveMemory( pBuf + offset + len, pBuf + offset, n * sizeof(sal_Unicode) );
+
+ /* insert the new characters */
+ for( n = 0; n < len; n++ )
+ {
+ /* Check ASCII range */
+ OSL_ENSURE( (*str & 0x80) == 0, "Found ASCII char > 127");
+
+ pBuf[offset + n] = (sal_Unicode)*(str++);
+ }
+
+ (*This)->length = nOldLen + len;
+ pBuf[ nOldLen + len ] = 0;
+ }
+}
+
+
diff --git a/sal/rtl/source/ustring.c b/sal/rtl/source/ustring.c
new file mode 100644
index 000000000000..b0bdd2d98e73
--- /dev/null
+++ b/sal/rtl/source/ustring.c
@@ -0,0 +1,934 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+#pragma warning(disable:4738) // storing 32-bit float result in memory, possible loss of performance
+#endif
+
+#include <rtl/memory.h>
+#include <osl/diagnose.h>
+#include <osl/interlck.h>
+#include <rtl/alloc.h>
+#include <osl/mutex.h>
+#include <osl/doublecheckedlocking.h>
+#include <rtl/tencinfo.h>
+
+#include <string.h>
+#include <sal/alloca.h>
+
+#include "hash.h"
+#include "strimp.h"
+#include "surrogates.h"
+#include <rtl/ustring.h>
+
+#include "rtl/math.h"
+#include "rtl/tencinfo.h"
+
+/* ======================================================================= */
+
+/* static data to be referenced by all empty strings
+ * the refCount is predefined to 1 and must never become 0 !
+ */
+static rtl_uString const aImplEmpty_rtl_uString =
+{
+ (sal_Int32) (SAL_STRING_INTERN_FLAG|SAL_STRING_STATIC_FLAG|1), /*sal_Int32 refCount; */
+ 0, /*sal_Int32 length; */
+ { 0 } /*sal_Unicode buffer[1];*/
+};
+
+/* ======================================================================= */
+
+#define IMPL_RTL_STRCODE sal_Unicode
+#define IMPL_RTL_USTRCODE( c ) (c)
+#define IMPL_RTL_STRNAME( n ) rtl_ustr_ ## n
+
+#define IMPL_RTL_STRINGNAME( n ) rtl_uString_ ## n
+#define IMPL_RTL_STRINGDATA rtl_uString
+#define IMPL_RTL_EMPTYSTRING aImplEmpty_rtl_uString
+#define IMPL_RTL_INTERN
+static void internRelease (rtl_uString *pThis);
+
+/* ======================================================================= */
+
+/* Include String/UString template code */
+
+#include "strtmpl.c"
+
+sal_Int32 rtl_ustr_indexOfAscii_WithLength(
+ sal_Unicode const * str, sal_Int32 len,
+ char const * subStr, sal_Int32 subLen)
+{
+ if (subLen > 0 && subLen <= len) {
+ sal_Int32 i;
+ for (i = 0; i <= len - subLen; ++i) {
+ if (rtl_ustr_asciil_reverseEquals_WithLength(
+ str + i, subStr, subLen))
+ {
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+
+sal_Int32 rtl_ustr_lastIndexOfAscii_WithLength(
+ sal_Unicode const * str, sal_Int32 len,
+ char const * subStr, sal_Int32 subLen)
+{
+ if (subLen > 0 && subLen <= len) {
+ sal_Int32 i;
+ for (i = len - subLen; i >= 0; --i) {
+ if (rtl_ustr_asciil_reverseEquals_WithLength(
+ str + i, subStr, subLen))
+ {
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+
+sal_Int32 SAL_CALL rtl_ustr_valueOfFloat(sal_Unicode * pStr, float f)
+{
+ rtl_uString * pResult = NULL;
+ sal_Int32 nLen;
+ rtl_math_doubleToUString(
+ &pResult, 0, 0, f, rtl_math_StringFormat_G,
+ RTL_USTR_MAX_VALUEOFFLOAT - RTL_CONSTASCII_LENGTH("-x.E-xxx"), '.', 0,
+ 0, sal_True);
+ nLen = pResult->length;
+ OSL_ASSERT(nLen < RTL_USTR_MAX_VALUEOFFLOAT);
+ rtl_copyMemory(pStr, pResult->buffer, (nLen + 1) * sizeof(sal_Unicode));
+ rtl_uString_release(pResult);
+ return nLen;
+}
+
+sal_Int32 SAL_CALL rtl_ustr_valueOfDouble(sal_Unicode * pStr, double d)
+{
+ rtl_uString * pResult = NULL;
+ sal_Int32 nLen;
+ rtl_math_doubleToUString(
+ &pResult, 0, 0, d, rtl_math_StringFormat_G,
+ RTL_USTR_MAX_VALUEOFDOUBLE - RTL_CONSTASCII_LENGTH("-x.E-xxx"), '.', 0,
+ 0, sal_True);
+ nLen = pResult->length;
+ OSL_ASSERT(nLen < RTL_USTR_MAX_VALUEOFDOUBLE);
+ rtl_copyMemory(pStr, pResult->buffer, (nLen + 1) * sizeof(sal_Unicode));
+ rtl_uString_release(pResult);
+ return nLen;
+}
+
+float SAL_CALL rtl_ustr_toFloat(sal_Unicode const * pStr)
+{
+ return (float) rtl_math_uStringToDouble(pStr,
+ pStr + rtl_ustr_getLength(pStr),
+ '.', 0, 0, 0);
+}
+
+double SAL_CALL rtl_ustr_toDouble(sal_Unicode const * pStr)
+{
+ return rtl_math_uStringToDouble(pStr, pStr + rtl_ustr_getLength(pStr), '.',
+ 0, 0, 0);
+}
+
+/* ======================================================================= */
+
+sal_Int32 SAL_CALL rtl_ustr_ascii_compare( const sal_Unicode* pStr1,
+ const sal_Char* pStr2 )
+{
+ sal_Int32 nRet;
+ while ( ((nRet = ((sal_Int32)(*pStr1))-
+ ((sal_Int32)((unsigned char)(*pStr2)))) == 0) &&
+ *pStr2 )
+ {
+ pStr1++;
+ pStr2++;
+ }
+
+ return nRet;
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL rtl_ustr_ascii_compare_WithLength( const sal_Unicode* pStr1,
+ sal_Int32 nStr1Len,
+ const sal_Char* pStr2 )
+{
+ sal_Int32 nRet = 0;
+ while( ((nRet = (nStr1Len ? (sal_Int32)(*pStr1) : 0)-
+ ((sal_Int32)((unsigned char)(*pStr2)))) == 0) &&
+ nStr1Len && *pStr2 )
+ {
+ pStr1++;
+ pStr2++;
+ nStr1Len--;
+ }
+
+ return nRet;
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL rtl_ustr_ascii_shortenedCompare_WithLength( const sal_Unicode* pStr1,
+ sal_Int32 nStr1Len,
+ const sal_Char* pStr2,
+ sal_Int32 nShortenedLength )
+{
+ const sal_Unicode* pStr1End = pStr1 + nStr1Len;
+ sal_Int32 nRet;
+ while ( (nShortenedLength > 0) &&
+ (pStr1 < pStr1End) && *pStr2 )
+ {
+ /* Check ASCII range */
+ OSL_ENSURE( (*pStr2 & 0x80) == 0, "Found ASCII char > 127");
+
+ nRet = ((sal_Int32)*pStr1)-
+ ((sal_Int32)(unsigned char)*pStr2);
+ if ( nRet != 0 )
+ return nRet;
+
+ nShortenedLength--;
+ pStr1++;
+ pStr2++;
+ }
+
+ if ( nShortenedLength <= 0 )
+ return 0;
+
+ if ( *pStr2 )
+ {
+ OSL_ENSURE( pStr1 == pStr1End, "pStr1 == pStr1End failed" );
+ // first is a substring of the second string => less (negative value)
+ nRet = -1;
+ }
+ else
+ {
+ // greater or equal
+ nRet = pStr1End - pStr1;
+ }
+
+ return nRet;
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL rtl_ustr_asciil_reverseCompare_WithLength( const sal_Unicode* pStr1,
+ sal_Int32 nStr1Len,
+ const sal_Char* pStr2,
+ sal_Int32 nStr2Len )
+{
+ const sal_Unicode* pStr1Run = pStr1+nStr1Len;
+ const sal_Char* pStr2Run = pStr2+nStr2Len;
+ sal_Int32 nRet;
+ while ( (pStr1 < pStr1Run) && (pStr2 < pStr2Run) )
+ {
+ pStr1Run--;
+ pStr2Run--;
+ nRet = ((sal_Int32)*pStr1Run)-((sal_Int32)*pStr2Run);
+ if ( nRet )
+ return nRet;
+ }
+
+ return nStr1Len - nStr2Len;
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Bool SAL_CALL rtl_ustr_asciil_reverseEquals_WithLength( const sal_Unicode* pStr1,
+ const sal_Char* pStr2,
+ sal_Int32 nStrLen )
+{
+ const sal_Unicode* pStr1Run = pStr1+nStrLen;
+ const sal_Char* pStr2Run = pStr2+nStrLen;
+ while ( pStr1 < pStr1Run )
+ {
+ pStr1Run--;
+ pStr2Run--;
+ if( *pStr1Run != (sal_Unicode)*pStr2Run )
+ return sal_False;
+ }
+
+ return sal_True;
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL rtl_ustr_ascii_compareIgnoreAsciiCase( const sal_Unicode* pStr1,
+ const sal_Char* pStr2 )
+{
+ sal_Int32 nRet;
+ sal_Int32 c1;
+ sal_Int32 c2;
+ do
+ {
+ /* If character between 'A' and 'Z', than convert it to lowercase */
+ c1 = (sal_Int32)*pStr1;
+ c2 = (sal_Int32)((unsigned char)*pStr2);
+ if ( (c1 >= 65) && (c1 <= 90) )
+ c1 += 32;
+ if ( (c2 >= 65) && (c2 <= 90) )
+ c2 += 32;
+ nRet = c1-c2;
+ if ( nRet != 0 )
+ return nRet;
+
+ pStr1++;
+ pStr2++;
+ }
+ while ( c2 );
+
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL rtl_ustr_ascii_compareIgnoreAsciiCase_WithLength( const sal_Unicode* pStr1,
+ sal_Int32 nStr1Len,
+ const sal_Char* pStr2 )
+{
+ sal_Int32 nRet;
+ sal_Int32 c1;
+ sal_Int32 c2;
+ do
+ {
+ if ( !nStr1Len )
+ return *pStr2 == '\0' ? 0 : -1;
+
+ /* If character between 'A' and 'Z', than convert it to lowercase */
+ c1 = (sal_Int32)*pStr1;
+ c2 = (sal_Int32)((unsigned char)*pStr2);
+ if ( (c1 >= 65) && (c1 <= 90) )
+ c1 += 32;
+ if ( (c2 >= 65) && (c2 <= 90) )
+ c2 += 32;
+ nRet = c1-c2;
+ if ( nRet != 0 )
+ return nRet;
+
+ pStr1++;
+ pStr2++;
+ nStr1Len--;
+ }
+ while( c2 );
+
+ return 0;
+}
+
+sal_Int32 rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths(
+ sal_Unicode const * first, sal_Int32 firstLen,
+ char const * second, sal_Int32 secondLen)
+{
+ sal_Int32 i;
+ sal_Int32 len = firstLen < secondLen ? firstLen : secondLen;
+ for (i = 0; i < len; ++i) {
+ sal_Int32 c1 = *first++;
+ sal_Int32 c2 = (unsigned char) *second++;
+ sal_Int32 d;
+ if (c1 >= 65 && c1 <= 90) {
+ c1 += 32;
+ }
+ if (c2 >= 65 && c2 <= 90) {
+ c2 += 32;
+ }
+ d = c1 - c2;
+ if (d != 0) {
+ return d;
+ }
+ }
+ return firstLen - secondLen;
+}
+
+/* ----------------------------------------------------------------------- */
+
+sal_Int32 SAL_CALL rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( const sal_Unicode* pStr1,
+ sal_Int32 nStr1Len,
+ const sal_Char* pStr2,
+ sal_Int32 nShortenedLength )
+{
+ const sal_Unicode* pStr1End = pStr1 + nStr1Len;
+ sal_Int32 nRet;
+ sal_Int32 c1;
+ sal_Int32 c2;
+ while ( (nShortenedLength > 0) &&
+ (pStr1 < pStr1End) && *pStr2 )
+ {
+ /* Check ASCII range */
+ OSL_ENSURE( (*pStr2 & 0x80) == 0, "Found ASCII char > 127");
+
+ /* If character between 'A' and 'Z', than convert it to lowercase */
+ c1 = (sal_Int32)*pStr1;
+ c2 = (sal_Int32)((unsigned char)*pStr2);
+ if ( (c1 >= 65) && (c1 <= 90) )
+ c1 += 32;
+ if ( (c2 >= 65) && (c2 <= 90) )
+ c2 += 32;
+ nRet = c1-c2;
+ if ( nRet != 0 )
+ return nRet;
+
+ nShortenedLength--;
+ pStr1++;
+ pStr2++;
+ }
+
+ if ( nShortenedLength <= 0 )
+ return 0;
+
+ if ( *pStr2 )
+ {
+ OSL_ENSURE( pStr1 == pStr1End, "pStr1 == pStr1End failed" );
+ // first is a substring of the second string => less (negative value)
+ nRet = -1;
+ }
+ else
+ {
+ // greater or equal
+ nRet = pStr1End - pStr1;
+ }
+
+ return nRet;
+}
+
+/* ----------------------------------------------------------------------- */
+
+void SAL_CALL rtl_uString_newFromAscii( rtl_uString** ppThis,
+ const sal_Char* pCharStr )
+{
+ sal_Int32 nLen;
+
+ if ( pCharStr )
+ {
+ const sal_Char* pTempStr = pCharStr;
+ while( *pTempStr )
+ pTempStr++;
+ nLen = pTempStr-pCharStr;
+ }
+ else
+ nLen = 0;
+
+ if ( !nLen )
+ {
+ IMPL_RTL_STRINGNAME( new )( ppThis );
+ return;
+ }
+
+ if ( *ppThis )
+ IMPL_RTL_STRINGNAME( release )( *ppThis );
+
+ *ppThis = IMPL_RTL_STRINGNAME( ImplAlloc )( nLen );
+ OSL_ASSERT(*ppThis != NULL);
+ if ( (*ppThis) )
+ {
+ IMPL_RTL_STRCODE* pBuffer = (*ppThis)->buffer;
+ do
+ {
+ /* Check ASCII range */
+ OSL_ENSURE( ((unsigned char)*pCharStr) <= 127,
+ "rtl_uString_newFromAscii() - Found ASCII char > 127" );
+
+ *pBuffer = *pCharStr;
+ pBuffer++;
+ pCharStr++;
+ }
+ while ( *pCharStr );
+ }
+}
+
+void SAL_CALL rtl_uString_newFromCodePoints(
+ rtl_uString ** newString, sal_uInt32 const * codePoints,
+ sal_Int32 codePointCount)
+{
+ sal_Int32 n;
+ sal_Int32 i;
+ sal_Unicode * p;
+ OSL_ASSERT(
+ newString != NULL &&
+ (codePoints != NULL || codePointCount == 0) &&
+ codePointCount >= 0);
+ if (codePointCount == 0) {
+ rtl_uString_new(newString);
+ return;
+ }
+ if (*newString != NULL) {
+ rtl_uString_release(*newString);
+ }
+ n = codePointCount;
+ for (i = 0; i < codePointCount; ++i) {
+ OSL_ASSERT(codePoints[i] <= 0x10FFFF);
+ if (codePoints[i] >= 0x10000) {
+ ++n;
+ }
+ }
+ /* Builds on the assumption that sal_Int32 uses 32 bit two's complement
+ representation with wrap around (the necessary number of UTF-16 code
+ units will be no larger than 2 * SAL_MAX_INT32, represented as
+ sal_Int32 -2): */
+ if (n < 0) {
+ *newString = NULL;
+ return;
+ }
+ *newString = rtl_uString_ImplAlloc(n);
+ if (*newString == NULL) {
+ return;
+ }
+ p = (*newString)->buffer;
+ for (i = 0; i < codePointCount; ++i) {
+ sal_uInt32 c = codePoints[i];
+ if (c < 0x10000) {
+ *p++ = (sal_Unicode) c;
+ } else {
+ c -= 0x10000;
+ *p++ = (sal_Unicode) ((c >> 10) | SAL_RTL_FIRST_HIGH_SURROGATE);
+ *p++ = (sal_Unicode) ((c & 0x3FF) | SAL_RTL_FIRST_LOW_SURROGATE);
+ }
+ }
+}
+
+/* ======================================================================= */
+
+static int rtl_ImplGetFastUTF8UnicodeLen( const sal_Char* pStr, sal_Int32 nLen )
+{
+ int n;
+ sal_uChar c;
+ const sal_Char* pEndStr;
+
+ n = 0;
+ pEndStr = pStr+nLen;
+ while ( pStr < pEndStr )
+ {
+ c = (sal_uChar)*pStr;
+
+ if ( !(c & 0x80) )
+ pStr++;
+ else if ( (c & 0xE0) == 0xC0 )
+ pStr += 2;
+ else if ( (c & 0xF0) == 0xE0 )
+ pStr += 3;
+ else if ( (c & 0xF8) == 0xF0 )
+ pStr += 4;
+ else if ( (c & 0xFC) == 0xF8 )
+ pStr += 5;
+ else if ( (c & 0xFE) == 0xFC )
+ pStr += 6;
+ else
+ pStr++;
+
+ n++;
+ }
+
+ return n;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static void rtl_string2UString_status( rtl_uString** ppThis,
+ const sal_Char* pStr,
+ sal_Int32 nLen,
+ rtl_TextEncoding eTextEncoding,
+ sal_uInt32 nCvtFlags,
+ sal_uInt32 *pInfo )
+{
+ OSL_ENSURE(rtl_isOctetTextEncoding(eTextEncoding),
+ "rtl_string2UString_status() - Wrong TextEncoding" );
+
+ if ( !nLen )
+ {
+ rtl_uString_new( ppThis );
+ if (pInfo != NULL) {
+ *pInfo = 0;
+ }
+ }
+ else
+ {
+ if ( *ppThis )
+ IMPL_RTL_STRINGNAME( release )( *ppThis );
+
+ /* Optimization for US-ASCII */
+ if ( eTextEncoding == RTL_TEXTENCODING_ASCII_US )
+ {
+ IMPL_RTL_STRCODE* pBuffer;
+ *ppThis = IMPL_RTL_STRINGNAME( ImplAlloc )( nLen );
+ if (*ppThis == NULL) {
+ if (pInfo != NULL) {
+ *pInfo = RTL_TEXTTOUNICODE_INFO_ERROR |
+ RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
+ }
+ return;
+ }
+ pBuffer = (*ppThis)->buffer;
+ do
+ {
+ /* Check ASCII range */
+ OSL_ENSURE( ((unsigned char)*pStr) <= 127,
+ "rtl_string2UString_status() - Found char > 127 and RTL_TEXTENCODING_ASCII_US is specified" );
+
+ *pBuffer = *pStr;
+ pBuffer++;
+ pStr++;
+ nLen--;
+ }
+ while ( nLen );
+ if (pInfo != NULL) {
+ *pInfo = 0;
+ }
+ }
+ else
+ {
+ rtl_uString* pTemp;
+ rtl_uString* pTemp2 = NULL;
+ rtl_TextToUnicodeConverter hConverter;
+ sal_uInt32 nInfo;
+ sal_Size nSrcBytes;
+ sal_Size nDestChars;
+ sal_Size nNewLen;
+
+ /* Optimization for UTF-8 - we try to calculate the exact length */
+ /* For all other encoding we try the maximum - and reallocate
+ the buffer if needed */
+ if ( eTextEncoding == RTL_TEXTENCODING_UTF8 )
+ {
+ nNewLen = rtl_ImplGetFastUTF8UnicodeLen( pStr, nLen );
+ /* Includes the string only ASCII, then we could copy
+ the buffer faster */
+ if ( nNewLen == (sal_Size)nLen )
+ {
+ IMPL_RTL_STRCODE* pBuffer;
+ *ppThis = IMPL_RTL_STRINGNAME( ImplAlloc )( nLen );
+ if (*ppThis == NULL)
+ {
+ if (pInfo != NULL) {
+ *pInfo = RTL_TEXTTOUNICODE_INFO_ERROR |
+ RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
+ }
+ return;
+ }
+ pBuffer = (*ppThis)->buffer;
+ do
+ {
+ /* Check ASCII range */
+ OSL_ENSURE( ((unsigned char)*pStr) <= 127,
+ "rtl_string2UString_status() - UTF8 test encoding is wrong" );
+
+ *pBuffer = *pStr;
+ pBuffer++;
+ pStr++;
+ nLen--;
+ }
+ while ( nLen );
+ if (pInfo != NULL) {
+ *pInfo = 0;
+ }
+ return;
+ }
+ }
+ else
+ nNewLen = nLen;
+
+ nCvtFlags |= RTL_TEXTTOUNICODE_FLAGS_FLUSH;
+ hConverter = rtl_createTextToUnicodeConverter( eTextEncoding );
+
+ pTemp = IMPL_RTL_STRINGNAME( ImplAlloc )( nNewLen );
+ if (pTemp == NULL) {
+ if (pInfo != NULL) {
+ *pInfo = RTL_TEXTTOUNICODE_INFO_ERROR |
+ RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
+ }
+ return;
+ }
+ nDestChars = rtl_convertTextToUnicode( hConverter, 0,
+ pStr, nLen,
+ pTemp->buffer, nNewLen,
+ nCvtFlags,
+ &nInfo, &nSrcBytes );
+
+ /* Buffer not big enough, try again with enough space */
+ /* Shouldn't be the case, but if we get textencoding which
+ could results in more unicode characters we have this
+ code here. Could be the case for apple encodings */
+ while ( nInfo & RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL )
+ {
+ rtl_freeMemory( pTemp );
+ nNewLen += 8;
+ pTemp = IMPL_RTL_STRINGNAME( ImplAlloc )( nNewLen );
+ if (pTemp == NULL) {
+ if (pInfo != NULL) {
+ *pInfo = RTL_TEXTTOUNICODE_INFO_ERROR |
+ RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL;
+ }
+ return;
+ }
+ nDestChars = rtl_convertTextToUnicode( hConverter, 0,
+ pStr, nLen,
+ pTemp->buffer, nNewLen,
+ nCvtFlags,
+ &nInfo, &nSrcBytes );
+ }
+
+ if (pInfo)
+ *pInfo = nInfo;
+
+ /* Set the buffer to the correct size or if there is too
+ much overhead, reallocate to the correct size */
+ if ( nNewLen > nDestChars+8 )
+ {
+ pTemp2 = IMPL_RTL_STRINGNAME( ImplAlloc )( nDestChars );
+ }
+ if (pTemp2 != NULL)
+ {
+ rtl_str_ImplCopy(pTemp2->buffer, pTemp->buffer, nDestChars);
+ rtl_freeMemory(pTemp);
+ pTemp = pTemp2;
+ }
+ else
+ {
+ pTemp->length = nDestChars;
+ pTemp->buffer[nDestChars] = 0;
+ }
+
+ rtl_destroyTextToUnicodeConverter( hConverter );
+ *ppThis = pTemp;
+
+ /* Results the conversion in an empty buffer -
+ create an empty string */
+ if ( pTemp && !nDestChars )
+ rtl_uString_new( ppThis );
+ }
+ }
+}
+
+void SAL_CALL rtl_string2UString( rtl_uString** ppThis,
+ const sal_Char* pStr,
+ sal_Int32 nLen,
+ rtl_TextEncoding eTextEncoding,
+ sal_uInt32 nCvtFlags )
+{
+ rtl_string2UString_status( ppThis, pStr, nLen, eTextEncoding,
+ nCvtFlags, NULL );
+}
+
+/* ----------------------------------------------------------------------- */
+
+typedef enum {
+ CANNOT_RETURN,
+ CAN_RETURN = 1
+} StrLifecycle;
+
+static oslMutex
+getInternMutex()
+{
+ static oslMutex pPoolGuard = NULL;
+ if( !pPoolGuard )
+ {
+ oslMutex pGlobalGuard;
+ pGlobalGuard = *osl_getGlobalMutex();
+ osl_acquireMutex( pGlobalGuard );
+ if( !pPoolGuard )
+ {
+ oslMutex p = osl_createMutex();
+ OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
+ pPoolGuard = p;
+ }
+ osl_releaseMutex( pGlobalGuard );
+ }
+ else
+ {
+ OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
+ }
+
+ return pPoolGuard;
+}
+
+/* returns true if we found a dup in the pool */
+static void rtl_ustring_intern_internal( rtl_uString ** newStr,
+ rtl_uString * str,
+ StrLifecycle can_return )
+{
+ oslMutex pPoolMutex;
+
+ pPoolMutex = getInternMutex();
+
+ osl_acquireMutex( pPoolMutex );
+
+ *newStr = rtl_str_hash_intern (str, can_return);
+
+ osl_releaseMutex( pPoolMutex );
+
+ if( can_return && *newStr != str )
+ { /* we dupped, then found a match */
+ rtl_freeMemory( str );
+ }
+}
+
+void SAL_CALL rtl_uString_intern( rtl_uString ** newStr,
+ rtl_uString * str)
+{
+ if (SAL_STRING_IS_INTERN(str))
+ {
+ IMPL_RTL_AQUIRE( str );
+ *newStr = str;
+ }
+ else
+ {
+ rtl_uString *pOrg = *newStr;
+ *newStr = NULL;
+ rtl_ustring_intern_internal( newStr, str, CANNOT_RETURN );
+ if (pOrg)
+ rtl_uString_release (pOrg);
+ }
+}
+
+void SAL_CALL rtl_uString_internConvert( rtl_uString ** newStr,
+ const sal_Char * str,
+ sal_Int32 len,
+ rtl_TextEncoding eTextEncoding,
+ sal_uInt32 convertFlags,
+ sal_uInt32 * pInfo )
+{
+ rtl_uString *scratch;
+
+ if (*newStr)
+ {
+ rtl_uString_release (*newStr);
+ *newStr = NULL;
+ }
+
+ if ( len < 256 )
+ { // try various optimisations
+ if ( len < 0 )
+ len = strlen( str );
+ if ( eTextEncoding == RTL_TEXTENCODING_ASCII_US )
+ {
+ int i;
+ rtl_uString *pScratch;
+ pScratch = alloca( sizeof( rtl_uString )
+ + len * sizeof (IMPL_RTL_STRCODE ) );
+ for (i = 0; i < len; i++)
+ {
+ /* Check ASCII range */
+ OSL_ENSURE( ((unsigned char)str[i]) <= 127,
+ "rtl_ustring_internConvert() - Found char > 127 and RTL_TEXTENCODING_ASCII_US is specified" );
+ pScratch->buffer[i] = str[i];
+ }
+ pScratch->length = len;
+ rtl_ustring_intern_internal( newStr, pScratch, CANNOT_RETURN );
+ return;
+ }
+ /* FIXME: we want a nice UTF-8 / alloca shortcut here */
+ }
+
+ scratch = NULL;
+ rtl_string2UString_status( &scratch, str, len, eTextEncoding, convertFlags,
+ pInfo );
+ if (!scratch) {
+ return;
+ }
+ rtl_ustring_intern_internal( newStr, scratch, CAN_RETURN );
+}
+
+static void
+internRelease (rtl_uString *pThis)
+{
+ oslMutex pPoolMutex;
+
+ rtl_uString *pFree = NULL;
+ if ( SAL_STRING_REFCOUNT(
+ osl_decrementInterlockedCount( &(pThis->refCount) ) ) == 0)
+ {
+ pPoolMutex = getInternMutex();
+ osl_acquireMutex( pPoolMutex );
+
+ rtl_str_hash_remove (pThis);
+
+ /* May have been separately acquired */
+ if ( SAL_STRING_REFCOUNT(
+ osl_incrementInterlockedCount( &(pThis->refCount) ) ) == 1 )
+ {
+ /* we got the last ref */
+ pFree = pThis;
+ }
+ else /* very unusual */
+ {
+ internRelease (pThis);
+ }
+
+ osl_releaseMutex( pPoolMutex );
+ }
+ if (pFree)
+ rtl_freeMemory (pFree);
+}
+
+sal_uInt32 SAL_CALL rtl_uString_iterateCodePoints(
+ rtl_uString const * string, sal_Int32 * indexUtf16,
+ sal_Int32 incrementCodePoints)
+{
+ sal_Int32 n;
+ sal_Unicode cu;
+ sal_uInt32 cp;
+ OSL_ASSERT(string != NULL && indexUtf16 != NULL);
+ n = *indexUtf16;
+ OSL_ASSERT(n >= 0 && n <= string->length);
+ while (incrementCodePoints < 0) {
+ OSL_ASSERT(n > 0);
+ cu = string->buffer[--n];
+ if (SAL_RTL_IS_LOW_SURROGATE(cu) && n != 0 &&
+ SAL_RTL_IS_HIGH_SURROGATE(string->buffer[n - 1]))
+ {
+ --n;
+ }
+ ++incrementCodePoints;
+ }
+ OSL_ASSERT(n >= 0 && n < string->length);
+ cu = string->buffer[n];
+ if (SAL_RTL_IS_HIGH_SURROGATE(cu) && string->length - n >= 2 &&
+ SAL_RTL_IS_LOW_SURROGATE(string->buffer[n + 1]))
+ {
+ cp = SAL_RTL_COMBINE_SURROGATES(cu, string->buffer[n + 1]);
+ } else {
+ cp = cu;
+ }
+ while (incrementCodePoints > 0) {
+ OSL_ASSERT(n < string->length);
+ cu = string->buffer[n++];
+ if (SAL_RTL_IS_HIGH_SURROGATE(cu) && n != string->length &&
+ SAL_RTL_IS_LOW_SURROGATE(string->buffer[n]))
+ {
+ ++n;
+ }
+ --incrementCodePoints;
+ }
+ OSL_ASSERT(n >= 0 && n <= string->length);
+ *indexUtf16 = n;
+ return cp;
+}
+
+sal_Bool rtl_convertStringToUString(
+ rtl_uString ** target, char const * source, sal_Int32 length,
+ rtl_TextEncoding encoding, sal_uInt32 flags) SAL_THROW_EXTERN_C()
+{
+ sal_uInt32 info;
+ rtl_string2UString_status(target, source, length, encoding, flags, &info);
+ return (sal_Bool) ((info & RTL_TEXTTOUNICODE_INFO_ERROR) == 0);
+}
diff --git a/sal/rtl/source/uuid.cxx b/sal/rtl/source/uuid.cxx
new file mode 100644
index 000000000000..79790c99887e
--- /dev/null
+++ b/sal/rtl/source/uuid.cxx
@@ -0,0 +1,180 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <osl/mutex.hxx>
+#include <rtl/random.h>
+#include <rtl/uuid.h>
+#include <rtl/digest.h>
+
+#define SWAP_INT32_TO_NETWORK(x)\
+ { sal_uInt32 y = x;\
+ sal_uInt8 *p = (sal_uInt8 * )&(x); \
+ p[0] = (sal_uInt8) ( ( y >> 24 ) & 0xff );\
+ p[1] = (sal_uInt8) ( ( y >> 16 ) & 0xff );\
+ p[2] = (sal_uInt8) ( ( y >> 8 ) & 0xff );\
+ p[3] = (sal_uInt8) ( ( y ) & 0xff);\
+ }
+#define SWAP_INT16_TO_NETWORK(x)\
+ { sal_uInt16 y = x;\
+ sal_uInt8 *p = (sal_uInt8 * )&(x); \
+ p[0] = (sal_uInt8) ( ( y >> 8 ) & 0xff );\
+ p[1] = (sal_uInt8) ( ( y ) & 0xff);\
+ }
+
+#define SWAP_NETWORK_TO_INT16(x)\
+ { sal_uInt16 y = x;\
+ sal_uInt8 *p = (sal_uInt8 * )&(y);\
+ x = ( ( ((sal_uInt16)p[0]) & 0xff) << 8 ) |\
+ ( ( (sal_uInt16)p[1]) & 0xff);\
+ }
+#define SWAP_NETWORK_TO_INT32(x)\
+ { sal_uInt32 y = x;\
+ sal_uInt8 *p = (sal_uInt8 * )&(y); \
+ x = ( ( ((sal_uInt32)p[0]) & 0xff) << 24 ) |\
+ ( ( ((sal_uInt32)p[1]) & 0xff) << 16 ) |\
+ ( ( ((sal_uInt32)p[2]) & 0xff) << 8 ) |\
+ ( ( (sal_uInt32)p[3]) & 0xff);\
+ }
+
+typedef struct _UUID
+{
+ sal_uInt32 time_low;
+ sal_uInt16 time_mid;
+ sal_uInt16 time_hi_and_version;
+ sal_uInt8 clock_seq_hi_and_reserved;
+ sal_uInt8 clock_seq_low;
+ sal_uInt8 node[6];
+} UUID;
+
+static void write_v3( sal_uInt8 *pUuid )
+{
+ UUID uuid;
+ // copy to avoid alignment problems
+ memcpy( &uuid , pUuid , 16 );
+
+ SWAP_NETWORK_TO_INT32( uuid.time_low );
+ SWAP_NETWORK_TO_INT16( uuid.time_mid );
+ SWAP_NETWORK_TO_INT16( uuid.time_hi_and_version );
+
+ /* put in the variant and version bits */
+ uuid.time_hi_and_version &= 0x0FFF;
+ uuid.time_hi_and_version |= (3 << 12);
+ uuid.clock_seq_hi_and_reserved &= 0x3F;
+ uuid.clock_seq_hi_and_reserved |= 0x80;
+
+ SWAP_INT32_TO_NETWORK( uuid.time_low );
+ SWAP_INT16_TO_NETWORK( uuid.time_mid );
+ SWAP_INT16_TO_NETWORK( uuid.time_hi_and_version );
+
+ memcpy( pUuid , &uuid , 16 );
+}
+
+
+extern "C" void SAL_CALL rtl_createUuid( sal_uInt8 *pTargetUUID ,
+ const sal_uInt8 *, sal_Bool )
+{
+ {
+ osl::MutexGuard g(osl::Mutex::getGlobalMutex());
+ static rtlRandomPool pool = NULL;
+ if (pool == NULL) {
+ pool = rtl_random_createPool();
+ if (pool == NULL) {
+ abort();
+ // only possible way to signal failure here (rtl_createUuid
+ // being part of a fixed C API)
+ }
+ }
+ if (rtl_random_getBytes(pool, pTargetUUID, 16) != rtl_Random_E_None) {
+ abort();
+ // only possible way to signal failure here (rtl_createUuid
+ // being part of a fixed C API)
+ }
+ }
+ // See ITU-T Recommendation X.667:
+ pTargetUUID[6] &= 0x0F;
+ pTargetUUID[6] |= 0x40;
+ pTargetUUID[8] &= 0x3F;
+ pTargetUUID[8] |= 0x80;
+}
+
+
+extern "C" void SAL_CALL rtl_createNamedUuid( sal_uInt8 *pTargetUUID,
+ const sal_uInt8 *pNameSpaceUUID,
+ const rtl_String *pName )
+{
+ rtlDigest digest = rtl_digest_createMD5 ();
+
+ rtl_digest_updateMD5( digest, pNameSpaceUUID , 16 );
+ rtl_digest_updateMD5( digest, pName->buffer , pName->length );
+
+ rtl_digest_getMD5( digest, pTargetUUID , 16 );
+ rtl_digest_destroyMD5 (digest);
+
+ write_v3(pTargetUUID);
+}
+
+
+
+extern "C" sal_Int32 SAL_CALL rtl_compareUuid( const sal_uInt8 *pUUID1 , const sal_uInt8 *pUUID2 )
+{
+ int i;
+ UUID u1;
+ UUID u2;
+ memcpy( &u1 , pUUID1 , 16 );
+ memcpy( &u2 , pUUID2 , 16 );
+
+ SWAP_NETWORK_TO_INT32( u1.time_low );
+ SWAP_NETWORK_TO_INT16( u1.time_mid );
+ SWAP_NETWORK_TO_INT16( u1.time_hi_and_version );
+
+ SWAP_NETWORK_TO_INT32( u2.time_low );
+ SWAP_NETWORK_TO_INT16( u2.time_mid );
+ SWAP_NETWORK_TO_INT16( u2.time_hi_and_version );
+
+#define CHECK(f1, f2) if (f1 != f2) return f1 < f2 ? -1 : 1;
+ CHECK(u1.time_low, u2.time_low);
+ CHECK(u1.time_mid, u2.time_mid);
+ CHECK(u1.time_hi_and_version, u2.time_hi_and_version);
+ CHECK(u1.clock_seq_hi_and_reserved, u2.clock_seq_hi_and_reserved);
+ CHECK(u1.clock_seq_low, u2.clock_seq_low);
+ for (i = 0; i < 6; i++)
+ {
+ if (u1.node[i] < u2.node[i])
+ return -1;
+ if (u1.node[i] > u2.node[i])
+ return 1;
+ }
+ return 0;
+
+}
+