Subversion Repositories HelenOS

Rev

Rev 4743 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4743 Rev 4756
1
/*
1
/*
2
 * Copyright (c) 2009 Lukas Mejdrech
2
 * Copyright (c) 2009 Lukas Mejdrech
3
 * All rights reserved.
3
 * All rights reserved.
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
6
 * modification, are permitted provided that the following conditions
7
 * are met:
7
 * are met:
8
 *
8
 *
9
 * - Redistributions of source code must retain the above copyright
9
 * - Redistributions of source code must retain the above copyright
10
 *   notice, this list of conditions and the following disclaimer.
10
 *   notice, this list of conditions and the following disclaimer.
11
 * - Redistributions in binary form must reproduce the above copyright
11
 * - Redistributions in binary form must reproduce the above copyright
12
 *   notice, this list of conditions and the following disclaimer in the
12
 *   notice, this list of conditions and the following disclaimer in the
13
 *   documentation and/or other materials provided with the distribution.
13
 *   documentation and/or other materials provided with the distribution.
14
 * - The name of the author may not be used to endorse or promote products
14
 * - The name of the author may not be used to endorse or promote products
15
 *   derived from this software without specific prior written permission.
15
 *   derived from this software without specific prior written permission.
16
 *
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
27
 */
28
 
28
 
29
/** @addtogroup net
29
/** @addtogroup net
30
 *  @{
30
 *  @{
31
 */
31
 */
32
 
32
 
33
/** @file
33
/** @file
34
 *  Character string to integer map implementation.
34
 *  Character string to integer map implementation.
35
 *  @see char_map.h
35
 *  @see char_map.h
36
 */
36
 */
37
 
37
 
38
#include <errno.h>
38
#include <errno.h>
39
#include <malloc.h>
39
#include <malloc.h>
40
#include <mem.h>
40
#include <mem.h>
41
#include <unistd.h>
41
#include <unistd.h>
42
 
42
 
43
#include "char_map.h"
43
#include "char_map.h"
44
 
44
 
45
/** Internal magic value for a&nbsp;consistency check.
45
/** Internal magic value for a&nbsp;consistency check.
46
 */
46
 */
47
#define CHAR_MAP_MAGIC_VALUE    0x12345611
47
#define CHAR_MAP_MAGIC_VALUE    0x12345611
48
 
48
 
49
/** Adds the value with the key to the map.
49
/** Adds the value with the key to the map.
50
 *  Creates new nodes to map the key.
50
 *  Creates new nodes to map the key.
51
 *  @param map The character string to integer map. Input/output parameter.
51
 *  @param[in,out] map The character string to integer map.
52
 *  @param identifier The key zero ('\\0') terminated character string. The key character string is processed until the first terminating zero ('\\0') character after the given length is found. Input parameter.
52
 *  @param[in] identifier The key zero ('\\0') terminated character string. The key character string is processed until the first terminating zero ('\\0') character after the given length is found.
53
 *  @param length The key character string length. The parameter may be zero (0) which means that the string is processed until the terminating zero ('\\0') character is found. Input parameter.
53
 *  @param[in] length The key character string length. The parameter may be zero (0) which means that the string is processed until the terminating zero ('\\0') character is found.
54
 *  @param value The integral value to be stored for the key character string. Input parameter.
54
 *  @param[in] value The integral value to be stored for the key character string.
55
 *  @returns EOK on success.
55
 *  @returns EOK on success.
56
 *  @returns ENOMEM if there is not enough memory left.
56
 *  @returns ENOMEM if there is not enough memory left.
57
 *  @returns EEXIST if the key character string is already used.
57
 *  @returns EEXIST if the key character string is already used.
58
 */
58
 */
59
int char_map_add_item( char_map_ref map, const char * identifier, size_t length, const int value );
59
int char_map_add_item( char_map_ref map, const char * identifier, size_t length, const int value );
60
 
60
 
