/* * llist_search: search for entry with val that matches * according to compare_function in list llist. Return * match in e. */ int llist_search(llist_entry **llist, void *val, int (*compare_function)(const char *, const char *), llist_entry **e) { llist_entry *ei; for (ei = (*llist); ei != NULL; ei = ei->next) if (compare_function(ei->val, val) == 0) { (*e) = ei; return 0; } return -1; }
static int ds_zval_compare_func(const void *a, const void *b) { zval retval; zval *x = (zval*) a; zval *y = (zval*) b; if (compare_function(&retval, x, y) == SUCCESS) { return (int) zval_get_long(&retval); } return 0; }
int llist_sort(llist_entry *llist, int (*compare_function)(llist_entry *, llist_entry *)) { llist_entry *lle1, *lle2; void *tmp_val; for (lle1 = llist; lle1 != NULL; lle1 = lle1->next) { for (lle2 = lle1->next; lle2 != NULL; lle2 = lle2->next) { if (compare_function(lle1, lle2) == 1) { tmp_val = lle1->val; lle1->val = lle2->val; lle2->val = tmp_val; } } } return 0; }
void merge_sort(void* Array, size_t size_of_array, size_t size_of_data, int (*compare_function)(const void*, const void*)) { if(size_of_array <= 1) return; else { void* Middle = Array + (size_of_array / 2) * size_of_data; void* End = Array + size_of_array * size_of_data; merge_sort((void*)Array , size_of_array / 2 , size_of_data, compare_function); merge_sort((void*)Middle , size_of_array - size_of_array / 2 , size_of_data, compare_function); void *buffer = malloc(size_of_array * size_of_data); void *first_iterator = Array, *second_iterator = Middle, *inserter = buffer; while((first_iterator < Middle) && (second_iterator < End)) { if(compare_function(first_iterator, second_iterator) <= 0) { memcpy(inserter, first_iterator, size_of_data); first_iterator += size_of_data; inserter += size_of_data; } else { memcpy(inserter, second_iterator, size_of_data); second_iterator += size_of_data; inserter += size_of_data; } } while(first_iterator < Middle) { memcpy(inserter, first_iterator, size_of_data); first_iterator += size_of_data; inserter += size_of_data; } while(second_iterator < End) { memcpy(inserter, second_iterator, size_of_data); second_iterator += size_of_data; inserter += size_of_data; } memcpy(Array, buffer, size_of_array * size_of_data); free(buffer); } }
static int spl_ptr_heap_zval_min_cmp(zval *a, zval *b, zval *object) { /* {{{ */ zval result; if (EG(exception)) { return 0; } if (object) { spl_heap_object *heap_object = Z_SPLHEAP_P(object); if (heap_object->fptr_cmp) { zend_long lval = 0; if (spl_ptr_heap_cmp_cb_helper(object, heap_object, a, b, &lval) == FAILURE) { /* exception or call failure */ return 0; } return lval > 0 ? 1 : (lval < 0 ? -1 : 0); } } compare_function(&result, b, a); return (int)Z_LVAL(result); }
list_t * list_sort(list_t *list, compare_function_t *compare_function) { if (list == NULL) { //TODO throw an error return NULL; } if (list->head == NULL) { return list; } if (compare_function == NULL) { //TODO throw an error return NULL; } //The sort is done using bubble sort //TODO Change to a better sorting algorithm bool swapped; do { swapped = false; list_elem_t *elem = list->head; while (elem->next != NULL) { if (compare_function(elem->value, elem->next->value) > 0) { list_swap_elements(list, elem, elem->next); swapped = true; } else { elem = elem->next; } } } while (swapped); return list; }
VALUE php_value_obj_equal(VALUE self, VALUE rhs) { zval *lhs_zv; zval *rhs_zv; zval *result; int cmp_ret; lhs_zv = get_zval(self); if (lhs_zv == NULL) { return Qnil; } if (cPhpEmbedValue == CLASS_OF(rhs)) { rhs_zv = get_zval(rhs); } else { rhs_zv = value_to_zval(rhs); } MAKE_STD_ZVAL(result); compare_function(result, lhs_zv, rhs_zv TSRMLS_CC); cmp_ret = Z_LVAL_P(result); FREE_ZVAL(result); return cmp_ret == 0 ? Qtrue : Qfalse; }
/* Given a type-library, merge it into the current engine state */ PHP_COM_DOTNET_API int php_com_import_typelib(ITypeLib *TL, int mode, int codepage TSRMLS_DC) { int i, j, interfaces; TYPEKIND pTKind; ITypeInfo *TypeInfo; VARDESC *pVarDesc; UINT NameCount; BSTR bstr_ids; zend_constant c; zval *exists, results, value; char *const_name; int len; if (TL == NULL) { return FAILURE; } interfaces = ITypeLib_GetTypeInfoCount(TL); for (i = 0; i < interfaces; i++) { ITypeLib_GetTypeInfoType(TL, i, &pTKind); if (pTKind == TKIND_ENUM) { ITypeLib_GetTypeInfo(TL, i, &TypeInfo); for (j = 0; ; j++) { if (FAILED(ITypeInfo_GetVarDesc(TypeInfo, j, &pVarDesc))) { break; } ITypeInfo_GetNames(TypeInfo, pVarDesc->memid, &bstr_ids, 1, &NameCount); if (NameCount != 1) { ITypeInfo_ReleaseVarDesc(TypeInfo, pVarDesc); continue; } const_name = php_com_olestring_to_string(bstr_ids, &len, codepage TSRMLS_CC); c.name = STR_INIT(const_name, len, 1); // TODO: avoid reallocation??? efree(const_name); if(c.name == NULL) { ITypeInfo_ReleaseVarDesc(TypeInfo, pVarDesc); continue; } //??? c.name_len++; /* include NUL */ SysFreeString(bstr_ids); /* sanity check for the case where the constant is already defined */ if ((exists = zend_get_constant(c.name TSRMLS_CC)) != NULL) { if (COMG(autoreg_verbose) && !compare_function(&results, &c.value, exists TSRMLS_CC)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type library constant %s is already defined", c.name); } STR_RELEASE(c.name); ITypeInfo_ReleaseVarDesc(TypeInfo, pVarDesc); continue; } /* register the constant */ php_com_zval_from_variant(&value, pVarDesc->lpvarValue, codepage TSRMLS_CC); if (Z_TYPE(value) == IS_INT) { c.flags = mode; ZVAL_INT(&c.value, Z_IVAL(value)); c.module_number = 0; zend_register_constant(&c TSRMLS_CC); } ITypeInfo_ReleaseVarDesc(TypeInfo, pVarDesc); } ITypeInfo_Release(TypeInfo); } } return SUCCESS; }
// クイックソートの実行 void chelp_qsort(void *base, UINT num, UINT width, int (*compare_function)(const void *, const void *)) { UCHAR *low; UCHAR *high; UCHAR *middle; UCHAR *low2; UCHAR *high2; UINT size; UCHAR *low_stack[CHELP_QSORT_STACKSIZE], *high_stack[CHELP_QSORT_STACKSIZE]; int stack_pointer = 0; if (num <= 1) { return; } low = (UCHAR *)base; high = (UCHAR *)base + width * (num - 1); LABEL_RECURSE: size = (UINT)(high - low) / width + 1; middle = low + (size / 2) * width; if (compare_function(low, middle) > 0) { chelp_swap(low, middle, width); } if (compare_function(low, high) > 0) { chelp_swap(low, high, width); } if (compare_function(middle, high) > 0) { chelp_swap(middle, high, width); } low2 = low; high2 = high; while (true) { if (middle > low2) { do { low2 += width; } while (low2 < middle && compare_function(low2, middle) <= 0); } if (middle <= low2) { do { low2 += width; } while (low2 <= high && compare_function(low2, middle) <= 0); } do { high2 -= width; } while (high2 > middle && compare_function(high2, middle) > 0); if (high2 < low2) { break; } chelp_swap(low2, high2, width); if (middle == high2) { middle = low2; } } high2 += width; if (middle < high2) { do { high2 -= width; } while (high2 > middle && compare_function(high2, middle) == 0); } if (middle >= high2) { do { high2 -= width; } while (high2 > low && compare_function(high2, middle) == 0); } if ((high2 - low) >= (high - low2)) { if (low < high2) { low_stack[stack_pointer] = low; high_stack[stack_pointer] = high2; stack_pointer++; } if (low2 < high) { low = low2; goto LABEL_RECURSE; } } else { if (low2 < high) { low_stack[stack_pointer] = low2; high_stack[stack_pointer] = high; stack_pointer++; } if (low < high2) { high = high2; goto LABEL_RECURSE; } } stack_pointer--; if (stack_pointer >= 0) { low = low_stack[stack_pointer]; high = high_stack[stack_pointer]; goto LABEL_RECURSE; } }
void filesort_heapsort(void **datap,size_t nitems,int(*compare_function)(const void*, const void*)) { void **datap1=&datap[-1]; size_t item; /* Fill the heap by pretending to insert the data that is already there */ for(item=2;item<=nitems;item++) { size_t index=item; /* Bubble up the new value (upside-down, put largest at top) */ while(index>1) { int newindex; void *temp; newindex=index/2; if(compare_function(datap1[index],datap1[newindex])<=0) /* reversed comparison to filesort_fixed() above */ break; temp=datap1[index]; datap1[index]=datap1[newindex]; datap1[newindex]=temp; index=newindex; } } /* Repeatedly pull out the root of the heap and swap with the bottom item */ for(item=nitems;item>1;item--) { size_t index=1; void *temp; temp=datap1[index]; datap1[index]=datap1[item]; datap1[item]=temp; /* Bubble down the new value (upside-down, put largest at top) */ while((2*index)<(item-1)) { int newindex; void *temp; newindex=2*index; if(compare_function(datap1[newindex],datap1[newindex+1])<=0) /* reversed comparison to filesort_fixed() above */ newindex=newindex+1; if(compare_function(datap1[index],datap1[newindex])>=0) /* reversed comparison to filesort_fixed() above */ break; temp=datap1[newindex]; datap1[newindex]=datap1[index]; datap1[index]=temp; index=newindex; } if((2*index)==(item-1)) { int newindex; void *temp; newindex=2*index; if(compare_function(datap1[index],datap1[newindex])>=0) /* reversed comparison to filesort_fixed() above */ ; /* break */ else { temp=datap1[newindex]; datap1[newindex]=datap1[index]; datap1[index]=temp; } } } }
index_t filesort_vary(int fd_in,int fd_out,int (*pre_sort_function)(void*,index_t), int (*compare_function)(const void*,const void*), int (*post_sort_function)(void*,index_t)) { int *fds=NULL,*heap=NULL; int nfiles=0,ndata=0; index_t count_out=0,count_in=0,total=0; size_t datasize=option_filesort_ramsize/option_filesort_threads; FILESORT_VARINT nextitemsize,largestitemsize=0; void *data,**datap; thread_data *threads; size_t item; int i,more=1; #if defined(USE_PTHREADS) && USE_PTHREADS int nthreads=0; #endif /* Allocate the RAM buffer and other bits */ threads=(thread_data*)malloc(option_filesort_threads*sizeof(thread_data)); for(i=0;i<option_filesort_threads;i++) { threads[i].running=0; threads[i].data=malloc(datasize); threads[i].datap=NULL; threads[i].filename=(char*)malloc(strlen(option_tmpdirname)+24); threads[i].compare=compare_function; } /* Loop around, fill the buffer, sort the data and write a temporary file */ if(ReadFileBuffered(fd_in,&nextitemsize,FILESORT_VARSIZE)) /* Always have the next item size known in advance */ goto tidy_and_exit; do { size_t ramused=FILESORT_VARALIGN-FILESORT_VARSIZE; int thread=0; #if defined(USE_PTHREADS) && USE_PTHREADS if(option_filesort_threads>1) { /* Find a spare slot (one *must* be unused at all times) */ pthread_mutex_lock(&running_mutex); for(thread=0;thread<option_filesort_threads;thread++) if(!threads[thread].running) break; pthread_mutex_unlock(&running_mutex); } #endif threads[thread].datap=threads[thread].data+datasize; threads[thread].n=0; /* Read in the data and create pointers */ while((ramused+FILESORT_VARSIZE+nextitemsize)<=(unsigned)((void*)threads[thread].datap-sizeof(void*)-threads[thread].data)) { FILESORT_VARINT itemsize=nextitemsize; *(FILESORT_VARINT*)(threads[thread].data+ramused)=itemsize; ramused+=FILESORT_VARSIZE; ReadFileBuffered(fd_in,threads[thread].data+ramused,itemsize); if(!pre_sort_function || pre_sort_function(threads[thread].data+ramused,count_in)) { *--threads[thread].datap=threads[thread].data+ramused; /* points to real data */ if(itemsize>largestitemsize) largestitemsize=itemsize; ramused+=itemsize; ramused =FILESORT_VARALIGN*((ramused+FILESORT_VARSIZE-1)/FILESORT_VARALIGN); ramused+=FILESORT_VARALIGN-FILESORT_VARSIZE; total++; threads[thread].n++; } else ramused-=FILESORT_VARSIZE; count_in++; if(ReadFileBuffered(fd_in,&nextitemsize,FILESORT_VARSIZE)) { more=0; break; } } /* No new data read in this time round */ if(threads[thread].n==0) break; /* Sort the data pointers using a heap sort (potentially in a thread) */ if(more==0 && nfiles==0) threads[thread].filename[0]=0; else sprintf(threads[thread].filename,"%s/filesort.%d.tmp",option_tmpdirname,nfiles); #if defined(USE_PTHREADS) && USE_PTHREADS /* Shortcut if only one file, don't write to disk */ if(more==0 && nfiles==0) filesort_heapsort(threads[thread].datap,threads[thread].n,threads[thread].compare); else if(option_filesort_threads>1) { pthread_mutex_lock(&running_mutex); while(nthreads==(option_filesort_threads-1)) { for(i=0;i<option_filesort_threads;i++) if(threads[i].running==2) { pthread_join(threads[i].thread,NULL); threads[i].running=0; nthreads--; } if(nthreads==(option_filesort_threads-1)) pthread_cond_wait(&running_cond,&running_mutex); } threads[thread].running=1; pthread_mutex_unlock(&running_mutex); pthread_create(&threads[thread].thread,NULL,(void* (*)(void*))filesort_vary_heapsort_thread,&threads[thread]); nthreads++; } else filesort_vary_heapsort_thread(&threads[thread]); #else /* Shortcut if only one file, don't write to disk */ if(more==0 && nfiles==0) filesort_heapsort(threads[thread].datap,threads[thread].n,threads[thread].compare); else filesort_vary_heapsort_thread(&threads[thread]); #endif nfiles++; } while(more); /* Wait for all of the threads to finish */ #if defined(USE_PTHREADS) && USE_PTHREADS while(option_filesort_threads>1 && nthreads) { pthread_mutex_lock(&running_mutex); pthread_cond_wait(&running_cond,&running_mutex); for(i=0;i<option_filesort_threads;i++) if(threads[i].running==2) { pthread_join(threads[i].thread,NULL); threads[i].running=0; nthreads--; } pthread_mutex_unlock(&running_mutex); } #endif /* Shortcut if only one file, lucky for us we still have the data in RAM) */ if(nfiles==1) { for(item=0;item<threads[0].n;item++) { if(!post_sort_function || post_sort_function(threads[0].datap[item],count_out)) { FILESORT_VARINT itemsize=*(FILESORT_VARINT*)(threads[0].datap[item]-FILESORT_VARSIZE); WriteFileBuffered(fd_out,threads[0].datap[item]-FILESORT_VARSIZE,itemsize+FILESORT_VARSIZE); count_out++; } } DeleteFile(threads[0].filename); goto tidy_and_exit; } /* Check that number of files is less than file size */ largestitemsize=FILESORT_VARALIGN*(1+(largestitemsize+FILESORT_VARALIGN-FILESORT_VARSIZE)/FILESORT_VARALIGN); logassert((unsigned)nfiles<((datasize-nfiles*sizeof(void*))/largestitemsize),"Too many temporary files (use more sorting memory?)"); /* Open all of the temporary files */ fds=(int*)malloc(nfiles*sizeof(int)); for(i=0;i<nfiles;i++) { char *filename=threads[0].filename; sprintf(filename,"%s/filesort.%d.tmp",option_tmpdirname,i); fds[i]=ReOpenFileBuffered(filename); DeleteFile(filename); } /* Perform an n-way merge using a binary heap */ heap=(int*)malloc((1+nfiles)*sizeof(int)); data=threads[0].data; datap=data+datasize-nfiles*sizeof(void*); /* Fill the heap to start with */ for(i=0;i<nfiles;i++) { int index; FILESORT_VARINT itemsize; datap[i]=data+FILESORT_VARALIGN-FILESORT_VARSIZE+i*largestitemsize; ReadFileBuffered(fds[i],&itemsize,FILESORT_VARSIZE); *(FILESORT_VARINT*)(datap[i]-FILESORT_VARSIZE)=itemsize; ReadFileBuffered(fds[i],datap[i],itemsize); index=i+1; heap[index]=i; /* Bubble up the new value */ while(index>1) { int newindex; int temp; newindex=index/2; if(compare_function(datap[heap[index]],datap[heap[newindex]])>=0) break; temp=heap[index]; heap[index]=heap[newindex]; heap[newindex]=temp; index=newindex; } } /* Repeatedly pull out the root of the heap and refill from the same file */ ndata=nfiles; do { int index=1; FILESORT_VARINT itemsize; if(!post_sort_function || post_sort_function(datap[heap[index]],count_out)) { itemsize=*(FILESORT_VARINT*)(datap[heap[index]]-FILESORT_VARSIZE); WriteFileBuffered(fd_out,datap[heap[index]]-FILESORT_VARSIZE,itemsize+FILESORT_VARSIZE); count_out++; } if(ReadFileBuffered(fds[heap[index]],&itemsize,FILESORT_VARSIZE)) { heap[index]=heap[ndata]; ndata--; } else { *(FILESORT_VARINT*)(datap[heap[index]]-FILESORT_VARSIZE)=itemsize; ReadFileBuffered(fds[heap[index]],datap[heap[index]],itemsize); } /* Bubble down the new value */ while((2*index)<ndata) { int newindex; int temp; newindex=2*index; if(compare_function(datap[heap[newindex]],datap[heap[newindex+1]])>=0) newindex=newindex+1; if(compare_function(datap[heap[index]],datap[heap[newindex]])<=0) break; temp=heap[newindex]; heap[newindex]=heap[index]; heap[index]=temp; index=newindex; } if((2*index)==ndata) { int newindex; int temp; newindex=2*index; if(compare_function(datap[heap[index]],datap[heap[newindex]])<=0) ; /* break */ else { temp=heap[newindex]; heap[newindex]=heap[index]; heap[index]=temp; } } } while(ndata>0); /* Tidy up */ tidy_and_exit: if(fds) { for(i=0;i<nfiles;i++) CloseFileBuffered(fds[i]); free(fds); } if(heap) free(heap); for(i=0;i<option_filesort_threads;i++) { free(threads[i].data); free(threads[i].filename); } free(threads); return(count_out); }