소스 검색

faux: Unfinished ini

Serj Kalichev 4 년 전
부모
커밋
70f95e15c6
11개의 변경된 파일306개의 추가작업 그리고 272개의 파일을 삭제
  1. 13 14
      faux/Makefile.am
  2. 44 44
      faux/ini.h
  3. 4 0
      faux/ini/Makefile.am
  4. 164 119
      faux/ini/ini.c
  5. 0 7
      faux/ini/module.am
  6. 67 64
      faux/ini/pair.c
  7. 4 12
      faux/ini/private.h
  8. 1 1
      faux/list.h
  9. 1 1
      faux/list/list.c
  10. 3 2
      faux/str.h
  11. 5 8
      faux/str/str.c

+ 13 - 14
faux/Makefile.am

@@ -9,26 +9,25 @@ nobase_include_HEADERS += \
 	faux/sysdb.h \
 	faux/conv.h \
 	faux/log.h \
-	faux/list.h
+	faux/list.h \
+	faux/ini.h
 
 #	faux/argv.h \
 #	faux/dump.h \
-#	faux/system.h \
-#	faux/ini.h
+#	faux/system.h
 
 EXTRA_DIST += \
 	faux/ctype/Makefile.am \
 	faux/str/Makefile.am \
 	faux/sysdb/Makefile.am \
 	faux/conv/Makefile.am \
-	faux/log/module.am \
-	faux/list/module.am
+	faux/log/Makefile.am \
+	faux/list/Makefile.am \
+	faux/ini/Makefile.am
 
-#	faux/argv/module.am \
-#	faux/dump/module.am \
-#	faux/system/module.am \
-#	faux/ini/module.am \
-#	faux/log/module.am \
+#	faux/argv/Makefile.am \
+#	faux/dump/Makefile.am \
+#	faux/system/Makefile.am \
 #	faux/README
 
 include $(top_srcdir)/faux/ctype/Makefile.am
@@ -37,8 +36,8 @@ include $(top_srcdir)/faux/sysdb/Makefile.am
 include $(top_srcdir)/faux/conv/Makefile.am
 include $(top_srcdir)/faux/log/Makefile.am
 include $(top_srcdir)/faux/list/Makefile.am
+include $(top_srcdir)/faux/ini/Makefile.am
 
-#include $(top_srcdir)/faux/argv/module.am
-#include $(top_srcdir)/faux/dump/module.am
-#include $(top_srcdir)/faux/system/module.am
-#include $(top_srcdir)/faux/ini/module.am
+#include $(top_srcdir)/faux/argv/Makefile.am
+#include $(top_srcdir)/faux/dump/Makefile.am
+#include $(top_srcdir)/faux/system/Makefile.am

+ 44 - 44
faux/ini.h

@@ -1,46 +1,46 @@
-/*
- * ini.h
+/** @file ini.h
+ * @brief Public interface to work with ini files and strings.
  */
 