61
/** Returns the node assigned to the key from the map.
61
/** Returns the node assigned to the key from the map.
62
 *  @param map The character string to integer map. Input parameter.
62
 *  @param[in] map The character string to integer map.
63
 *  @param identifier The key zero ('\\0') terminated character string. The key character string is processed until the first terminating zero ('\\0') character after the given length is found. Input parameter.
63
 *  @param[in] identifier The key zero ('\\0') terminated character string. The key character string is processed until the first terminating zero ('\\0') character after the given length is found.
64
 *  @param length The key character string length. The parameter may be zero (0) which means that the string is processed until the terminating zero ('\\0') character is found. Input parameter.
64
 *  @param[in] length The key character string length. The parameter may be zero (0) which means that the string is processed until the terminating zero ('\\0') character is found.
65
 *  @returns The node holding the integral value assigned to the key character string.
65
 *  @returns The node holding the integral value assigned to the key character string.
66
 *  @returns NULL if the key is not assigned a&nbsp;node.
66
 *  @returns NULL if the key is not assigned a&nbsp;node.
67
 */
67
 */
68
char_map_ref    char_map_find_node( const char_map_ref map, const char * identifier, const size_t length );
68
char_map_ref    char_map_find_node( const char_map_ref map, const char * identifier, const size_t length );
69
 
69
 
70
/** Returns the value assigned to the map.
70
/** Returns the value assigned to the map.
71
 *  @param map The character string to integer map. Input parameter.
71
 *  @param[in] map The character string to integer map.
72
 *  @returns The integral value assigned to the map.
72
 *  @returns The integral value assigned to the map.
73
 *  @returns CHAR_MAP_NULL if the map is not assigned a&nbsp;value.
73
 *  @returns CHAR_MAP_NULL if the map is not assigned a&nbsp;value.
74
 */
74
 */
75
int char_map_get_value( const char_map_ref map );
75
int char_map_get_value( const char_map_ref map );
76
 
76
 
77
/** Checks if the map is valid.
77
/** Checks if the map is valid.
78
 *  @param map The character string to integer map. Input parameter.
78
 *  @param[in] map The character string to integer map.
79
 *  @returns TRUE if the map is valid.
79
 *  @returns TRUE if the map is valid.
80
 *  @returns FALSE otherwise.
80
 *  @returns FALSE otherwise.
81
 */
81
 */
82
int char_map_is_valid( const char_map_ref map );
82
int char_map_is_valid( const char_map_ref map );
83
 
83
 
84
int char_map_add( char_map_ref map, const char * identifier, size_t length, const int value ){
84
int char_map_add( char_map_ref map, const char * identifier, size_t length, const int value ){
85
    if( char_map_is_valid( map ) && ( identifier ) && (( length ) || ( * identifier ))){
85
    if( char_map_is_valid( map ) && ( identifier ) && (( length ) || ( * identifier ))){
86
        int index;
86
        int index;
87
 
87
 
88
        for( index = 0; index < map->next; ++ index ){
88
        for( index = 0; index < map->next; ++ index ){
89
            if( map->items[ index ]->c == * identifier ){
89
            if( map->items[ index ]->c == * identifier ){
90
                ++ identifier;
90
                ++ identifier;
91
                if(( length > 1 ) || (( length == 0 ) && ( * identifier ))){
91
                if(( length > 1 ) || (( length == 0 ) && ( * identifier ))){
92
                    return char_map_add( map->items[ index ], identifier, length ? length - 1 : 0, value );
92
                    return char_map_add( map->items[ index ], identifier, length ? length - 1 : 0, value );
93
                }else{
93
                }else{
94
                    if( map->items[ index ]->value != CHAR_MAP_NULL ) return EEXISTS;
94
                    if( map->items[ index ]->value != CHAR_MAP_NULL ) return EEXISTS;
95
                    map->items[ index ]->value = value;
95
                    map->items[ index ]->value = value;
96
                    return EOK;
96
                    return EOK;
97
                }
97
                }
98
            }
98
            }
99
        }
99
        }
100
        return char_map_add_item( map, identifier, length, value );
100
        return char_map_add_item( map, identifier, length, value );
101
    }
101
    }
102
    return EINVAL;
102
    return EINVAL;
103
}
103
}
104
 
104
 
