summaryrefslogtreecommitdiffstats
path: root/runtime/list.c
blob: c504ed3679d94debcb2c7e7ec80ff0ec7e5597cb (plain)
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#ifndef _LIST_C_ /* -*- linux-c -*- */
#define _LIST_C_

#ifndef NEED_INT64_KEYS
#error Before including list.c, "#define KEY1_TYPE INT64" and include "map-keys.c"
#endif

#if !defined(NEED_STRING_VALS) && !defined(NEED_INT64_VALS)
#error Before including list.c, "#define VALUE_TYPE" to "INT64" or "STRING" and include "map-values.c"
#endif

#include "map.c"
#include "copy.c"

/**********************  List Functions *********************/
/** @file list.c
 * @brief List Functions
 */

/** @addtogroup lists
 * Lists are special cases of maps.
 * @b Example:
 * @include list.c
 * @{ */

/** Create a new list.
 * A list is a map that internally has an incrementing long key for each member.
 * Lists do not wrap if elements are added to exceed their maximum size.
 * @param max_entries The maximum number of entries allowed. Currently that number will
 * be preallocated.  If max_entries is 0, there will be no maximum and entries
 * will be allocated dynamically.
 * @param type Type of values stored in this list. 
 * @return A MAP on success or NULL on failure.
 * @sa foreach
 */

MAP _stp_list_new(unsigned max_entries, int type)
{
  MAP map = _stp_map_new_int64 (max_entries, type);
  map->no_wrap = 1;
  return map;
}

/** Clears a list.
 * All elements in the list are deleted.
 * @param map 
 */

void _stp_list_clear(MAP map)
{
	if (map == NULL)
		return;

	if (!list_empty(&map->head)) {
		struct map_node *ptr = (struct map_node *)map->head.next;

		while (ptr && ptr != (struct map_node *)&map->head) {
			struct map_node *next = (struct map_node *)ptr->lnode.next;

			/* remove node from old hash list */
			hlist_del_init(&ptr->hnode);

			/* remove from entry list */
			list_del(&ptr->lnode);
			
			list_add(&ptr->lnode, &map->pool);

			map->num--;
			ptr = next;
		}
	}

	if (map->num != 0) {
		_stp_warn ("list is supposed to be empty (has %d)\n", map->num);
	}
}

#ifdef NEED_STRING_VALS
/** Adds a C string to a list.
 * @param map
 * @param str
 * @sa _stp_list_add()
 */

inline void _stp_list_add_str(MAP map, char *str)
{
	_stp_map_key_int64 (map, map->num);
	_stp_map_set_str(map, str);
}

/** Adds a String to a list.
 * @param map
 * @param str String to add.
 * @sa _stp_list_add()
 */

inline void _stp_list_add_string (MAP map, String str)
{
	_stp_map_key_int64 (map, map->num);
	_stp_map_set_str(map, str->buf);
}
#endif /* NEED_STRING_VALS */

#ifdef NEED_INT64_VALS
/** Adds an int64 to a list.
 * @param map
 * @param val
 * @sa _stp_list_add()
 */

inline void _stp_list_add_int64(MAP map, int64_t val)
{
	_stp_map_key_int64 (map, map->num);
	_stp_map_set_int64(map, val);
}
#endif /* NEED_INT64_VALS */

/** Get the number of elements in a list.
 * @param map
 * @returns The number of elements in a list.
 */

inline int _stp_list_size(MAP map)
{
	return map->num;
}

/** Copy an argv from user space to a List.
 *
 * @param list A list.
 * @param argv Source argv, in user space.
 * @return number of elements in <i>list</i>
 *
 * @b Example:
 * @include argv.c
 */

int _stp_copy_argv_from_user (MAP list, char __user *__user *argv)
{
	char str[128];
	char __user *vstr;
	int len;

	if (argv)
		argv++;

	while (argv != NULL) {
		if (get_user (vstr, argv))
			break;
		
		if (vstr == NULL)
			break;
		
		len = _stp_strncpy_from_user(str, vstr, 128);
		str[len] = 0;
		_stp_list_add_str (list, str);
		argv++;
	}
	return list->num;
}

/** @} */
#endif /* _LIST_C_ */