summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLode <lvandeve@gmail.com>2016-04-18 21:15:36 +0200
committerLode <lvandeve@gmail.com>2016-04-18 21:15:36 +0200
commit95a4f6983a153cff048c85cc4a109f8338b602c8 (patch)
treef9daf28deac6f8235eff6347a81260bc42403dc4
parent4949c6ded8e8292715db77357d9d302f45c892b2 (diff)
replace qsort with custom sort for compatibility with some platforms
-rw-r--r--lodepng.cpp37
-rw-r--r--lodepng.h3
2 files changed, 29 insertions, 11 deletions
diff --git a/lodepng.cpp b/lodepng.cpp
index 59e3af9..08d1bfb 100644
--- a/lodepng.cpp
+++ b/lodepng.cpp
@@ -1,5 +1,5 @@
/*
-LodePNG version 20160409
+LodePNG version 20160418
Copyright (c) 2005-2016 Lode Vandevenne
@@ -39,7 +39,7 @@ Rename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for
#pragma warning( disable : 4996 ) /*VS does not like fopen, but fopen_s is not standard C so unusable here*/
#endif /*_MSC_VER */
-const char* LODEPNG_VERSION_STRING = "20160409";
+const char* LODEPNG_VERSION_STRING = "20160418";
/*
This source file is built up in the following large parts. The code sections
@@ -727,14 +727,31 @@ static BPMNode* bpmnode_create(BPMLists* lists, int weight, unsigned index, BPMN
return result;
}
-static int bpmnode_compare(const void* a, const void* b)
+/*sort the leaves with stable mergesort*/
+static void bpmnode_sort(BPMNode* leaves, size_t num)
{
- int wa = ((const BPMNode*)a)->weight;
- int wb = ((const BPMNode*)b)->weight;
- if(wa < wb) return -1;
- if(wa > wb) return 1;
- /*make the qsort a stable sort*/
- return ((const BPMNode*)a)->index < ((const BPMNode*)b)->index ? 1 : -1;
+ BPMNode* mem = (BPMNode*)malloc(sizeof(*leaves) * num);
+ size_t width, counter = 0;
+ for(width = 1; width < num; width *= 2)
+ {
+ BPMNode* a = (counter & 1) ? mem : leaves;
+ BPMNode* b = (counter & 1) ? leaves : mem;
+ size_t p;
+ for(p = 0; p < num; p += 2 * width)
+ {
+ size_t q = (p + width > num) ? num : (p + width);
+ size_t r = (p + 2 * width > num) ? num : (p + 2 * width);
+ size_t i = p, j = q, k;
+ for(k = p; k < r; k++)
+ {
+ if(i < q && (j >= r || a[i].weight <= a[j].weight)) b[k] = a[i++];
+ else b[k] = a[j++];
+ }
+ }
+ counter++;
+ }
+ if(counter & 1) memcpy(leaves, mem, sizeof(*leaves) * num);
+ free(mem);
}
/*Boundary Package Merge step, numpresent is the amount of leaves, and c is the current chain.*/
@@ -814,7 +831,7 @@ unsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequen
BPMLists lists;
BPMNode* node;
- qsort(leaves, numpresent, sizeof(BPMNode), bpmnode_compare);
+ bpmnode_sort(leaves, numpresent);
lists.listsize = maxbitlen;
lists.memsize = 2 * maxbitlen * (maxbitlen + 1);
diff --git a/lodepng.h b/lodepng.h
index 33f1051..ee08cea 100644
--- a/lodepng.h
+++ b/lodepng.h
@@ -1,5 +1,5 @@
/*
-LodePNG version 20160409
+LodePNG version 20160418
Copyright (c) 2005-2016 Lode Vandevenne
@@ -1607,6 +1607,7 @@ yyyymmdd.
Some changes aren't backwards compatible. Those are indicated with a (!)
symbol.
+*) 18 apr 2016: Changed qsort to custom stable sort (for platforms w/o qsort).
*) 09 apr 2016: Fixed colorkey usage detection, and better file loading (within
the limits of pure C90).
*) 08 dec 2015: Made load_file function return error if file can't be opened.