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