glib-mini.c revision aadb3b585bfe9f7ddd00d8c4276db4828665a81e
124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Copyright 2014 The Android Open Source Project
224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// This software is licensed under the terms of the GNU General Public
424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// License version 2, as published by the Free Software Foundation, and
524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// may be copied, distributed, and modified under those terms.
624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// This program is distributed in the hope that it will be useful,
824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// but WITHOUT ANY WARRANTY; without even the implied warranty of
924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10d891f9b872103235cfd2ed452c6f14a4394d9b3aDaniel Malea// GNU General Public License for more details.
11d891f9b872103235cfd2ed452c6f14a4394d9b3aDaniel Malea
1224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <glib.h>
1324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
1424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <limits.h>
1524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <stdarg.h>
1624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <stdio.h>
17b1888f24fa181489840b9acf193e224d125d0776Greg Clayton#include <stdlib.h>
1824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <string.h>
1949ce8969d3154e1560106cfe530444c09410f217Greg Clayton
2036b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton// Print a panic message then exit the program immediately.
2124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid g_panic(const char* fmt, ...){
2224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner  va_list args;
2324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner  fprintf(stderr, "MiniGLib:PANIC: ");
24b1db658333cdebca31a128be95e926d80c3c7796Greg Clayton  va_start(args, fmt);
253e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton  vfprintf(stderr, fmt, args);
2636b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton  va_end(args);
27e4b9c1fb338ee1ada72e6a3c198afb342d68c5c1Greg Clayton  exit(1);
2824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
2924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
3024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
3124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Heap allocation.
3224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
3324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid* g_malloc(size_t size) {
345a15e6927b5b3234fb3e688717297ba6b5dd6ad7Jim Ingham  if (size == 0)
355a15e6927b5b3234fb3e688717297ba6b5dd6ad7Jim Ingham    return NULL;
365a15e6927b5b3234fb3e688717297ba6b5dd6ad7Jim Ingham
375a15e6927b5b3234fb3e688717297ba6b5dd6ad7Jim Ingham  void* ptr = malloc(size);
385a15e6927b5b3234fb3e688717297ba6b5dd6ad7Jim Ingham  if (ptr == NULL)
395a15e6927b5b3234fb3e688717297ba6b5dd6ad7Jim Ingham    g_panic("Can't allocate %zu bytes!\n", size);
4024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
4124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner  return ptr;
4224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
4324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
445a15e6927b5b3234fb3e688717297ba6b5dd6ad7Jim Ingham
4594a5d0de4433dce556db59758f3d6124eb0e1a2aJim Inghamvoid* g_malloc0(size_t size) {
4624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner  void* ptr = g_malloc(size);
4724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner  if (ptr == NULL)
48c833295baeec641086f536e78050388af36784f8Jim Ingham    return NULL;
4924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
505a15e6927b5b3234fb3e688717297ba6b5dd6ad7Jim Ingham  memset(ptr, 0, size);
5124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner  return ptr;
5224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
5324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
5424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
5524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid* g_realloc(void* ptr, size_t size) {
5624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner  if (size == 0) {
5724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    g_free(ptr);
5824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return NULL;
5924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner  }
6024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner  void* new_ptr = realloc(ptr, size);
6124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner  if (new_ptr == NULL)
6224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    g_panic("Can't reallocate pointer %p to %zu bytes!\n", ptr, size);
633e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton
64ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton  return new_ptr;
653e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton}
663e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton
673e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton
683e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Claytonvoid g_free(void* ptr) {
693e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton  if (ptr)
703e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton    free(ptr);
713e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton}
72b1db658333cdebca31a128be95e926d80c3c7796Greg Clayton
73b1db658333cdebca31a128be95e926d80c3c7796Greg Clayton// Strings.
74b1db658333cdebca31a128be95e926d80c3c7796Greg Clayton
75b1db658333cdebca31a128be95e926d80c3c7796Greg Claytonchar* g_strdup(const char* str) {
76b170aee2daacc83e3d71c3e3acc9d56c89893a7bGreg Clayton  if (str == NULL)
77b170aee2daacc83e3d71c3e3acc9d56c89893a7bGreg Clayton    return NULL;
78b1db658333cdebca31a128be95e926d80c3c7796Greg Clayton
79b1db658333cdebca31a128be95e926d80c3c7796Greg Clayton  size_t len = strlen(str);
80b1db658333cdebca31a128be95e926d80c3c7796Greg Clayton  char* copy = g_malloc(len + 1);
81b1db658333cdebca31a128be95e926d80c3c7796Greg Clayton  memcpy(copy, str, len + 1);
82b1db658333cdebca31a128be95e926d80c3c7796Greg Clayton  return copy;
83b1db658333cdebca31a128be95e926d80c3c7796Greg Clayton}
84b1db658333cdebca31a128be95e926d80c3c7796Greg Clayton
8536b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton
86b170aee2daacc83e3d71c3e3acc9d56c89893a7bGreg Claytonchar* g_strndup(const char* str, size_t size) {
8736b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton  const char *end = memchr(str, 0, size);
8836b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton  char *copy;
8936b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton
9036b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton  if (end)
9136b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton    size = end - str;
9236b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton
9336b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton  copy = g_malloc(size + 1);
9436b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton  memcpy(copy, str, size);
957980d35608225dc71b3dd946d4c3aea85bc24e85Greg Clayton  copy[size] = 0;
967980d35608225dc71b3dd946d4c3aea85bc24e85Greg Clayton  return copy;
9736b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton}
9836b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton
9936b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton
10036b877d2d27f7d1890f2d13807a3addb216648e2Greg Claytonchar* g_strdup_printf(const char* fmt, ...) {
10136b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton  char* result;
10236b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton  va_list args;
10336b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton  va_start(args, fmt);
10436b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton  g_vasprintf(&result, fmt, args);
10536b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton  va_end(args);
10636b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton  return result;
10736b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton}
10836b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton
10997a19b21dacd9063bb5475812df7781777262198Greg Clayton
11036b877d2d27f7d1890f2d13807a3addb216648e2Greg Claytonchar* g_strdup_vprintf(const char* fmt, va_list args) {
11136b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton  char* result;
11297a19b21dacd9063bb5475812df7781777262198Greg Clayton  g_vasprintf(&result, fmt, args);
11336b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton  return result;
11436b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton}
11536b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton
11636b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton
11736b877d2d27f7d1890f2d13807a3addb216648e2Greg Claytonint g_vasprintf(char** str, const char* fmt, va_list args) {
11836b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton#ifdef _WIN32
11936b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton  // On Win32, vsnprintf() is broken and always returns -1 in case of truncation,
12036b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton  // so make an educated guess, and try again if that fails with a larger pool.
12136b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton  size_t capacity = 128;
12236b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton  char* buffer = g_malloc(capacity);
12336b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton  for (;;) {
12436b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton    va_list args2;
12536b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton    va_copy(args2, args);
12636b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton    int len = vsnprintf(buffer, capacity, fmt, args2);
12736b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton    if (len >= 0) {
12836b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton      *str = buffer;
12936b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton      return len;
13036b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton    }
13136b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton    va_end(args2);
13236b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton
133ee72ab615fc4f27591cc70756d0fea7a811d95a6Greg Clayton    capacity *= 2;
134ee72ab615fc4f27591cc70756d0fea7a811d95a6Greg Clayton    if (capacity > INT_MAX)
135ee72ab615fc4f27591cc70756d0fea7a811d95a6Greg Clayton      g_panic("Formatted string is too long!\n");
136ee72ab615fc4f27591cc70756d0fea7a811d95a6Greg Clayton
137ee72ab615fc4f27591cc70756d0fea7a811d95a6Greg Clayton    buffer = g_realloc(buffer, capacity);
138ee72ab615fc4f27591cc70756d0fea7a811d95a6Greg Clayton  }
139ee72ab615fc4f27591cc70756d0fea7a811d95a6Greg Clayton#else
140ee72ab615fc4f27591cc70756d0fea7a811d95a6Greg Clayton  // On other systems, vsnprintf() works properly and returns the size of the
141ee72ab615fc4f27591cc70756d0fea7a811d95a6Greg Clayton  // formatted string without truncation.
142ee72ab615fc4f27591cc70756d0fea7a811d95a6Greg Clayton  va_list args2;
14336b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton  va_copy(args2, args);
14436b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton  int len = vsnprintf(NULL, 0, fmt, args2);
14536b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton  va_end(args2);
14636b877d2d27f7d1890f2d13807a3addb216648e2Greg Clayton  if (len < 0)
147b1db658333cdebca31a128be95e926d80c3c7796Greg Clayton    g_panic("Can't format string!\n");
1483e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton
1493e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton  char* result = g_malloc(len + 1);
1503e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton  va_copy(args2, args);
1513e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton  vsnprintf(result, (size_t)len, fmt, args2);
1523e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton  va_end(args2);
153b1db658333cdebca31a128be95e926d80c3c7796Greg Clayton
154b1db658333cdebca31a128be95e926d80c3c7796Greg Clayton  *str = result;
1553e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton  return len;
156b170aee2daacc83e3d71c3e3acc9d56c89893a7bGreg Clayton#endif
157b170aee2daacc83e3d71c3e3acc9d56c89893a7bGreg Clayton}
1583e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton
1593e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton
1603e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton// Single-linked list
1613e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton
1623e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Claytonstatic GSList* _g_slist_alloc(void) {
1633e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton  return (GSList*) g_malloc(sizeof(GSList));
1643e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton}
165b1db658333cdebca31a128be95e926d80c3c7796Greg Clayton
166b1db658333cdebca31a128be95e926d80c3c7796Greg Claytonvoid g_slist_free(GSList* list) {
167b1db658333cdebca31a128be95e926d80c3c7796Greg Clayton  while (list) {
168b1db658333cdebca31a128be95e926d80c3c7796Greg Clayton    GSList* next = list->next;
169aad2b0f2e5da0ecbf22ab7fead4c06671f64c6c5Greg Clayton    g_free(list);
1703e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton    list = next;
171b170aee2daacc83e3d71c3e3acc9d56c89893a7bGreg Clayton  }
1723e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton}
1733e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton
174b170aee2daacc83e3d71c3e3acc9d56c89893a7bGreg ClaytonGSList* g_slist_last(GSList* list) {
175b170aee2daacc83e3d71c3e3acc9d56c89893a7bGreg Clayton  while (list && list->next)
176b170aee2daacc83e3d71c3e3acc9d56c89893a7bGreg Clayton    list = list->next;
177b1db658333cdebca31a128be95e926d80c3c7796Greg Clayton  return list;
1783e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton}
179ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton
180b170aee2daacc83e3d71c3e3acc9d56c89893a7bGreg ClaytonGSList* g_slist_find(GSList* list, const void* data) {
1813e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton  while (list) {
1823e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton    if (list->data == data)
1833e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton      break;
1843e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton    list = list->next;
1853e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton  }
1863e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton  return list;
1873e8c25f62f92145b6fb699b379cbfe72b1245d4aGreg Clayton}
188ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton
189ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg ClaytonGSList* g_slist_append(GSList* list, void* data) {
190ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton  GSList* new_list = _g_slist_alloc();
191ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton  new_list->data = data;
192ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton  new_list->next = NULL;
193ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton
19424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner  if (!list)
19524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return new_list;
196ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton
197ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton  GSList* last = g_slist_last(list);
198b170aee2daacc83e3d71c3e3acc9d56c89893a7bGreg Clayton  last->next = new_list;
1997508e732818c32e1cfeaaf7d1d507fe3834ce9d2Jim Ingham  return list;
200b1888f24fa181489840b9acf193e224d125d0776Greg Clayton}
201b170aee2daacc83e3d71c3e3acc9d56c89893a7bGreg Clayton
202b170aee2daacc83e3d71c3e3acc9d56c89893a7bGreg ClaytonGSList* g_slist_prepend(GSList* list, void* data) {
203b170aee2daacc83e3d71c3e3acc9d56c89893a7bGreg Clayton  GSList* new_list = _g_slist_alloc();
204b170aee2daacc83e3d71c3e3acc9d56c89893a7bGreg Clayton  new_list->data = data;
205b170aee2daacc83e3d71c3e3acc9d56c89893a7bGreg Clayton  new_list->next = list;
206b170aee2daacc83e3d71c3e3acc9d56c89893a7bGreg Clayton  return new_list;
207aad2b0f2e5da0ecbf22ab7fead4c06671f64c6c5Greg Clayton}
208b170aee2daacc83e3d71c3e3acc9d56c89893a7bGreg Clayton
209b170aee2daacc83e3d71c3e3acc9d56c89893a7bGreg ClaytonGSList* g_slist_remove(GSList* list, const void* data) {
210b170aee2daacc83e3d71c3e3acc9d56c89893a7bGreg Clayton  GSList** pnode = &list;
211b170aee2daacc83e3d71c3e3acc9d56c89893a7bGreg Clayton  for (;;) {
212b170aee2daacc83e3d71c3e3acc9d56c89893a7bGreg Clayton    GSList* node = *pnode;
213b170aee2daacc83e3d71c3e3acc9d56c89893a7bGreg Clayton    if (!node)
214b170aee2daacc83e3d71c3e3acc9d56c89893a7bGreg Clayton      break;
2157508e732818c32e1cfeaaf7d1d507fe3834ce9d2Jim Ingham    if (node->data == data) {
216b170aee2daacc83e3d71c3e3acc9d56c89893a7bGreg Clayton      *pnode = node->next;
217b170aee2daacc83e3d71c3e3acc9d56c89893a7bGreg Clayton      g_slist_free(node);
218b170aee2daacc83e3d71c3e3acc9d56c89893a7bGreg Clayton      break;
2197f206ba4fb363f9ed3fc641d24a3e0477c6bdf36Greg Clayton    }
2207f206ba4fb363f9ed3fc641d24a3e0477c6bdf36Greg Clayton    pnode = &node->next;
2217f206ba4fb363f9ed3fc641d24a3e0477c6bdf36Greg Clayton  }
2226f8d385ccfa5951709cd7efb28b20a255008ad3dJason Molenda  return list;
2236f8d385ccfa5951709cd7efb28b20a255008ad3dJason Molenda}
2246f8d385ccfa5951709cd7efb28b20a255008ad3dJason Molenda
2254349bcb8ec51f3fd447b511b2ce8292a92d3c771Michael Sartainvoid g_slist_foreach(GSList* list, GFunc func, void* user_data) {
2264349bcb8ec51f3fd447b511b2ce8292a92d3c771Michael Sartain  while (list) {
2274349bcb8ec51f3fd447b511b2ce8292a92d3c771Michael Sartain    GSList* next = list->next;
2284349bcb8ec51f3fd447b511b2ce8292a92d3c771Michael Sartain    (*func)(list->data, user_data);
2294349bcb8ec51f3fd447b511b2ce8292a92d3c771Michael Sartain    list = next;
2304349bcb8ec51f3fd447b511b2ce8292a92d3c771Michael Sartain  }
2314349bcb8ec51f3fd447b511b2ce8292a92d3c771Michael Sartain}
2324349bcb8ec51f3fd447b511b2ce8292a92d3c771Michael Sartain
2334349bcb8ec51f3fd447b511b2ce8292a92d3c771Michael Sartain//
2344349bcb8ec51f3fd447b511b2ce8292a92d3c771Michael Sartainstatic GSList* g_slist_sort_merge(GSList* l1,
2354349bcb8ec51f3fd447b511b2ce8292a92d3c771Michael Sartain                                  GSList* l2,
2366f8d385ccfa5951709cd7efb28b20a255008ad3dJason Molenda                                  GFunc compare_func,
2374349bcb8ec51f3fd447b511b2ce8292a92d3c771Michael Sartain                                  void* user_data) {
238fb4677272d725374b7ff8f20e97f67ee98fca3ffGreg Clayton  GSList* list = NULL;
239fb4677272d725374b7ff8f20e97f67ee98fca3ffGreg Clayton  GSList** tail = &list;
240fb4677272d725374b7ff8f20e97f67ee98fca3ffGreg Clayton
241e4b9c1fb338ee1ada72e6a3c198afb342d68c5c1Greg Clayton  while (l1 && l2) {
2427508e732818c32e1cfeaaf7d1d507fe3834ce9d2Jim Ingham    int cmp = ((GCompareDataFunc) compare_func)(l1->data, l2->data, user_data);
243fb4677272d725374b7ff8f20e97f67ee98fca3ffGreg Clayton    if (cmp <= 0) {
244fb4677272d725374b7ff8f20e97f67ee98fca3ffGreg Clayton      *tail = l1;
245fb4677272d725374b7ff8f20e97f67ee98fca3ffGreg Clayton      tail = &l1->next;
246ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton      l1 = l1->next;
247ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton    } else {
248ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton      *tail = l2;
249ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton      tail = &l2->next;
250ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton      l2 = l2->next;
251ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton    }
252ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton  }
253ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton  *tail = l1 ? l1 : l2;
254ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton
255ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton  return list;
256ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton}
257ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton
258edd6ade11daf4995c5dac468ed6ae6f55dfaac87Greg Claytonstatic GSList* g_slist_sort_real(GSList* list,
259edd6ade11daf4995c5dac468ed6ae6f55dfaac87Greg Clayton                                 GFunc compare_func,
260edd6ade11daf4995c5dac468ed6ae6f55dfaac87Greg Clayton                                 void* user_data) {
261ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton
262ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton  if (!list)
263ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton    return NULL;
264ed0a0fbd021e44727469d6fa20cc337c58bd04c3Greg Clayton  if (!list->next)
2657508e732818c32e1cfeaaf7d1d507fe3834ce9d2Jim Ingham    return list;
266e4b9c1fb338ee1ada72e6a3c198afb342d68c5c1Greg Clayton
2679ce953807eb814a93b449dc243de4f7bf32c3115Greg Clayton  // Split list into two halves.
2689ce953807eb814a93b449dc243de4f7bf32c3115Greg Clayton  GSList* l1 = list;
269b170aee2daacc83e3d71c3e3acc9d56c89893a7bGreg Clayton  GSList* l2 = list->next;
270b170aee2daacc83e3d71c3e3acc9d56c89893a7bGreg Clayton
2719ce953807eb814a93b449dc243de4f7bf32c3115Greg Clayton  while (l2->next && l2->next->next) {
2729ce953807eb814a93b449dc243de4f7bf32c3115Greg Clayton    l2 = l2->next->next;
2739ce953807eb814a93b449dc243de4f7bf32c3115Greg Clayton    l1 = l1->next;
27424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner  }
275e4b9c1fb338ee1ada72e6a3c198afb342d68c5c1Greg Clayton  l2 = l1->next;
27624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner  l1->next = NULL;
2777508e732818c32e1cfeaaf7d1d507fe3834ce9d2Jim Ingham
2787508e732818c32e1cfeaaf7d1d507fe3834ce9d2Jim Ingham  return g_slist_sort_merge(
279fa2f48b09bfe19cc42309744a30c90d0d03a79c7Greg Clayton      g_slist_sort_real(list, compare_func, user_data),
280fa2f48b09bfe19cc42309744a30c90d0d03a79c7Greg Clayton      g_slist_sort_real(l2, compare_func, user_data),
28197a19b21dacd9063bb5475812df7781777262198Greg Clayton      compare_func,
28297a19b21dacd9063bb5475812df7781777262198Greg Clayton      user_data);
283940b103224f3062578c7a7e6e76d8bf4a7956f2aGreg Clayton}
284fa2f48b09bfe19cc42309744a30c90d0d03a79c7Greg Clayton
285fa2f48b09bfe19cc42309744a30c90d0d03a79c7Greg ClaytonGSList* g_slist_sort(GSList* list, GCompareFunc compare_func) {
286fa2f48b09bfe19cc42309744a30c90d0d03a79c7Greg Clayton  return g_slist_sort_real(list, (GFunc) compare_func, NULL);
28797a19b21dacd9063bb5475812df7781777262198Greg Clayton}
28897a19b21dacd9063bb5475812df7781777262198Greg Clayton