From 508dece619e26b08a95fa856581d14816b2eef1f Mon Sep 17 00:00:00 2001
From: Chernov Dmitriy <cd_work@mail.ru>
Date: 周一, 29 2月 2016 22:16:38 +0800
Subject: [PATCH] manual heap ready

---
 libscpi/inc/scpi/types.h     |    2 
 libscpi/src/minimal.c        |   12 +-
 libscpi/src/parser.c         |   44 ++++------
 libscpi/inc/scpi/config.h    |   18 ++--
 libscpi/src/utils_private.h  |    5 
 libscpi/src/error.c          |    7 -
 libscpi/inc/scpi/constants.h |    5 +
 libscpi/src/utils.c          |  103 ++++++++++++++++++++++---
 8 files changed, 137 insertions(+), 59 deletions(-)

diff --git a/libscpi/inc/scpi/config.h b/libscpi/inc/scpi/config.h
index 75b9731..ea19d8e 100644
--- a/libscpi/inc/scpi/config.h
+++ b/libscpi/inc/scpi/config.h
@@ -263,17 +263,19 @@
 		#include <stdlib.h>
 		#include <string.h>
 		#include <malloc.h>
-		#define SCPIDEFINE_strdup(h,s)			strdup((s))
-		#define SCPIDEFINE_free(h,s)			free((s))
+		#define SCPIDEFINE_DESCRIPTION_MAX_PARTS	2
+		#define SCPIDEFINE_strdup(h, s)				strdup((s))
+		#define SCPIDEFINE_free(h, s, r)			free((s))
 	#else
-		#define SCPIDEFINE_strdup(h,s)			OUR_strdup((h), (s))
-		#define SCPIDEFINE_free(h,s)			OUR_free((h), (s))
-		#define SCPIDEFINE_get_1st_part(s,l)	OUR_get_1st_part((s),(l))
-		#define SCPIDEFINE_get_2st_part(s,l)	OUR_get_2nd_part((s),(l))
+		#define SCPIDEFINE_DESCRIPTION_MAX_PARTS	3
+		#define SCPIDEFINE_strdup(h, s)				OUR_strdup((h), (s))
+		#define SCPIDEFINE_free(h, s, r)			OUR_free((h), (s), (r))
+		#define SCPIDEFINE_get_parts(h, s, l1, s2, l2)	OUR_get_parts((h), (s), (l1), (s2), (l2))
 	#endif
 #else
-	#define SCPIDEFINE_strdup(h,s)				(void)(s)
-	#define SCPIDEFINE_free(h,s)				(void)(s)
+	#define SCPIDEFINE_DESCRIPTION_MAX_PARTS	1
+	#define SCPIDEFINE_strdup(h, s)				NULL
+	#define SCPIDEFINE_free(h, s, r)			(void)
 #endif
 
 #ifdef	__cplusplus
diff --git a/libscpi/inc/scpi/constants.h b/libscpi/inc/scpi/constants.h
index 61cd9a6..e2ad2d0 100644
--- a/libscpi/inc/scpi/constants.h
+++ b/libscpi/inc/scpi/constants.h
@@ -48,6 +48,11 @@
      */
 #define SCPI_STD_VERSION_REVISION "1999.0"
 
+/* 21.8 :ERRor Subsystem
+ * The maximum string length of <Error/event_description> plus <Device-dependent_info> is 255 characters.
+ */
+#define SCPI_STD_ERROR_DESC_CHARS_LIMIT 255
+
 #ifdef	__cplusplus
 }
 #endif
