You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							195 lines
						
					
					
						
							5.4 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							195 lines
						
					
					
						
							5.4 KiB
						
					
					
				| /** | |
|   @file  | |
|  | |
|   @ingroup cstringstream | |
|  | |
|   @brief Simple string streams in C. | |
|  | |
|   @author Fabio Somenzi | |
|  | |
|   @copyright@parblock | |
|   Copyright (c) 2014-2015, Regents of the University of Colorado | |
|  | |
|   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 the University of Colorado 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 OWNER 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. | |
|   @endparblock | |
|  | |
| */ | |
| 
 | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include "cstringstream.h" | |
|  | |
| /** | |
|  * @brief Type of a simple extensible string buffer. | |
|  */ | |
| struct _cstringstream { | |
|   size_t capacity; /**< elements allocated */ | |
|   size_t inUse;    /**< elements currently in use */ | |
|   char * data;     /**< actual data */ | |
| }; | |
| 
 | |
| cstringstream newStringStream(void) { | |
|   cstringstream ss; | |
|   ss = (cstringstream) malloc(sizeof(struct _cstringstream)); | |
|   if (!ss) return NULL; | |
|   ss->capacity = 1; /* parsimonious */ | |
|   ss->inUse = 0; | |
|   ss->data = (char *) malloc(sizeof(char) * ss->capacity); | |
|   if (!ss->data) { | |
|     free(ss); | |
|     return NULL; | |
|   } | |
|   return ss; | |
| } | |
| 
 | |
| void deleteStringStream(cstringstream ss) { | |
|   if (ss) { | |
|     free(ss->data); | |
|     free(ss); | |
|   } | |
| } | |
| 
 | |
| int clearStringStream(cstringstream ss) { | |
|   if (!ss) return -1; | |
|   ss->inUse = 0; | |
|   return 0; | |
| } | |
| 
 | |
| cstringstream copyStringStream(const_cstringstream src) { | |
|   cstringstream dest; | |
|   if (!src) return 0; | |
|   dest = newStringStream(); | |
|   if (!dest) return 0; | |
|   if (resizeStringStream(dest, src->inUse)) { | |
|     deleteStringStream(dest); | |
|     return 0; | |
|   } | |
|   strncpy(dest->data, src->data, src->inUse); | |
|   return dest; | |
| } | |
| 
 | |
| int resizeStringStream(cstringstream ss, size_t newSize) { | |
|   if (newSize > ss->capacity) { | |
|     /* To avoid too many calls to realloc, we choose the larger of | |
|      * twice the current size and the new requested size. */ | |
|     size_t newCapacity = 2 * ss->capacity; | |
|     if (newCapacity < newSize) | |
|       newCapacity = newSize; | |
|     char * tmp = (char *) realloc(ss->data, newCapacity * sizeof(char)); | |
|     /* If the allocation fails, leave the array alone. */ | |
|     if (!tmp) return -1; | |
|     ss->data = tmp; | |
|     ss->capacity = newCapacity; | |
|   } | |
|   /* Here we are guaranteed that newSize <= ss->capacity. */ | |
|   ss->inUse = newSize; | |
|   return 0; | |
| } | |
| 
 | |
| int sizeStringStream(const_cstringstream ss, size_t * num) { | |
|   if (!ss || !num) return -1; | |
|   *num = ss->inUse; | |
|   return 0; | |
| } | |
| 
 | |
| int getStringStream(const_cstringstream ss, size_t index, char * c) { | |
|   if (!ss || !c || index >= ss->inUse) return -1; | |
|   *c = ss->data[index]; | |
|   return 0; | |
| } | |
| 
 | |
| int appendCharStringStream(cstringstream ss, char c) { | |
|   if (!ss) return -1; | |
|   if (resizeStringStream(ss, ss->inUse + 1)) return -1; | |
|   /* Now we have space. */ | |
|   ss->data[ss->inUse-1] = c; | |
|   return 0; | |
| } | |
| 
 | |
| int appendStringStringStream(cstringstream ss, char const * s) { | |
|   if (!ss) return -1; | |
|   size_t len = strlen(s); | |
|   if (resizeStringStream(ss, ss->inUse + len)) return -1; | |
|   /* Now we have space. */ | |
|   strncpy(ss->data + ss->inUse - len, s, len);  | |
|   return 0; | |
| } | |
| 
 | |
| int appendIntStringStream(cstringstream ss, int d) { | |
|   char str[256]; | |
|   if (!ss) return -1; | |
|   sprintf(str, "%d", d); | |
|   return appendStringStringStream(ss, str); | |
| } | |
| 
 | |
| int appendUnsignedStringStream(cstringstream ss, unsigned u) { | |
|   char str[256]; | |
|   if (!ss) return -1; | |
|   sprintf(str, "%u", u); | |
|   return appendStringStringStream(ss, str); | |
| } | |
| 
 | |
| int appendLongStringStream(cstringstream ss, long ld) { | |
|   char str[256]; | |
|   if (!ss) return -1; | |
|   sprintf(str, "%ld", ld); | |
|   return appendStringStringStream(ss, str); | |
| } | |
| 
 | |
| int appendUnsignedLongStringStream(cstringstream ss, unsigned long lu) { | |
|   char str[256]; | |
|   if (!ss) return -1; | |
|   sprintf(str, "%lu", lu); | |
|   return appendStringStringStream(ss, str); | |
| } | |
| 
 | |
| int appendDoubleStringStream(cstringstream ss, double g) { | |
|   char str[256]; | |
|   if (!ss) return -1; | |
|   sprintf(str, "%g", g); | |
|   return appendStringStringStream(ss, str); | |
| } | |
| 
 | |
| int putStringStream(cstringstream ss, size_t index, char c) { | |
|   if (!ss || index >= ss->inUse) return -1; | |
|   ss->data[index] = c; | |
|   return 0; | |
| } | |
| 
 | |
| char * stringFromStringStream(const_cstringstream ss) { | |
|   if (!ss) return 0; | |
|   char * str = (char *) malloc(sizeof(char) * (ss->inUse + 1)); | |
|   if (!str) return 0; | |
|   strncpy(str, ss->data, ss->inUse); | |
|   str[ss->inUse] = '\0'; | |
|   return str; | |
| }
 |