summaryrefslogtreecommitdiff
path: root/src/libaudcore/index.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libaudcore/index.cc')
-rw-r--r--src/libaudcore/index.cc53
1 files changed, 52 insertions, 1 deletions
diff --git a/src/libaudcore/index.cc b/src/libaudcore/index.cc
index 75aa559..84ca64d 100644
--- a/src/libaudcore/index.cc
+++ b/src/libaudcore/index.cc
@@ -1,6 +1,6 @@
/*
* index.cc
- * Copyright 2014 John Lindgren
+ * Copyright 2014-2016 John Lindgren
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -42,6 +42,9 @@ static void do_erase (void * data, int len, aud::EraseFunc erase_func)
EXPORT void IndexBase::clear (aud::EraseFunc erase_func)
{
+ if (! m_data)
+ return;
+
__sync_sub_and_fetch (& misc_bytes_allocated, m_size);
do_erase (m_data, m_len, erase_func);
@@ -57,6 +60,9 @@ EXPORT void * IndexBase::insert (int pos, int len)
assert (pos <= m_len);
assert (len >= 0);
+ if (! len)
+ goto out;
+
if (pos < 0)
pos = m_len; /* insert at end */
@@ -86,6 +92,7 @@ EXPORT void * IndexBase::insert (int pos, int len)
memmove ((char *) m_data + pos + len, (char *) m_data + pos, m_len - pos);
m_len += len;
+out:
return (char *) m_data + pos;
}
@@ -93,6 +100,9 @@ EXPORT void IndexBase::insert (int pos, int len, aud::FillFunc fill_func)
{
void * to = insert (pos, len);
+ if (! len)
+ return;
+
if (fill_func)
fill_func (to, len);
else
@@ -103,6 +113,9 @@ EXPORT void IndexBase::insert (const void * from, int pos, int len, aud::CopyFun
{
void * to = insert (pos, len);
+ if (! len)
+ return;
+
if (copy_func)
copy_func (from, to, len);
else
@@ -117,6 +130,9 @@ EXPORT void IndexBase::remove (int pos, int len, aud::EraseFunc erase_func)
if (len < 0)
len = m_len - pos; /* remove all following */
+ if (! len)
+ return;
+
do_erase ((char *) m_data + pos, len, erase_func);
memmove ((char *) m_data + pos, (char *) m_data + pos + len, m_len - pos - len);
m_len -= len;
@@ -130,6 +146,9 @@ EXPORT void IndexBase::erase (int pos, int len, aud::FillFunc fill_func, aud::Er
if (len < 0)
len = m_len - pos; /* erase all following */
+ if (! len)
+ return;
+
do_erase ((char *) m_data + pos, len, erase_func);
do_fill ((char *) m_data + pos, len, fill_func);
}
@@ -140,6 +159,9 @@ EXPORT void IndexBase::shift (int from, int to, int len, aud::FillFunc fill_func
assert (from >= 0 && from + len <= m_len);
assert (to >= 0 && to + len <= m_len);
+ if (! len)
+ return;
+
int erase_len = aud::min (len, abs (to - from));
if (to < from)
@@ -165,6 +187,9 @@ EXPORT void IndexBase::move_from (IndexBase & b, int from, int to, int len,
if (len < 0)
len = b.m_len - from; /* copy all following */
+ if (! len)
+ return;
+
if (expand)
{
assert (to <= m_len);
@@ -192,5 +217,31 @@ EXPORT void IndexBase::move_from (IndexBase & b, int from, int to, int len,
EXPORT void IndexBase::sort (CompareFunc compare, int elemsize, void * userdata)
{
+ if (! m_len)
+ return;
+
+ // since we require GLib >= 2.32, g_qsort_with_data performs a stable sort
g_qsort_with_data (m_data, m_len / elemsize, elemsize, compare, userdata);
}
+
+EXPORT int IndexBase::bsearch (const void * key, CompareFunc compare,
+ int elemsize, void * userdata) const
+{
+ int top = 0;
+ int bottom = m_len / elemsize;
+
+ while (top < bottom)
+ {
+ int middle = top + (bottom - top) / 2;
+ int match = compare (key, (char *) m_data + middle * elemsize, userdata);
+
+ if (match < 0)
+ bottom = middle;
+ else if (match > 0)
+ top = middle + 1;
+ else
+ return middle;
+ }
+
+ return -1;
+}