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 DbgPrint("Cluster %s is created\n", cluster->name);
209 s_info.cluster_list = eina_list_append(s_info.cluster_list, cluster);
213 HAPI struct cluster *group_find_cluster(const char *name)
216 struct cluster *cluster;
218 EINA_LIST_FOREACH(s_info.cluster_list, l, cluster) {
219 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 DbgPrint("Category %s is created\n", category->name);
247 cluster->category_list = eina_list_append(cluster->category_list, category);
251 static inline void destroy_cluster(struct cluster *cluster)
253 struct category *category;
257 EINA_LIST_FOREACH_SAFE(cluster->category_list, l, n, category) {
258 group_destroy_category(category);
261 DbgPrint("Destroy cluster: %s\n", cluster->name);
262 DbgFree(cluster->name);
266 HAPI int group_destroy_cluster(struct cluster *cluster)
270 struct cluster *item;
272 EINA_LIST_FOREACH_SAFE(s_info.cluster_list, l, n, item) {
273 if (item == cluster) {
274 s_info.cluster_list = eina_list_remove_list(s_info.cluster_list, l);
275 destroy_cluster(cluster);
276 return LB_STATUS_SUCCESS;
280 return LB_STATUS_ERROR_NOT_EXIST;
283 static inline void destroy_category(struct category *category)
287 struct context_info *info;
289 EINA_LIST_FOREACH_SAFE(category->info_list, l, n, info) {
290 group_destroy_context_info(info);
293 DbgPrint("Destroy category: %s\n", category->name);
294 DbgFree(category->name);
298 HAPI int group_destroy_category(struct category *category)
300 struct cluster *cluster;
302 cluster = category->cluster;
304 cluster->category_list = eina_list_remove(cluster->category_list, category);
306 destroy_category(category);
307 return LB_STATUS_SUCCESS;
310 HAPI struct category *group_find_category(struct cluster *cluster, const char *name)
312 struct category *category;
315 EINA_LIST_FOREACH(cluster->category_list, l, category) {
316 if (!strcasecmp(category->name, name))
323 HAPI Eina_List * const group_context_info_list(struct category *category)
325 return category->info_list;
328 HAPI Eina_List *const group_context_item_list(struct context_info *info)
330 return info->context_list;
333 HAPI Eina_List *const group_context_option_list(struct context_item *item)
335 return item->option_list;
338 HAPI Eina_List *const group_cluster_list(void)
340 return s_info.cluster_list;
343 HAPI Eina_List * const group_category_list(struct cluster *cluster)
345 return cluster->category_list;
348 HAPI struct context_info * const group_context_info_from_item(struct context_item *item)
353 HAPI struct category * const group_category_from_context_info(struct context_info *info)
355 return info->category;
358 HAPI const char * const group_pkgname_from_context_info(struct context_info *info)
360 return info->pkgname;
363 HAPI const char * const group_option_item_key(struct context_option *option)
368 HAPI const char * const group_option_item_value(struct context_option *option)
370 return option->value;
373 HAPI const char * const group_context_item(struct context_item *item)
375 return item->ctx_item;
378 HAPI int group_context_item_add_data(struct context_item *item, const char *tag, void *data)
380 struct context_item_data *tmp;
382 tmp = malloc(sizeof(*tmp));
384 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))
410 HAPI void *group_context_item_del_data(struct context_item *item, const char *tag)
412 struct context_item_data *tmp;
416 EINA_LIST_FOREACH_SAFE(item->data_list, l, n, tmp) {
417 if (!strcmp(tmp->tag, tag)) {
420 item->data_list = eina_list_remove(item->data_list, tmp);
434 HAPI const char * const group_category_name(struct category *category)
436 return category ? category->name : NULL;
439 HAPI const char * const group_cluster_name(struct cluster *cluster)
441 return cluster ? cluster->name : NULL;
444 HAPI const char *group_cluster_name_by_category(struct category *category)
446 return !category ? NULL : (category->cluster ? category->cluster->name : NULL);
449 static inline char *get_token(char *ptr, int *len)
455 ErrPrint("Start brace but len = 0\n");
461 while (_len > 0 && isspace(ptr[_len]))
465 ErrPrint("Token has no string\n");
469 name = malloc(_len + 1);
471 ErrPrint("Heap: %s\n", strerror(errno));
475 strncpy(name, ptr - *len, _len);
482 HAPI int group_add_livebox(const char *group, const char *pkgname)
484 struct cluster *cluster;
485 struct category *category;
486 struct context_info *info;
487 struct context_item *item;
498 CONTEXT_OPTION_VALUE,
499 CONTEXT_ERROR = 0xFFFFFFFF,
508 /* Skip the first space characters */
509 while (*ptr && isspace(*ptr)) ptr++;
514 name = get_token(ptr, &len);
516 ErrPrint("Failed to get token\n");
517 return LB_STATUS_ERROR_FAULT;
519 /* cluster{category{context{key=value,key=value},context{key=value}}} */
520 /* cluster{category} */
524 cluster = group_find_cluster(name);
526 cluster = group_create_cluster(name);
529 ErrPrint("Failed to get cluster\n");
531 return LB_STATUS_ERROR_FAULT;
538 category = group_find_category(cluster, name);
540 category = group_create_category(cluster, name);
543 ErrPrint("Failed to get category\n");
545 return LB_STATUS_ERROR_FAULT;
548 info = group_create_context_info(category, pkgname);
550 ErrPrint("Failed to create ctx info\n");
552 return LB_STATUS_ERROR_FAULT;
555 state = CONTEXT_ITEM;
559 item = group_add_context_item(info, name);
561 ErrPrint("Failed to create a context item\n");
563 return LB_STATUS_ERROR_FAULT;
566 state = CONTEXT_OPTION_KEY;
569 case CONTEXT_OPTION_KEY:
570 case CONTEXT_OPTION_VALUE:
572 ErrPrint("Invalid state\n");
574 return LB_STATUS_ERROR_FAULT;
581 while (*ptr && isspace(*ptr)) ptr++;
583 } else if (*ptr == ',') {
584 name = get_token(ptr, &len);
586 ErrPrint("Failed to get token (len:%d)\n", len);
589 while (*ptr && isspace(*ptr)) ptr++;
596 ErrPrint("Invalid state\n");
598 return LB_STATUS_ERROR_FAULT;
600 cluster = group_find_cluster(name);
602 cluster = group_create_cluster(name);
605 ErrPrint("Failed to get cluster\n");
607 return LB_STATUS_ERROR_FAULT;
615 ErrPrint("Invalid state\n");
617 return LB_STATUS_ERROR_FAULT;
619 category = group_find_category(cluster, name);
621 category = group_create_category(cluster, name);
624 ErrPrint("Failed to get category\n");
626 return LB_STATUS_ERROR_FAULT;
629 info = group_create_context_info(category, pkgname);
631 ErrPrint("Failed to create ctx info\n");
633 return LB_STATUS_ERROR_FAULT;
636 state = CONTEXT_ITEM;
640 category = group_find_category(cluster, name);
642 category = group_create_category(cluster, name);
645 ErrPrint("Failed to get category\n");
647 return LB_STATUS_ERROR_FAULT;
650 info = group_create_context_info(category, pkgname);
652 ErrPrint("Failed to create ctx info\n");
654 return LB_STATUS_ERROR_FAULT;
656 DbgPrint("Keep this syntax only for the compatibility\n");
657 } else if (is_open == 2) {
658 item = group_add_context_item(info, name);
660 ErrPrint("Failed to create a context item\n");
662 return LB_STATUS_ERROR_FAULT;
664 state = CONTEXT_OPTION_KEY;
666 ErrPrint("Invalid state\n");
668 return LB_STATUS_ERROR_FAULT;
672 case CONTEXT_OPTION_VALUE:
674 ErrPrint("Invalid state\n");
676 return LB_STATUS_ERROR_FAULT;
679 if (group_add_option(item, key, name) < 0)
680 ErrPrint("Failed to add a new option: %s - %s\n", key, name);
685 state = CONTEXT_OPTION_KEY;
687 case CONTEXT_OPTION_KEY:
689 ErrPrint("Invalid state (%s)\n", name);
691 return LB_STATUS_ERROR_FAULT;
697 while (*ptr && isspace(*ptr)) ptr++;
699 } else if (*ptr == '=') {
700 if (is_open != 3 || state != CONTEXT_OPTION_KEY) {
701 ErrPrint("Invalid state\n");
702 return LB_STATUS_ERROR_FAULT;
705 key = get_token(ptr, &len);
707 ErrPrint("Failed to get token\n");
708 return LB_STATUS_ERROR_FAULT;
711 state = CONTEXT_OPTION_VALUE;
714 while (*ptr && isspace(*ptr)) ptr++;
716 } else if (*ptr == '}') {
718 ErrPrint("Invalid state\n");
719 return LB_STATUS_ERROR_FAULT;
722 name = get_token(ptr, &len);
724 ErrPrint("Failed to get token, len:%d\n", len);
728 while (*ptr && isspace(*ptr)) ptr++;
734 category = group_find_category(cluster, name);
736 category = group_create_category(cluster, name);
739 ErrPrint("Failed to get category\n");
741 return LB_STATUS_ERROR_FAULT;
744 info = group_create_context_info(category, pkgname);
746 ErrPrint("Failed to create ctx info\n");
748 return LB_STATUS_ERROR_FAULT;
751 DbgPrint("Keep this syntax only for the compatibility: %s\n", name);
756 category = group_find_category(cluster, name);
758 category = group_create_category(cluster, name);
761 ErrPrint("Failed to get category\n");
763 return LB_STATUS_ERROR_FAULT;
766 info = group_create_context_info(category, pkgname);
768 ErrPrint("Failed to create ctx info\n");
770 return LB_STATUS_ERROR_FAULT;
773 DbgPrint("Keep this syntax only for the compatibility: %s\n", name);
775 } else if (is_open == 2) {
778 ErrPrint("Invalid state\n");
780 return LB_STATUS_ERROR_FAULT;
783 case CONTEXT_OPTION_VALUE:
785 ErrPrint("Invalid state (%s)\n", name);
787 return LB_STATUS_ERROR_FAULT;
790 if (group_add_option(item, key, name) < 0)
791 ErrPrint("Failed to add a new option: %s - %s\n", key, name);
796 state = CONTEXT_ITEM;
798 case CONTEXT_OPTION_KEY:
801 ErrPrint("Invalid state (%s)\n", name);
809 while (*ptr && isspace(*ptr)) ptr++;
817 if (state != CLUSTER)
818 return LB_STATUS_ERROR_INVALID;
820 return LB_STATUS_SUCCESS;
823 HAPI int group_del_livebox(const char *pkgname)
831 struct cluster *cluster;
832 struct category *category;
833 struct context_info *info;
835 EINA_LIST_FOREACH_SAFE(s_info.cluster_list, l, n, cluster) {
836 EINA_LIST_FOREACH_SAFE(cluster->category_list, s_l, s_n, category) {
837 EINA_LIST_FOREACH_SAFE(category->info_list, i_l, i_n, info) {
838 if (!strcmp(pkgname, info->pkgname))
839 group_destroy_context_info(info);
842 if (!category->info_list)
843 group_destroy_category(category);
846 if (!cluster->category_list)
847 group_destroy_cluster(cluster);
850 return LB_STATUS_SUCCESS;
853 HAPI int group_init(void)
855 return LB_STATUS_SUCCESS;
858 HAPI int group_fini(void)
860 struct cluster *cluster;
861 struct category *category;
863 EINA_LIST_FREE(s_info.cluster_list, cluster) {
865 EINA_LIST_FREE(cluster->category_list, category) {
866 destroy_category(category);
869 destroy_cluster(cluster);
871 return LB_STATUS_SUCCESS;