105
int char_map_add_item( char_map_ref map, const char * identifier, size_t length, const int value ){
105
int char_map_add_item( char_map_ref map, const char * identifier, size_t length, const int value ){
106
    if( map->next == ( map->size - 1 )){
106
    if( map->next == ( map->size - 1 )){
107
        char_map_ref    * tmp;
107
        char_map_ref    * tmp;
108
 
108
 
109
        tmp = ( char_map_ref * ) realloc( map->items, sizeof( char_map_ref ) * 2 * map->size );
109
        tmp = ( char_map_ref * ) realloc( map->items, sizeof( char_map_ref ) * 2 * map->size );
110
        if( ! tmp ) return ENOMEM;
110
        if( ! tmp ) return ENOMEM;
111
        map->size *= 2;
111
        map->size *= 2;
112
        map->items = tmp;
112
        map->items = tmp;
113
    }
113
    }
114
    map->items[ map->next ] = ( char_map_ref ) malloc( sizeof( char_map_t ));
114
    map->items[ map->next ] = ( char_map_ref ) malloc( sizeof( char_map_t ));
115
    if( ! map->items[ map->next ] ) return ENOMEM;
115
    if( ! map->items[ map->next ] ) return ENOMEM;
116
    if( char_map_initialize( map->items[ map->next ] ) != EOK ){
116
    if( char_map_initialize( map->items[ map->next ] ) != EOK ){
117
        free( map->items[ map->next ] );
117
        free( map->items[ map->next ] );
118
        map->items[ map->next ] = NULL;
118
        map->items[ map->next ] = NULL;
119
        return ENOMEM;
119
        return ENOMEM;
120
    }
120
    }
121
    map->items[ map->next ]->c = * identifier;
121
    map->items[ map->next ]->c = * identifier;
122
    ++ identifier;
122
    ++ identifier;
123
    ++ map->next;
123
    ++ map->next;
124
    if(( length > 1 ) || (( length == 0 ) && ( * identifier ))){
124
    if(( length > 1 ) || (( length == 0 ) && ( * identifier ))){
125
        map->items[ map->next - 1 ]->value = CHAR_MAP_NULL;
125
        map->items[ map->next - 1 ]->value = CHAR_MAP_NULL;
126
        return char_map_add_item( map->items[ map->next - 1 ], identifier, length ? length - 1 : 0, value );
126
        return char_map_add_item( map->items[ map->next - 1 ], identifier, length ? length - 1 : 0, value );
127
    }else{
127
    }else{
128
        map->items[ map->next - 1 ]->value = value;
128
        map->items[ map->next - 1 ]->value = value;
129
    }
129
    }
130
    return EOK;
130
    return EOK;
131
}
131
}
132
 
132
 
133
void char_map_destroy( char_map_ref map ){
133
void char_map_destroy( char_map_ref map ){
134
    if( char_map_is_valid( map )){
134
    if( char_map_is_valid( map )){
135
        int index;
135
        int index;
136
 
136
 
137
        map->magic = 0;
137
        map->magic = 0;
138
        for( index = 0; index < map->next; ++ index ){
138
        for( index = 0; index < map->next; ++ index ){
139
            char_map_destroy( map->items[ index ] );
139
            char_map_destroy( map->items[ index ] );
140
        }
140
        }
141
        free( map->items );
141
        free( map->items );
142
        map->items = NULL;
142
        map->items = NULL;
143
    }
143
    }
144
}
144
}
145
 
145
 
146
int char_map_exclude( char_map_ref map, const char * identifier, size_t length ){
146
int char_map_exclude( char_map_ref map, const char * identifier, size_t length ){
147
    char_map_ref    node;
147
    char_map_ref    node;
148
 
148
 
149
    node = char_map_find_node( map, identifier, length );
149
    node = char_map_find_node( map, identifier, length );
150
    if( node ){
150
    if( node ){
151
        int value;
151
        int value;
152
 
152
 
153
        value = node->value;
153
        value = node->value;
154
        node->value = CHAR_MAP_NULL;
154
        node->value = CHAR_MAP_NULL;
155
        return value;
155
        return value;
156
    }
156
    }
157
    return CHAR_MAP_NULL;
157
    return CHAR_MAP_NULL;
158
}
158
}
159
 
159
 
160
int char_map_find( const char_map_ref map, const char * identifier, size_t length ){
160
int char_map_find( const char_map_ref map, const char * identifier, size_t length ){
161
    char_map_ref    node;
161
    char_map_ref    node;
162
 
162
 
163
    node = char_map_find_node( map, identifier, length );
163
    node = char_map_find_node( map, identifier, length );
164
    return node ? node->value : CHAR_MAP_NULL;
164
    return node ? node->value : CHAR_MAP_NULL;
165
}
165
}
166
 