diff --git a/libscpi/inc/scpi/types.h b/libscpi/inc/scpi/types.h
index 8dbcd64..085ca00 100644
--- a/libscpi/inc/scpi/types.h
+++ b/libscpi/inc/scpi/types.h
@@ -203,7 +203,7 @@
 
 	struct _scpi_error_info_heap_t {
         int16_t wr;
-        int16_t rd;
+        //int16_t rd;
         int16_t count;
         int16_t size;
         char * data;
diff --git a/libscpi/src/error.c b/libscpi/src/error.c
index ca48cc5..7b17f4c 100644
--- a/libscpi/src/error.c
+++ b/libscpi/src/error.c
@@ -84,7 +84,7 @@
 #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION
 	scpi_error_t error;
 	while(fifo_remove(&context->error_queue, &error)){
-		SCPIDEFINE_free(&context->error_info_heap, error.device_dependent_info);
+		SCPIDEFINE_free(&context->error_info_heap, error.device_dependent_info, false);
 	}
 #endif	
     fifo_clear(&context->error_queue);
@@ -138,9 +138,7 @@
 
 static scpi_bool_t SCPI_ErrorAddInternal(scpi_t * context, int16_t err, char * info) {
     if (!fifo_add(&context->error_queue, err, info)) {
-		scpi_error_t * error;
-        fifo_remove_last(&context->error_queue, error);
-		SCPIDEFINE_free(&context->error_info_heap, error->device_dependent_info);
+        fifo_remove_last(&context->error_queue, NULL);
         fifo_add(&context->error_queue, SCPI_ERROR_QUEUE_OVERFLOW, NULL);
         return FALSE;
     }
@@ -193,6 +191,7 @@
 	SCPI_ErrorEmit(context, err);
 	if (queue_overflow) {
 		SCPI_ErrorEmit(context, SCPI_ERROR_QUEUE_OVERFLOW);
+		SCPIDEFINE_free(&context->error_info_heap, info_ptr, true);
 	}
 
 	if (context) {
diff --git a/libscpi/src/minimal.c b/libscpi/src/minimal.c
index f5372ff..f2af219 100644
--- a/libscpi/src/minimal.c
+++ b/libscpi/src/minimal.c
@@ -77,15 +77,15 @@
  * @return 
  */
 scpi_result_t SCPI_SystemErrorNextQ(scpi_t * context) {
-	scpi_error_t error;
+	SCPI_ResultInt32(context,context->error_info_heap.count);
+	
+	scpi_error_t error;	
 	SCPI_ErrorPopEx(context, &error);
 	SCPI_ResultError(context, &error);
+	
+	SCPI_ResultInt32(context,context->error_info_heap.count);
 	return SCPI_RES_OK;
-    
-	//int16_t err = SCPI_ErrorPop(context);
-    //SCPI_ResultInt32(context, error.error_code);
-    //SCPI_ResultText(context, SCPI_ErrorTranslate(error.error_code));
-    //return SCPI_RES_OK;
+
 }
 
 /**
diff --git a/libscpi/src/parser.c b/libscpi/src/parser.c
index ca0aa93..fd85e47 100644
--- a/libscpi/src/parser.c
+++ b/libscpi/src/parser.c
@@ -269,8 +269,10 @@
     context->buffer.length = input_buffer_length;
     context->buffer.position = 0;
 	context->error_info_heap.data = error_info_heap;
-	context->error_info_heap.position = 0;
-	context->error_info_heap.length = error_info_heap_length;
+	context->error_info_heap.wr = 0;
+	context->error_info_heap.size = error_info_heap_length;
+	context->error_info_heap.count = context->error_info_heap.size;
+	memset(context->error_info_heap.data,0,context->error_info_heap.size);
     SCPI_ErrorInit(context, error_queue_data, error_queue_size);
 }
 
@@ -507,36 +509,32 @@
     return result;
 }
 
-#if USE_DEVICE_DEPENDENT_ERROR_INFORMATION
-	#if USE_MEMORY_ALLOCATION_FREE
-		#define MAX_BUFF_SIZE	2
-	#else
-		#define MAX_BUFF_SIZE	3
-	#endif
-#else
-	#define MAX_BUFF_SIZE	1
-#endif
 
-static size_t startoutputlimit = 0;
-
+/**
+ * Write string withn " to the result
+ * @param context
+ * @param data
+ * @return
+ */
+static size_t outputlimit_0=0;
 size_t SCPI_ResultError(scpi_t * context, scpi_error_t * error) {
  	size_t result = 0;
-	size_t outputlimit = startoutputlimit++;
+	size_t outputlimit = outputlimit_0++; //SCPI_STD_ERROR_DESC_CHARS_LIMIT;
 	size_t step = 0;
 	const char * quote;
 
-	char * data[MAX_BUFF_SIZE];
-	size_t len[MAX_BUFF_SIZE];
+	char * data[SCPIDEFINE_DESCRIPTION_MAX_PARTS];
+	size_t len[SCPIDEFINE_DESCRIPTION_MAX_PARTS];
 	 
 	data[0] = SCPI_ErrorTranslate(error->error_code);
 	len[0] = strlen(data[0]);
+	
 #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION
+	data[1] = error->device_dependent_info;
 	#if USE_MEMORY_ALLOCATION_FREE
-		data[1] = error->device_dependent_info;
 		len[1] = error->device_dependent_info ? strlen(data[1]) : 0;
 	#else
-		data[1] = SCPIDEFINE_get_1st_part(error->device_dependent_info,&len[1]);
-		data[2] = SCPIDEFINE_get_1st_part(data[1],&len[2]);
+		SCPIDEFINE_get_parts(&context->error_info_heap, data[1], &len[1], &data[2], &len[2]);
 	#endif
 #endif
 
@@ -544,7 +542,7 @@
 	result += writeDelimiter(context);
 	result += writeData(context, "\"", 1);	
 	
-	for(size_t i = 0; data[i] && outputlimit && (i < MAX_BUFF_SIZE); i++){
+	for(size_t i = 0; data[i] && outputlimit && (i < SCPIDEFINE_DESCRIPTION_MAX_PARTS); i++){
 		if(i==1){
 			result += writeSemicolon(context);
 			outputlimit -= 1;
@@ -575,15 +573,11 @@
 	result += writeData(context, "\"", 1);
 	
 	#if USE_DEVICE_DEPENDENT_ERROR_INFORMATION
-		#if USE_MEMORY_ALLOCATION_FREE
-			SCPIDEFINE_free(error->device_dependent_info);
-		#else
-		#endif
+		SCPIDEFINE_free(&context->error_info_heap, error->device_dependent_info, false);
 	#endif
 	
 	return result;
 }
-#undef MAX_BUFF_SIZE
 
 /**
  * Write arbitrary block header with length
diff --git a/libscpi/src/utils.c b/libscpi/src/utils.c
index 945a625..de8fb64 100644
--- a/libscpi/src/utils.c
+++ b/libscpi/src/utils.c
@@ -751,8 +751,16 @@
 #endif
 
 #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION && !USE_MEMORY_ALLOCATION_FREE
+/**
+ * Duplicate string if "strdup" ("malloc/free") not supported on system.
+ * Allocate space in heap if it possible
+ *
+ * @param heap - pointer to manual allocated heap buffer
+ * @param s - current pointer of duplication string
+ * @return - pointer of duplicated string or NULL, if duplicate is not possible.
+ */
 char * OUR_strdup(scpi_error_info_heap_t * heap, const char *s) {
-	if(!heap || !s) {
+	if(!s || !heap) {
 		return NULL;
 	}
 	if(heap->data[heap->wr]!='\0'){
@@ -763,20 +771,91 @@
 	if(len > heap->count){
 		return NULL;
 	}
-	size_t f_part=(&heap->data[heap->wr]-heap->data)
+	char * ptrs = s;
+	char * head = &heap->data[heap->wr];
+	size_t rem = heap->size - (&heap->data[heap->wr]-heap->data);
+	size_t sstp = 0;
+	
+	if(len >= rem){
+		memcpy(&heap->data[heap->wr],s,rem);
+		len = len - rem;
+		ptrs += rem;
+		heap->wr = 0;
+		heap->count -= rem;
+	}
+	
+	memcpy(&heap->data[heap->wr],ptrs,len);
+	heap->wr += len;
+	heap->count -= len;
+	
+	return head;
+}
+
+/**
+ * Return pointers and lengths two parts of string in the circular buffer from heap
+ *
+ * @param heap - pointer to manual allocated heap buffer
+ * @param s - pointer of duplicate string.
+ * @return len1 - lenght of first part of string.
+ * @return s2 - pointer of second part of string, if string splited .
+ * @return len2 - lenght of second part of string.
+ */
+scpi_bool_t OUR_get_parts(scpi_error_info_heap_t * heap, const char * s, size_t * len1, const char ** s2, size_t * len2) {
+	if(!heap || !s || !len1 || !s2 || !len2) {
+		return FALSE;
+	}
+	
+	if(*s == '\0') {
+		return FALSE;
+	}
+	
+	*len1 = 0;
+	size_t rem = heap->size - (s - heap->data);
+	*len1 = strnlen(s, rem);
+
+	if(&s[*len1-1] == &heap->data[heap->size-1]){
+		*s2 = heap->data;
+		*len2 = strnlen(*s2, heap->size);
+	}else{
+		*s2 = NULL;
+		*len2 = 0;	
+	}
+	return TRUE;
+}
+
+/**
+ * Frees space in heap, if "malloc/free" not supported on system, or nothing.
+ *
+ * @param heap - pointer to manual allocated heap buffer
+ * @param s - pointer of duplicate string
+ * @param rollback - backward write pointer in heap
+ */
+void OUR_free(scpi_error_info_heap_t * heap, const char * s, scpi_bool_t rollback) {
+	
+	if(!s) return;
+	
+	char * data_add;
+	size_t len[2];
+		
+	if( !OUR_get_parts( heap, s, &len[0], &data_add, &len[1] ) ) return;
 	
 	
-	return NULL;
+	if(data_add) {
+		len[1]++;
+		memset(data_add,0,len[1]);
+		heap->count += len[1];
+	} else {
+		len[0]++;
+	}
+	memset(s,0,len[0]);
+	heap->count += len[0];
+	if(rollback){
+		heap->wr-=len[0];
+		heap->wr-=len[1];
+		if(heap->wr < 0)heap->wr += heap->size;
+	}
 }
-void OUR_free(scpi_error_info_heap_t * heap, const char *s) {
-	
-}
-char * OUR_get_1st_part(const char *s, size_t * len) {
-	return NULL;
-}
-char * OUR_get_2nd_part(const char *s, size_t * len) {
-	return NULL;
-}
+
 #endif
 
 // Floating point to string conversion routines
diff --git a/libscpi/src/utils_private.h b/libscpi/src/utils_private.h
index 68b52bc..09aad22 100644
--- a/libscpi/src/utils_private.h
+++ b/libscpi/src/utils_private.h
@@ -89,9 +89,8 @@
 
 #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION && !USE_MEMORY_ALLOCATION_FREE
 	char * OUR_strdup(scpi_error_info_heap_t * heap, const char *s) LOCAL;
-	void OUR_free(scpi_error_info_heap_t * heap, const char *s) LOCAL;
-	char * OUR_get_1st_part(const char *s, size_t * len) LOCAL;
-	char * OUR_get_2nd_part(const char *s, size_t * len) LOCAL;
+	void OUR_free(scpi_error_info_heap_t * heap, const char *s, scpi_bool_t rollback) LOCAL;
+	scpi_bool_t OUR_get_parts(scpi_error_info_heap_t * heap, const char *s1, size_t * len1, const char ** s2, size_t * len2) LOCAL;
 #endif
 
 #ifndef min

--
Gitblit v1.9.1