| 
									
										
										
										
											2012-07-30 22:31:34 -06:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Based on intlist.c by: | 
					
						
							|  |  |  |  * (c) 2009 Arnaldo Carvalho de Melo <acme@redhat.com> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Licensed under the GPLv2. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <errno.h>
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <linux/compiler.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "intlist.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-11 01:15:03 +03:00
										 |  |  | static struct rb_node *intlist__node_new(struct rblist *rblist __maybe_unused, | 
					
						
							| 
									
										
										
										
											2012-07-30 22:31:34 -06:00
										 |  |  | 					 const void *entry) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i = (int)((long)entry); | 
					
						
							|  |  |  | 	struct rb_node *rc = NULL; | 
					
						
							|  |  |  | 	struct int_node *node = malloc(sizeof(*node)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (node != NULL) { | 
					
						
							|  |  |  | 		node->i = i; | 
					
						
							| 
									
										
										
										
											2013-09-28 13:13:02 -06:00
										 |  |  | 		node->priv = NULL; | 
					
						
							| 
									
										
										
										
											2012-07-30 22:31:34 -06:00
										 |  |  | 		rc = &node->rb_node; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return rc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void int_node__delete(struct int_node *ilist) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	free(ilist); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-11 01:15:03 +03:00
										 |  |  | static void intlist__node_delete(struct rblist *rblist __maybe_unused, | 
					
						
							| 
									
										
										
										
											2012-07-30 22:31:34 -06:00
										 |  |  | 				 struct rb_node *rb_node) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct int_node *node = container_of(rb_node, struct int_node, rb_node); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int_node__delete(node); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int intlist__node_cmp(struct rb_node *rb_node, const void *entry) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i = (int)((long)entry); | 
					
						
							|  |  |  | 	struct int_node *node = container_of(rb_node, struct int_node, rb_node); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return node->i - i; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int intlist__add(struct intlist *ilist, int i) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return rblist__add_node(&ilist->rblist, (void *)((long)i)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-31 12:28:47 +05:30
										 |  |  | void intlist__remove(struct intlist *ilist, struct int_node *node) | 
					
						
							| 
									
										
										
										
											2012-07-30 22:31:34 -06:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-08-31 12:28:47 +05:30
										 |  |  | 	rblist__remove_node(&ilist->rblist, &node->rb_node); | 
					
						
							| 
									
										
										
										
											2012-07-30 22:31:34 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-08 21:26:52 -06:00
										 |  |  | static struct int_node *__intlist__findnew(struct intlist *ilist, | 
					
						
							|  |  |  | 					   int i, bool create) | 
					
						
							| 
									
										
										
										
											2012-07-30 22:31:34 -06:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-10-08 21:26:52 -06:00
										 |  |  | 	struct int_node *node = NULL; | 
					
						
							| 
									
										
										
										
											2013-01-24 16:10:42 -03:00
										 |  |  | 	struct rb_node *rb_node; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (ilist == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2012-07-30 22:31:34 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-08 21:26:52 -06:00
										 |  |  | 	if (create) | 
					
						
							|  |  |  | 		rb_node = rblist__findnew(&ilist->rblist, (void *)((long)i)); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		rb_node = rblist__find(&ilist->rblist, (void *)((long)i)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-30 22:31:34 -06:00
										 |  |  | 	if (rb_node) | 
					
						
							|  |  |  | 		node = container_of(rb_node, struct int_node, rb_node); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return node; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-08 21:26:52 -06:00
										 |  |  | struct int_node *intlist__find(struct intlist *ilist, int i) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return __intlist__findnew(ilist, i, false); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct int_node *intlist__findnew(struct intlist *ilist, int i) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return __intlist__findnew(ilist, i, true); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-24 16:17:27 -03:00
										 |  |  | static int intlist__parse_list(struct intlist *ilist, const char *s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	char *sep; | 
					
						
							|  |  |  | 	int err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	do { | 
					
						
							|  |  |  | 		long value = strtol(s, &sep, 10); | 
					
						
							|  |  |  | 		err = -EINVAL; | 
					
						
							|  |  |  | 		if (*sep != ',' && *sep != '\0') | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		err = intlist__add(ilist, value); | 
					
						
							|  |  |  | 		if (err) | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		s = sep + 1; | 
					
						
							|  |  |  | 	} while (*sep != '\0'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return err; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct intlist *intlist__new(const char *slist) | 
					
						
							| 
									
										
										
										
											2012-07-30 22:31:34 -06:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct intlist *ilist = malloc(sizeof(*ilist)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (ilist != NULL) { | 
					
						
							|  |  |  | 		rblist__init(&ilist->rblist); | 
					
						
							|  |  |  | 		ilist->rblist.node_cmp    = intlist__node_cmp; | 
					
						
							|  |  |  | 		ilist->rblist.node_new    = intlist__node_new; | 
					
						
							|  |  |  | 		ilist->rblist.node_delete = intlist__node_delete; | 
					
						
							| 
									
										
										
										
											2013-01-24 16:17:27 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (slist && intlist__parse_list(ilist, slist)) | 
					
						
							|  |  |  | 			goto out_delete; | 
					
						
							| 
									
										
										
										
											2012-07-30 22:31:34 -06:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ilist; | 
					
						
							| 
									
										
										
										
											2013-01-24 16:17:27 -03:00
										 |  |  | out_delete: | 
					
						
							|  |  |  | 	intlist__delete(ilist); | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							| 
									
										
										
										
											2012-07-30 22:31:34 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void intlist__delete(struct intlist *ilist) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (ilist != NULL) | 
					
						
							|  |  |  | 		rblist__delete(&ilist->rblist); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct int_node *node = NULL; | 
					
						
							|  |  |  | 	struct rb_node *rb_node; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rb_node = rblist__entry(&ilist->rblist, idx); | 
					
						
							|  |  |  | 	if (rb_node) | 
					
						
							|  |  |  | 		node = container_of(rb_node, struct int_node, rb_node); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return node; | 
					
						
							|  |  |  | } |