aboutsummaryrefslogtreecommitdiff
path: root/src/SString.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/SString.c')
-rw-r--r--src/SString.c196
1 files changed, 178 insertions, 18 deletions
diff --git a/src/SString.c b/src/SString.c
index 63aa8c5..b0b1477 100644
--- a/src/SString.c
+++ b/src/SString.c
@@ -24,10 +24,13 @@ typedef enum { MAKE_NULL_ALLOC, NEW_NULL_ALLOC, BUFFER_NULL_ALLOC }
SSTRING_ERROR;
static void String_HandleSeriousError( SSTRING_ERROR );
+#define LINE_END_BUFSIZE 3
+
typedef struct String_tag
{
size_t length;
SSCHAR *chars;
+ SSCHAR line_end[LINE_END_BUFSIZE];
} String_placeholder;
static SSCHAR kLineEndChar = '\n';
@@ -45,6 +48,14 @@ StringGetBuffer( const String * s )
{
return s->chars;
}
+
+void
+StringCopyBuffer( const String * s, SSCHAR * buf, size_t bufSize )
+{
+ strncpy( buf, s->chars, bufSize );
+ buf[bufSize-1] = '\0';
+}
+
/*
* Returns 0 if index is not in the string
*/
@@ -83,6 +94,7 @@ String_Make( const SSCHAR * c_string )
}
else
BufferForThisManyChars( s, 0 );
+ s->line_end[0] = kLineEndChar;
}
else
String_HandleSeriousError( MAKE_NULL_ALLOC );
@@ -95,7 +107,11 @@ String_Make( const SSCHAR * c_string )
String *
String_Copy( const String * other )
{
- return StringSetToCString( String_New(), StringGetBuffer( other ) );
+ String *s = StringSetToCString( String_New(),
+ StringGetBuffer( other ) );
+ memcpy( s->line_end, other->line_end, LINE_END_BUFSIZE
+ * sizeof( SSCHAR ) );
+ return s;
}
void
@@ -118,6 +134,23 @@ StringTruncate( String * s, size_t n )
}
String *
+StringTrimLeading( String * s, size_t n )
+{
+ const size_t orig_len = StringLength( s );
+
+ if( orig_len > 0 && n > 0 )
+ {
+ const size_t position = MIN( orig_len, n ) - 1;
+ const size_t new_len = orig_len - position;
+
+ memmove( 0, s->chars + position, new_len );
+ s->chars[new_len] = '\0';
+ s->length = new_len;
+ }
+ return s;
+}
+
+String *
StringSetNthChar( String * s, size_t n, SSCHAR c )
{
if( n < s->length )
@@ -168,6 +201,31 @@ StringSetToCString( String * s, const SSCHAR *c_string )
return StringSetToBuffer( s, c_string, strlen( c_string ) );
}
+size_t
+StringSetNextToken( const String *s, String *token,
+ const SSCHAR *delim, size_t start )
+{
+ if( start < s->length )
+ {
+ const size_t ndelims = strlen( delim );
+ size_t next = s->length;
+ size_t d;
+
+ for( d = 0; d < ndelims; d++ )
+ {
+ size_t nextDelim = start;
+ if( StringFindCharFrom( s, delim[d], &nextDelim ) )
+ next = MIN( nextDelim, next );
+ }
+
+ StringSetRange( token, s, start, next - start );
+
+ return next < s->length ? next + 1 : next;
+ }
+ else
+ return 0;
+}
+
String *
StringConcatCString( String * s, const SSCHAR *c_string )
{
@@ -183,13 +241,11 @@ String *
StringSetToBuffer( String * s, const SSCHAR *buf, size_t len )
{
if( s != NULL && buf != NULL )
- {
if( BufferForThisManyChars( s, len ) )
{
strncpy( s->chars, buf, len );
s->chars[ len ] = '\0';
}
- }
return s;
}
@@ -198,17 +254,31 @@ StringSet( String * s, const String * other )
{
return StringSetToCString( s, StringGetBuffer( other ) );
}
-
+/*
+ * Take care! What if this String's buffer is the same as the other's?
+ * For now, this can happen only if the other String is the same as this
+ * String.
+ *
+ * This needs thought for every String that takes a String argument,
+ * and for the ones that take C strings as well.
+ */
String *
-StringSetSubString( String * s, const String * other,
- size_t first, size_t last )
+StringSetRange( String * s, const String * other,
+ size_t first, size_t length )
{
const size_t other_length = other->length;
- const size_t veryFirst = MIN( MIN( first, last ), other_length ),
- veryLast = MIN( MAX( first, last ), other_length ),
- length = ( veryLast + 1 ) - veryFirst;
+ const size_t veryFirst = MIN( first + 1, other_length ) - 1,
+ minLength = MIN( first + length, other_length ),
+ newLength = minLength - veryFirst;
- return StringSetToBuffer( s, other->chars + veryFirst, length );
+ return StringSetToBuffer( s, other->chars + veryFirst, newLength );
+}
+
+String *
+StringSetToPartAfter( String * s, const String * other, size_t position )
+{
+ return StringSetRange( s, other,
+ position + 1, StringLength( other ) - position );
}
/*
@@ -217,7 +287,7 @@ StringSetSubString( String * s, const String * other,
* On output, is position where char was found.
*/
SSBOOL
-StringFindChar( const String *s, SSCHAR theChar, size_t * position )
+StringFindCharFrom( const String *s, SSCHAR theChar, size_t * position )
{
SSCHAR * charPtr;
@@ -234,7 +304,7 @@ StringFindChar( const String *s, SSCHAR theChar, size_t * position )
}
SSBOOL
-StringFindSubString( const String * s, const String * other,
+StringFindStringFrom( const String * s, const String * other,
size_t * position )
{
SSCHAR * charPtr;
@@ -362,9 +432,10 @@ StringConcat( String * s, const String * other )
* On unix the default \n works; on the Mac, you might want \r
*/
void
-String_SetLineEndCharacter( SSCHAR c )
+String_SetLineEndCharacter( String * s, const SSCHAR *end )
{
- kLineEndChar = c;
+ strncpy( s->line_end, end, LINE_END_BUFSIZE );
+ s->line_end[LINE_END_BUFSIZE - 1] = '\0';
}
String *
@@ -425,12 +496,101 @@ StringConcatDouble( String * s, double d )
snprintf( buf, sizeof( buf ), "%f", d );
return StringConcatCString( s, buf );
}
+/*a
+ *
+ * 0) It's inappropritate to handle string and character convesions.
+ * And there are some very specific-use conversions, such as 't'
+ *
+ * 1) I'm not sure I completely understand all the conversions.
+ * specifically, I don't get G and g.
+ *
+ * 2) There are several standards, including C99 and SUSv2
+ *
+ * 3) I haven't done long long or long double
+ *
+ * 4) Mixed up notions of unsigned with hex and octal...wrong?
+ *
+ *
+ *
+ */
+static void
+addNumericMods( char * format, SSFORMAT f )
+{
+ strcat( format, "%" );
+ if( f & SFMT_LEFT_ALIGN )
+ strcat( format, "-" );
+ if( f & SFMT_PRINT_SIGN )
+ strcat( format, "+" );
+ if( f & SFMT_ADD_SIGN_SPACE )
+ strcat( format, " " );
+ if( f & SFMT_PAD_ZERO )
+ strcat( format, "0" );
+ if( f & SFMT_ALT )
+ strcat( format, "#" );
+}
+#define EMPTYSTRING { '\0' }
+String *
+StringConcatFormattedDecimal( String *s, long int d,
+ int width, int precision, SSINT_FORMAT f )
+{
+ char buf[DECIMALBUFSIZE] = EMPTYSTRING;
+ char format[16] = EMPTYSTRING;
+ addNumericMods( format, f );
+ strcat( format, "*.*ld" );
+ snprintf( buf, sizeof( buf ), format, width, precision, d );
+ return StringConcatCString( s, buf );
+}
String *
-StringConcatFormattedDouble( String * s, int ndigits, int ndec, double d )
-{
- char buf[DECIMALBUFSIZE] = { '\0' };
- snprintf( buf, sizeof( buf ), "%*.*f", ndigits, ndec, d );
+StringConcatFormattedUnsigned( String *s, unsigned long int n,
+ int width, int precision, SSINT_FORMAT f )
+{
+ char buf[DECIMALBUFSIZE] = EMPTYSTRING;
+ char format[16] = EMPTYSTRING;
+ addNumericMods( format, f );
+ strcat( format, "*.*l" );
+ if( f & SFMT_HEX )
+ {
+ if( f & SFMT_LOWERCASE )
+ strcat( format, "x" );
+ else
+ strcat( format, "X" );
+ }
+ else if( f & SFMT_OCTAL )
+ strcat( format, "o" );
+ else
+ strcat( format, "u" );
+ snprintf( buf, sizeof( buf ), format, width, precision, n );
+ return StringConcatCString( s, buf );
+}
+
+String *
+StringConcatFormattedDouble( String *s, double d,
+ int width, int precision, SSDOUBLE_FORMAT f )
+{
+ char buf[DECIMALBUFSIZE] = EMPTYSTRING;
+ char format[16] = EMPTYSTRING;
+ addNumericMods( format, f );
+ if( f & SFMT_ALWAYS_POINT )
+ strcat( format, "#" );
+ strcat( format, "*.*" );
+ if( f & SFMT_EXPONENTIAL )
+ {
+ if( f & SFMT_LOWERCASE )
+ strcat( format, "e" );
+ else
+ strcat( format, "E" );
+ }
+ if( f & SFMT_DISCRETIONARY_EXP )
+ {
+ if( f & SFMT_LOWERCASE )
+ strcat( format, "g" );
+ else
+ strcat( format, "G" );
+ }
+ else
+ strcat( format, "f" );
+ snprintf( buf, sizeof( buf ), format, width, precision, d );
return StringConcatCString( s, buf );
}