2 * Copyright 2013 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.1 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://floralicense.org/license/
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <stdlib.h> /* malloc */
21 #include <string.h> /* strdup */
25 #include <livebox-errno.h>
35 Eina_List *cluster_list;
42 Eina_List *category_list;
47 struct cluster *cluster;
48 Eina_List *info_list; /* list of instances of the struct inst_info */
53 struct category *category;
54 Eina_List *context_list; /* context item list */
57 struct context_item_data {
64 struct context_info *info;
65 Eina_List *option_list;
69 struct context_option {
70 struct context_item *item;
75 HAPI struct context_info *group_create_context_info(struct category *category, const char *pkgname)
77 struct context_info *info;
79 info = calloc(1, sizeof(*info));
81 ErrPrint("Heap: %s\n", strerror(errno));
85 info->pkgname = strdup(pkgname);
87 ErrPrint("Heap: %s\n", strerror(errno));
92 info->category = category;
93 category->info_list = eina_list_append(category->info_list, info);
97 static inline void del_options(struct context_item *item)
99 struct context_option *option;
101 EINA_LIST_FREE(item->option_list, option) {
102 DbgFree(option->key);
103 DbgFree(option->value);
108 static inline void del_context_item(struct context_info *info)
110 struct context_item *item;
112 EINA_LIST_FREE(info->context_list, item) {
114 DbgFree(item->ctx_item);
119 HAPI struct context_item *group_add_context_item(struct context_info *info, const char *ctx_item)
121 struct context_item *item;
123 item = calloc(1, sizeof(*item));
125 ErrPrint("Heap: %s\n", strerror(errno));
129 item->ctx_item = strdup(ctx_item);
130 if (!item->ctx_item) {
131 ErrPrint("Heap: %s\n", strerror(errno));
137 info->context_list = eina_list_append(info->context_list, item);
141 HAPI int group_add_option(struct context_item *item, const char *key, const char *value)
143 struct context_option *option;
145 option = calloc(1, sizeof(*option));
147 ErrPrint("Heap: %s\n", strerror(errno));
148 return LB_STATUS_ERROR_MEMORY;
151 option->key = strdup(key);
153 ErrPrint("Heap: %s\n", strerror(errno));
155 return LB_STATUS_ERROR_MEMORY;
158 option->value = strdup(value);
159 if (!option->value) {
160 ErrPrint("Heap: %s\n", strerror(errno));
161 DbgFree(option->key);
163 return LB_STATUS_ERROR_MEMORY;
167 item->option_list = eina_list_append(item->option_list, option);
168 return LB_STATUS_SUCCESS;
171 HAPI int group_destroy_context_info(struct context_info *info)
173 struct category *category;
175 category = info->category;
177 ErrPrint("No category found\n");
178 return LB_STATUS_ERROR_INVALID;
181 category->info_list = eina_list_remove(category->info_list, info);
183 del_context_item(info);
184 DbgFree(info->pkgname);
186 return LB_STATUS_SUCCESS;
189 HAPI struct cluster *group_create_cluster(const char *name)
191 struct cluster *cluster;
193 cluster = malloc(sizeof(*cluster));
195 ErrPrint("Heap: %s\n", strerror(errno));
199 cluster->name = strdup(name);
200 if (!cluster->name) {
201 ErrPrint("Heap: %s\n", strerror(errno));
206 cluster->category_list = NULL;
208 s_info.cluster_list = eina_list_append(s_info.cluster_list, cluster);
212 HAPI struct cluster *group_find_cluster(const char *name)
215 struct cluster *cluster;
217 EINA_LIST_FOREACH(s_info.cluster_list, l, cluster) {
218 if (!strcasecmp(cluster->name, name)) {
226 HAPI struct category *group_create_category(struct cluster *cluster, const char *name)
228 struct category *category;
230 category = malloc(sizeof(*category));
232 ErrPrint("Heap: %s\n", strerror(errno));
236 category->name = strdup(name);
237 if (!category->name) {
238 ErrPrint("Heap: %s\n", strerror(errno));
243 category->cluster = cluster;
244 category->info_list = NULL;
246 cluster->category_list = eina_list_append(cluster->category_list, category);
250 static inline void destroy_cluster(struct cluster *cluster)
252 struct category *category;
256 EINA_LIST_FOREACH_SAFE(cluster->category_list, l, n, category) {
257 group_destroy_category(category);
260 DbgFree(cluster->name);
264 HAPI int group_destroy_cluster(struct cluster *cluster)
268 struct cluster *item;
270 EINA_LIST_FOREACH_SAFE(s_info.cluster_list, l, n, item) {
271 if (item == cluster) {
272 s_info.cluster_list = eina_list_remove_list(s_info.cluster_list, l);
273 destroy_cluster(cluster);
274 return LB_STATUS_SUCCESS;
278 return LB_STATUS_ERROR_NOT_EXIST;
281 static inline void destroy_category(struct category *category)
285 struct context_info *info;
287 EINA_LIST_FOREACH_SAFE(category->info_list, l, n, info) {
288 group_destroy_context_info(info);
291 DbgFree(category->name);
295 HAPI int group_destroy_category(struct category *category)
297 struct cluster *cluster;
299 cluster = category->cluster;
301 cluster->category_list = eina_list_remove(cluster->category_list, category);
304 destroy_category(category);
305 return LB_STATUS_SUCCESS;
308 HAPI struct category *group_find_category(struct cluster *cluster, const char *name)
310 struct category *category;
313 EINA_LIST_FOREACH(cluster->category_list, l, category) {
314 if (!strcasecmp(category->name, name)) {
322 HAPI Eina_List * const group_context_info_list(struct category *category)
324 return category->info_list;
327 HAPI Eina_List *const group_context_item_list(struct context_info *info)
329 return info->context_list;
332 HAPI Eina_List *const group_context_option_list(struct context_item *item)
334 return item->option_list;
337 HAPI Eina_List *const group_cluster_list(void)
339 return s_info.cluster_list;
342 HAPI Eina_List * const group_category_list(struct cluster *cluster)
344 return cluster->category_list;
347 HAPI struct context_info * const group_context_info_from_item(struct context_item *item)
352 HAPI struct category * const group_category_from_context_info(struct context_info *info)
354 return info->category;
357 HAPI const char * const group_pkgname_from_context_info(struct context_info *info)
359 return info->pkgname;
362 HAPI const char * const group_option_item_key(struct context_option *option)
367 HAPI const char * const group_option_item_value(struct context_option *option)
369 return option->value;
372 HAPI const char * const group_context_item(struct context_item *item)
374 return item->ctx_item;
377 HAPI int group_context_item_add_data(struct context_item *item, const char *tag, void *data)
379 struct context_item_data *tmp;
381 tmp = malloc(sizeof(*tmp));
383 return LB_STATUS_ERROR_MEMORY;
386 tmp->tag = strdup(tag);
389 return LB_STATUS_ERROR_MEMORY;
393 item->data_list = eina_list_append(item->data_list, tmp);
394 return LB_STATUS_SUCCESS;
397 HAPI void *group_context_item_data(struct context_item *item, const char *tag)
399 struct context_item_data *tmp;
402 EINA_LIST_FOREACH(item->data_list, l, tmp) {
403 if (!strcmp(tmp->tag, tag)) {
411 HAPI void *group_context_item_del_data(struct context_item *item, const char *tag)
413 struct context_item_data *tmp;
417 EINA_LIST_FOREACH_SAFE(item->data_list, l, n, tmp) {
418 if (!strcmp(tmp->tag, tag)) {
421 item->data_list = eina_list_remove(item->data_list, tmp);
435 HAPI const char * const group_category_name(struct category *category)
437 return category ? category->name : NULL;
440 HAPI const char * const group_cluster_name(struct cluster *cluster)
442 return cluster ? cluster->name : NULL;
445 HAPI const char *group_cluster_name_by_category(struct category *category)
447 return !category ? NULL : (category->cluster ? category->cluster->name : NULL);
450 static inline char *get_token(char *ptr, int *len)
456 ErrPrint("Start brace but len = 0\n");
462 while (_len > 0 && isspace(ptr[_len])) {
467 ErrPrint("Token has no string\n");
471 name = malloc(_len + 1);
473 ErrPrint("Heap: %s\n", strerror(errno));
477 strncpy(name, ptr - *len, _len);
484 HAPI int group_add_livebox(const char *group, const char *pkgname)
486 struct cluster *cluster;
487 struct category *category;
488 struct context_info *info = NULL;
489 struct context_item *item = NULL;
500 CONTEXT_OPTION_VALUE,
501 CONTEXT_ERROR = 0xFFFFFFFF
510 /* Skip the first space characters */
511 while (*ptr && isspace(*ptr)) ptr++;
516 name = get_token(ptr, &len);
518 ErrPrint("Failed to get token\n");
519 return LB_STATUS_ERROR_FAULT;
521 /* cluster{category{context{key=value,key=value},context{key=value}}} */
522 /* cluster{category} */
526 cluster = group_find_cluster(name);
528 cluster = group_create_cluster(name);
532 ErrPrint("Failed to get cluster\n");
534 return LB_STATUS_ERROR_FAULT;
541 category = group_find_category(cluster, name);
543 category = group_create_category(cluster, name);
547 ErrPrint("Failed to get category\n");
549 return LB_STATUS_ERROR_FAULT;
552 info = group_create_context_info(category, pkgname);
554 ErrPrint("Failed to create ctx info\n");
556 return LB_STATUS_ERROR_FAULT;
559 state = CONTEXT_ITEM;
563 item = group_add_context_item(info, name);
565 ErrPrint("Failed to create a context item\n");
567 return LB_STATUS_ERROR_FAULT;
570 state = CONTEXT_OPTION_KEY;
573 case CONTEXT_OPTION_KEY:
574 case CONTEXT_OPTION_VALUE:
576 ErrPrint("Invalid state\n");
578 return LB_STATUS_ERROR_FAULT;
585 while (*ptr && isspace(*ptr)) ptr++;
587 } else if (*ptr == ',') {
588 name = get_token(ptr, &len);
590 ErrPrint("Failed to get token (len:%d)\n", len);
593 while (*ptr && isspace(*ptr)) ptr++;
600 ErrPrint("Invalid state\n");
602 return LB_STATUS_ERROR_FAULT;
604 cluster = group_find_cluster(name);
606 cluster = group_create_cluster(name);
610 ErrPrint("Failed to get cluster\n");
612 return LB_STATUS_ERROR_FAULT;
620 ErrPrint("Invalid state\n");
622 return LB_STATUS_ERROR_FAULT;
624 category = group_find_category(cluster, name);
626 category = group_create_category(cluster, name);
630 ErrPrint("Failed to get category\n");
632 return LB_STATUS_ERROR_FAULT;
635 info = group_create_context_info(category, pkgname);
637 ErrPrint("Failed to create ctx info\n");
639 return LB_STATUS_ERROR_FAULT;
642 state = CONTEXT_ITEM;
646 category = group_find_category(cluster, name);
648 category = group_create_category(cluster, name);
652 ErrPrint("Failed to get category\n");
654 return LB_STATUS_ERROR_FAULT;
657 info = group_create_context_info(category, pkgname);
659 ErrPrint("Failed to create ctx info\n");
661 return LB_STATUS_ERROR_FAULT;
663 } else if (is_open == 2) {
664 item = group_add_context_item(info, name);
666 ErrPrint("Failed to create a context item\n");
668 return LB_STATUS_ERROR_FAULT;
670 state = CONTEXT_OPTION_KEY;
672 ErrPrint("Invalid state\n");
674 return LB_STATUS_ERROR_FAULT;
678 case CONTEXT_OPTION_VALUE:
680 ErrPrint("Invalid state\n");
682 return LB_STATUS_ERROR_FAULT;
685 if (group_add_option(item, key, name) < 0) {
686 ErrPrint("Failed to add a new option: %s - %s\n", key, name);
692 state = CONTEXT_OPTION_KEY;
694 case CONTEXT_OPTION_KEY:
696 ErrPrint("Invalid state (%s)\n", name);
698 return LB_STATUS_ERROR_FAULT;
704 while (*ptr && isspace(*ptr)) ptr++;
706 } else if (*ptr == '=') {
707 if (is_open != 3 || state != CONTEXT_OPTION_KEY) {
708 ErrPrint("Invalid state\n");
709 return LB_STATUS_ERROR_FAULT;
712 key = get_token(ptr, &len);
714 ErrPrint("Failed to get token\n");
715 return LB_STATUS_ERROR_FAULT;
718 state = CONTEXT_OPTION_VALUE;
721 while (*ptr && isspace(*ptr)) ptr++;
723 } else if (*ptr == '}') {
725 ErrPrint("Invalid state\n");
726 return LB_STATUS_ERROR_FAULT;
729 name = get_token(ptr, &len);
731 ErrPrint("Failed to get token, len:%d\n", len);
735 while (*ptr && isspace(*ptr)) ptr++;
741 category = group_find_category(cluster, name);
743 category = group_create_category(cluster, name);
747 ErrPrint("Failed to get category\n");
749 return LB_STATUS_ERROR_FAULT;
752 info = group_create_context_info(category, pkgname);
754 ErrPrint("Failed to create ctx info\n");
756 return LB_STATUS_ERROR_FAULT;
763 category = group_find_category(cluster, name);
765 category = group_create_category(cluster, name);
769 ErrPrint("Failed to get category\n");
771 return LB_STATUS_ERROR_FAULT;
774 info = group_create_context_info(category, pkgname);
776 ErrPrint("Failed to create ctx info\n");
778 return LB_STATUS_ERROR_FAULT;
782 } else if (is_open == 2) {
785 ErrPrint("Invalid state\n");
787 return LB_STATUS_ERROR_FAULT;
790 case CONTEXT_OPTION_VALUE:
792 ErrPrint("Invalid state (%s)\n", name);
794 return LB_STATUS_ERROR_FAULT;
797 if (group_add_option(item, key, name) < 0) {
798 ErrPrint("Failed to add a new option: %s - %s\n", key, name);
804 state = CONTEXT_ITEM;
806 case CONTEXT_OPTION_KEY:
809 ErrPrint("Invalid state (%s)\n", name);
817 while (*ptr && isspace(*ptr)) ptr++;
825 /* If some cases, the key is not released, try release it, doesn't need to check NULL */
828 if (state != CLUSTER) {
829 return LB_STATUS_ERROR_INVALID;
832 return LB_STATUS_SUCCESS;
835 HAPI int group_del_livebox(const char *pkgname)
843 struct cluster *cluster;
844 struct category *category;
845 struct context_info *info;
847 EINA_LIST_FOREACH_SAFE(s_info.cluster_list, l, n, cluster) {
848 EINA_LIST_FOREACH_SAFE(cluster->category_list, s_l, s_n, category) {
849 EINA_LIST_FOREACH_SAFE(category->info_list, i_l, i_n, info) {
850 if (!strcmp(pkgname, info->pkgname)) {
851 group_destroy_context_info(info);
855 if (!category->info_list) {
856 group_destroy_category(category);
860 if (!cluster->category_list) {
861 group_destroy_cluster(cluster);
865 return LB_STATUS_SUCCESS;
868 HAPI int group_init(void)
870 return LB_STATUS_SUCCESS;
873 HAPI int group_fini(void)
875 struct cluster *cluster;
876 struct category *category;
878 EINA_LIST_FREE(s_info.cluster_list, cluster) {
880 EINA_LIST_FREE(cluster->category_list, category) {
881 destroy_category(category);
884 destroy_cluster(cluster);
886 return LB_STATUS_SUCCESS;