📄 sfltok.c
字号:
/* ----------------------------------------------------------------<Prolog>-
Name: sflenv.c
Title: String token manipulation functions.
Package: Standard Function Library (SFL)
Written: 1996/09/10 iMatix SFL project team <sfl@imatix.com>
Revised: 2000/01/11
Copyright: Copyright (c) 1996-2000 iMatix Corporation
License: This is free software; you can redistribute it and/or modify
it under the terms of the SFL License Agreement as provided
in the file LICENSE.TXT. This software is distributed in
the hope that it will be useful, but without any warranty.
------------------------------------------------------------------</Prolog>-*/
#include "prelude.h" /* Universal header file */
#include "sflstr.h" /* Conversion functions */
#include "sfllist.h" /* Linked-list functions */
#include "sflmem.h" /* Memory allocation functions */
#include "sflsymb.h" /* Symbol table functions */
#include "sfltok.h" /* Prototypes for functions */
/* ---------------------------------------------------------------------[<]-
Function: tok_split
Synopsis: Accepts a string and breaks it into words, delimited by white
space (spaces, tabs, newlines). Returns an array of strings which ends
in a NULL string. If the string is empty or NULL, returns an array
containing a single NULL value. The array is allocated dynamically by
this function, and you must call tok_free() to release it when you have
finished. Returns NULL if there was insufficient memory to complete the
split operation.
---------------------------------------------------------------------[>]-*/
char **
tok_split (
const char *string)
{
char
*buffer,
*bufptr,
**token_list, /* Returned token list */
last_char = '\0'; /* Last character parsed */
int
word_count = 0, /* Number of words in string */
word_nbr;
/* Allocate space for work string, up to the size of the input string */
if (string == NULL)
string = "";
buffer = mem_alloc (strlen (string) + 1);
if (buffer == NULL)
return (NULL);
/* Now copy string and eliminate whitespace */
bufptr = buffer; /* Move to start of target buffer */
while (*string) /* Copy entire string */
if (isspace (*string)) /* Collapse whitespace to */
{ /* a single null byte */
while (isspace (*string))
string++;
if (bufptr > buffer)
{
word_count++; /* We have a new word */
last_char = *bufptr++ = '\0';
}
}
else
last_char = *bufptr++ = *string++;
/* Count last word if it was not terminated in a white space */
if (last_char > 0)
word_count++;
*bufptr = '\0'; /* End with final NULL */
/* The token list starts with a pointer to the buffer, then has one */
/* pointer to each string in the buffer. It ends with a null pointer. */
/* We return the address of the first string pointer, i.e. the caller */
/* does not see the pointer to the buffer. We can thus get away with */
/* just two allocs; one for the buffer and one for the token list. */
token_list = mem_alloc (sizeof (char *) * (word_count + 2));
if (token_list == NULL)
return (NULL);
token_list [0] = buffer; /* Store buffer address */
token_list++; /* and bump starting address */
bufptr = buffer;
for (word_nbr = 0; word_nbr < word_count; word_nbr++)
{
token_list [word_nbr] = bufptr;
bufptr += strlen (bufptr) + 1;
}
token_list [word_count] = NULL; /* Store final null pointer */
return (token_list);
}
/* ---------------------------------------------------------------------[<]-
Function: tok_split_rich
Synopsis: Works as the tok_split() function, but handles tokens that are
delimited by user-specified characters. A typical use of this function
is to handle quoted strings. Each character in the delims argument is a
potential token delimiter. For instance, to handle strings defined with
single or double quotes, you could pass "\"'" as the delims argument.
Note that this function always splits on spaces outside delimited tokens.
---------------------------------------------------------------------[>]-*/
char **
tok_split_rich (
const char *string,
const char *delims)
{
char
*buffer,
*bufptr,
**token_list, /* Returned token list */
delim, /* Current delimiter character */
last_char = '\0'; /* Last character parsed */
int
word_count = 0, /* Number of words in string */
word_nbr;
/* Allocate space for work string, up to the size of the input string */
buffer = mem_alloc (strlen (string) + 1);
if (buffer == NULL)
return (NULL);
/* Now copy string and eliminate spaces and cut on delimiters */
bufptr = buffer; /* Move to start of target buffer */
if (string) /* Allow string to be NULL */
{
while (*string) /* Copy entire string */
if (strchr (delims, *string))
{ /* User-specified delimiter */
word_count++; /* Count the word */
delim = *string++; /* and skip the delimiter */
while (*string != delim)
{
if (*string)
*bufptr++ = *string++;
else
break; /* Unfinished token, but allright */
}
last_char = *bufptr++ = '\0';
if (*string == delim)
string++; /* Skip final delimiter */
while (isspace (*string))
string++; /* and any trailing spaces */
}
else
if (isspace (*string)) /* Collapse whitespace to */
{ /* a single null byte */
word_count++; /* unless at the start */
while (isspace (*string))
string++;
if (bufptr > buffer)
last_char = *bufptr++ = '\0';
}
else
last_char = *bufptr++ = *string++;
}
/* Count last word if it was not terminated in a white space */
if (last_char > 0)
word_count++;
*bufptr = '\0'; /* End with final NULL */
/* The token list starts with a pointer to the buffer, then has one */
/* pointer to each string in the buffer. It ends with a null pointer. */
/* We return the address of the first string pointer, i.e. the caller */
/* does not see the pointer to the buffer. We can thus get away with */
/* just two allocs; one for the buffer and one for the token list. */
token_list = mem_alloc (sizeof (char *) * (word_count + 2));
if (token_list == NULL)
return (NULL);
token_list [0] = buffer; /* Store buffer address */
token_list++; /* and bump starting address */
bufptr = buffer;
for (word_nbr = 0; word_nbr < word_count; word_nbr++)
{
token_list [word_nbr] = bufptr;
bufptr += strlen (bufptr) + 1;
}
token_list [word_count] = NULL; /* Store final null pointer */
return (token_list);
}
/* ---------------------------------------------------------------------[<]-
Function: tok_free
Synopsis: Frees the memory allocated by a tok_split() call. You should
call this function for each call to tok_split(), to avoid memory leaks.
Do not try to free the allocated memory yourself, as the structure of a
token list is not documented and may change over time.
---------------------------------------------------------------------[>]-*/
void
tok_free (
char **token_list)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -