slist.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
  9. *
  10. * This software is licensed as described in the file COPYING, which
  11. * you should have received as part of this distribution. The terms
  12. * are also available at https://curl.se/docs/copyright.html.
  13. *
  14. * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  15. * copies of the Software, and permit persons to whom the Software is
  16. * furnished to do so, under the terms of the COPYING file.
  17. *
  18. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  19. * KIND, either express or implied.
  20. *
  21. * SPDX-License-Identifier: curl
  22. *
  23. ***************************************************************************/
  24. #include "curl_setup.h"
  25. #include <curl/curl.h>
  26. #include "slist.h"
  27. /* The last #include files should be: */
  28. #include "curl_memory.h"
  29. #include "memdebug.h"
  30. /* returns last node in linked list */
  31. static struct curl_slist *slist_get_last(struct curl_slist *list)
  32. {
  33. struct curl_slist *item;
  34. /* if caller passed us a NULL, return now */
  35. if(!list)
  36. return NULL;
  37. /* loop through to find the last item */
  38. item = list;
  39. while(item->next) {
  40. item = item->next;
  41. }
  42. return item;
  43. }
  44. /*
  45. * Curl_slist_append_nodup() appends a string to the linked list. Rather than
  46. * copying the string in dynamic storage, it takes its ownership. The string
  47. * should have been malloc()ated. Curl_slist_append_nodup always returns
  48. * the address of the first record, so that you can use this function as an
  49. * initialization function as well as an append function.
  50. * If an error occurs, NULL is returned and the string argument is NOT
  51. * released.
  52. */
  53. struct curl_slist *Curl_slist_append_nodup(struct curl_slist *list, char *data)
  54. {
  55. struct curl_slist *last;
  56. struct curl_slist *new_item;
  57. DEBUGASSERT(data);
  58. new_item = malloc(sizeof(struct curl_slist));
  59. if(!new_item)
  60. return NULL;
  61. new_item->next = NULL;
  62. new_item->data = data;
  63. /* if this is the first item, then new_item *is* the list */
  64. if(!list)
  65. return new_item;
  66. last = slist_get_last(list);
  67. last->next = new_item;
  68. return list;
  69. }
  70. /*
  71. * curl_slist_append() appends a string to the linked list. It always returns
  72. * the address of the first record, so that you can use this function as an
  73. * initialization function as well as an append function. If you find this
  74. * bothersome, then simply create a separate _init function and call it
  75. * appropriately from within the program.
  76. */
  77. struct curl_slist *curl_slist_append(struct curl_slist *list,
  78. const char *data)
  79. {
  80. char *dupdata = strdup(data);
  81. if(!dupdata)
  82. return NULL;
  83. list = Curl_slist_append_nodup(list, dupdata);
  84. if(!list)
  85. free(dupdata);
  86. return list;
  87. }
  88. /*
  89. * Curl_slist_duplicate() duplicates a linked list. It always returns the
  90. * address of the first record of the cloned list or NULL in case of an
  91. * error (or if the input list was NULL).
  92. */
  93. struct curl_slist *Curl_slist_duplicate(struct curl_slist *inlist)
  94. {
  95. struct curl_slist *outlist = NULL;
  96. struct curl_slist *tmp;
  97. while(inlist) {
  98. tmp = curl_slist_append(outlist, inlist->data);
  99. if(!tmp) {
  100. curl_slist_free_all(outlist);
  101. return NULL;
  102. }
  103. outlist = tmp;
  104. inlist = inlist->next;
  105. }
  106. return outlist;
  107. }
  108. /* be nice and clean up resources */
  109. void curl_slist_free_all(struct curl_slist *list)
  110. {
  111. struct curl_slist *next;
  112. struct curl_slist *item;
  113. if(!list)
  114. return;
  115. item = list;
  116. do {
  117. next = item->next;
  118. Curl_safefree(item->data);
  119. free(item);
  120. item = next;
  121. } while(next);
  122. }