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