166
 
167
char_map_ref char_map_find_node( const char_map_ref map, const char * identifier, size_t length ){
167
char_map_ref char_map_find_node( const char_map_ref map, const char * identifier, size_t length ){
168
    if( ! char_map_is_valid( map )) return NULL;
168
    if( ! char_map_is_valid( map )) return NULL;
169
    if( length || ( * identifier )){
169
    if( length || ( * identifier )){
170
        int index;
170
        int index;
171
 
171
 
172
        for( index = 0; index < map->next; ++ index ){
172
        for( index = 0; index < map->next; ++ index ){
173
            if( map->items[ index ]->c == * identifier ){
173
            if( map->items[ index ]->c == * identifier ){
174
                ++ identifier;
174
                ++ identifier;
175
                if( length == 1 ) return map->items[ index ];
175
                if( length == 1 ) return map->items[ index ];
176
                return char_map_find_node( map->items[ index ], identifier, length ? length - 1 : 0 );
176
                return char_map_find_node( map->items[ index ], identifier, length ? length - 1 : 0 );
177
            }
177
            }
178
        }
178
        }
179
        return NULL;
179
        return NULL;
180
    }
180
    }
181
    return map;
181
    return map;
182
}
182
}
183
 
183
 
184
int char_map_get_value( const char_map_ref map ){
184
int char_map_get_value( const char_map_ref map ){
185
    return char_map_is_valid( map ) ? map->value : CHAR_MAP_NULL;
185
    return char_map_is_valid( map ) ? map->value : CHAR_MAP_NULL;
186
}
186
}
187
 
187
 
188
int char_map_initialize( char_map_ref map ){
188
int char_map_initialize( char_map_ref map ){
189
    if( ! map ) return EINVAL;
189
    if( ! map ) return EINVAL;
190
    map->c = '\0';
190
    map->c = '\0';
191
    map->value = CHAR_MAP_NULL;
191
    map->value = CHAR_MAP_NULL;
192
    map->size = 2;
192
    map->size = 2;
193
    map->next = 0;
193
    map->next = 0;
194
    map->items = malloc( sizeof( char_map_ref ) * map->size );
194
    map->items = malloc( sizeof( char_map_ref ) * map->size );
195
    if( ! map->items ){
195
    if( ! map->items ){
196
        map->magic = 0;
196
        map->magic = 0;
197
        return ENOMEM;
197
        return ENOMEM;
198
    }
198
    }
199
    map->items[ map->next ] = NULL;
199
    map->items[ map->next ] = NULL;
200
    map->magic = CHAR_MAP_MAGIC_VALUE;
200
    map->magic = CHAR_MAP_MAGIC_VALUE;
201
    return EOK;
201
    return EOK;
202
}
202
}
203
 
203
 
204
int char_map_is_valid( const char_map_ref map ){
204
int char_map_is_valid( const char_map_ref map ){
205
    return map && ( map->magic == CHAR_MAP_MAGIC_VALUE );
205
    return map && ( map->magic == CHAR_MAP_MAGIC_VALUE );
206
}
206
}
207
 
207
 
208
int char_map_update( char_map_ref map, const char * identifier, const size_t length, const int value ){
208
int char_map_update( char_map_ref map, const char * identifier, const size_t length, const int value ){
209
    char_map_ref    node;
209
    char_map_ref    node;
210
 
210
 
211
//  if( ! char_map_is_valid( map )) return EINVAL;
211
//  if( ! char_map_is_valid( map )) return EINVAL;
212
    node = char_map_find_node( map, identifier, length );
212
    node = char_map_find_node( map, identifier, length );
213
    if( node ){
213
    if( node ){
214
        node->value = value;
214
        node->value = value;
215
        return EOK;
215
        return EOK;
216
    }else{
216
    }else{
217
        return char_map_add( map, identifier, length, value );
217
        return char_map_add( map, identifier, length, value );
218
    }
218
    }
219
}
219
}
220
 
220
 
221
/** @}
221
/** @}
222
 */
222
 */
223
 
223