1 /**
2  * \file mlt_tokeniser.c
3  * \brief string tokeniser
4  * \see mlt_tokeniser_s
5  *
6  * Copyright (C) 2002-2014 Meltytech, LLC
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  */
22 
23 /* System header files */
24 #include <stdlib.h>
25 #include <string.h>
26 
27 /* Application header files */
28 #include "mlt_tokeniser.h"
29 
30 /** Initialise a tokeniser.
31 */
32 
mlt_tokeniser_init()33 mlt_tokeniser mlt_tokeniser_init( )
34 {
35 	mlt_tokeniser tokeniser = calloc( 1, sizeof( mlt_tokeniser_t ) );
36 	tokeniser->input = NULL;
37 	tokeniser->tokens = NULL;
38 	tokeniser->count = 0;
39 	tokeniser->size = 0;
40 	return tokeniser;
41 }
42 
43 /** Clear the tokeniser.
44 */
45 
mlt_tokeniser_clear(mlt_tokeniser tokeniser)46 static void mlt_tokeniser_clear( mlt_tokeniser tokeniser )
47 {
48 	int index = 0;
49 	for ( index = 0; index < tokeniser->count; index ++ )
50 		free( tokeniser->tokens[ index ] );
51 	tokeniser->count = 0;
52 	free( tokeniser->input );
53 	tokeniser->input = NULL;
54 }
55 
56 /** Append a string to the tokeniser.
57 */
58 
mlt_tokeniser_append(mlt_tokeniser tokeniser,char * token)59 static int mlt_tokeniser_append( mlt_tokeniser tokeniser, char *token )
60 {
61 	int error = 0;
62 
63 	if ( tokeniser->count == tokeniser->size )
64 	{
65 		tokeniser->size += 20;
66 		tokeniser->tokens = realloc( tokeniser->tokens, tokeniser->size * sizeof( char * ) );
67 	}
68 
69 	if ( tokeniser->tokens != NULL )
70 	{
71 		tokeniser->tokens[ tokeniser->count ++ ] = strdup( token );
72 	}
73 	else
74 	{
75 		tokeniser->count = 0;
76 		error = -1;
77 	}
78 	return error;
79 }
80 
81 /** Parse a string by splitting on the delimiter provided.
82 */
83 
mlt_tokeniser_parse_new(mlt_tokeniser tokeniser,char * string,const char * delimiter)84 int mlt_tokeniser_parse_new( mlt_tokeniser tokeniser, char *string, const char *delimiter )
85 {
86 	if ( !string || !delimiter ) return 0;
87 	int count = 0;
88 	int length = strlen( string );
89 	int delimiter_size = strlen( delimiter );
90 	int index = 0;
91 	char *token = strdup( string );
92 
93 	mlt_tokeniser_clear( tokeniser );
94 	tokeniser->input = strdup( string );
95 	strcpy( token, "" );
96 
97 	for ( index = 0; index < length; )
98 	{
99 		char *start = string + index;
100 		char *end = strstr( start, delimiter );
101 
102 		if ( end == NULL )
103 		{
104 			strcat( token, start );
105 			mlt_tokeniser_append( tokeniser, token );
106 			index = length;
107 			count ++;
108 		}
109 		else if ( start != end )
110 		{
111 			strncat( token, start, end - start );
112 			index += end - start;
113 			if ( strchr( token, '\"' ) == NULL || token[ strlen( token ) - 1 ] == '\"' )
114 			{
115 				mlt_tokeniser_append( tokeniser, token );
116 				strcpy( token, "" );
117 				count ++;
118 			}
119 			else while ( strncmp( string + index, delimiter, delimiter_size ) == 0 )
120 			{
121 				strncat( token, delimiter, delimiter_size );
122 				index += delimiter_size;
123 			}
124 		}
125 		else
126 		{
127 			index += delimiter_size;
128 		}
129 	}
130 
131 	/* Special case - malformed string condition */
132 	if ( !strcmp( token, "" ) )
133 	{
134 		count = 0 - ( count - 1 );
135 		mlt_tokeniser_append( tokeniser, token );
136 	}
137 
138 	free( token );
139 	return count;
140 }
141 
142 /** Get the original input.
143 */
144 
mlt_tokeniser_get_input(mlt_tokeniser tokeniser)145 char *mlt_tokeniser_get_input( mlt_tokeniser tokeniser )
146 {
147 	return tokeniser->input;
148 }
149 
150 /** Get the number of tokens.
151 */
152 
mlt_tokeniser_count(mlt_tokeniser tokeniser)153 int mlt_tokeniser_count( mlt_tokeniser tokeniser )
154 {
155 	return tokeniser->count;
156 }
157 
158 /** Get a token as a string.
159 */
160 
mlt_tokeniser_get_string(mlt_tokeniser tokeniser,int index)161 char *mlt_tokeniser_get_string( mlt_tokeniser tokeniser, int index )
162 {
163 	if ( index < tokeniser->count )
164 		return tokeniser->tokens[ index ];
165 	else
166 		return NULL;
167 }
168 
169 /** Close the tokeniser.
170 */
171 
mlt_tokeniser_close(mlt_tokeniser tokeniser)172 void mlt_tokeniser_close( mlt_tokeniser tokeniser )
173 {
174 	mlt_tokeniser_clear( tokeniser );
175 	free( tokeniser->tokens );
176 	free( tokeniser );
177 }
178