| 
									
										
										
										
											2022-04-05 19:47:10 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * SPDX-FileCopyrightText: 2013-2019 Tom G. Huang | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * SPDX-License-Identifier: BSD-3-Clause | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2022-04-05 19:46:48 +02:00
										 |  |  | /*******************************************************************************
 | 
					
						
							|  |  |  |  * arg_dstr: Implements the dynamic string utilities | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This file is part of the argtable3 library. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (C) 2013-2019 Tom G. Huang | 
					
						
							|  |  |  |  * <tomghuang@gmail.com> | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Redistribution and use in source and binary forms, with or without | 
					
						
							|  |  |  |  * modification, are permitted provided that the following conditions are met: | 
					
						
							|  |  |  |  *     * Redistributions of source code must retain the above copyright | 
					
						
							|  |  |  |  *       notice, this list of conditions and the following disclaimer. | 
					
						
							|  |  |  |  *     * Redistributions in binary form must reproduce the above copyright | 
					
						
							|  |  |  |  *       notice, this list of conditions and the following disclaimer in the | 
					
						
							|  |  |  |  *       documentation and/or other materials provided with the distribution. | 
					
						
							|  |  |  |  *     * Neither the name of STEWART HEITMANN nor the  names of its contributors | 
					
						
							|  |  |  |  *       may be used to endorse or promote products derived from this software | 
					
						
							|  |  |  |  *       without specific prior written permission. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | 
					
						
							|  |  |  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
					
						
							|  |  |  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 
					
						
							|  |  |  |  * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, | 
					
						
							|  |  |  |  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 
					
						
							|  |  |  |  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 
					
						
							|  |  |  |  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | 
					
						
							|  |  |  |  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
					
						
							|  |  |  |  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 
					
						
							|  |  |  |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
					
						
							|  |  |  |  ******************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "argtable3.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef ARG_AMALGAMATION
 | 
					
						
							|  |  |  | #include "argtable3_private.h"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <stdarg.h>
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(_MSC_VER)
 | 
					
						
							|  |  |  | #pragma warning(push)
 | 
					
						
							|  |  |  | #pragma warning(disable : 4996)
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define START_VSNBUFF 16
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * This dynamic string module is adapted from TclResult.c in the Tcl library. | 
					
						
							|  |  |  |  * Here is the copyright notice from the library: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This software is copyrighted by the Regents of the University of | 
					
						
							|  |  |  |  * California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState | 
					
						
							|  |  |  |  * Corporation and other parties.  The following terms apply to all files | 
					
						
							|  |  |  |  * associated with the software unless explicitly disclaimed in | 
					
						
							|  |  |  |  * individual files. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The authors hereby grant permission to use, copy, modify, distribute, | 
					
						
							|  |  |  |  * and license this software and its documentation for any purpose, provided | 
					
						
							|  |  |  |  * that existing copyright notices are retained in all copies and that this | 
					
						
							|  |  |  |  * notice is included verbatim in any distributions. No written agreement, | 
					
						
							|  |  |  |  * license, or royalty fee is required for any of the authorized uses. | 
					
						
							|  |  |  |  * Modifications to this software may be copyrighted by their authors | 
					
						
							|  |  |  |  * and need not follow the licensing terms described here, provided that | 
					
						
							|  |  |  |  * the new terms are clearly indicated on the first page of each file where | 
					
						
							|  |  |  |  * they apply. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY | 
					
						
							|  |  |  |  * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES | 
					
						
							|  |  |  |  * ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY | 
					
						
							|  |  |  |  * DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE | 
					
						
							|  |  |  |  * POSSIBILITY OF SUCH DAMAGE. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, | 
					
						
							|  |  |  |  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, | 
					
						
							|  |  |  |  * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE | 
					
						
							|  |  |  |  * IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE | 
					
						
							|  |  |  |  * NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR | 
					
						
							|  |  |  |  * MODIFICATIONS. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * GOVERNMENT USE: If you are acquiring this software on behalf of the | 
					
						
							|  |  |  |  * U.S. government, the Government shall have only "Restricted Rights" | 
					
						
							|  |  |  |  * in the software and related documentation as defined in the Federal | 
					
						
							|  |  |  |  * Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2).  If you | 
					
						
							|  |  |  |  * are acquiring the software on behalf of the Department of Defense, the | 
					
						
							|  |  |  |  * software shall be classified as "Commercial Computer Software" and the | 
					
						
							|  |  |  |  * Government shall have only "Restricted Rights" as defined in Clause | 
					
						
							|  |  |  |  * 252.227-7014 (b) (3) of DFARs.  Notwithstanding the foregoing, the | 
					
						
							|  |  |  |  * authors grant the U.S. Government and others acting in its behalf | 
					
						
							|  |  |  |  * permission to use and distribute the software in accordance with the | 
					
						
							|  |  |  |  * terms specified in this license. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct _internal_arg_dstr { | 
					
						
							|  |  |  |     char* data; | 
					
						
							|  |  |  |     arg_dstr_freefn* free_proc; | 
					
						
							|  |  |  |     char sbuf[ARG_DSTR_SIZE + 1]; | 
					
						
							|  |  |  |     char* append_data; | 
					
						
							|  |  |  |     int append_data_size; | 
					
						
							|  |  |  |     int append_used; | 
					
						
							|  |  |  | } _internal_arg_dstr_t; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void setup_append_buf(arg_dstr_t res, int newSpace); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | arg_dstr_t arg_dstr_create(void) { | 
					
						
							|  |  |  |     _internal_arg_dstr_t* h = (_internal_arg_dstr_t*)xmalloc(sizeof(_internal_arg_dstr_t)); | 
					
						
							|  |  |  |     memset(h, 0, sizeof(_internal_arg_dstr_t)); | 
					
						
							|  |  |  |     h->sbuf[0] = 0; | 
					
						
							|  |  |  |     h->data = h->sbuf; | 
					
						
							|  |  |  |     h->free_proc = ARG_DSTR_STATIC; | 
					
						
							|  |  |  |     return h; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void arg_dstr_destroy(arg_dstr_t ds) { | 
					
						
							|  |  |  |     if (ds == NULL) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     arg_dstr_reset(ds); | 
					
						
							|  |  |  |     xfree(ds); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void arg_dstr_set(arg_dstr_t ds, char* str, arg_dstr_freefn* free_proc) { | 
					
						
							|  |  |  |     int length; | 
					
						
							|  |  |  |     register arg_dstr_freefn* old_free_proc = ds->free_proc; | 
					
						
							|  |  |  |     char* old_result = ds->data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (str == NULL) { | 
					
						
							|  |  |  |         ds->sbuf[0] = 0; | 
					
						
							|  |  |  |         ds->data = ds->sbuf; | 
					
						
							|  |  |  |         ds->free_proc = ARG_DSTR_STATIC; | 
					
						
							|  |  |  |     } else if (free_proc == ARG_DSTR_VOLATILE) { | 
					
						
							|  |  |  |         length = (int)strlen(str); | 
					
						
							|  |  |  |         if (length > ARG_DSTR_SIZE) { | 
					
						
							|  |  |  |             ds->data = (char*)xmalloc((unsigned)length + 1); | 
					
						
							|  |  |  |             ds->free_proc = ARG_DSTR_DYNAMIC; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             ds->data = ds->sbuf; | 
					
						
							|  |  |  |             ds->free_proc = ARG_DSTR_STATIC; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         strcpy(ds->data, str); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         ds->data = str; | 
					
						
							|  |  |  |         ds->free_proc = free_proc; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * If the old result was dynamically-allocated, free it up. Do it here, | 
					
						
							|  |  |  |      * rather than at the beginning, in case the new result value was part of | 
					
						
							|  |  |  |      * the old result value. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((old_free_proc != 0) && (old_result != ds->data)) { | 
					
						
							|  |  |  |         if (old_free_proc == ARG_DSTR_DYNAMIC) { | 
					
						
							|  |  |  |             xfree(old_result); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             (*old_free_proc)(old_result); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((ds->append_data != NULL) && (ds->append_data_size > 0)) { | 
					
						
							|  |  |  |         xfree(ds->append_data); | 
					
						
							|  |  |  |         ds->append_data = NULL; | 
					
						
							|  |  |  |         ds->append_data_size = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | char* arg_dstr_cstr(arg_dstr_t ds) /* Interpreter whose result to return. */ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return ds->data; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void arg_dstr_cat(arg_dstr_t ds, const char* str) { | 
					
						
							|  |  |  |     setup_append_buf(ds, (int)strlen(str) + 1); | 
					
						
							|  |  |  |     memcpy(ds->data + strlen(ds->data), str, strlen(str)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void arg_dstr_catc(arg_dstr_t ds, char c) { | 
					
						
							|  |  |  |     setup_append_buf(ds, 2); | 
					
						
							|  |  |  |     memcpy(ds->data + strlen(ds->data), &c, 1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * The logic of the `arg_dstr_catf` function is adapted from the `bformat` | 
					
						
							|  |  |  |  * function in The Better String Library by Paul Hsieh. Here is the copyright | 
					
						
							|  |  |  |  * notice from the library: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (c) 2014, Paul Hsieh | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Redistribution and use in source and binary forms, with or without | 
					
						
							|  |  |  |  * modification, are permitted provided that the following conditions are met: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * * Redistributions of source code must retain the above copyright notice, this | 
					
						
							|  |  |  |  *   list of conditions and the following disclaimer. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * * Redistributions in binary form must reproduce the above copyright notice, | 
					
						
							|  |  |  |  *   this list of conditions and the following disclaimer in the documentation | 
					
						
							|  |  |  |  *   and/or other materials provided with the distribution. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * * Neither the name of bstrlib nor the names of its | 
					
						
							|  |  |  |  *   contributors may be used to endorse or promote products derived from | 
					
						
							|  |  |  |  *   this software without specific prior written permission. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | 
					
						
							|  |  |  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
					
						
							|  |  |  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 
					
						
							|  |  |  |  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | 
					
						
							|  |  |  |  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
					
						
							|  |  |  |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | 
					
						
							|  |  |  |  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | 
					
						
							|  |  |  |  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | 
					
						
							|  |  |  |  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
					
						
							|  |  |  |  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void arg_dstr_catf(arg_dstr_t ds, const char* fmt, ...) { | 
					
						
							|  |  |  |     va_list arglist; | 
					
						
							|  |  |  |     char* buff; | 
					
						
							|  |  |  |     int n, r; | 
					
						
							|  |  |  |     size_t slen; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (fmt == NULL) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Since the length is not determinable beforehand, a search is
 | 
					
						
							|  |  |  |        performed using the truncating "vsnprintf" call (to avoid buffer | 
					
						
							|  |  |  |        overflows) on increasing potential sizes for the output result. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((n = (int)(2 * strlen(fmt))) < START_VSNBUFF) | 
					
						
							|  |  |  |         n = START_VSNBUFF; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     buff = (char*)xmalloc((size_t)(n + 2)); | 
					
						
							|  |  |  |     memset(buff, 0, (size_t)(n + 2)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (;;) { | 
					
						
							|  |  |  |         va_start(arglist, fmt); | 
					
						
							|  |  |  |         r = vsnprintf(buff, (size_t)(n + 1), fmt, arglist); | 
					
						
							|  |  |  |         va_end(arglist); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         slen = strlen(buff); | 
					
						
							|  |  |  |         if (slen < (size_t)n) | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (r > n) | 
					
						
							|  |  |  |             n = r; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             n += n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         xfree(buff); | 
					
						
							|  |  |  |         buff = (char*)xmalloc((size_t)(n + 2)); | 
					
						
							|  |  |  |         memset(buff, 0, (size_t)(n + 2)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     arg_dstr_cat(ds, buff); | 
					
						
							|  |  |  |     xfree(buff); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void setup_append_buf(arg_dstr_t ds, int new_space) { | 
					
						
							|  |  |  |     int total_space; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * Make the append buffer larger, if that's necessary, then copy the | 
					
						
							|  |  |  |      * data into the append buffer and make the append buffer the official | 
					
						
							|  |  |  |      * data. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     if (ds->data != ds->append_data) { | 
					
						
							|  |  |  |         /*
 | 
					
						
							|  |  |  |          * If the buffer is too big, then free it up so we go back to a | 
					
						
							|  |  |  |          * smaller buffer. This avoids tying up memory forever after a large | 
					
						
							|  |  |  |          * operation. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         if (ds->append_data_size > 500) { | 
					
						
							|  |  |  |             xfree(ds->append_data); | 
					
						
							|  |  |  |             ds->append_data = NULL; | 
					
						
							|  |  |  |             ds->append_data_size = 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         ds->append_used = (int)strlen(ds->data); | 
					
						
							|  |  |  |     } else if (ds->data[ds->append_used] != 0) { | 
					
						
							|  |  |  |         /*
 | 
					
						
							|  |  |  |          * Most likely someone has modified a result created by | 
					
						
							|  |  |  |          * arg_dstr_cat et al. so that it has a different size. Just | 
					
						
							|  |  |  |          * recompute the size. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         ds->append_used = (int)strlen(ds->data); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     total_space = new_space + ds->append_used; | 
					
						
							|  |  |  |     if (total_space >= ds->append_data_size) { | 
					
						
							|  |  |  |         char* newbuf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (total_space < 100) { | 
					
						
							|  |  |  |             total_space = 200; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             total_space *= 2; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         newbuf = (char*)xmalloc((unsigned)total_space); | 
					
						
							|  |  |  |         memset(newbuf, 0, (size_t)total_space); | 
					
						
							|  |  |  |         strcpy(newbuf, ds->data); | 
					
						
							|  |  |  |         if (ds->append_data != NULL) { | 
					
						
							|  |  |  |             xfree(ds->append_data); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         ds->append_data = newbuf; | 
					
						
							|  |  |  |         ds->append_data_size = total_space; | 
					
						
							|  |  |  |     } else if (ds->data != ds->append_data) { | 
					
						
							|  |  |  |         strcpy(ds->append_data, ds->data); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     arg_dstr_free(ds); | 
					
						
							|  |  |  |     ds->data = ds->append_data; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void arg_dstr_free(arg_dstr_t ds) { | 
					
						
							|  |  |  |     if (ds->free_proc != NULL) { | 
					
						
							|  |  |  |         if (ds->free_proc == ARG_DSTR_DYNAMIC) { | 
					
						
							|  |  |  |             xfree(ds->data); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             (*ds->free_proc)(ds->data); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         ds->free_proc = NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void arg_dstr_reset(arg_dstr_t ds) { | 
					
						
							|  |  |  |     arg_dstr_free(ds); | 
					
						
							|  |  |  |     if ((ds->append_data != NULL) && (ds->append_data_size > 0)) { | 
					
						
							|  |  |  |         xfree(ds->append_data); | 
					
						
							|  |  |  |         ds->append_data = NULL; | 
					
						
							|  |  |  |         ds->append_data_size = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ds->data = ds->sbuf; | 
					
						
							|  |  |  |     ds->sbuf[0] = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(_MSC_VER)
 | 
					
						
							|  |  |  | #pragma warning(pop)
 | 
					
						
							|  |  |  | #endif
 |