-#ifndef _lub_ini_h
-#define _lub_ini_h
-
-#include "lub/c_decl.h"
-#include "lub/list.h"
-
-typedef struct lub_pair_s lub_pair_t;
-typedef struct lub_ini_s lub_ini_t;
-typedef lub_list_node_t lub_ini_node_t;
-
-_BEGIN_C_DECL
-
-/* Pair */
-int lub_pair_compare(const void *first, const void *second);
-void lub_pair_init(lub_pair_t *instance, const char *name, const char *value);
-lub_pair_t *lub_pair_new(const char *name, const char *value);
-void lub_pair_fini(lub_pair_t *instance);
-void lub_pair_free(void *instance);
-const char *lub_pair__get_name(const lub_pair_t *instance);
-void lub_pair__set_name(lub_pair_t *instance, const char *name);
-const char *lub_pair__get_value(const lub_pair_t *instance);
-void lub_pair__set_value(lub_pair_t *instance, const char *value);
-
-/* Ini */
-void lub_ini_init(lub_ini_t *instance);
-lub_ini_t *lub_ini_new(void);
-void lub_ini_fini(lub_ini_t *instance);
-void lub_ini_free(lub_ini_t *instance);
-lub_pair_t *lub_ini_find_pair(const lub_ini_t *instance, const char *name);
-const char *lub_ini_find(const lub_ini_t *instance, const char *name);
-void lub_ini_add(lub_ini_t *instance, lub_pair_t *pair);
-int lub_ini_parse_str(lub_ini_t *instance, const char *ini);
-int lub_ini_parse_file(lub_ini_t *instance, const char *fn);
-lub_ini_node_t *lub_ini__get_head(lub_ini_t *instance);
-lub_ini_node_t *lub_ini__get_tail(lub_ini_t *instance);
-lub_ini_node_t *lub_ini__get_next(lub_ini_node_t *node);
-lub_ini_node_t *lub_ini__get_prev(lub_ini_node_t *node);
-lub_pair_t *lub_ini__iter_data(lub_ini_node_t *node);
-
-_END_C_DECL
-
-#endif				/* _lub_ini_h */
+#ifndef _faux_ini_h
+#define _faux_ini_h
+
+#include "faux/types.h"
+#include "faux/list.h"
+
+typedef struct faux_pair_s faux_pair_t;
+typedef struct faux_ini_s faux_ini_t;
+typedef faux_list_node_t faux_ini_node_t;
+
+C_DECL_BEGIN
+
+// Pair
+int faux_pair_compare(const void *first, const void *second);
+faux_pair_t *faux_pair_new(const char *name, const char *value);
+void faux_pair_free(void *pair);
+
+const char *faux_pair_name(const faux_pair_t *pair);
+void faux_pair_set_name(faux_pair_t *pair, const char *name);
+const char *faux_pair_value(const faux_pair_t *pair);
+void faux_pair_set_value(faux_pair_t *pair, const char *value);
+
+// Ini
+faux_ini_t *faux_ini_new(void);
+void faux_ini_free(faux_ini_t *ini);
+
+faux_ini_node_t *faux_ini_head(const faux_ini_t *ini);
+faux_ini_node_t *faux_ini_tail(const faux_ini_t *ini);
+faux_ini_node_t *faux_ini_next(const faux_ini_node_t *node);
+faux_ini_node_t *faux_ini_prev(const faux_ini_node_t *node);
+faux_pair_t *faux_ini_data(const faux_ini_node_t *node);
+
+faux_pair_t *faux_ini_add(faux_ini_t *ini, const char *name, const char *value);
+int faux_ini_parse_str(faux_ini_t *ini, const char *str);
+int faux_ini_parse_file(faux_ini_t *ini, const char *fn);
+
+faux_pair_t *faux_ini_find_pair(const faux_ini_t *ini, const char *name);
+const char *faux_ini_find(const faux_ini_t *ini, const char *name);
+
+C_DECL_END
+
+#endif				/* _faux_ini_h */

+ 4 - 0
faux/ini/Makefile.am

@@ -0,0 +1,4 @@
+libfaux_la_SOURCES += \
+	faux/ini/pair.c \
+	faux/ini/ini.c \
+	faux/ini/private.h

+ 164 - 119
faux/ini/ini.c

@@ -1,154 +1,183 @@
-/*
- * ini.c
+/** @file ini.c
+ * @brief Functions for working with INI files.
  */
 
-#include "private.h"
-#include "lub/string.h"
-
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <assert.h>
 #include <ctype.h>
 
-/*--------------------------------------------------------- */
-void lub_ini_init(lub_ini_t *this)
-{
-	assert(this);
-	memset(this, 0, sizeof(*this));
-	this->list = lub_list_new(lub_pair_compare, lub_pair_free);
-}
+#include "private.h"
+#include "faux/str.h"
+#include "faux/ini.h"
 
