1823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin/*
2823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin * Copyright (C) 2012 The Android Open Source Project
3823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin *
4823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin * Licensed under the Apache License, Version 2.0 (the "License");
5823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin * you may not use this file except in compliance with the License.
6823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin * You may obtain a copy of the License at
7823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin *
8823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin *      http://www.apache.org/licenses/LICENSE-2.0
9823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin *
10823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin * Unless required by applicable law or agreed to in writing, software
11823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin * distributed under the License is distributed on an "AS IS" BASIS,
12823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin * See the License for the specific language governing permissions and
14823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin * limitations under the License.
15823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin */
16823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin
17823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin#include <stdlib.h>
18823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin#include "qsort_r_compat.h"
19823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin
20823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin/*
21823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin * Note: This code is only used on the host, and is primarily here for
22823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin * Mac OS compatibility. Apparently, glibc and Apple's libc disagree on
23823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin * the parameter order for qsort_r.
24823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin */
25823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin
26823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin#if HAVE_BSD_QSORT_R
27823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin
28823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin/*
29823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin * BSD qsort_r parameter order is as we have defined here.
30823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin */
31823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin
32823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavinvoid qsort_r_compat(void* base, size_t nel, size_t width, void* thunk,
33823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin        int (*compar)(void*, const void* , const void*)) {
34823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin    qsort_r(base, nel, width, thunk, compar);
35823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin}
36823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin
37823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin#elif HAVE_GNU_QSORT_R
38823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin
39823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin/*
40823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin * GNU qsort_r parameter order places the thunk parameter last.
41823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin */
42823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin
43823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavinstruct compar_data {
44823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin    void* thunk;
45823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin    int (*compar)(void*, const void* , const void*);
46823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin};
47823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin
48823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavinstatic int compar_wrapper(const void* a, const void* b, void* data) {
49823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin    struct compar_data* compar_data = (struct compar_data*)data;
50823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin    return compar_data->compar(compar_data->thunk, a, b);
51823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin}
52823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin
53823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavinvoid qsort_r_compat(void* base, size_t nel, size_t width, void* thunk,
54823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin        int (*compar)(void*, const void* , const void*)) {
55823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin    struct compar_data compar_data;
56823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin    compar_data.thunk = thunk;
57823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin    compar_data.compar = compar;
58823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin    qsort_r(base, nel, width, compar_wrapper, &compar_data);
59823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin}
60823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin
61823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin#else
62823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin
63823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin/*
64823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin * Emulate qsort_r using thread local storage to access the thunk data.
65823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin */
66823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin
67823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin#include <cutils/threads.h>
68823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin
69823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavinstatic thread_store_t compar_data_key = THREAD_STORE_INITIALIZER;
70823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin
71823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavinstruct compar_data {
72823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin    void* thunk;
73823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin    int (*compar)(void*, const void* , const void*);
74823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin};
75823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin
76823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavinstatic int compar_wrapper(const void* a, const void* b) {
77823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin    struct compar_data* compar_data = (struct compar_data*)thread_store_get(&compar_data_key);
78823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin    return compar_data->compar(compar_data->thunk, a, b);
79823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin}
80823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin
81823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavinvoid qsort_r_compat(void* base, size_t nel, size_t width, void* thunk,
82823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin        int (*compar)(void*, const void* , const void*)) {
83823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin    struct compar_data compar_data;
84823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin    compar_data.thunk = thunk;
85823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin    compar_data.compar = compar;
86823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin    thread_store_set(&compar_data_key, &compar_data, NULL);
87823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin    qsort(base, nel, width, compar_wrapper);
88823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin}
89823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin
90823abb63145c7a7db2b766cf7bb816cbdac1de66Dima Zavin#endif
91