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;
|
|
}
|