-/*--------------------------------------------------------- */
-lub_ini_t *lub_ini_new(void)
-{
-	lub_ini_t *this;
 
-	this = malloc(sizeof(*this));
-	if (this)
-		lub_ini_init(this);
+faux_ini_t *faux_ini_new(void) {
 
-	return this;
-}
+	faux_ini_t *ini;
 
-/*--------------------------------------------------------- */
-void lub_ini_fini(lub_ini_t *this)
-{
-	lub_list_free_all(this->list);
-}
+	ini = malloc(sizeof(*ini));
+	if (!ini)
+		return NULL;
+
+	// Init
+	memset(ini, 0, sizeof(*ini));
+	ini->list = faux_list_new(faux_pair_compare, faux_pair_free);
 
-/*--------------------------------------------------------- */
-void lub_ini_free(lub_ini_t *this)
-{
-	assert(this);
-	lub_ini_fini(this);
-	free(this);
+	return ini;
 }
 
-/*--------------------------------------------------------- */
-void lub_ini_add(lub_ini_t *this, lub_pair_t *pair)
-{
-	assert(this);
-	lub_list_add(this->list, pair);
+
+void faux_ini_free(faux_ini_t *ini) {
+
+	assert(ini);
+	if (!ini)
+		return;
+
+	faux_list_free(ini->list);
+	free(ini);
 }
 
-/*--------------------------------------------------------- */
-/* Find pair by name */
-lub_pair_t *lub_ini_find_pair(const lub_ini_t *this, const char *name)
-{
-	lub_list_node_t *iter;
-	lub_pair_t *pair;
 
-	if (!this || !name)
+faux_pair_t *faux_ini_add(faux_ini_t *ini, const char *name, const char *value) {
+
+	faux_pair_t *pair = NULL;
+	faux_list_node_t *node = NULL;
+	faux_pair_t *found_pair = NULL;
+
+	assert(ini);
+	if (!ini)
+		return NULL;
+
+	pair = faux_pair_new(name, value);
+	if (!pair)
 		return NULL;
-	/* Iterate elements */
-	for(iter = lub_list__get_head(this->list);
-		iter; iter = lub_list_node__get_next(iter)) {
-		int res;
-		pair = (lub_pair_t *)lub_list_node__get_data(iter);
-		res = strcmp(lub_pair__get_name(pair), name);
-		if (!res)
-			return pair;
-		if (res > 0) /* No chance to find name */
-			break;
+	node = faux_list_add_find(ini->list, pair);
+	if (NULL == node) { // Something went wrong
+		faux_pair_free(pair);
+		return NULL;
+	}
+	found_pair = faux_list_data(node);
+	if (found_pair != pair) { // Item already exists
+		faux_pair_free(pair);
+		faux_pair_set_value(found_pair, value); // Replace value by new one
+		return found_pair;
 	}
 
-	return NULL;
+	return pair;
 }
 
-/*--------------------------------------------------------- */
+
 /* Find pair by name */
-const char *lub_ini_find(const lub_ini_t *this, const char *name)
-{
-	lub_pair_t *pair = lub_ini_find_pair(this, name);
+faux_pair_t *faux_ini_find_pair(const faux_ini_t *ini, const char *name) {
+
+	faux_list_node_t *iter = NULL;
+	faux_pair_t *pair = NULL;
+
+	assert(ini);
+	assert(name);
+	if (!ini || !name)
+		return NULL;
 
+	pair = faux_pair_new(name, NULL);
 	if (!pair)
 		return NULL;
-	return lub_pair__get_value(pair);
+	iter = faux_list_find_node(ini->list, faux_pair_compare, pair);
+	faux_pair_free(pair);
+
+	return faux_list_data(iter);
 }
 
-/*--------------------------------------------------------- */
-int lub_ini_parse_str(lub_ini_t *this, const char *ini)
-{
-	char *buffer;
+
+/* Find value by name */
+const char *faux_ini_find(const faux_ini_t *ini, const char *name) {
+
+	faux_pair_t *pair = faux_ini_find_pair(ini, name);
+
+	if (!pair)
+		return NULL;
+
+	return faux_pair_value(pair);
+}
+
+
+int faux_ini_parse_str(faux_ini_t *ini, const char *string) {
+
+	char *buffer = NULL;
 	char *saveptr = NULL;
-	char *line;
+	char *line = NULL;
 
-	buffer = lub_string_dup(ini);
-	/* Now loop though each line */
+	assert(ini);
+	if (!ini)
+		return -1;
+	if (!string)
+		return 0;
+
+	buffer = faux_str_dup(string);
+	// Now loop though each line
 	for (line = strtok_r(buffer, "\n", &saveptr);
 		line; line = strtok_r(NULL, "\n", &saveptr)) {
 
-		char *str, *name, *value, *savestr = NULL, *ns = line;
-		const char *begin;
-		size_t len, offset, quoted;
-		char *rname, *rvalue;
-		lub_pair_t *pair;
-
-		if (!*ns) /* Empty */
+		char *str = NULL;
+		char *name = NULL;
+		char *value = NULL;
+		char *savestr = NULL;
+		char *ns = line;
+		const char *begin = NULL;
+		size_t len = 0;
+		size_t offset = 0;
+		size_t quoted = 0;
+		char *rname = NULL;
+		char *rvalue = NULL;
+
+		if (!*ns) // Empty
 			continue;
 		while (*ns && isspace(*ns))
 			ns++;
-		if ('#' == *ns) /* Comment */
+		if ('#' == *ns) // Comment
 			continue;
-		if ('=' == *ns) /* Broken string */
+		if ('=' == *ns) // Broken string
 			continue;
-		str = lub_string_dup(ns);
+		str = faux_str_dup(ns);
 		name = strtok_r(str, "=", &savestr);
 		if (!name) {
-			lub_string_free(str);
+			faux_str_free(str);
 			continue;
 		}
 		value = strtok_r(NULL, "=", &savestr);
-		begin = lub_string_nextword(name, &len, &offset, &quoted);
-		rname = lub_string_dupn(begin, len);
-		if (!value) /* Empty value */
+		begin = faux_str_nextword(name, &len, &offset, &quoted);
+		rname = faux_str_dupn(begin, len);
+		if (!value) { // Empty value
 			rvalue = NULL;
-		else {
-			begin = lub_string_nextword(value, &len, &offset, &quoted);
-			rvalue = lub_string_dupn(begin, len);
+		} else {
+			begin = faux_str_nextword(value, &len, &offset, &quoted);
+			rvalue = faux_str_dupn(begin, len);
 		}
-		pair = lub_pair_new(rname, rvalue);
-		lub_ini_add(this, pair);
-		lub_string_free(rname);
-		lub_string_free(rvalue);
-		lub_string_free(str);
+		faux_ini_add(ini, rname, rvalue);
+		faux_str_free(rname);
+		faux_str_free(rvalue);
+		faux_str_free(str);
 	}
-	lub_string_free(buffer);
+	faux_str_free(buffer);
 
 	return 0;
 }
 
-/*--------------------------------------------------------- */
-int lub_ini_parse_file(lub_ini_t *this, const char *fn)
-{
+
+int faux_ini_parse_file(faux_ini_t *ini, const char *fn) {
+
 	int ret = -1;
-	FILE *f;
-	char *buf;
+	FILE *f = NULL;
+	char *buf = NULL;
 	unsigned int p = 0;
 	const int chunk_size = 128;
 	int size = chunk_size;
 
+	assert(ini);
+	assert(fn);
+	if (!ini)
+		return -1;
 	if (!fn || !*fn)
 		return -1;
 	f = fopen(fn, "r");
@@ -157,9 +186,10 @@ int lub_ini_parse_file(lub_ini_t *this, const char *fn)
 
 	buf = malloc(size);
 	while (fgets(buf + p, size - p, f)) {
-		char *tmp;
+		char *tmp = NULL;
+
 		if (feof(f) || strchr(buf + p, '\n') || strchr(buf + p, '\r')) {
-			lub_ini_parse_str(this, buf);
+			faux_ini_parse_str(ini, buf);
 			p = 0;
 			continue;
 		}
@@ -179,37 +209,52 @@ error:
 	return ret;
 }
 
-/*--------------------------------------------------------- */
-lub_ini_node_t *lub_ini__get_head(lub_ini_t *this)
-{
-	return lub_list__get_head(this->list);
-}
 
-/*--------------------------------------------------------- */
-lub_ini_node_t *lub_ini__get_tail(lub_ini_t *this)
-{
-	return lub_list__get_tail(this->list);
+faux_ini_node_t *faux_ini_head(const faux_ini_t *ini) {
+
+	assert(ini);
+	if (!ini)
+		return NULL;
+
+	return faux_list_head(ini->list);
 }
 
-/*--------------------------------------------------------- */
 
-lub_ini_node_t *lub_ini__get_next(lub_ini_node_t *node)
-{
-	return lub_list_node__get_next(node);
+faux_ini_node_t *faux_ini_tail(const faux_ini_t *ini) {
+
+	assert(ini);
+	if (!ini)
+		return NULL;
+
+	return faux_list_tail(ini->list);
 }
 
-/*--------------------------------------------------------- */
 
-lub_ini_node_t *lub_ini__get_prev(lub_ini_node_t *node)
-{
-	return lub_list_node__get_next(node);
+faux_ini_node_t *faux_ini_next(const faux_ini_node_t *node) {
+
+	assert(node);
+	if (!node)
+		return NULL;
+
+	return faux_list_next_node(node);
 }
 
-/*--------------------------------------------------------- */
 
-lub_pair_t *lub_ini__iter_data(lub_ini_node_t *node)
-{
-	return (lub_pair_t *)lub_list_node__get_data(node);
+faux_ini_node_t *faux_ini_prev(const faux_ini_node_t *node) {
+
+	assert(node);
+	if (!node)
+		return NULL;
+
+	return faux_list_prev_node(node);
 }
 
-/*--------------------------------------------------------- */
+
+faux_pair_t *faux_ini_data(const faux_ini_node_t *node) {
+
+	assert(node);
+	if (!node)
+		return NULL;
+
+	return (faux_pair_t *)faux_list_data(node);
+}

+ 0 - 7
faux/ini/module.am

@@ -1,7 +0,0 @@
-liblub_la_SOURCES += \
-	lub/ini/pair.c \
-	lub/ini/ini.c \
-	lub/ini/private.h
-
-
-

+ 67 - 64
faux/ini/pair.c

@@ -1,89 +1,92 @@
-/*
- * pair.c
+/** @file pair.c
+ * Ini file pairs key/value.
  */
 
-#include "private.h"
-#include "lub/string.h"
-
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
 
-/*--------------------------------------------------------- */
-int lub_pair_compare(const void *first, const void *second)
-{
-	const lub_pair_t *f = (const lub_pair_t *)first;
-	const lub_pair_t *s = (const lub_pair_t *)second;
+#include "private.h"
+#include "faux/str.h"
+#include "faux/ini.h"
+
+int faux_pair_compare(const void *first, const void *second) {
+
+	const faux_pair_t *f = (const faux_pair_t *)first;
+	const faux_pair_t *s = (const faux_pair_t *)second;
 
 	return strcmp(f->name, s->name);
 }
 
-/*--------------------------------------------------------- */
-void lub_pair_init(lub_pair_t *this, const char *name, const char *value)
-{
-	assert(this);
-	memset(this, 0, sizeof(*this));
-	this->name = lub_string_dup(name);
-	this->value = lub_string_dup(value);
-}
 
-/*--------------------------------------------------------- */
-lub_pair_t *lub_pair_new(const char *name, const char *value)
-{
-	lub_pair_t *this;
+faux_pair_t *faux_pair_new(const char *name, const char *value) {
 
-	this = malloc(sizeof(*this));
-	if (this)
-		lub_pair_init(this, name, value);
+	faux_pair_t *pair = NULL;
 
-	return this;
-}
+	pair = malloc(sizeof(*pair));
+	assert(pair);
+	if (!pair)
+		return NULL;
 
-/*--------------------------------------------------------- */
-void lub_pair_fini(lub_pair_t *this)
-{
-	assert(this);
-	lub_string_free(this->name);
-	lub_string_free(this->value);
-}
+	// Initialize
+	memset(pair, 0, sizeof(*pair));
+	pair->name = faux_str_dup(name);
+	pair->value = faux_str_dup(value);
 
-/*--------------------------------------------------------- */
-void lub_pair_free(void *data)
-{
-	assert(data);
-	lub_pair_t *this = (lub_pair_t *)data;
-	lub_pair_fini(this);
-	free(this);
+	return pair;
 }
 
-/*--------------------------------------------------------- */
-const char *lub_pair__get_name(const lub_pair_t *this)
-{
-	assert(this);
-	return this->name;
+
+void faux_pair_free(void *ptr) {
+
+	faux_pair_t *pair = (faux_pair_t *)ptr;
+
+	assert(pair);
+	if (!pair)
+		return;
+	faux_str_free(pair->name);
+	faux_str_free(pair->value);
+	free(pair);
 }
 
-/*--------------------------------------------------------- */
-void lub_pair__set_name(lub_pair_t *this, const char *name)
-{
-	assert(this);
-	lub_string_free(this->name);
-	this->name = lub_string_dup(name);
+
+const char *faux_pair_name(const faux_pair_t *pair) {
+
+	assert(pair);
+	if (!pair)
+		return NULL;
+
+	return pair->name;
 }
 
-/*--------------------------------------------------------- */
-const char *lub_pair__get_value(const lub_pair_t *this)
-{
-	assert(this);
-	return this->value;
+
+void faux_pair_set_name(faux_pair_t *pair, const char *name) {
+
+	assert(pair);
+	if (!pair)
+		return;
+
+	faux_str_free(pair->name);
+	pair->name = faux_str_dup(name);
 }
 
-/*--------------------------------------------------------- */
-void lub_pair__set_value(lub_pair_t *this, const char *value)
-{
-	assert(this);
-	lub_string_free(this->value);
-	this->value = lub_string_dup(value);
+
+const char *faux_pair_value(const faux_pair_t *pair) {
+
+	assert(pair);
+	if (!pair)
+		return NULL;
+
+	return pair->value;
 }
 
-/*--------------------------------------------------------- */
+
+void faux_pair_set_value(faux_pair_t *pair, const char *value) {
+
+	assert(pair);
+	if (!pair)
+		return;
+
+	faux_str_free(pair->value);
+	pair->value = faux_str_dup(value);
+}

+ 4 - 12
faux/ini/private.h

@@ -1,18 +1,10 @@
-/*
- * lub/ini/private.h
- *
- * Class to parse ini-like strings/files.
- */
+#include "faux/list.h"
 
-#include "lub/string.h"
-#include "lub/list.h"
-#include "lub/ini.h"
-
-struct lub_pair_s {
+struct faux_pair_s {
 	char *name;
 	char *value;
 };
 
-struct lub_ini_s {
-	lub_list_t *list;
+struct faux_ini_s {
+	faux_list_t *list;
 };

+ 1 - 1
faux/list.h

@@ -36,7 +36,7 @@ size_t faux_list_len(const faux_list_t *list);
 
 faux_list_node_t *faux_list_add(faux_list_t *list, void *data);
 faux_list_node_t *faux_list_add_uniq(faux_list_t *list, void *data);
-faux_list_node_t *faux_list_find_add(faux_list_t *list, void *data);
+faux_list_node_t *faux_list_add_find(faux_list_t *list, void *data);
 void *faux_list_takeaway(faux_list_t *list, faux_list_node_t *node);
 int faux_list_del(faux_list_t *list, faux_list_node_t *node);
 

+ 1 - 1
faux/list/list.c

@@ -361,7 +361,7 @@ faux_list_node_t *faux_list_add_uniq(faux_list_t *list, void *data) {
  * @param [in] data User data.
  * @return Newly created list node, existent equal node or NULL on error.
  */
-faux_list_node_t *faux_list_find_add(faux_list_t *list, void *data) {
+faux_list_node_t *faux_list_add_find(faux_list_t *list, void *data) {
 
 	return faux_list_add_generic(list, data, BOOL_TRUE, BOOL_TRUE);
 }

+ 3 - 2
faux/str.h

@@ -16,7 +16,7 @@
 
 C_DECL_BEGIN
 
-void faux_str_free(char **str);
+void faux_str_free(char *str);
 
 char *faux_str_dupn(const char *str, size_t n);
 char *faux_str_dup(const char *str);
@@ -26,9 +26,10 @@ char *faux_str_cat(char **str, const char *text);
 
 char *faux_str_tolower(const char *str);
 
+int faux_str_casecmp(const char *str1, const char *str2);
+
 
 //const char *faux_str_suffix(const char *string);
-//int faux_str_nocasecmp(const char *cs, const char *ct);
 //const char *faux_str_nocasestr(const char *cs, const char *ct);
 /*
  * These are the escape characters which are used by default when 

+ 5 - 8
faux/str/str.c

@@ -22,17 +22,14 @@
  *
  * Safely free the memory allocated for the string. You can use NULL
  * pointer with this function. POSIX's free() checks for the NULL pointer
- * but not all systems do so. Function uses address of string pointer as an
- * argument to NULLify pointer after freeing.
+ * but not all systems do so.
  *
- * @param [in] str Address of string pointer
+ * @param [in] str String to free
  */
-void faux_str_free(char **str) {
+void faux_str_free(char *str) {
 
-	if (!*str)
-		return;
-	free(*str);
-	*str = NULL;
+	if (str)
+		free(str);
 }