/* * Helper functions for ntdll * * Copyright 2000 Juergen Schmied * Copyright 2010 Marcus Meissner * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include "ntstatus.h" #define WIN32_NO_STATUS #include "wine/debug.h" #include "ntdll_misc.h" #include "wmistr.h" #include "evntrace.h" #include "evntprov.h" WINE_DEFAULT_DEBUG_CHANNEL(ntdll); LPCSTR debugstr_us( const UNICODE_STRING *us ) { if (!us) return ""; return debugstr_wn(us->Buffer, us->Length / sizeof(WCHAR)); } static int __cdecl compare_wrapper(void *ctx, const void *e1, const void *e2) { int (__cdecl *compare)( const void *, const void * ) = ctx; return compare( e1, e2 ); } static inline void swap(char *l, char *r, size_t size) { char tmp; while(size--) { tmp = *l; *l++ = *r; *r++ = tmp; } } static void small_sort(void *base, size_t nmemb, size_t size, int (CDECL *compar)(void *, const void *, const void *), void *context) { size_t e, i; char *max, *p; for(e=nmemb; e>1; e--) { max = base; for(i=1; i 0) max = p; } if(p != max) swap(p, max, size); } } static void quick_sort(void *base, size_t nmemb, size_t size, int (CDECL *compar)(void *, const void *, const void *), void *context) { size_t stack_lo[8*sizeof(size_t)], stack_hi[8*sizeof(size_t)]; size_t beg, end, lo, hi, med; int stack_pos; stack_pos = 0; stack_lo[stack_pos] = 0; stack_hi[stack_pos] = nmemb-1; #define X(i) ((char*)base+size*(i)) while(stack_pos >= 0) { beg = stack_lo[stack_pos]; end = stack_hi[stack_pos--]; if(end-beg < 8) { small_sort(X(beg), end-beg+1, size, compar, context); continue; } lo = beg; hi = end; med = lo + (hi-lo+1)/2; if(compar(context, X(lo), X(med)) > 0) swap(X(lo), X(med), size); if(compar(context, X(lo), X(hi)) > 0) swap(X(lo), X(hi), size); if(compar(context, X(med), X(hi)) > 0) swap(X(med), X(hi), size); lo++; hi--; while(1) { while(lo <= hi) { if(lo!=med && compar(context, X(lo), X(med))>0) break; lo++; } while(med != hi) { if(compar(context, X(hi), X(med)) <= 0) break; hi--; } if(hi < lo) break; swap(X(lo), X(hi), size); if(hi == med) med = lo; lo++; hi--; } while(hi > beg) { if(hi!=med && compar(context, X(hi), X(med))!=0) break; hi--; } if(hi-beg >= end-lo) { stack_lo[++stack_pos] = beg; stack_hi[stack_pos] = hi; stack_lo[++stack_pos] = lo; stack_hi[stack_pos] = end; }else { stack_lo[++stack_pos] = lo; stack_hi[stack_pos] = end; stack_lo[++stack_pos] = beg; stack_hi[stack_pos] = hi; } } #undef X } /********************************************************************* * qsort_s (NTDLL.@) */ void __cdecl qsort_s( void *base, size_t nmemb, size_t size, int (__cdecl *compar)(void *, const void *, const void *), void *context ) { const size_t total_size = nmemb * size; if (!base && nmemb) return; if (!size) return; if (!compar) return; if (total_size / size != nmemb) return; if (nmemb < 2) return; quick_sort( base, nmemb, size, compar, context ); } /********************************************************************* * qsort (NTDLL.@) */ void __cdecl qsort( void *base, size_t nmemb, size_t size, int (__cdecl *compar)(const void *, const void *) ) { qsort_s( base, nmemb, size, compare_wrapper, compar ); } /********************************************************************* * bsearch_s (NTDLL.@) */ void * __cdecl bsearch_s( const void *key, const void *base, size_t nmemb, size_t size, int (__cdecl *compare)(void *, const void *, const void *), void *ctx ) { ssize_t min = 0; ssize_t max = nmemb - 1; if (!size) return NULL; if (!compare) return NULL; while (min <= max) { ssize_t cursor = min + (max - min) / 2; int ret = compare(ctx, key,(const char *)base+(cursor*size)); if (!ret) return (char*)base+(cursor*size); if (ret < 0) max = cursor - 1; else min = cursor + 1; } return NULL; } /********************************************************************* * bsearch (NTDLL.@) */ void * __cdecl bsearch( const void *key, const void *base, size_t nmemb, size_t size, int (__cdecl *compar)(const void *, const void *) ) { return bsearch_s( key, base, nmemb, size, compare_wrapper, compar ); } /********************************************************************* * _lfind (NTDLL.@) */ void * __cdecl _lfind( const void *key, const void *base, unsigned int *nmemb, size_t size, int(__cdecl *compar)(const void *, const void *) ) { size_t i, n = *nmemb; for (i=0;i