File: splitstr.c

package info (click to toggle)
gfsecret 0.5.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,964 kB
  • sloc: sh: 5,079; ansic: 3,118; makefile: 41; sed: 16
file content (102 lines) | stat: -rw-r--r-- 2,886 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/*
 * splitstr - Incenp.org Notch Library: string-spliter module
 * Copyright (C) 2011 Damien Goutte-Gattat
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <splitstr.h>
#include <errno.h>

#include <xmem.h>

/*
 * The following call
 *
 *   splitstr("to split this string", ' ', NULL);
 *
 * would return a pointer to a memory area whose contents would
 * look like as depicted:
 *
 * 0    4    8    12   16   20     23           29         34
 * +----+----+----+----+----+------+------------+----------+--------------+
 * | 20 | 23 | 29 | 34 |NULL|t|o|\0|s|p|l|i|t|\0|t|h|i|s|\0|s|t|r|i|n|g|\0|
 * +----+----+----+----+----+------+------------+----------+--------------+
 *
 * |<---------------------->|<------------------------------------------->|
 * |(n + 1) * sizeof(char *)|                    n + l                    |
 *
 * with `n' being the number of tokens, and `l' the total count of
 * characters in all tokens.
 *
 * The memory is allocated in a single block, so it can be freed by a
 * single call to free().
 */

char **
splitstr(const char *str, char delim, size_t *ntoken)
{
    const char *cursor;
    char *copy, **index;
    size_t n, l;
    int is_token;

    if ( ! str ) {
        errno = EINVAL;
        return NULL;
    }

    /* First parsing to compute the amount of memory needed. */
    for ( n = l = is_token = 0, cursor = str; *cursor; cursor++ ) {
        if ( *cursor != delim ) {
            if ( ! is_token ) {
                is_token = 1;
                n += 1;
            }
            l += 1;
        }
        else
            is_token = 0;
    }

    index = xmalloc((n + 1) * sizeof(char *) + l + n);
    copy = (char *)(index + (n + 1));

    /* Second parsing to copy the tokens in the buffer. */
    for ( n = l = is_token = 0, cursor = str; *cursor; cursor++ ) {
        if ( *cursor != delim ) {
            if ( ! is_token ) {
                is_token = 1;
                index[n++] = copy;
            }
            *copy++ = *cursor;
        }
        else {
            is_token = 0;
            if ( n && *(copy - 1) )
                *copy++ = '\0';
        }
    }
    *copy = '\0';
    index[n] = NULL;

    if ( ntoken )
        *ntoken = n;

    return index;
}