Home | History | Annotate | Download | only in aapt
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <stdlib.h>
     18 #include "qsort_r_compat.h"
     19 
     20 /*
     21  * Note: This code is only used on the host, and is primarily here for
     22  * Mac OS compatibility. Apparently, glibc and Apple's libc disagree on
     23  * the parameter order for qsort_r.
     24  */
     25 
     26 #if HAVE_BSD_QSORT_R
     27 
     28 /*
     29  * BSD qsort_r parameter order is as we have defined here.
     30  */
     31 
     32 void qsort_r_compat(void* base, size_t nel, size_t width, void* thunk,
     33         int (*compar)(void*, const void* , const void*)) {
     34     qsort_r(base, nel, width, thunk, compar);
     35 }
     36 
     37 #elif HAVE_GNU_QSORT_R
     38 
     39 /*
     40  * GNU qsort_r parameter order places the thunk parameter last.
     41  */
     42 
     43 struct compar_data {
     44     void* thunk;
     45     int (*compar)(void*, const void* , const void*);
     46 };
     47 
     48 static int compar_wrapper(const void* a, const void* b, void* data) {
     49     struct compar_data* compar_data = (struct compar_data*)data;
     50     return compar_data->compar(compar_data->thunk, a, b);
     51 }
     52 
     53 void qsort_r_compat(void* base, size_t nel, size_t width, void* thunk,
     54         int (*compar)(void*, const void* , const void*)) {
     55     struct compar_data compar_data;
     56     compar_data.thunk = thunk;
     57     compar_data.compar = compar;
     58     qsort_r(base, nel, width, compar_wrapper, &compar_data);
     59 }
     60 
     61 #else
     62 
     63 /*
     64  * Emulate qsort_r using thread local storage to access the thunk data.
     65  */
     66 
     67 #include <cutils/threads.h>
     68 
     69 static thread_store_t compar_data_key = THREAD_STORE_INITIALIZER;
     70 
     71 struct compar_data {
     72     void* thunk;
     73     int (*compar)(void*, const void* , const void*);
     74 };
     75 
     76 static int compar_wrapper(const void* a, const void* b) {
     77     struct compar_data* compar_data = (struct compar_data*)thread_store_get(&compar_data_key);
     78     return compar_data->compar(compar_data->thunk, a, b);
     79 }
     80 
     81 void qsort_r_compat(void* base, size_t nel, size_t width, void* thunk,
     82         int (*compar)(void*, const void* , const void*)) {
     83     struct compar_data compar_data;
     84     compar_data.thunk = thunk;
     85     compar_data.compar = compar;
     86     thread_store_set(&compar_data_key, &compar_data, NULL);
     87     qsort(base, nel, width, compar_wrapper);
     88 }
     89 
     90 #endif
     91