#endif /* not WINDOWS */
-/* Encode the string S of length LENGTH to base64 format and place it
+/* Encode the string STR of length LENGTH to base64 format and place it
to B64STORE. The output will be \0-terminated, and must point to a
writable buffer of at least 1+BASE64_LENGTH(length) bytes. It
returns the length of the resulting base64 data, not counting the
base64 data. */
int
-base64_encode (const char *s, int length, char *b64store)
+base64_encode (const char *str, int length, char *b64store)
{
/* Conversion table. */
static char tbl[64] = {
'4','5','6','7','8','9','+','/'
};
int i;
- unsigned char *p = (unsigned char *) b64store;
+ const unsigned char *s = (const unsigned char *) str;
+ char *p = b64store;
/* Transform the 3x8 bits to 4x6 bits, as required by base64. */
for (i = 0; i < length; i += 3)
/* ...and zero-terminate it. */
*p = '\0';
- return p - (unsigned char *) b64store;
+ return p - b64store;
}
#define IS_ASCII(c) (((c) & 0x80) == 0)
#undef IS_ASCII
#undef IS_BASE64
#undef NEXT_BASE64_CHAR
+\f
+/* Simple merge sort for use by stable_sort. Implementation courtesy
+ Zeljko Vrba. */
+
+static void
+mergesort_internal (void *base, void *temp, size_t size, size_t from, size_t to,
+ int (*cmpfun) PARAMS ((const void *, const void *)))
+{
+#define ELT(array, pos) ((char *)(array) + (pos) * size)
+ if (from < to)
+ {
+ size_t i, j, k;
+ size_t mid = (to + from) / 2;
+ mergesort_internal (base, temp, size, from, mid, cmpfun);
+ mergesort_internal (base, temp, size, mid + 1, to, cmpfun);
+ i = from;
+ j = mid + 1;
+ for (k = from; (i <= mid) && (j <= to); k++)
+ if (cmpfun (ELT (base, i), ELT (base, j)) <= 0)
+ memcpy (ELT (temp, k), ELT (base, i++), size);
+ else
+ memcpy (ELT (temp, k), ELT (base, j++), size);
+ while (i <= mid)
+ memcpy (ELT (temp, k++), ELT (base, i++), size);
+ while (j <= to)
+ memcpy (ELT (temp, k++), ELT (base, j++), size);
+ for (k = from; k <= to; k++)
+ memcpy (ELT (base, k), ELT (temp, k), size);
+ }
+#undef ELT
+}
+
+/* Stable sort with interface exactly like standard library's qsort.
+ Uses mergesort internally, allocating temporary storage with
+ alloca. */
+
+void
+stable_sort (void *base, size_t nmemb, size_t size,
+ int (*cmpfun) PARAMS ((const void *, const void *)))
+{
+ if (size > 1)
+ {
+ void *temp = alloca (nmemb * size * sizeof (void *));
+ mergesort_internal (base, temp, size, 0, nmemb - 1, cmpfun);
+ }
+}