Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
O
OBITools3
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
23
Issues
23
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
Operations
Operations
Incidents
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
OBITools
OBITools3
Commits
651c1d78
Commit
651c1d78
authored
Jan 31, 2017
by
Celine Mercier
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
utilities: bsearch and qsort with additional user_data pointer argument
parent
c0bcdce7
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
227 additions
and
0 deletions
+227
-0
src/utils.c
src/utils.c
+190
-0
src/utils.h
src/utils.h
+37
-0
No files found.
src/utils.c
View file @
651c1d78
...
...
@@ -116,3 +116,193 @@ void* obi_get_memory_aligned_on_16(int size, int* shift)
return
(
memory
);
}
/*
* A generic implementation of binary search for the Linux kernel
*
* Copyright (C) 2008-2009 Ksplice, Inc.
* Author: Tim Abbott <tabbott@ksplice.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2.
*/
void
*
bsearch_user_data
(
const
void
*
key
,
const
void
*
base
,
size_t
num
,
size_t
size
,
const
void
*
user_data
,
int
(
*
cmp
)(
const
void
*
key
,
const
void
*
elt
,
const
void
*
user_data
))
{
size_t
start
=
0
;
size_t
end
=
num
;
size_t
mid
;
int
result
;
while
(
start
<
end
)
{
mid
=
start
+
(
end
-
start
)
/
2
;
result
=
cmp
(
key
,
base
+
mid
*
size
,
user_data
);
if
(
result
<
0
)
end
=
mid
;
else
if
(
result
>
0
)
start
=
mid
+
1
;
else
return
(
void
*
)
base
+
mid
*
size
;
}
return
NULL
;
}
/*
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
*/
#define MIN(a,b) ((a) < (b) ? a : b)
#define swapcode(TYPE, parmi, parmj, n) { \
long i = (n) / sizeof (TYPE); \
register TYPE *pi = (TYPE *) (parmi); \
register TYPE *pj = (TYPE *) (parmj); \
do { \
register TYPE t = *pi; \
*pi++ = *pj; \
*pj++ = t; \
} while (--i > 0); \
}
#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
static
__inline
void
swapfunc
(
char
*
a
,
char
*
b
,
int
n
,
int
swaptype
)
{
if
(
swaptype
<=
1
)
swapcode
(
long
,
a
,
b
,
n
)
else
swapcode
(
char
,
a
,
b
,
n
)
}
#define swap(a, b) \
if (swaptype == 0) { \
long t = *(long *)(a); \
*(long *)(a) = *(long *)(b); \
*(long *)(b) = t; \
} else \
swapfunc(a, b, es, swaptype)
#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
static
__inline
char
*
med3
(
char
*
a
,
char
*
b
,
char
*
c
,
const
void
*
user_data
,
int
(
*
cmp
)(
const
void
*
,
const
void
*
,
const
void
*
))
{
return
cmp
(
a
,
b
,
user_data
)
<
0
?
(
cmp
(
b
,
c
,
user_data
)
<
0
?
b
:
(
cmp
(
a
,
c
,
user_data
)
<
0
?
c
:
a
))
:
(
cmp
(
b
,
c
,
user_data
)
>
0
?
b
:
(
cmp
(
a
,
c
,
user_data
)
<
0
?
a
:
c
));
}
void
qsort_user_data
(
void
*
aa
,
size_t
n
,
size_t
es
,
const
void
*
user_data
,
int
(
*
cmp
)(
const
void
*
,
const
void
*
,
const
void
*
))
{
char
*
pa
,
*
pb
,
*
pc
,
*
pd
,
*
pl
,
*
pm
,
*
pn
;
int
d
,
r
,
swaptype
,
swap_cnt
;
register
char
*
a
=
aa
;
loop:
SWAPINIT
(
a
,
es
);
swap_cnt
=
0
;
if
(
n
<
7
)
{
for
(
pm
=
(
char
*
)
a
+
es
;
pm
<
(
char
*
)
a
+
n
*
es
;
pm
+=
es
)
for
(
pl
=
pm
;
pl
>
(
char
*
)
a
&&
cmp
(
pl
-
es
,
pl
,
user_data
)
>
0
;
pl
-=
es
)
swap
(
pl
,
pl
-
es
);
return
;
}
pm
=
(
char
*
)
a
+
(
n
/
2
)
*
es
;
if
(
n
>
7
)
{
pl
=
(
char
*
)
a
;
pn
=
(
char
*
)
a
+
(
n
-
1
)
*
es
;
if
(
n
>
40
)
{
d
=
(
n
/
8
)
*
es
;
pl
=
med3
(
pl
,
pl
+
d
,
pl
+
2
*
d
,
user_data
,
cmp
);
pm
=
med3
(
pm
-
d
,
pm
,
pm
+
d
,
user_data
,
cmp
);
pn
=
med3
(
pn
-
2
*
d
,
pn
-
d
,
pn
,
user_data
,
cmp
);
}
pm
=
med3
(
pl
,
pm
,
pn
,
user_data
,
cmp
);
}
swap
(
a
,
pm
);
pa
=
pb
=
(
char
*
)
a
+
es
;
pc
=
pd
=
(
char
*
)
a
+
(
n
-
1
)
*
es
;
for
(;;)
{
while
(
pb
<=
pc
&&
(
r
=
cmp
(
pb
,
a
,
user_data
))
<=
0
)
{
if
(
r
==
0
)
{
swap_cnt
=
1
;
swap
(
pa
,
pb
);
pa
+=
es
;
}
pb
+=
es
;
}
while
(
pb
<=
pc
&&
(
r
=
cmp
(
pc
,
a
,
user_data
))
>=
0
)
{
if
(
r
==
0
)
{
swap_cnt
=
1
;
swap
(
pc
,
pd
);
pd
-=
es
;
}
pc
-=
es
;
}
if
(
pb
>
pc
)
break
;
swap
(
pb
,
pc
);
swap_cnt
=
1
;
pb
+=
es
;
pc
-=
es
;
}
if
(
swap_cnt
==
0
)
{
/* Switch to insertion sort */
for
(
pm
=
(
char
*
)
a
+
es
;
pm
<
(
char
*
)
a
+
n
*
es
;
pm
+=
es
)
for
(
pl
=
pm
;
pl
>
(
char
*
)
a
&&
cmp
(
pl
-
es
,
pl
,
user_data
)
>
0
;
pl
-=
es
)
swap
(
pl
,
pl
-
es
);
return
;
}
pn
=
(
char
*
)
a
+
n
*
es
;
r
=
MIN
(
pa
-
(
char
*
)
a
,
pb
-
pa
);
vecswap
(
a
,
pb
-
r
,
r
);
r
=
MIN
((
long
)(
pd
-
pc
),
(
long
)(
pn
-
pd
-
es
));
vecswap
(
pb
,
pn
-
r
,
r
);
if
((
r
=
pb
-
pa
)
>
(
int
)
es
)
qsort_user_data
(
a
,
r
/
es
,
es
,
user_data
,
cmp
);
if
((
r
=
pd
-
pc
)
>
(
int
)
es
)
{
/* Iterate rather than recurse to save stack space */
a
=
pn
-
r
;
n
=
r
/
es
;
goto
loop
;
}
/* qsort(pn - r, r / es, es, cmp);*/
}
src/utils.h
View file @
651c1d78
...
...
@@ -74,4 +74,41 @@ char* obi_format_date(time_t date);
void
*
obi_get_memory_aligned_on_16
(
int
size
,
int
*
shift
);
/**
* @brief Version of quick sort modified to allow the user to provide an
* additional pointer sent to the comparison function.
*
* @param key This is the pointer to the object that serves as key for the search, type-casted as a void*.
* @param base This is the pointer to the first object of the array where the search is performed, type-casted as a void*.
* @param num This is the number of elements in the array pointed by base.
* @param size This is the size in bytes of each element in the array.
* @param user_data This is an additional pointer passed to the comparison function.
* @param cmp This is the function that compares two elements, eventually with an additional pointer.
*
* @returns A pointer to an entry in the array that matches the search key.
* @retval NULL if key is not found.
*
* @since January 2017
* @author original code modified by Celine Mercier (celine.mercier@metabarcoding.org)
*/
void
*
bsearch_user_data
(
const
void
*
key
,
const
void
*
base
,
size_t
num
,
size_t
size
,
const
void
*
user_data
,
int
(
*
cmp
)(
const
void
*
key
,
const
void
*
elt
,
const
void
*
user_data
));
/**
* @brief Version of quick sort modified to allow the user to provide an
* additional pointer sent to the comparison function.
*
* @param aa This is the pointer to the first element of the array to be sorted.
* @param n This is the number of elements in the array pointed by base.
* @param es This is the size in bytes of each element in the array.
* @param user_data This is an additional pointer passed to the comparison function.
* @param cmp This is the function that compares two elements, eventually with an additional pointer.
*
* @since January 2017
* @author original code modified by Celine Mercier (celine.mercier@metabarcoding.org)
*/
void
qsort_user_data
(
void
*
aa
,
size_t
n
,
size_t
es
,
const
void
*
user_data
,
int
(
*
cmp
)(
const
void
*
,
const
void
*
,
const
void
*
));
#endif
/* UTILS_H_ */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment