14a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown/*
24a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown * Copyright (C) 2012 The Android Open Source Project
34a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown *
44a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
54a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown * you may not use this file except in compliance with the License.
64a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown * You may obtain a copy of the License at
74a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown *
84a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
94a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown *
104a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown * Unless required by applicable law or agreed to in writing, software
114a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
124a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown * See the License for the specific language governing permissions and
144a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown * limitations under the License.
154a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown */
164a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown
174a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown#include <stdlib.h>
184a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown#include <cutils/qsort_r_compat.h>
194a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown
204a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown#if HAVE_BSD_QSORT_R
214a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown
224a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown/*
234a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown * BSD qsort_r parameter order is as we have defined here.
244a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown */
254a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown
264a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brownvoid qsort_r_compat(void* base, size_t nel, size_t width, void* thunk,
274a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown        int (*compar)(void*, const void* , const void*)) {
284a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown    qsort_r(base, nel, width, thunk, compar);
294a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown}
304a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown
314a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown#elif HAVE_GNU_QSORT_R
324a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown
334a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown/*
344a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown * GNU qsort_r parameter order places the thunk parameter last.
354a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown */
364a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown
374a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brownstruct compar_data {
384a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown    void* thunk;
394a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown    int (*compar)(void*, const void* , const void*);
404a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown};
414a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown
424a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brownstatic int compar_wrapper(const void* a, const void* b, void* data) {
434a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown    struct compar_data* compar_data = (struct compar_data*)data;
444a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown    return compar_data->compar(compar_data->thunk, a, b);
454a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown}
464a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown
474a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brownvoid qsort_r_compat(void* base, size_t nel, size_t width, void* thunk,
484a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown        int (*compar)(void*, const void* , const void*)) {
494a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown    struct compar_data compar_data;
504a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown    compar_data.thunk = thunk;
514a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown    compar_data.compar = compar;
524a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown    qsort_r(base, nel, width, compar_wrapper, &compar_data);
534a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown}
544a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown
554a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown#else
564a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown
574a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown/*
584a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown * Emulate qsort_r using thread local storage to access the thunk data.
594a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown */
604a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown
614a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown#include <cutils/threads.h>
624a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown
634a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brownstatic thread_store_t compar_data_key = THREAD_STORE_INITIALIZER;
644a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown
654a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brownstruct compar_data {
664a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown    void* thunk;
674a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown    int (*compar)(void*, const void* , const void*);
684a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown};
694a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown
704a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brownstatic int compar_wrapper(const void* a, const void* b) {
714a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown    struct compar_data* compar_data = (struct compar_data*)thread_store_get(&compar_data_key);
724a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown    return compar_data->compar(compar_data->thunk, a, b);
734a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown}
744a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown
754a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brownvoid qsort_r_compat(void* base, size_t nel, size_t width, void* thunk,
764a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown        int (*compar)(void*, const void* , const void*)) {
774a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown    struct compar_data compar_data;
784a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown    compar_data.thunk = thunk;
794a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown    compar_data.compar = compar;
804a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown    thread_store_set(&compar_data_key, &compar_data, NULL);
814a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown    qsort(base, nel, width, compar_wrapper);
824a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown}
834a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown
844a6b384f607feed3755cfcbcdfded55fc2ccce82Jeff Brown#endif
85