You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by wr...@apache.org on 2016/01/27 01:08:59 UTC
svn commit: r1726928 - in /apr/apr/trunk: CMakeLists.txt SConscript
include/apr_cstr.h include/apr_errno.h strings/apr_cstr.c
Author: wrowe
Date: Wed Jan 27 00:08:59 2016
New Revision: 1726928
URL: http://svn.apache.org/viewvc?rev=1726928&view=rev
Log:
Introduce the subset of svn_cstring_ functions into APR as the apr_cstr_
family of functions. Requires the introduction of APR_ERANGE.
Solves apr_cstr_casecmp[n] for ASCII and EBCDIC and borrows
from the work of jim, ylavic and wrowe, see r1715401 forwards in;
http://svn.apache.org/viewvc/httpd/httpd/trunk/server/util.c?view=log&pathrev=1722194
More performance review is needed against different compilers, so went ahead
and borrowed original svn implementation as a basis, and we can port whichever
performance enhancements test out more efficiently.
Proposing for APR 1.6.0 which is the thought behind the initial @since tags.
These must be changed if not accepted for backport.
Note that the svn_cstring_join function could not be implemented as-is
due to the absence of svn's counted string functionality. It deserves
an implementation if not already present, or should be removed before
tagging or backporting.
No whitespace/formatting cleanup on this pass in order to preserve as
much of the svn attributions as possible. This can happen in a later
pass to conform to APR's style conventions. While renaming the functions,
declarations themsel
Added:
apr/apr/trunk/include/apr_cstr.h
- copied, changed from r1717268, subversion/trunk/subversion/include/svn_string.h
apr/apr/trunk/strings/apr_cstr.c
- copied, changed from r1717268, subversion/trunk/subversion/libsvn_subr/string.c
Modified:
apr/apr/trunk/CMakeLists.txt
apr/apr/trunk/SConscript
apr/apr/trunk/include/apr_errno.h
Modified: apr/apr/trunk/CMakeLists.txt
URL: http://svn.apache.org/viewvc/apr/apr/trunk/CMakeLists.txt?rev=1726928&r1=1726927&r2=1726928&view=diff
==============================================================================
--- apr/apr/trunk/CMakeLists.txt (original)
+++ apr/apr/trunk/CMakeLists.txt Wed Jan 27 00:08:59 2016
@@ -156,6 +156,7 @@ SET(APR_PUBLIC_HEADERS_STATIC
include/apr_base64.h
include/apr_buckets.h
include/apr_crypto.h
+ include/apr_cstr.h
include/apr_date.h
include/apr_dbd.h
include/apr_dbm.h
@@ -309,6 +310,7 @@ SET(APR_SOURCES
random/unix/sha2_glue.c
shmem/win32/shm.c
strings/apr_cpystrn.c
+ strings/apr_cstr.c
strings/apr_fnmatch.c
strings/apr_snprintf.c
strings/apr_strings.c
Modified: apr/apr/trunk/SConscript
URL: http://svn.apache.org/viewvc/apr/apr/trunk/SConscript?rev=1726928&r1=1726927&r2=1726928&view=diff
==============================================================================
--- apr/apr/trunk/SConscript (original)
+++ apr/apr/trunk/SConscript Wed Jan 27 00:08:59 2016
@@ -8,7 +8,7 @@ files = env.core_lib_files()
libapr = env.SharedLibrary('apr-%d' % (major), files)
tests = Split("""
abts.c testutil.c
- testtime.c teststr.c testvsn.c testipsub.c testshm.c
+ testtime.c testcstr.c teststr.c testvsn.c testipsub.c testshm.c
testmmap.c testud.c testtable.c testsleep.c testpools.c
testfmt.c testfile.c testdir.c testfileinfo.c testrand.c
testdso.c testoc.c testdup.c testsockets.c testproc.c
Copied: apr/apr/trunk/include/apr_cstr.h (from r1717268, subversion/trunk/subversion/include/svn_string.h)
URL: http://svn.apache.org/viewvc/apr/apr/trunk/include/apr_cstr.h?p2=apr/apr/trunk/include/apr_cstr.h&p1=subversion/trunk/subversion/include/svn_string.h&r1=1717268&r2=1726928&rev=1726928&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_string.h (original)
+++ apr/apr/trunk/include/apr_cstr.h Wed Jan 27 00:08:59 2016
@@ -1,6 +1,4 @@
-/**
- * @copyright
- * ====================================================================
+/* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
@@ -18,429 +16,51 @@
* specific language governing permissions and limitations
* under the License.
* ====================================================================
- * @endcopyright
- *
- * @file svn_string.h
- * @brief Counted-length strings for Subversion, plus some C string goodies.
- *
- * There are two string datatypes: @c svn_string_t and @c svn_stringbuf_t.
- * The former is a simple pointer/length pair useful for passing around
- * strings (or arbitrary bytes) with a counted length. @c svn_stringbuf_t is
- * buffered to enable efficient appending of strings without an allocation
- * and copy for each append operation.
- *
- * @c svn_string_t contains a <tt>const char *</tt> for its data, so it is
- * most appropriate for constant data and for functions which expect constant,
- * counted data. Functions should generally use <tt>const @c svn_string_t
- * *</tt> as their parameter to indicate they are expecting a constant,
- * counted string.
- *
- * @c svn_stringbuf_t uses a plain <tt>char *</tt> for its data, so it is
- * most appropriate for modifiable data.
- *
- * <h3>Invariants</h3>
- *
- * 1. Null termination:
- *
- * Both structures maintain a significant invariant:
- *
- * <tt>s->data[s->len] == '\\0'</tt>
- *
- * The functions defined within this header file will maintain
- * the invariant (which does imply that memory is
- * allocated/defined as @c len+1 bytes). If code outside of the
- * @c svn_string.h functions manually builds these structures,
- * then they must enforce this invariant.
- *
- * Note that an @c svn_string(buf)_t may contain binary data,
- * which means that strlen(s->data) does not have to equal @c
- * s->len. The null terminator is provided to make it easier to
- * pass @c s->data to C string interfaces.
- *
- *
- * 2. Non-NULL input:
- *
- * All the functions assume their input data pointer is non-NULL,
- * unless otherwise documented, and may seg fault if passed
- * NULL. The input data may *contain* null bytes, of course, just
- * the data pointer itself must not be NULL.
- *
- * <h3>Memory allocation</h3>
- *
- * All the functions make a deep copy of all input data, and never store
- * a pointer to the original input data.
*/
+/**
+ * @file apr_cstr.h
+ * @brief C string goodies.
+ */
-#ifndef SVN_STRING_H
-#define SVN_STRING_H
+#ifndef APR_CSTR_H
+#define APR_CSTR_H
#include <apr.h> /* for apr_size_t */
#include <apr_pools.h> /* for apr_pool_t */
#include <apr_tables.h> /* for apr_array_header_t */
-#include "svn_types.h" /* for svn_boolean_t, svn_error_t */
-
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/**
- * @defgroup svn_string String handling
- * @{
- */
-
-
-
-/** A simple counted string. */
-typedef struct svn_string_t
-{
- const char *data; /**< pointer to the bytestring */
- apr_size_t len; /**< length of bytestring */
-} svn_string_t;
-
-/** A buffered string, capable of appending without an allocation and copy
- * for each append. */
-typedef struct svn_stringbuf_t
-{
- /** a pool from which this string was originally allocated, and is not
- * necessarily specific to this string. This is used only for allocating
- * more memory from when the string needs to grow.
- */
- apr_pool_t *pool;
-
- /** pointer to the bytestring */
- char *data;
-
- /** length of bytestring */
- apr_size_t len;
-
- /** total size of buffer allocated */
- apr_size_t blocksize;
-} svn_stringbuf_t;
-
-
-/**
- * @defgroup svn_string_svn_string_t svn_string_t functions
- * @{
- */
-
-/** Create a new string copied from the null-terminated C string @a cstring.
- */
-svn_string_t *
-svn_string_create(const char *cstring, apr_pool_t *pool);
-
-/** Create a new, empty string.
- *
- * @since New in 1.8.
- */
-svn_string_t *
-svn_string_create_empty(apr_pool_t *pool);
-
-/** Create a new string copied from a generic string of bytes, @a bytes, of
- * length @a size bytes. @a bytes is NOT assumed to be null-terminated, but
- * the new string will be.
- *
- * @since Since 1.9, @a bytes can be NULL if @a size is zero.
- */
-svn_string_t *
-svn_string_ncreate(const char *bytes, apr_size_t size, apr_pool_t *pool);
-
-/** Create a new string copied from the stringbuf @a strbuf.
- */
-svn_string_t *
-svn_string_create_from_buf(const svn_stringbuf_t *strbuf, apr_pool_t *pool);
-
-/** Create a new string by printf-style formatting using @a fmt and the
- * variable arguments, which are as appropriate for apr_psprintf().
- */
-svn_string_t *
-svn_string_createf(apr_pool_t *pool, const char *fmt, ...)
- __attribute__((format(printf, 2, 3)));
-
-/** Create a new string by printf-style formatting using @c fmt and @a ap.
- * This is the same as svn_string_createf() except for the different
- * way of passing the variable arguments.
- */
-svn_string_t *
-svn_string_createv(apr_pool_t *pool, const char *fmt, va_list ap)
- __attribute__((format(printf, 2, 0)));
-
-/** Return TRUE if @a str is empty (has length zero). */
-svn_boolean_t
-svn_string_isempty(const svn_string_t *str);
-
-/** Return a duplicate of @a original_string.
+ * @defgroup apr_cstr C (POSIX) locale string functions
+ * @ingroup apr_strings
*
- * @since Since 1.9, @a original_string can be NULL in which case NULL will
- * be returned.
- */
-svn_string_t *
-svn_string_dup(const svn_string_t *original_string, apr_pool_t *pool);
-
-/** Return @c TRUE iff @a str1 and @a str2 have identical length and data. */
-svn_boolean_t
-svn_string_compare(const svn_string_t *str1, const svn_string_t *str2);
-
-/** Return offset of first non-whitespace character in @a str, or return
- * @a str->len if none.
- */
-apr_size_t
-svn_string_first_non_whitespace(const svn_string_t *str);
-
-/** Return position of last occurrence of @a ch in @a str, or return
- * @a str->len if no occurrence.
- */
-apr_size_t
-svn_string_find_char_backward(const svn_string_t *str, char ch);
-
-/** @} */
-
-
-/**
- * @defgroup svn_string_svn_stringbuf_t svn_stringbuf_t functions
+ * The apr_cstr_* functions provide traditional C char * string text handling,
+ * and notabilty they treat all text in the C (a.k.a. POSIX) locale using the
+ * minimal POSIX character set, represented in either ASCII or a corresponding
+ * EBCDIC subset.
+ *
+ * Character values outside of that set are treated as opaque bytes, and all
+ * multi-byte character sequences are handled as individual distinct octets.
+ *
+ * Multi-byte characters sequences whose octets fall in the ASCII range cause
+ * unexpected results, such as in the ISO-2022-JP code page where ASCII octets
+ * occur within both shift-state and multibyte sequences.
+ *
+ * In the case of the UTF-8 encoding, all multibyte characters all fall outside
+ * of the C/POSIX range of characters, so these functions are generally safe
+ * to use on UTF-8 strings. The programmer must be aware that each octet may
+ * not represent a distinct printable character in such encodings.
+ *
+ * The standard C99/POSIX string functions, rather than apr_cstr, should be
+ * used in all cases where the current locale and encoding of the text is
+ * significant.
* @{
*/
-/** Create a new stringbuf copied from the null-terminated C string
- * @a cstring.
- */
-svn_stringbuf_t *
-svn_stringbuf_create(const char *cstring, apr_pool_t *pool);
-
-/** Create a new stringbuf copied from the generic string of bytes, @a bytes,
- * of length @a size bytes. @a bytes is NOT assumed to be null-terminated,
- * but the new stringbuf will be.
- *
- * @since Since 1.9, @a bytes can be NULL if @a size is zero.
- */
-svn_stringbuf_t *
-svn_stringbuf_ncreate(const char *bytes, apr_size_t size, apr_pool_t *pool);
-
-/** Create a new, empty stringbuf.
- *
- * @since New in 1.8.
- */
-svn_stringbuf_t *
-svn_stringbuf_create_empty(apr_pool_t *pool);
-
-/** Create a new, empty stringbuf with at least @a minimum_size bytes of
- * space available in the memory block.
- *
- * The allocated string buffer will be at least one byte larger than
- * @a minimum_size to account for a final '\\0'.
- *
- * @since New in 1.6.
- */
-svn_stringbuf_t *
-svn_stringbuf_create_ensure(apr_size_t minimum_size, apr_pool_t *pool);
-
-/** Create a new stringbuf copied from the string @a str.
- */
-svn_stringbuf_t *
-svn_stringbuf_create_from_string(const svn_string_t *str, apr_pool_t *pool);
-
-/** Create a new stringbuf using the given @a str as initial buffer.
- * Allocate the result in @a pool. In contrast to #svn_stringbuf_create,
- * the contents of @a str may change when the stringbuf gets modified.
- *
- * @since New in 1.9
- */
-svn_stringbuf_t *
-svn_stringbuf_create_wrap(char *str, apr_pool_t *pool);
-
-/** Create a new stringbuf by printf-style formatting using @a fmt and the
- * variable arguments, which are as appropriate for apr_psprintf().
- */
-svn_stringbuf_t *
-svn_stringbuf_createf(apr_pool_t *pool, const char *fmt, ...)
- __attribute__((format(printf, 2, 3)));
-
-/** Create a new stringbuf by printf-style formatting using @c fmt and @a ap.
- * This is the same as svn_stringbuf_createf() except for the different
- * way of passing the variable arguments.
- */
-svn_stringbuf_t *
-svn_stringbuf_createv(apr_pool_t *pool, const char *fmt, va_list ap)
- __attribute__((format(printf, 2, 0)));
-
-/** Make sure that @a str has at least @a minimum_size
- * bytes of space available in the memory block.
- *
- * The allocated string buffer will be at least one byte larger than
- * @a minimum_size to account for a final '\\0'.
- *
- * @note: Before Subversion 1.8 this function did not ensure space for
- * one byte more than @a minimum_size. If compatibility with pre-1.8
- * behaviour is required callers must assume space for only
- * @a minimum_size-1 data bytes plus a final '\\0'.
- */
-void
-svn_stringbuf_ensure(svn_stringbuf_t *str, apr_size_t minimum_size);
-
-/** Set @a str to a copy of the null-terminated C string @a value. */
-void
-svn_stringbuf_set(svn_stringbuf_t *str, const char *value);
-
-/** Set @a str to empty (zero length). */
-void
-svn_stringbuf_setempty(svn_stringbuf_t *str);
-
-/** Return @c TRUE if @a str is empty (has length zero). */
-svn_boolean_t
-svn_stringbuf_isempty(const svn_stringbuf_t *str);
-
-/** Chop @a nbytes bytes off end of @a str, but not more than @a str->len. */
-void
-svn_stringbuf_chop(svn_stringbuf_t *str, apr_size_t nbytes);
-
-/** Fill @a str with character @a c. */
-void
-svn_stringbuf_fillchar(svn_stringbuf_t *str, unsigned char c);
-
-/** Append the single character @a byte onto @a targetstr.
- *
- * This is an optimized version of svn_stringbuf_appendbytes()
- * that is much faster to call and execute. Gains vary with the ABI.
- * The advantages extend beyond the actual call because the reduced
- * register pressure allows for more optimization within the caller.
- *
- * Reallocs if necessary. @a targetstr is affected, nothing else is.
- * @since New in 1.7.
- */
-void
-svn_stringbuf_appendbyte(svn_stringbuf_t *targetstr,
- char byte);
-
-/** Append the array of bytes @a bytes of length @a count onto @a targetstr.
- *
- * Reallocs if necessary. @a targetstr is affected, nothing else is.
- *
- * @since 1.9 @a bytes can be NULL if @a count is zero.
- */
-void
-svn_stringbuf_appendbytes(svn_stringbuf_t *targetstr,
- const char *bytes,
- apr_size_t count);
-
-/** Append @a byte @a count times onto @a targetstr.
- *
- * Reallocs if necessary. @a targetstr is affected, nothing else is.
- * @since New in 1.9.
- */
-void
-svn_stringbuf_appendfill(svn_stringbuf_t *targetstr,
- char byte,
- apr_size_t count);
-
-/** Append the stringbuf @c appendstr onto @a targetstr.
- *
- * Reallocs if necessary. @a targetstr is affected, nothing else is.
- */
-void
-svn_stringbuf_appendstr(svn_stringbuf_t *targetstr,
- const svn_stringbuf_t *appendstr);
-
-/** Append the C string @a cstr onto @a targetstr.
- *
- * Reallocs if necessary. @a targetstr is affected, nothing else is.
- */
-void
-svn_stringbuf_appendcstr(svn_stringbuf_t *targetstr,
- const char *cstr);
-
-/** Insert into @a str at position @a pos an array of bytes @a bytes
- * which is @a count bytes long.
- *
- * The resulting string will be @c count+str->len bytes long. If
- * @a pos is larger than or equal to @c str->len, simply append @a bytes.
- *
- * Reallocs if necessary. @a str is affected, nothing else is.
- *
- * @note The inserted string may be a sub-range of @a str.
- *
- * @since New in 1.8.
- *
- * @since Since 1.9, @a bytes can be NULL if @a count is zero.
- */
-void
-svn_stringbuf_insert(svn_stringbuf_t *str,
- apr_size_t pos,
- const char *bytes,
- apr_size_t count);
-
-/** Remove @a count bytes from @a str, starting at position @a pos.
- *
- * If that range exceeds the current string data, truncate @a str at
- * @a pos. If @a pos is larger than or equal to @c str->len, this will
- * be a no-op. Otherwise, the resulting string will be @c str->len-count
- * bytes long.
- *
- * @since New in 1.8.
- */
-void
-svn_stringbuf_remove(svn_stringbuf_t *str,
- apr_size_t pos,
- apr_size_t count);
-
-/** Replace in @a str the substring which starts at @a pos and is @a
- * old_count bytes long with a new substring @a bytes which is @a
- * new_count bytes long.
- *
- * This is faster but functionally equivalent to the following sequence:
- * @code
- svn_stringbuf_remove(str, pos, old_count);
- svn_stringbuf_insert(str, pos, bytes, new_count);
- * @endcode
- *
- * @since New in 1.8.
- *
- * @since Since 1.9, @a bytes can be NULL if @a new_count is zero.
- */
-void
-svn_stringbuf_replace(svn_stringbuf_t *str,
- apr_size_t pos,
- apr_size_t old_count,
- const char *bytes,
- apr_size_t new_count);
-
-/** Return a duplicate of @a original_string. */
-svn_stringbuf_t *
-svn_stringbuf_dup(const svn_stringbuf_t *original_string, apr_pool_t *pool);
-
-/** Return @c TRUE iff @a str1 and @a str2 have identical length and data. */
-svn_boolean_t
-svn_stringbuf_compare(const svn_stringbuf_t *str1,
- const svn_stringbuf_t *str2);
-
-/** Return offset of first non-whitespace character in @a str, or return
- * @a str->len if none.
- */
-apr_size_t
-svn_stringbuf_first_non_whitespace(const svn_stringbuf_t *str);
-
-/** Strip whitespace from both sides of @a str (modified in place). */
-void
-svn_stringbuf_strip_whitespace(svn_stringbuf_t *str);
-
-/** Return position of last occurrence of @a ch in @a str, or return
- * @a str->len if no occurrence.
- */
-apr_size_t
-svn_stringbuf_find_char_backward(const svn_stringbuf_t *str, char ch);
-
-/** Return @c TRUE iff @a str1 and @a str2 have identical length and data. */
-svn_boolean_t
-svn_string_compare_stringbuf(const svn_string_t *str1,
- const svn_stringbuf_t *str2);
-
-/** @} */
-
-
-/**
- * @defgroup svn_string_cstrings C string functions
- * @{
- */
/** Divide @a input into substrings, interpreting any char from @a sep
* as a token separator.
@@ -455,37 +75,39 @@ svn_string_compare_stringbuf(const svn_s
*
* If @a chop_whitespace is TRUE, then remove leading and trailing
* whitespace from the returned strings.
+ *
+ * @since New in 1.6
*/
-apr_array_header_t *
-svn_cstring_split(const char *input,
- const char *sep_chars,
- svn_boolean_t chop_whitespace,
- apr_pool_t *pool);
+apr_array_header_t * apr_cstr_split(const char *input,
+ const char *sep_chars,
+ int chop_whitespace,
+ apr_pool_t *pool);
-/** Like svn_cstring_split(), but append to existing @a array instead of
+/** Like apr_cstr_split(), but append to existing @a array instead of
* creating a new one. Allocate the copied substrings in @a pool
* (i.e., caller decides whether or not to pass @a array->pool as @a pool).
+ *
+ * @since New in 1.6
*/
-void
-svn_cstring_split_append(apr_array_header_t *array,
- const char *input,
- const char *sep_chars,
- svn_boolean_t chop_whitespace,
- apr_pool_t *pool);
+void apr_cstr_split_append(apr_array_header_t *array,
+ const char *input,
+ const char *sep_chars,
+ int chop_whitespace,
+ apr_pool_t *pool);
/** Return @c TRUE iff @a str matches any of the elements of @a list, a list
* of zero or more glob patterns.
+ *
+ * @since New in 1.6
*/
-svn_boolean_t
-svn_cstring_match_glob_list(const char *str, const apr_array_header_t *list);
+int apr_cstr_match_glob_list(const char *str, const apr_array_header_t *list);
/** Return @c TRUE iff @a str exactly matches any of the elements of @a list.
*
- * @since new in 1.7
+ * @since New in 1.6
*/
-svn_boolean_t
-svn_cstring_match_list(const char *str, const apr_array_header_t *list);
+int apr_cstr_match_list(const char *str, const apr_array_header_t *list);
/**
* Get the next token from @a *str interpreting any char from @a sep as a
@@ -496,45 +118,56 @@ svn_cstring_match_list(const char *str,
*
* @note The content of @a *str may be modified by this function.
*
- * @since New in 1.8.
+ * @since New in 1.6.
*/
-char *
-svn_cstring_tokenize(const char *sep, char **str);
+char * apr_cstr_tokenize(const char *sep, char **str);
/**
* Return the number of line breaks in @a msg, allowing any kind of newline
* termination (CR, LF, CRLF, or LFCR), even inconsistent.
*
- * @since New in 1.2.
+ * @since New in 1.6.
*/
-int
-svn_cstring_count_newlines(const char *msg);
+int apr_cstr_count_newlines(const char *msg);
+#if 0 /* XXX: stringbuf logic is not present in APR */
/**
* Return a cstring which is the concatenation of @a strings (an array
* of char *) each followed by @a separator (that is, @a separator
* will also end the resulting string). Allocate the result in @a pool.
* If @a strings is empty, then return the empty string.
*
- * @since New in 1.2.
+ * @since New in 1.6.
*/
-char *
-svn_cstring_join(const apr_array_header_t *strings,
- const char *separator,
- apr_pool_t *pool);
+char * apr_cstr_join(const apr_array_header_t *strings,
+ const char *separator,
+ apr_pool_t *pool);
+#endif
/**
* Compare two strings @a atr1 and @a atr2, treating case-equivalent
- * unaccented Latin (ASCII subset) letters as equal.
+ * unaccented Latin (C/POSIX ASCII subset) alpha characters as equal.
+ *
+ * Returns in integer greater than, equal to, or less than 0,
+ * according to whether @a str1 is considered greater than, equal to,
+ * or less than @a str2.
+ *
+ * @since New in 1.6.
+ */
+int apr_cstr_casecmp(const char *str1, const char *str2);
+
+/**
+ * Compare two strings @a atr1 and @a atr2 of @n (or shorter) length,
+ * treating case-equivalent unaccented Latin (C/POSIX ASCII subset)
+ * alpha characters as equal.
*
* Returns in integer greater than, equal to, or less than 0,
* according to whether @a str1 is considered greater than, equal to,
* or less than @a str2.
*
- * @since New in 1.5.
+ * @since New in 1.6.
*/
-int
-svn_cstring_casecmp(const char *str1, const char *str2);
+int apr_cstr_casecmpn(const char *str1, const char *str2, apr_size_t n);
/**
* Parse the C string @a str into a 64 bit number, and return it in @a *n.
@@ -553,36 +186,33 @@ svn_cstring_casecmp(const char *str1, co
* else a leading '0' means octal (implemented, though not documented, in
* apr_strtoi64() in APR 0.9.0 through 1.5.0), else use base ten.
*
- * @since New in 1.7.
+ * @since New in 1.6.
*/
-svn_error_t *
-svn_cstring_strtoi64(apr_int64_t *n, const char *str,
- apr_int64_t minval, apr_int64_t maxval,
- int base);
+apr_status_t apr_cstr_strtoi64(apr_int64_t *n, const char *str,
+ apr_int64_t minval, apr_int64_t maxval,
+ int base);
/**
* Parse the C string @a str into a 64 bit number, and return it in @a *n.
* Assume that the number is represented in base 10.
* Raise an error if conversion fails (e.g. due to overflow).
*
- * The behaviour otherwise is as described for svn_cstring_strtoi64().
+ * The behaviour otherwise is as described for apr_cstr_strtoi64().
*
- * @since New in 1.7.
+ * @since New in 1.6.
*/
-svn_error_t *
-svn_cstring_atoi64(apr_int64_t *n, const char *str);
+apr_status_t apr_cstr_atoi64(apr_int64_t *n, const char *str);
/**
* Parse the C string @a str into a 32 bit number, and return it in @a *n.
* Assume that the number is represented in base 10.
* Raise an error if conversion fails (e.g. due to overflow).
*
- * The behaviour otherwise is as described for svn_cstring_strtoi64().
+ * The behaviour otherwise is as described for apr_cstr_strtoi64().
*
- * @since New in 1.7.
+ * @since New in 1.6.
*/
-svn_error_t *
-svn_cstring_atoi(int *n, const char *str);
+apr_status_t apr_cstr_atoi(int *n, const char *str);
/**
* Parse the C string @a str into an unsigned 64 bit number, and return
@@ -598,61 +228,53 @@ svn_cstring_atoi(int *n, const char *str
* returned.
*
* If @a base is zero, then a leading '0x' or '0X' prefix means hexadecimal,
- * else a leading '0' means octal (implemented, though not documented, in
- * apr_strtoi64() in APR 0.9.0 through 1.5.0), else use base ten.
+ * else a leading '0' means octal (as implemented, though not documented, in
+ * apr_strtoi64(), else use base ten.
+ *
+ * @warning The implementation returns APR_ERANGE if the parsed number
+ * is greater than APR_INT64_MAX, even if it is not greater than @a maxval.
*
- * @warning The implementation used since version 1.7 returns an error
- * if the parsed number is greater than APR_INT64_MAX, even if it is not
- * greater than @a maxval.
- *
- * @since New in 1.7.
- */
-svn_error_t *
-svn_cstring_strtoui64(apr_uint64_t *n, const char *str,
- apr_uint64_t minval, apr_uint64_t maxval,
- int base);
+ * @since New in 1.6.
+ */
+apr_status_t apr_cstr_strtoui64(apr_uint64_t *n, const char *str,
+ apr_uint64_t minval, apr_uint64_t maxval,
+ int base);
/**
* Parse the C string @a str into an unsigned 64 bit number, and return
* it in @a *n. Assume that the number is represented in base 10.
* Raise an error if conversion fails (e.g. due to overflow).
*
- * The behaviour otherwise is as described for svn_cstring_strtoui64(),
+ * The behaviour otherwise is as described for apr_cstr_strtoui64(),
* including the upper limit of APR_INT64_MAX.
*
- * @since New in 1.7.
+ * @since New in 1.6.
*/
-svn_error_t *
-svn_cstring_atoui64(apr_uint64_t *n, const char *str);
+apr_status_t apr_cstr_atoui64(apr_uint64_t *n, const char *str);
/**
* Parse the C string @a str into an unsigned 32 bit number, and return
* it in @a *n. Assume that the number is represented in base 10.
* Raise an error if conversion fails (e.g. due to overflow).
*
- * The behaviour otherwise is as described for svn_cstring_strtoui64(),
+ * The behaviour otherwise is as described for apr_cstr_strtoui64(),
* including the upper limit of APR_INT64_MAX.
*
- * @since New in 1.7.
+ * @since New in 1.6.
*/
-svn_error_t *
-svn_cstring_atoui(unsigned int *n, const char *str);
+apr_status_t apr_cstr_atoui(unsigned int *n, const char *str);
/**
* Skip the common prefix @a prefix from the C string @a str, and return
* a pointer to the next character after the prefix.
* Return @c NULL if @a str does not start with @a prefix.
*
- * @since New in 1.9.
+ * @since New in 1.6.
*/
-const char *
-svn_cstring_skip_prefix(const char *str, const char *prefix);
-
-/** @} */
+const char * apr_cstr_skip_prefix(const char *str, const char *prefix);
/** @} */
-
#ifdef __cplusplus
}
#endif /* __cplusplus */
Modified: apr/apr/trunk/include/apr_errno.h
URL: http://svn.apache.org/viewvc/apr/apr/trunk/include/apr_errno.h?rev=1726928&r1=1726927&r2=1726928&view=diff
==============================================================================
--- apr/apr/trunk/include/apr_errno.h (original)
+++ apr/apr/trunk/include/apr_errno.h Wed Jan 27 00:08:59 2016
@@ -846,6 +846,13 @@ APR_DECLARE(char *) apr_strerror(apr_sta
#define APR_EOPNOTSUPP (APR_OS_START_CANONERR + 28)
#endif
+/** @see APR_STATUS_IS_ERANGE */
+#ifdef ERANGE
+#define APR_ERANGE ERANGE
+#else
+#define APR_ERANGE (APR_OS_START_CANONERR + 29)
+#endif
+
/** @} */
#if defined(OS2) && !defined(DOXYGEN)
@@ -988,6 +995,7 @@ APR_DECLARE(char *) apr_strerror(apr_sta
|| (s) == APR_OS_START_SYSERR + SOCEAFNOSUPPORT)
#define APR_STATUS_IS_EOPNOTSUPP(s) ((s) == APR_EOPNOTSUPP \
|| (s) == APR_OS_START_SYSERR + SOCEOPNOTSUPP)
+#define APR_STATUS_IS_ERANGE(s) ((s) == APR_ERANGE)
/*
Sorry, too tired to wrap this up for OS2... feel free to
@@ -1134,6 +1142,7 @@ APR_DECLARE(char *) apr_strerror(apr_sta
|| (s) == APR_OS_START_SYSERR + WSAEAFNOSUPPORT)
#define APR_STATUS_IS_EOPNOTSUPP(s) ((s) == APR_EOPNOTSUPP \
|| (s) == APR_OS_START_SYSERR + WSAEOPNOTSUPP)
+#define APR_STATUS_IS_ERANGE(s) ((s) == APR_ERANGE)
#elif defined(NETWARE) && defined(USE_WINSOCK) && !defined(DOXYGEN) /* !defined(OS2) && !defined(WIN32) */
@@ -1197,6 +1206,7 @@ APR_DECLARE(char *) apr_strerror(apr_sta
|| (s) == APR_OS_START_SYSERR + WSAEAFNOSUPPORT)
#define APR_STATUS_IS_EOPNOTSUPP(s) ((s) == APR_EOPNOTSUPP \
|| (s) == APR_OS_START_SYSERR + WSAEOPNOTSUPP)
+#define APR_STATUS_IS_ERANGE(s) ((s) == APR_ERANGE)
#else /* !defined(NETWARE) && !defined(OS2) && !defined(WIN32) */
@@ -1318,6 +1328,9 @@ APR_DECLARE(char *) apr_strerror(apr_sta
#define APR_STATUS_IS_EAFNOSUPPORT(s) ((s) == APR_EAFNOSUPPORT)
/** Socket operation not supported */
#define APR_STATUS_IS_EOPNOTSUPP(s) ((s) == APR_EOPNOTSUPP)
+
+/** Numeric value not representable */
+#define APR_STATUS_IS_ERANGE(s) ((s) == APR_ERANGE)
/** @} */
#endif /* !defined(NETWARE) && !defined(OS2) && !defined(WIN32) */
Copied: apr/apr/trunk/strings/apr_cstr.c (from r1717268, subversion/trunk/subversion/libsvn_subr/string.c)
URL: http://svn.apache.org/viewvc/apr/apr/trunk/strings/apr_cstr.c?p2=apr/apr/trunk/strings/apr_cstr.c&p1=subversion/trunk/subversion/libsvn_subr/string.c&r1=1717268&r2=1726928&rev=1726928&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/string.c (original)
+++ apr/apr/trunk/strings/apr_cstr.c Wed Jan 27 00:08:59 2016
@@ -1,10 +1,4 @@
-/*
- * string.c: routines to manipulate counted-length strings
- * (svn_stringbuf_t and svn_string_t) and C strings.
- *
- *
- * ====================================================================
- * Licensed to the Apache Software Foundation (ASF) under one
+/* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
@@ -20,793 +14,41 @@
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
- * ====================================================================
- */
-
-
-
-#include <apr.h>
-#include <assert.h>
-
-#include <string.h> /* for memcpy(), memcmp(), strlen() */
-#include <apr_fnmatch.h>
-#include "svn_string.h" /* loads "svn_types.h" and <apr_pools.h> */
-#include "svn_ctype.h"
-#include "private/svn_dep_compat.h"
-#include "private/svn_string_private.h"
-
-#include "svn_private_config.h"
-
-
-
-/* Allocate the space for a memory buffer from POOL.
- * Return a pointer to the new buffer in *DATA and its size in *SIZE.
- * The buffer size will be at least MINIMUM_SIZE.
- *
- * N.B.: The stringbuf creation functions use this, but since stringbufs
- * always consume at least 1 byte for the NUL terminator, the
- * resulting data pointers will never be NULL.
*/
-static APR_INLINE void
-membuf_create(void **data, apr_size_t *size,
- apr_size_t minimum_size, apr_pool_t *pool)
-{
- /* apr_palloc will allocate multiples of 8.
- * Thus, we would waste some of that memory if we stuck to the
- * smaller size. Note that this is safe even if apr_palloc would
- * use some other alignment or none at all. */
- minimum_size = APR_ALIGN_DEFAULT(minimum_size);
- *data = apr_palloc(pool, minimum_size);
- *size = minimum_size;
-}
-
-/* Ensure that the size of a given memory buffer is at least MINIMUM_SIZE
- * bytes. If *SIZE is already greater than or equal to MINIMUM_SIZE,
- * this function does nothing.
- *
- * If *SIZE is 0, the allocated buffer size will be MINIMUM_SIZE
- * rounded up to the nearest APR alignment boundary. Otherwse, *SIZE
- * will be multiplied by a power of two such that the result is
- * greater or equal to MINIMUM_SIZE. The pointer to the new buffer
- * will be returned in *DATA, and its size in *SIZE.
- */
-static APR_INLINE void
-membuf_ensure(void **data, apr_size_t *size,
- apr_size_t minimum_size, apr_pool_t *pool)
-{
- if (minimum_size > *size)
- {
- apr_size_t new_size = *size;
-
- if (new_size == 0)
- new_size = minimum_size;
- else
- while (new_size < minimum_size)
- {
- const apr_size_t prev_size = new_size;
- new_size *= 2;
-
- /* check for apr_size_t overflow */
- if (prev_size > new_size)
- {
- new_size = minimum_size;
- break;
- }
- }
-
- membuf_create(data, size, new_size, pool);
- }
-}
-
-void
-svn_membuf__create(svn_membuf_t *membuf, apr_size_t size, apr_pool_t *pool)
-{
- membuf_create(&membuf->data, &membuf->size, size, pool);
- membuf->pool = pool;
-}
-
-void
-svn_membuf__ensure(svn_membuf_t *membuf, apr_size_t size)
-{
- membuf_ensure(&membuf->data, &membuf->size, size, membuf->pool);
-}
-
-void
-svn_membuf__resize(svn_membuf_t *membuf, apr_size_t size)
-{
- const void *const old_data = membuf->data;
- const apr_size_t old_size = membuf->size;
-
- membuf_ensure(&membuf->data, &membuf->size, size, membuf->pool);
-
- /* If we re-allocated MEMBUF->DATA, it cannot be NULL.
- * Statically initialized membuffers (OLD_DATA) may be NULL, though. */
- if (old_data && old_data != membuf->data)
- memcpy(membuf->data, old_data, old_size);
-}
-
-/* Always provide an out-of-line implementation of svn_membuf__zero */
-#undef svn_membuf__zero
-void
-svn_membuf__zero(svn_membuf_t *membuf)
-{
- SVN_MEMBUF__ZERO(membuf);
-}
-
-/* Always provide an out-of-line implementation of svn_membuf__nzero */
-#undef svn_membuf__nzero
-void
-svn_membuf__nzero(svn_membuf_t *membuf, apr_size_t size)
-{
- SVN_MEMBUF__NZERO(membuf, size);
-}
-
-static APR_INLINE svn_boolean_t
-string_compare(const char *str1,
- const char *str2,
- apr_size_t len1,
- apr_size_t len2)
-{
- /* easy way out :) */
- if (len1 != len2)
- return FALSE;
-
- /* now the strings must have identical lengths */
-
- if ((memcmp(str1, str2, len1)) == 0)
- return TRUE;
- else
- return FALSE;
-}
-
-static APR_INLINE apr_size_t
-string_first_non_whitespace(const char *str, apr_size_t len)
-{
- apr_size_t i;
-
- for (i = 0; i < len; i++)
- {
- if (! svn_ctype_isspace(str[i]))
- return i;
- }
-
- /* if we get here, then the string must be entirely whitespace */
- return len;
-}
-
-static APR_INLINE apr_size_t
-find_char_backward(const char *str, apr_size_t len, char ch)
-{
- apr_size_t i = len;
-
- while (i != 0)
- {
- if (str[--i] == ch)
- return i;
- }
-
- /* char was not found, return len */
- return len;
-}
-
-
-/* svn_string functions */
-
-/* Return a new svn_string_t object, allocated in POOL, initialized with
- * DATA and SIZE. Do not copy the contents of DATA, just store the pointer.
- * SIZE is the length in bytes of DATA, excluding the required NUL
- * terminator. */
-static svn_string_t *
-create_string(const char *data, apr_size_t size,
- apr_pool_t *pool)
-{
- svn_string_t *new_string;
-
- new_string = apr_palloc(pool, sizeof(*new_string));
-
- new_string->data = data;
- new_string->len = size;
-
- return new_string;
-}
-
-/* A data buffer for a zero-length string (just a null terminator). Many
- * svn_string_t instances may share this same buffer. */
-static const char empty_buffer[1] = {0};
-
-svn_string_t *
-svn_string_create_empty(apr_pool_t *pool)
-{
- svn_string_t *new_string = apr_palloc(pool, sizeof(*new_string));
- new_string->data = empty_buffer;
- new_string->len = 0;
-
- return new_string;
-}
-
-
-svn_string_t *
-svn_string_ncreate(const char *bytes, apr_size_t size, apr_pool_t *pool)
-{
- void *mem;
- char *data;
- svn_string_t *new_string;
-
- /* Allocate memory for svn_string_t and data in one chunk. */
- mem = apr_palloc(pool, sizeof(*new_string) + size + 1);
- data = (char*)mem + sizeof(*new_string);
-
- new_string = mem;
- new_string->data = data;
- new_string->len = size;
-
- /* If SIZE is 0, NULL is valid for BYTES. */
- if (size)
- memcpy(data, bytes, size);
-
- /* Null termination is the convention -- even if we suspect the data
- to be binary, it's not up to us to decide, it's the caller's
- call. Heck, that's why they call it the caller! */
- data[size] = '\0';
-
- return new_string;
-}
-
-
-svn_string_t *
-svn_string_create(const char *cstring, apr_pool_t *pool)
-{
- return svn_string_ncreate(cstring, strlen(cstring), pool);
-}
-
-
-svn_string_t *
-svn_string_create_from_buf(const svn_stringbuf_t *strbuf, apr_pool_t *pool)
-{
- return svn_string_ncreate(strbuf->data, strbuf->len, pool);
-}
-
-
-svn_string_t *
-svn_string_createv(apr_pool_t *pool, const char *fmt, va_list ap)
-{
- char *data = apr_pvsprintf(pool, fmt, ap);
-
- /* wrap an svn_string_t around the new data */
- return create_string(data, strlen(data), pool);
-}
-
-
-svn_string_t *
-svn_string_createf(apr_pool_t *pool, const char *fmt, ...)
-{
- svn_string_t *str;
-
- va_list ap;
- va_start(ap, fmt);
- str = svn_string_createv(pool, fmt, ap);
- va_end(ap);
-
- return str;
-}
-
-
-svn_boolean_t
-svn_string_isempty(const svn_string_t *str)
-{
- return (str->len == 0);
-}
-
-
-svn_string_t *
-svn_string_dup(const svn_string_t *original_string, apr_pool_t *pool)
-{
- return (original_string ? svn_string_ncreate(original_string->data,
- original_string->len, pool)
- : NULL);
-}
-
-
-
-svn_boolean_t
-svn_string_compare(const svn_string_t *str1, const svn_string_t *str2)
-{
- return
- string_compare(str1->data, str2->data, str1->len, str2->len);
-}
-
-
-
-apr_size_t
-svn_string_first_non_whitespace(const svn_string_t *str)
-{
- return
- string_first_non_whitespace(str->data, str->len);
-}
-
-apr_size_t
-svn_string_find_char_backward(const svn_string_t *str, char ch)
-{
- return find_char_backward(str->data, str->len, ch);
-}
-
-svn_string_t *
-svn_stringbuf__morph_into_string(svn_stringbuf_t *strbuf)
-{
- /* In debug mode, detect attempts to modify the original STRBUF object.
- */
-#ifdef SVN_DEBUG
- strbuf->pool = NULL;
- strbuf->blocksize = strbuf->len + 1;
+#include "apr.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include "apr_fnmatch.h"
+#if 0
+#define APR_WANT_STDIO
+#define APR_WANT_STRFUNC
#endif
+#include "apr_want.h"
+#include "apr_cstr.h"
- /* Both, svn_string_t and svn_stringbuf_t are public API structures
- * since the svn epoch. Thus, we can rely on their precise layout not
- * to change.
- *
- * It just so happens that svn_string_t is structurally equivalent
- * to the (data, len) sub-set of svn_stringbuf_t. There is also no
- * difference in alignment and padding. So, we can just re-interpret
- * that part of STRBUF as a svn_string_t.
- *
- * However, since svn_string_t does not know about the blocksize
- * member in svn_stringbuf_t, any attempt to re-size the returned
- * svn_string_t might invalidate the STRBUF struct. Hence, we consider
- * the source STRBUF "consumed".
- *
- * Modifying the string character content is fine, though.
- */
- return (svn_string_t *)&strbuf->data;
-}
-
-
-
-/* svn_stringbuf functions */
-
-svn_stringbuf_t *
-svn_stringbuf_create_empty(apr_pool_t *pool)
-{
- return svn_stringbuf_create_ensure(0, pool);
-}
-
-svn_stringbuf_t *
-svn_stringbuf_create_ensure(apr_size_t blocksize, apr_pool_t *pool)
-{
- void *mem;
- svn_stringbuf_t *new_string;
-
- ++blocksize; /* + space for '\0' */
-
- /* Allocate memory for svn_string_t and data in one chunk. */
- membuf_create(&mem, &blocksize, blocksize + sizeof(*new_string), pool);
-
- /* Initialize header and string */
- new_string = mem;
- new_string->data = (char*)mem + sizeof(*new_string);
- new_string->data[0] = '\0';
- new_string->len = 0;
- new_string->blocksize = blocksize - sizeof(*new_string);
- new_string->pool = pool;
-
- return new_string;
-}
-
-svn_stringbuf_t *
-svn_stringbuf_ncreate(const char *bytes, apr_size_t size, apr_pool_t *pool)
-{
- svn_stringbuf_t *strbuf = svn_stringbuf_create_ensure(size, pool);
-
- /* If SIZE is 0, NULL is valid for BYTES. */
- if (size)
- memcpy(strbuf->data, bytes, size);
-
- /* Null termination is the convention -- even if we suspect the data
- to be binary, it's not up to us to decide, it's the caller's
- call. Heck, that's why they call it the caller! */
- strbuf->data[size] = '\0';
- strbuf->len = size;
-
- return strbuf;
-}
-
-
-svn_stringbuf_t *
-svn_stringbuf_create(const char *cstring, apr_pool_t *pool)
-{
- return svn_stringbuf_ncreate(cstring, strlen(cstring), pool);
-}
-
-
-svn_stringbuf_t *
-svn_stringbuf_create_from_string(const svn_string_t *str, apr_pool_t *pool)
-{
- return svn_stringbuf_ncreate(str->data, str->len, pool);
-}
-
-svn_stringbuf_t *
-svn_stringbuf_create_wrap(char *str, apr_pool_t *pool)
-{
- svn_stringbuf_t *result = apr_palloc(pool, sizeof(*result));
- result->pool = pool;
- result->data = str;
- result->len = strlen(str);
- result->blocksize = result->len + 1;
-
- return result;
-}
-
-svn_stringbuf_t *
-svn_stringbuf_createv(apr_pool_t *pool, const char *fmt, va_list ap)
-{
- char *data = apr_pvsprintf(pool, fmt, ap);
- apr_size_t size = strlen(data);
- svn_stringbuf_t *new_string;
-
- new_string = apr_palloc(pool, sizeof(*new_string));
- new_string->data = data;
- new_string->len = size;
- new_string->blocksize = size + 1;
- new_string->pool = pool;
-
- return new_string;
-}
-
-
-svn_stringbuf_t *
-svn_stringbuf_createf(apr_pool_t *pool, const char *fmt, ...)
-{
- svn_stringbuf_t *str;
-
- va_list ap;
- va_start(ap, fmt);
- str = svn_stringbuf_createv(pool, fmt, ap);
- va_end(ap);
-
- return str;
-}
-
-
-void
-svn_stringbuf_fillchar(svn_stringbuf_t *str, unsigned char c)
-{
- memset(str->data, c, str->len);
-}
-
-
-void
-svn_stringbuf_set(svn_stringbuf_t *str, const char *value)
-{
- apr_size_t amt = strlen(value);
-
- svn_stringbuf_ensure(str, amt);
- memcpy(str->data, value, amt + 1);
- str->len = amt;
-}
-
-void
-svn_stringbuf_setempty(svn_stringbuf_t *str)
-{
- if (str->len > 0)
- str->data[0] = '\0';
-
- str->len = 0;
-}
-
-
-void
-svn_stringbuf_chop(svn_stringbuf_t *str, apr_size_t nbytes)
-{
- if (nbytes > str->len)
- str->len = 0;
- else
- str->len -= nbytes;
-
- str->data[str->len] = '\0';
-}
-
-
-svn_boolean_t
-svn_stringbuf_isempty(const svn_stringbuf_t *str)
-{
- return (str->len == 0);
-}
-
-
-void
-svn_stringbuf_ensure(svn_stringbuf_t *str, apr_size_t minimum_size)
-{
- void *mem = NULL;
- ++minimum_size; /* + space for '\0' */
-
- membuf_ensure(&mem, &str->blocksize, minimum_size, str->pool);
- if (mem && mem != str->data)
- {
- if (str->data)
- memcpy(mem, str->data, str->len + 1);
- str->data = mem;
- }
-}
-
-
-/* WARNING - Optimized code ahead!
- * This function has been hand-tuned for performance. Please read
- * the comments below before modifying the code.
- */
-void
-svn_stringbuf_appendbyte(svn_stringbuf_t *str, char byte)
-{
- char *dest;
- apr_size_t old_len = str->len;
-
- /* In most cases, there will be pre-allocated memory left
- * to just write the new byte at the end of the used section
- * and terminate the string properly.
- */
- if (str->blocksize > old_len + 1)
- {
- /* The following read does not depend this write, so we
- * can issue the write first to minimize register pressure:
- * The value of old_len+1 is no longer needed; on most processors,
- * dest[old_len+1] will be calculated implicitly as part of
- * the addressing scheme.
- */
- str->len = old_len+1;
-
- /* Since the compiler cannot be sure that *src->data and *src
- * don't overlap, we read src->data *once* before writing
- * to *src->data. Replacing dest with str->data would force
- * the compiler to read it again after the first byte.
- */
- dest = str->data;
-
- /* If not already available in a register as per ABI, load
- * "byte" into the register (e.g. the one freed from old_len+1),
- * then write it to the string buffer and terminate it properly.
- *
- * Including the "byte" fetch, all operations so far could be
- * issued at once and be scheduled at the CPU's descression.
- * Most likely, no-one will soon depend on the data that will be
- * written in this function. So, no stalls there, either.
- */
- dest[old_len] = byte;
- dest[old_len+1] = '\0';
- }
- else
- {
- /* we need to re-allocate the string buffer
- * -> let the more generic implementation take care of that part
- */
-
- /* Depending on the ABI, "byte" is a register value. If we were
- * to take its address directly, the compiler might decide to
- * put in on the stack *unconditionally*, even if that would
- * only be necessary for this block.
- */
- char b = byte;
- svn_stringbuf_appendbytes(str, &b, 1);
- }
-}
-
-
-void
-svn_stringbuf_appendbytes(svn_stringbuf_t *str, const char *bytes,
- apr_size_t count)
-{
- apr_size_t total_len;
- void *start_address;
-
- if (!count)
- /* Allow BYTES to be NULL by avoiding passing it to memcpy. */
- return;
-
- total_len = str->len + count; /* total size needed */
-
- /* svn_stringbuf_ensure adds 1 for null terminator. */
- svn_stringbuf_ensure(str, total_len);
-
- /* get address 1 byte beyond end of original bytestring */
- start_address = (str->data + str->len);
-
- memcpy(start_address, bytes, count);
- str->len = total_len;
-
- str->data[str->len] = '\0'; /* We don't know if this is binary
- data or not, but convention is
- to null-terminate. */
-}
-
-void
-svn_stringbuf_appendfill(svn_stringbuf_t *str,
- char byte,
- apr_size_t count)
-{
- apr_size_t new_len = str->len + count;
- svn_stringbuf_ensure(str, new_len);
-
- memset(str->data + str->len, byte, count);
-
- /* update buffer length and always NUL-terminate it */
- str->len = new_len;
- str->data[new_len] = '\0';
-}
-
-
-void
-svn_stringbuf_appendstr(svn_stringbuf_t *targetstr,
- const svn_stringbuf_t *appendstr)
-{
- svn_stringbuf_appendbytes(targetstr, appendstr->data, appendstr->len);
-}
-
-
-void
-svn_stringbuf_appendcstr(svn_stringbuf_t *targetstr, const char *cstr)
-{
- svn_stringbuf_appendbytes(targetstr, cstr, strlen(cstr));
-}
-
-void
-svn_stringbuf_insert(svn_stringbuf_t *str,
- apr_size_t pos,
- const char *bytes,
- apr_size_t count)
-{
- /* For COUNT==0, we allow BYTES to be NULL. It's a no-op in that case. */
- if (count == 0)
- return;
-
- /* special case: BYTES overlaps with this string -> copy the source */
- if (bytes + count > str->data && bytes < str->data + str->blocksize)
- bytes = apr_pmemdup(str->pool, bytes, count);
-
- if (pos > str->len)
- pos = str->len;
-
- svn_stringbuf_ensure(str, str->len + count);
- memmove(str->data + pos + count, str->data + pos, str->len - pos + 1);
- memcpy(str->data + pos, bytes, count);
-
- str->len += count;
-}
-
-void
-svn_stringbuf_remove(svn_stringbuf_t *str,
- apr_size_t pos,
- apr_size_t count)
-{
- if (pos > str->len)
- pos = str->len;
- if (count > str->len - pos)
- count = str->len - pos;
-
- memmove(str->data + pos, str->data + pos + count, str->len - pos - count + 1);
- str->len -= count;
-}
-
-void
-svn_stringbuf_replace(svn_stringbuf_t *str,
- apr_size_t pos,
- apr_size_t old_count,
- const char *bytes,
- apr_size_t new_count)
-{
- /* For COUNT==0, we allow BYTES to be NULL.
- * In that case, this is just a substring removal. */
- if (new_count == 0)
- {
- svn_stringbuf_remove(str, pos, old_count);
- return;
- }
-
- /* special case: BYTES overlaps with this string -> copy the source */
- if (bytes + new_count > str->data && bytes < str->data + str->blocksize)
- bytes = apr_pmemdup(str->pool, bytes, new_count);
-
- if (pos > str->len)
- pos = str->len;
- if (old_count > str->len - pos)
- old_count = str->len - pos;
-
- if (old_count < new_count)
- {
- apr_size_t delta = new_count - old_count;
- svn_stringbuf_ensure(str, str->len + delta);
- }
-
- if (old_count != new_count)
- memmove(str->data + pos + new_count, str->data + pos + old_count,
- str->len - pos - old_count + 1);
-
- memcpy(str->data + pos, bytes, new_count);
- str->len += new_count - old_count;
-}
-
-
-svn_stringbuf_t *
-svn_stringbuf_dup(const svn_stringbuf_t *original_string, apr_pool_t *pool)
-{
- return (svn_stringbuf_ncreate(original_string->data,
- original_string->len, pool));
-}
-
-
-
-svn_boolean_t
-svn_stringbuf_compare(const svn_stringbuf_t *str1,
- const svn_stringbuf_t *str2)
-{
- return string_compare(str1->data, str2->data, str1->len, str2->len);
-}
-
-
-
-apr_size_t
-svn_stringbuf_first_non_whitespace(const svn_stringbuf_t *str)
-{
- return string_first_non_whitespace(str->data, str->len);
-}
-
-
-void
-svn_stringbuf_strip_whitespace(svn_stringbuf_t *str)
-{
- /* Find first non-whitespace character */
- apr_size_t offset = svn_stringbuf_first_non_whitespace(str);
-
- /* Go ahead! Waste some RAM, we've got pools! :) */
- str->data += offset;
- str->len -= offset;
- str->blocksize -= offset;
-
- /* Now that we've trimmed the front, trim the end, wasting more RAM. */
- while ((str->len > 0) && svn_ctype_isspace(str->data[str->len - 1]))
- str->len--;
- str->data[str->len] = '\0';
-}
-
-
-apr_size_t
-svn_stringbuf_find_char_backward(const svn_stringbuf_t *str, char ch)
-{
- return find_char_backward(str->data, str->len, ch);
-}
-
-
-svn_boolean_t
-svn_string_compare_stringbuf(const svn_string_t *str1,
- const svn_stringbuf_t *str2)
-{
- return string_compare(str1->data, str2->data, str1->len, str2->len);
-}
-
-
-
-/*** C string stuff. ***/
-
-void
-svn_cstring_split_append(apr_array_header_t *array,
- const char *input,
- const char *sep_chars,
- svn_boolean_t chop_whitespace,
- apr_pool_t *pool)
+void apr_cstr_split_append(apr_array_header_t *array,
+ const char *input,
+ const char *sep_chars,
+ int chop_whitespace,
+ apr_pool_t *pool)
{
char *pats;
char *p;
pats = apr_pstrdup(pool, input); /* strtok wants non-const data */
- p = svn_cstring_tokenize(sep_chars, &pats);
+ p = apr_cstr_tokenize(sep_chars, &pats);
while (p)
{
if (chop_whitespace)
{
- while (svn_ctype_isspace(*p))
+ while (apr_isspace(*p))
p++;
{
char *e = p + (strlen(p) - 1);
- while ((e >= p) && (svn_ctype_isspace(*e)))
+ while ((e >= p) && (apr_isspace(*e)))
e--;
*(++e) = '\0';
}
@@ -815,27 +57,26 @@ svn_cstring_split_append(apr_array_heade
if (p[0] != '\0')
APR_ARRAY_PUSH(array, const char *) = p;
- p = svn_cstring_tokenize(sep_chars, &pats);
+ p = apr_cstr_tokenize(sep_chars, &pats);
}
return;
}
-apr_array_header_t *
-svn_cstring_split(const char *input,
- const char *sep_chars,
- svn_boolean_t chop_whitespace,
- apr_pool_t *pool)
+apr_array_header_t * apr_cstr_split(const char *input,
+ const char *sep_chars,
+ int chop_whitespace,
+ apr_pool_t *pool)
{
apr_array_header_t *a = apr_array_make(pool, 5, sizeof(input));
- svn_cstring_split_append(a, input, sep_chars, chop_whitespace, pool);
+ apr_cstr_split_append(a, input, sep_chars, chop_whitespace, pool);
return a;
}
-svn_boolean_t svn_cstring_match_glob_list(const char *str,
- const apr_array_header_t *list)
+int apr_cstr_match_glob_list(const char *str,
+ const apr_array_header_t *list)
{
int i;
@@ -850,8 +91,7 @@ svn_boolean_t svn_cstring_match_glob_lis
return FALSE;
}
-svn_boolean_t
-svn_cstring_match_list(const char *str, const apr_array_header_t *list)
+int apr_cstr_match_list(const char *str, const apr_array_header_t *list)
{
int i;
@@ -866,8 +106,7 @@ svn_cstring_match_list(const char *str,
return FALSE;
}
-char *
-svn_cstring_tokenize(const char *sep, char **str)
+char * apr_cstr_tokenize(const char *sep, char **str)
{
char *token;
char *next;
@@ -907,7 +146,7 @@ svn_cstring_tokenize(const char *sep, ch
return token;
}
-int svn_cstring_count_newlines(const char *msg)
+int apr_cstr_count_newlines(const char *msg)
{
int count = 0;
const char *p;
@@ -931,10 +170,10 @@ int svn_cstring_count_newlines(const cha
return count;
}
-char *
-svn_cstring_join(const apr_array_header_t *strings,
- const char *separator,
- apr_pool_t *pool)
+#if 0 /* XXX: stringbuf logic is not present in APR */
+char * apr_cstr_join(const apr_array_header_t *strings,
+ const char *separator,
+ apr_pool_t *pool)
{
svn_stringbuf_t *new_str = svn_stringbuf_create_empty(pool);
size_t sep_len = strlen(separator);
@@ -948,24 +187,126 @@ svn_cstring_join(const apr_array_header_
}
return new_str->data;
}
+#endif
+
+#if !APR_CHARSET_EBCDIC
+/*
+ * Our own known-fast translation table for casecmp by character.
+ * Only ASCII alpha characters 41-5A are folded to 61-7A, other
+ * octets (such as extended latin alphabetics) are never case-folded.
+ * NOTE: Other than Alpha A-Z/a-z, each code point is unique!
+ */
+static const unsigned char ucharmap[] = {
+ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+ 'x', 'y', 'z', 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+ 'x', 'y', 'z', 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+#else /* APR_CHARSET_EBCDIC */
+/*
+ * Derived from apr-iconv/ccs/cp037.c for EBCDIC case comparison,
+ * provides unique identity of every char value (strict ISO-646
+ * conformance, arbitrary election of an ISO-8859-1 ordering, and
+ * very arbitrary control code assignments into C1 to achieve
+ * identity and a reversible mapping of code points),
+ * then folding the equivalences of ASCII 41-5A into 61-7A,
+ * presenting comparison results in a somewhat ISO/IEC 10646
+ * (ASCII-like) order, depending on the EBCDIC code page in use.
+ *
+ * NOTE: Other than Alpha A-Z/a-z, each code point is unique!
+ */
+static const unsigned char ucharmap[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F,
+ 0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87,
+ 0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B,
+ 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07,
+ 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,
+ 0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A,
+ 0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5,
+ 0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
+ 0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF,
+ 0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAC,
+ 0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5,
+ 0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
+ 0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF,
+ 0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
+ 0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1,
+ 0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
+ 0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4,
+ 0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0xDD, 0xDE, 0xAE,
+ 0x5E, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC,
+ 0xBD, 0xBE, 0x5B, 0x5D, 0xAF, 0xA8, 0xB4, 0xD7,
+ 0x7B, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5,
+ 0x7D, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
+ 0x71, 0x72, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF,
+ 0x5C, 0xF7, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F
+};
+#endif
+
+int apr_cstr_casecmp(const char *str1, const char *str2)
+{
+ for (;;)
+ {
+ const int c1 = (int)(*((const unsigned char *)str1++));
+ const int c2 = (int)(*((const unsigned char *)str2++));
+ const int cmp = ucharmap[c1] - ucharmap[c2];
+ if (cmp || !c1 || !c2)
+ return cmp;
+ }
+}
-int
-svn_cstring_casecmp(const char *str1, const char *str2)
+int apr_cstr_casecmpn(const char *str1, const char *str2, apr_size_t n)
{
- for (;;)
+ while (n--)
{
- const int a = *str1++;
- const int b = *str2++;
- const int cmp = svn_ctype_casecmp(a, b);
- if (cmp || !a || !b)
- return cmp;
+ const int c1 = (int)(*((const unsigned char *)str1++));
+ const int c2 = (int)(*((const unsigned char *)str2++));
+ const int cmp = ucharmap[c1] - ucharmap[c2];
+ if (cmp || !c1 || !c2)
+ return cmp;
}
+ return 0;
}
-svn_error_t *
-svn_cstring_strtoui64(apr_uint64_t *n, const char *str,
- apr_uint64_t minval, apr_uint64_t maxval,
- int base)
+apr_status_t apr_cstr_strtoui64(apr_uint64_t *n, const char *str,
+ apr_uint64_t minval, apr_uint64_t maxval,
+ int base)
{
apr_int64_t val;
char *endptr;
@@ -977,41 +318,31 @@ svn_cstring_strtoui64(apr_uint64_t *n, c
* ### APR needs a apr_strtoui64() function. */
val = apr_strtoi64(str, &endptr, base);
if (errno == EINVAL || endptr == str || str[0] == '\0' || *endptr != '\0')
- return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
- _("Could not convert '%s' into a number"),
- str);
+ return APR_EINVAL;
if ((errno == ERANGE && (val == APR_INT64_MIN || val == APR_INT64_MAX)) ||
val < 0 || (apr_uint64_t)val < minval || (apr_uint64_t)val > maxval)
- /* ### Mark this for translation when gettext doesn't choke on macros. */
- return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
- "Number '%s' is out of range "
- "'[%" APR_UINT64_T_FMT ", %" APR_UINT64_T_FMT "]'",
- str, minval, maxval);
+ return APR_ERANGE;
*n = val;
- return SVN_NO_ERROR;
+ return APR_SUCCESS;
}
-svn_error_t *
-svn_cstring_atoui64(apr_uint64_t *n, const char *str)
+apr_status_t apr_cstr_atoui64(apr_uint64_t *n, const char *str)
{
- return svn_error_trace(svn_cstring_strtoui64(n, str, 0,
- APR_UINT64_MAX, 10));
+ return apr_cstr_strtoui64(n, str, 0, APR_UINT64_MAX, 10);
}
-svn_error_t *
-svn_cstring_atoui(unsigned int *n, const char *str)
+apr_status_t apr_cstr_atoui(unsigned int *n, const char *str)
{
apr_uint64_t val;
-
- SVN_ERR(svn_cstring_strtoui64(&val, str, 0, APR_UINT32_MAX, 10));
- *n = (unsigned int)val;
- return SVN_NO_ERROR;
+ apr_status_t rv = apr_cstr_strtoui64(&val, str, 0, APR_UINT32_MAX, 10);
+ if (rv == APR_SUCCESS)
+ *n = (unsigned int)val;
+ return rv;
}
-svn_error_t *
-svn_cstring_strtoi64(apr_int64_t *n, const char *str,
- apr_int64_t minval, apr_int64_t maxval,
- int base)
+apr_status_t apr_cstr_strtoi64(apr_int64_t *n, const char *str,
+ apr_int64_t minval, apr_int64_t maxval,
+ int base)
{
apr_int64_t val;
char *endptr;
@@ -1021,455 +352,32 @@ svn_cstring_strtoi64(apr_int64_t *n, con
val = apr_strtoi64(str, &endptr, base);
if (errno == EINVAL || endptr == str || str[0] == '\0' || *endptr != '\0')
- return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
- _("Could not convert '%s' into a number"),
- str);
+ return APR_EINVAL;
if ((errno == ERANGE && (val == APR_INT64_MIN || val == APR_INT64_MAX)) ||
val < minval || val > maxval)
- /* ### Mark this for translation when gettext doesn't choke on macros. */
- return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
- "Number '%s' is out of range "
- "'[%" APR_INT64_T_FMT ", %" APR_INT64_T_FMT "]'",
- str, minval, maxval);
+ return APR_ERANGE;
*n = val;
- return SVN_NO_ERROR;
+ return APR_SUCCESS;
}
-svn_error_t *
-svn_cstring_atoi64(apr_int64_t *n, const char *str)
+apr_status_t apr_cstr_atoi64(apr_int64_t *n, const char *str)
{
- return svn_error_trace(svn_cstring_strtoi64(n, str, APR_INT64_MIN,
- APR_INT64_MAX, 10));
+ return apr_cstr_strtoi64(n, str, APR_INT64_MIN, APR_INT64_MAX, 10);
}
-svn_error_t *
-svn_cstring_atoi(int *n, const char *str)
+apr_status_t apr_cstr_atoi(int *n, const char *str)
{
apr_int64_t val;
+ apr_status_t rv;
- SVN_ERR(svn_cstring_strtoi64(&val, str, APR_INT32_MIN, APR_INT32_MAX, 10));
- *n = (int)val;
- return SVN_NO_ERROR;
-}
-
-unsigned long
-svn__strtoul(const char* buffer, const char** end)
-{
- unsigned long result = 0;
-
- /* this loop will execute in just 2 CPU cycles, confirmed by measurement:
- 7 macro-ops (max 4 / cycle => 2 cycles)
- 1 load (max 1 / cycle)
- 1 jumps (compare + conditional jump == 1 macro op; max 1 / cycle)
- 2 arithmetic ops (subtract, increment; max 3 / cycle)
- 2 scale-and-add AGU ops (max 3 / cycle)
- 1 compiler-generated move operation
- dependency chain: temp = result * 4 + result; result = temp * 2 + c
- (2 ops with latency 1 => 2 cycles)
- */
- while (1)
- {
- unsigned long c = (unsigned char)*buffer - (unsigned char)'0';
- if (c > 9)
- break;
-
- result = result * 10 + c;
- ++buffer;
- }
-
- *end = buffer;
- return result;
-}
-
-/* "Precalculated" itoa values for 2 places (including leading zeros).
- * For maximum performance, make sure all table entries are word-aligned.
- */
-static const char decimal_table[100][4]
- = { "00", "01", "02", "03", "04", "05", "06", "07", "08", "09"
- , "10", "11", "12", "13", "14", "15", "16", "17", "18", "19"
- , "20", "21", "22", "23", "24", "25", "26", "27", "28", "29"
- , "30", "31", "32", "33", "34", "35", "36", "37", "38", "39"
- , "40", "41", "42", "43", "44", "45", "46", "47", "48", "49"
- , "50", "51", "52", "53", "54", "55", "56", "57", "58", "59"
- , "60", "61", "62", "63", "64", "65", "66", "67", "68", "69"
- , "70", "71", "72", "73", "74", "75", "76", "77", "78", "79"
- , "80", "81", "82", "83", "84", "85", "86", "87", "88", "89"
- , "90", "91", "92", "93", "94", "95", "96", "97", "98", "99"};
-
-/* Copy the two bytes at SOURCE[0] and SOURCE[1] to DEST[0] and DEST[1] */
-#define COPY_TWO_BYTES(dest,source)\
- memcpy((dest), (source), 2)
-
-apr_size_t
-svn__ui64toa(char * dest, apr_uint64_t number)
-{
- char buffer[SVN_INT64_BUFFER_SIZE];
- apr_uint32_t reduced; /* used for 32 bit DIV */
- char* target;
-
- /* Small numbers are by far the most common case.
- * Therefore, we use special code.
- */
- if (number < 100)
- {
- if (number < 10)
- {
- dest[0] = (char)('0' + number);
- dest[1] = 0;
- return 1;
- }
- else
- {
- COPY_TWO_BYTES(dest, decimal_table[(apr_size_t)number]);
- dest[2] = 0;
- return 2;
- }
- }
-
- /* Standard code. Write string in pairs of chars back-to-front */
- buffer[SVN_INT64_BUFFER_SIZE - 1] = 0;
- target = &buffer[SVN_INT64_BUFFER_SIZE - 3];
-
- /* Loop may be executed 0 .. 2 times. */
- while (number >= 100000000)
- {
- /* Number is larger than 100^4, i.e. we can write 4x2 chars.
- * Also, use 32 bit DIVs as these are about twice as fast.
- */
- reduced = (apr_uint32_t)(number % 100000000);
- number /= 100000000;
-
- COPY_TWO_BYTES(target - 0, decimal_table[reduced % 100]);
- reduced /= 100;
- COPY_TWO_BYTES(target - 2, decimal_table[reduced % 100]);
- reduced /= 100;
- COPY_TWO_BYTES(target - 4, decimal_table[reduced % 100]);
- reduced /= 100;
- COPY_TWO_BYTES(target - 6, decimal_table[reduced % 100]);
- target -= 8;
- }
-
- /* Now, the number fits into 32 bits, but may still be larger than 99 */
- reduced = (apr_uint32_t)(number);
- while (reduced >= 100)
- {
- COPY_TWO_BYTES(target, decimal_table[reduced % 100]);
- reduced /= 100;
- target -= 2;
- }
-
- /* The number is now smaller than 100 but larger than 1 */
- COPY_TWO_BYTES(target, decimal_table[reduced]);
-
- /* Correction for uneven count of places. */
- if (reduced < 10)
- ++target;
-
- /* Copy to target */
- memcpy(dest, target, &buffer[SVN_INT64_BUFFER_SIZE] - target);
- return &buffer[SVN_INT64_BUFFER_SIZE] - target - 1;
-}
-
-apr_size_t
-svn__i64toa(char * dest, apr_int64_t number)
-{
- if (number >= 0)
- return svn__ui64toa(dest, (apr_uint64_t)number);
-
- *dest = '-';
- return svn__ui64toa(dest + 1, 0 - (apr_uint64_t)number) + 1;
-}
-
-static void
-ui64toa_sep(apr_uint64_t number, char separator, char *buffer)
-{
- apr_size_t length = svn__ui64toa(buffer, number);
- apr_size_t i;
-
- for (i = length; i > 3; i -= 3)
- {
- memmove(&buffer[i - 2], &buffer[i - 3], length - i + 3);
- buffer[i-3] = separator;
- length++;
- }
-
- buffer[length] = 0;
-}
-
-char *
-svn__ui64toa_sep(apr_uint64_t number, char separator, apr_pool_t *pool)
-{
- char buffer[2 * SVN_INT64_BUFFER_SIZE];
- ui64toa_sep(number, separator, buffer);
-
- return apr_pstrdup(pool, buffer);
-}
-
-char *
-svn__i64toa_sep(apr_int64_t number, char separator, apr_pool_t *pool)
-{
- char buffer[2 * SVN_INT64_BUFFER_SIZE];
- if (number < 0)
- {
- buffer[0] = '-';
- ui64toa_sep((apr_uint64_t)(-number), separator, &buffer[1]);
- }
- else
- ui64toa_sep((apr_uint64_t)(number), separator, buffer);
-
- return apr_pstrdup(pool, buffer);
-}
-
-apr_size_t
-svn__ui64tobase36(char *dest, apr_uint64_t value)
-{
- char *dest_start = dest;
- if (value < 10)
- {
- /* pretty frequent and trivial case. Make it fast. */
- *(dest++) = (char)(value) + '0';
- }
- else
- {
- char buffer[SVN_INT64_BUFFER_SIZE];
- char *p = buffer;
-
- /* write result as little-endian to buffer */
- while (value > 0)
- {
- char c = (char)(value % 36);
- value /= 36;
-
- *p = (c <= 9) ? (c + '0') : (c - 10 + 'a');
- ++p;
- }
-
- /* copy as big-endian to DEST */
- while (p > buffer)
- *(dest++) = *(--p);
- }
-
- *dest = '\0';
- return dest - dest_start;
-}
-
-apr_uint64_t
-svn__base36toui64(const char **next, const char *source)
-{
- apr_uint64_t result = 0;
- apr_uint64_t factor = 1;
- int i = 0;
- char digits[SVN_INT64_BUFFER_SIZE];
-
- /* convert digits to numerical values and count the number of places.
- * Also, prevent buffer overflow. */
- while (i < sizeof(digits))
- {
- char c = *source;
- if (c < 'a')
- {
- /* includes detection of NUL terminator */
- if (c < '0' || c > '9')
- break;
-
- c -= '0';
- }
- else
- {
- if (c < 'a' || c > 'z')
- break;
-
- c -= 'a' - 10;
- }
-
- digits[i++] = c;
- source++;
- }
-
- /* fold digits into the result */
- while (i > 0)
- {
- result += factor * (apr_uint64_t)digits[--i];
- factor *= 36;
- }
-
- if (next)
- *next = source;
-
- return result;
-}
-
-
-apr_size_t
-svn_cstring__similarity(const char *stra, const char *strb,
- svn_membuf_t *buffer, apr_size_t *rlcs)
-{
- svn_string_t stringa, stringb;
- stringa.data = stra;
- stringa.len = strlen(stra);
- stringb.data = strb;
- stringb.len = strlen(strb);
- return svn_string__similarity(&stringa, &stringb, buffer, rlcs);
-}
-
-apr_size_t
-svn_string__similarity(const svn_string_t *stringa,
- const svn_string_t *stringb,
- svn_membuf_t *buffer, apr_size_t *rlcs)
-{
- const char *stra = stringa->data;
- const char *strb = stringb->data;
- const apr_size_t lena = stringa->len;
- const apr_size_t lenb = stringb->len;
- const apr_size_t total = lena + lenb;
- const char *enda = stra + lena;
- const char *endb = strb + lenb;
- apr_size_t lcs = 0;
-
- /* Skip the common prefix ... */
- while (stra < enda && strb < endb && *stra == *strb)
- {
- ++stra; ++strb;
- ++lcs;
- }
-
- /* ... and the common suffix */
- while (stra < enda && strb < endb)
- {
- --enda; --endb;
- if (*enda != *endb)
- {
- ++enda; ++endb;
- break;
- }
-
- ++lcs;
- }
-
- if (stra < enda && strb < endb)
- {
- const apr_size_t resta = enda - stra;
- const apr_size_t restb = endb - strb;
- const apr_size_t slots = (resta > restb ? restb : resta);
- apr_size_t *curr, *prev;
- const char *pstr;
-
- /* The outer loop must iterate on the longer string. */
- if (resta < restb)
- {
- pstr = stra;
- stra = strb;
- strb = pstr;
-
- pstr = enda;
- enda = endb;
- endb = pstr;
- }
-
- /* Allocate two columns in the LCS matrix
- ### Optimize this to (slots + 2) instesd of 2 * (slots + 1) */
- svn_membuf__ensure(buffer, 2 * (slots + 1) * sizeof(apr_size_t));
- svn_membuf__nzero(buffer, (slots + 2) * sizeof(apr_size_t));
- prev = buffer->data;
- curr = prev + slots + 1;
-
- /* Calculate LCS length of the remainder */
- for (pstr = stra; pstr < enda; ++pstr)
- {
- apr_size_t i;
- for (i = 1; i <= slots; ++i)
- {
- if (*pstr == strb[i-1])
- curr[i] = prev[i-1] + 1;
- else
- curr[i] = (curr[i-1] > prev[i] ? curr[i-1] : prev[i]);
- }
-
- /* Swap the buffers, making the previous one current */
- {
- apr_size_t *const temp = prev;
- prev = curr;
- curr = temp;
- }
- }
-
- lcs += prev[slots];
- }
-
- if (rlcs)
- *rlcs = lcs;
-
- /* Return similarity ratio rounded to 4 significant digits */
- if (total)
- return ((2 * SVN_STRING__SIM_RANGE_MAX * lcs + total/2) / total);
- else
- return SVN_STRING__SIM_RANGE_MAX;
-}
-
-apr_size_t
-svn_cstring__match_length(const char *a,
- const char *b,
- apr_size_t max_len)
-{
- apr_size_t pos = 0;
-
-#if SVN_UNALIGNED_ACCESS_IS_OK
-
- /* Chunky processing is so much faster ...
- *
- * We can't make this work on architectures that require aligned access
- * because A and B will probably have different alignment. So, skipping
- * the first few chars until alignment is reached is not an option.
- */
- for (; pos + sizeof(apr_size_t) <= max_len; pos += sizeof(apr_size_t))
- if (*(const apr_size_t*)(a + pos) != *(const apr_size_t*)(b + pos))
- break;
-
-#endif
-
- for (; pos < max_len; ++pos)
- if (a[pos] != b[pos])
- break;
-
- return pos;
-}
-
-apr_size_t
-svn_cstring__reverse_match_length(const char *a,
- const char *b,
- apr_size_t max_len)
-{
- apr_size_t pos = 0;
-
-#if SVN_UNALIGNED_ACCESS_IS_OK
-
- /* Chunky processing is so much faster ...
- *
- * We can't make this work on architectures that require aligned access
- * because A and B will probably have different alignment. So, skipping
- * the first few chars until alignment is reached is not an option.
- */
- for (pos = sizeof(apr_size_t); pos <= max_len; pos += sizeof(apr_size_t))
- if (*(const apr_size_t*)(a - pos) != *(const apr_size_t*)(b - pos))
- break;
-
- pos -= sizeof(apr_size_t);
-
-#endif
-
- /* If we find a mismatch at -pos, pos-1 characters matched.
- */
- while (++pos <= max_len)
- if (a[0-pos] != b[0-pos])
- return pos - 1;
-
- /* No mismatch found -> at least MAX_LEN matching chars.
- */
- return max_len;
+ rv = apr_cstr_strtoi64(&val, str, APR_INT32_MIN, APR_INT32_MAX, 10);
+ if (rv == APR_SUCCESS)
+ *n = (int)val;
+ return rv;
}
const char *
-svn_cstring_skip_prefix(const char *str, const char *prefix)
+apr_cstr_skip_prefix(const char *str, const char *prefix)
{
apr_size_t len = strlen(prefix);
Re: svn commit: r1726928 - in /apr/apr/trunk: CMakeLists.txt
SConscript include/apr_cstr.h include/apr_errno.h strings/apr_cstr.c
Posted by Ruediger Pluem <rp...@apache.org>.
On 01/27/2016 01:08 AM, wrowe@apache.org wrote:
> Author: wrowe
> Date: Wed Jan 27 00:08:59 2016
> New Revision: 1726928
>
> URL: http://svn.apache.org/viewvc?rev=1726928&view=rev
> Log:
> Introduce the subset of svn_cstring_ functions into APR as the apr_cstr_
> family of functions. Requires the introduction of APR_ERANGE.
> Solves apr_cstr_casecmp[n] for ASCII and EBCDIC and borrows
> from the work of jim, ylavic and wrowe, see r1715401 forwards in;
> http://svn.apache.org/viewvc/httpd/httpd/trunk/server/util.c?view=log&pathrev=1722194
> More performance review is needed against different compilers, so went ahead
> and borrowed original svn implementation as a basis, and we can port whichever
> performance enhancements test out more efficiently.
>
> Proposing for APR 1.6.0 which is the thought behind the initial @since tags.
> These must be changed if not accepted for backport.
>
> Note that the svn_cstring_join function could not be implemented as-is
> due to the absence of svn's counted string functionality. It deserves
> an implementation if not already present, or should be removed before
> tagging or backporting.
>
> No whitespace/formatting cleanup on this pass in order to preserve as
> much of the svn attributions as possible. This can happen in a later
> pass to conform to APR's style conventions. While renaming the functions,
> declarations themsel
>
> Added:
> apr/apr/trunk/include/apr_cstr.h
> - copied, changed from r1717268, subversion/trunk/subversion/include/svn_string.h
> apr/apr/trunk/strings/apr_cstr.c
> - copied, changed from r1717268, subversion/trunk/subversion/libsvn_subr/string.c
> Modified:
> apr/apr/trunk/CMakeLists.txt
> apr/apr/trunk/SConscript
> apr/apr/trunk/include/apr_errno.h
>
> Modified: apr/apr/trunk/SConscript
> URL: http://svn.apache.org/viewvc/apr/apr/trunk/SConscript?rev=1726928&r1=1726927&r2=1726928&view=diff
> ==============================================================================
> --- apr/apr/trunk/SConscript (original)
> +++ apr/apr/trunk/SConscript Wed Jan 27 00:08:59 2016
> @@ -8,7 +8,7 @@ files = env.core_lib_files()
> libapr = env.SharedLibrary('apr-%d' % (major), files)
> tests = Split("""
> abts.c testutil.c
> - testtime.c teststr.c testvsn.c testipsub.c testshm.c
> + testtime.c testcstr.c teststr.c testvsn.c testipsub.c testshm.c
I don't see any testcstr.c.
> testmmap.c testud.c testtable.c testsleep.c testpools.c
> testfmt.c testfile.c testdir.c testfileinfo.c testrand.c
> testdso.c testoc.c testdup.c testsockets.c testproc.c
>
Regards
RĂ¼diger