Explorar o código

scheme: Macros for add, find, compare and compare_by_key standard functions

Serj Kalichev %!s(int64=3) %!d(string=hai) anos
pai
achega
144aa10eb6
Modificáronse 7 ficheiros con 186 adicións e 95 borrados
  1. 51 2
      klish/khelper.h
  2. 14 2
      klish/kptype.h
  3. 3 1
      klish/kscheme.h
  4. 3 2
      klish/kscheme/ischeme.c
  5. 86 25
      klish/kscheme/kptype.c
  6. 22 45
      klish/kscheme/kscheme.c
  7. 7 18
      klish/kscheme/kview.c

+ 51 - 2
klish/khelper.h

@@ -10,7 +10,7 @@
 
 // Function to get value from structure by name
 #define _KGET(obj, type, name) \
-	type obj##_##name(const obj##_t *inst)
+	type k##obj##_##name(const k##obj##_t *inst)
 #define KGET(obj, type, name) \
 	_KGET(obj, type, name) { \
 		assert(inst); \
@@ -29,7 +29,7 @@
 
 // Function to set value to structure by name
 #define _KSET(obj, type, name) \
-	bool_t obj##_set_##name(obj##_t *inst, type val)
+	bool_t k##obj##_set_##name(k##obj##_t *inst, type val)
 #define KSET(obj, type, name) \
 	_KSET(obj, type, name) { \
 		assert(inst); \
@@ -71,4 +71,53 @@
 #define KSET_BOOL(obj, name) \
 	KSET(obj, bool_t, name)
 
+// Function to add object to list
+#define _KADD_NESTED(obj, nested) \
+	bool_t k##obj##_add_##nested(k##obj##_t *inst, k##nested##_t *subobj)
+#define KADD_NESTED(obj, nested) \
+	_KADD_NESTED(obj, nested) { \
+	assert(inst); \
+	if (!inst) \
+		return BOOL_FALSE; \
+	assert(subobj); \
+	if (!subobj) \
+		return BOOL_FALSE; \
+	if (!faux_list_add(inst->nested##s, subobj)) \
+		return BOOL_FALSE; \
+	return BOOL_TRUE; \
+}
+
+#define _KFIND_NESTED(obj, nested) \
+	k##nested##_t *k##obj##_find_##nested(const k##obj##_t *inst, const char *str_key)
+#define KFIND_NESTED(obj, nested) \
+	_KFIND_NESTED(obj, nested) { \
+	assert(inst); \
+	if (!inst) \
+		return NULL; \
+	assert(str_key); \
+	if (!str_key) \
+		return NULL; \
+	return (k##nested##_t *)faux_list_kfind(inst->nested##s, str_key); \
+}
+
+// Compare functions. For lists
+#define _KCMP_NESTED(obj, nested, field) \
+	int k##obj##_##nested##_compare(const void *first, const void *second)
+#define KCMP_NESTED(obj, nested, field) \
+	_KCMP_NESTED(obj, nested, field) { \
+	const k##nested##_t *f = (const k##nested##_t *)first; \
+	const k##nested##_t *s = (const k##nested##_t *)second; \
+	return strcmp(k##nested##_##field(f), k##nested##_##field(s)); \
+}
+
+#define _KCMP_NESTED_BY_KEY(obj, nested, field) \
+	int k##obj##_##nested##_kcompare(const void *key, const void *list_item)
+#define KCMP_NESTED_BY_KEY(obj, nested, field) \
+	_KCMP_NESTED_BY_KEY(obj, nested, field) { \
+	const char *f = (const char *)key; \
+	const k##nested##_t *s = (const k##nested##_t *)list_item; \
+	return strcmp(f, k##nested##_##field(s)); \
+}
+
+
 #endif // _khelper_h

+ 14 - 2
klish/kptype.h

@@ -17,14 +17,26 @@ typedef struct iptype_s {
 } iptype_t;
 
 
+typedef enum {
+	KPTYPE_ERROR_OK,
+	KPTYPE_ERROR_INTERNAL,
+	KPTYPE_ERROR_ALLOC,
+	KPTYPE_ERROR_ATTR_NAME,
+	KPTYPE_ERROR_ATTR_HELP,
+} kptype_error_e;
+
+
 C_DECL_BEGIN
 
-kptype_t *kptype_new(iptype_t info);
-kptype_t *kptype_new_static(iptype_t info);
 void kptype_free(kptype_t *ptype);
+bool_t kptype_parse(kptype_t *ptype, const iptype_t *info, kptype_error_e *error);
+kptype_t *kptype_new(const iptype_t *info, kptype_error_e *error);
+const char *kptype_strerror(kptype_error_e error);
 
 const char *kptype_name(const kptype_t *ptype);
+bool_t kptype_set_name(kptype_t *ptype, const char *name);
 const char *kptype_help(const kptype_t *ptype);
+bool_t kptype_set_help(kptype_t *ptype, const char *help);
 
 C_DECL_END
 

+ 3 - 1
klish/kscheme.h

@@ -56,10 +56,12 @@ C_DECL_BEGIN
 
 kscheme_t *kscheme_new(kscheme_error_e *error);
 void kscheme_free(kscheme_t *scheme);
-
 const char *kscheme_strerror(kscheme_error_e error);
+
 bool_t kscheme_add_view(kscheme_t *scheme, kview_t *view);
 kview_t *kscheme_find_view(const kscheme_t *scheme, const char *name);
+bool_t kscheme_add_ptype(kscheme_t *scheme, kptype_t *ptype);
+kptype_t *kscheme_find_ptype(const kscheme_t *scheme, const char *name);
 
 kscheme_t *kscheme_from_ischeme(ischeme_t *ischeme, faux_error_t *error_stack);
 

+ 3 - 2
klish/kscheme/ischeme.c

@@ -74,7 +74,7 @@ kview_t *kview_from_iview(iview_t *iview, faux_error_t *error_stack)
 }
 
 
-bool_t kptype_nested_from_iptype(kptype_t *kptype, iview_t *iptype,
+bool_t kptype_nested_from_iptype(kptype_t *kptype, iptype_t *iptype,
 	faux_error_t *error_stack)
 {
 	if (!kptype || !iptype) {
@@ -90,6 +90,7 @@ bool_t kptype_nested_from_iptype(kptype_t *kptype, iview_t *iptype,
 		for (p_iaction = *iptype->actions; *p_iaction; p_iaction++) {
 			kaction_t *kaction = NULL;
 			iaction_t *iaction = *p_iaction;
+iaction = iaction;
 printf("action\n");
 //			kaction = kaction_from_iaction(iaction, error_stack);
 //			if (!kaction)
@@ -129,7 +130,7 @@ kptype_t *kptype_from_iptype(iptype_t *iptype, faux_error_t *error_stack)
 	if (error_stack && (faux_error_len(error_stack) > error_stack_len)) {
 		char *msg = NULL;
 		msg = faux_str_sprintf("PTYPE \"%s\": Illegal nested elements",
-			kptype_name(kview));
+			kptype_name(kptype));
 		faux_error_add(error_stack, msg);
 		faux_str_free(msg);
 	}

+ 86 - 25
klish/kscheme/kptype.c

@@ -5,16 +5,28 @@
 
 #include <faux/str.h>
 #include <faux/list.h>
+#include <klish/khelper.h>
 #include <klish/kptype.h>
 
 
 struct kptype_s {
-	bool_t is_static;
-	iptype_t info;
+	char *name;
+	char *help;
 };
 
 
-static kptype_t *kptype_new_internal(iptype_t info, bool_t is_static)
+// Simple attributes
+
+// Name
+KGET_STR(ptype, name);
+KSET_STR_ONCE(ptype, name);
+
+// Help
+KGET_STR(ptype, help);
+KSET_STR(ptype, help);
+
+
+static kptype_t *kptype_new_empty(void)
 {
 	kptype_t *ptype = NULL;
 
@@ -24,22 +36,34 @@ static kptype_t *kptype_new_internal(iptype_t info, bool_t is_static)
 		return NULL;
 
 	// Initialize
-	ptype->is_static = is_static;
-	ptype->info = info;
+	ptype->name = NULL;
+	ptype->help = NULL;
 
 	return ptype;
 }
 
 
-kptype_t *kptype_new(iptype_t info)
+kptype_t *kptype_new(const iptype_t *info, kptype_error_e *error)
 {
-	return kptype_new_internal(info, BOOL_FALSE);
-}
+	kptype_t *ptype = NULL;
 
+	ptype = kptype_new_empty();
+	assert(ptype);
+	if (!ptype) {
+		if (error)
+			*error = KPTYPE_ERROR_ALLOC;
+		return NULL;
+	}
 
-kptype_t *kptype_new_static(iptype_t info)
-{
-	return kptype_new_internal(info, BOOL_TRUE);
+	if (!info)
+		return ptype;
+
+	if (!kptype_parse(ptype, info, error)) {
+		kptype_free(ptype);
+		return NULL;
+	}
+
+	return ptype;
 }
 
 
@@ -48,30 +72,67 @@ void kptype_free(kptype_t *ptype)
 	if (!ptype)
 		return;
 
-	if (!ptype->is_static) {
-		faux_str_free(ptype->info.name);
-		faux_str_free(ptype->info.help);
-	}
+	faux_str_free(ptype->name);
+	faux_str_free(ptype->help);
 
 	faux_free(ptype);
 }
 
 
-const char *kptype_name(const kptype_t *ptype)
+const char *kptype_strerror(kptype_error_e error)
 {
-	assert(ptype);
-	if (!ptype)
-		return NULL;
+	const char *str = NULL;
+
+	switch (error) {
+	case KPTYPE_ERROR_OK:
+		str = "Ok";
+		break;
+	case KPTYPE_ERROR_INTERNAL:
+		str = "Internal error";
+		break;
+	case KPTYPE_ERROR_ALLOC:
+		str = "Memory allocation error";
+		break;
+	case KPTYPE_ERROR_ATTR_NAME:
+		str = "Illegal 'name' attribute";
+		break;
+	case KPTYPE_ERROR_ATTR_HELP:
+		str = "Illegal 'help' attribute";
+		break;
+	default:
+		str = "Unknown error";
+		break;
+	}
 
-	return ptype->info.name;
+	return str;
 }
 
 
-const char *kptype_help(const kptype_t *ptype)
+bool_t kptype_parse(kptype_t *ptype, const iptype_t *info, kptype_error_e *error)
 {
-	assert(ptype);
-	if (!ptype)
-		return NULL;
+	bool_t retval = BOOL_TRUE;
+
+	// Name [mandatory]
+	if (faux_str_is_empty(info->name)) {
+		if (error)
+			*error = KPTYPE_ERROR_ATTR_NAME;
+		retval = BOOL_FALSE;
+	} else {
+		if (!kptype_set_name(ptype, info->name)) {
+			if (error)
+				*error = KPTYPE_ERROR_ATTR_NAME;
+			retval = BOOL_FALSE;
+		}
+	}
+
+	// Help
+	if (!faux_str_is_empty(info->name)) {
+		if (!kptype_set_help(ptype, info->help)) {
+			if (error)
+				*error = KPTYPE_ERROR_ATTR_HELP;
+			retval = BOOL_FALSE;
+		}
+	}
 
-	return ptype->info.help;
+	return retval;
 }

+ 22 - 45
klish/kscheme/kscheme.c

@@ -5,31 +5,30 @@
 
 #include <faux/str.h>
 #include <faux/list.h>
+#include <klish/khelper.h>
+#include <klish/kptype.h>
 #include <klish/kview.h>
 #include <klish/kscheme.h>
 
 
 struct kscheme_s {
+	faux_list_t *ptypes;
 	faux_list_t *views;
 };
 
+// Simple methods
 
-static int kscheme_view_compare(const void *first, const void *second)
-{
-	const kview_t *f = (const kview_t *)first;
-	const kview_t *s = (const kview_t *)second;
-
-	return strcmp(kview_name(f), kview_name(s));
-}
-
+// PTYPE list
+KCMP_NESTED(scheme, ptype, name);
+KCMP_NESTED_BY_KEY(scheme, ptype, name);
+KADD_NESTED(scheme, ptype);
+KFIND_NESTED(scheme, ptype);
 
-static int kscheme_view_kcompare(const void *key, const void *list_item)
-{
-	const char *f = (const char *)key;
-	const kview_t *s = (const kview_t *)list_item;
-
-	return strcmp(f, kview_name(s));
-}
+// VIEW list
+KCMP_NESTED(scheme, view, name);
+KCMP_NESTED_BY_KEY(scheme, view, name);
+KADD_NESTED(scheme, view);
+KFIND_NESTED(scheme, view);
 
 
 kscheme_t *kscheme_new(kscheme_error_e *error)
@@ -44,7 +43,13 @@ kscheme_t *kscheme_new(kscheme_error_e *error)
 		return NULL;
 	}
 
-	// Initialize
+	// PTYPE list
+	scheme->ptypes = faux_list_new(FAUX_LIST_SORTED, FAUX_LIST_UNIQUE,
+		kscheme_ptype_compare, kscheme_ptype_kcompare,
+		(void (*)(void *))kptype_free);
+	assert(scheme->ptypes);
+
+	// VIEW list
 	scheme->views = faux_list_new(FAUX_LIST_SORTED, FAUX_LIST_UNIQUE,
 		kscheme_view_compare, kscheme_view_kcompare,
 		(void (*)(void *))kview_free);
@@ -59,6 +64,7 @@ void kscheme_free(kscheme_t *scheme)
 	if (!scheme)
 		return;
 
+	faux_list_free(scheme->ptypes);
 	faux_list_free(scheme->views);
 	faux_free(scheme);
 }
@@ -85,32 +91,3 @@ const char *kscheme_strerror(kscheme_error_e error)
 
 	return str;
 }
-
-
-bool_t kscheme_add_view(kscheme_t *scheme, kview_t *view)
-{
-	assert(scheme);
-	if (!scheme)
-		return BOOL_FALSE;
-	assert(view);
-	if (!view)
-		return BOOL_FALSE;
-
-	if (!faux_list_add(scheme->views, view))
-		return BOOL_FALSE;
-
-	return BOOL_TRUE;
-}
-
-
-kview_t *kscheme_find_view(const kscheme_t *scheme, const char *name)
-{
-	assert(scheme);
-	if (!scheme)
-		return NULL;
-	assert(name);
-	if (!name)
-		return NULL;
-
-	return (kview_t *)faux_list_kfind(scheme->views, name);
-}

+ 7 - 18
klish/kscheme/kview.c

@@ -16,8 +16,13 @@ struct kview_s {
 
 
 // Simple attributes
-KGET_STR(kview, name);
-KSET_STR_ONCE(kview, name);
+
+// Name
+KGET_STR(view, name);
+KSET_STR_ONCE(view, name);
+
+// COMMAND's list
+KADD_NESTED(view, command);
 
 
 static int kview_command_compare(const void *first, const void *second)
@@ -140,19 +145,3 @@ bool_t kview_parse(kview_t *view, const iview_t *info, kview_error_e *error)
 
 	return retval;
 }
-
-
-bool_t kview_add_command(kview_t *view, kcommand_t *command)
-{
-	assert(view);
-	if (!view)
-		return BOOL_FALSE;
-	assert(command);
-	if (!command)
-		return BOOL_FALSE;
-
-	if (!faux_list_add(view->commands, command))
-		return BOOL_FALSE;
-
-	return BOOL_TRUE;
-}