speechd-discuss
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH (speechd)] Cleaner implementation of escape_dot in libspeechd.c.


From: Christopher Brannon
Subject: [PATCH (speechd)] Cleaner implementation of escape_dot in libspeechd.c.
Date: Mon, 1 Mar 2010 09:30:09 -0600

The previous implementation only escaped a period in two cases:
1. The input string was one character long, and it only contained
a period.
2. The period was surrounded by newline delimiters.  I.E., it replaced
\r\n.\r\n with \r\n..\r\n

What happens if you want to send a line
containing nothing but two periods?
The last implementation would send \r\n..\r\n for both the input
\r\n.\r\n and the input \r\n..\r\n
Instead, if a line starts with period, we should always prepend period.

The previous version also used some helper functions for constructing
dynamic strings.  Those were removed, and we now allocate all the memory
that we need at the start of escape_dot.
---
 src/c/api/libspeechd.c |  130 +++++++++++++++++-------------------------------
 1 files changed, 46 insertions(+), 84 deletions(-)

diff --git a/src/c/api/libspeechd.c b/src/c/api/libspeechd.c
index b8274bc..bb29060 100644
--- a/src/c/api/libspeechd.c
+++ b/src/c/api/libspeechd.c
@@ -48,13 +48,9 @@
 
 /* --------------  Private functions headers ------------------------*/
 
-typedef struct {
-    char *str;
-    size_t bytes;
-}_SPDString;
 
 static int spd_set_priority(SPDConnection* connection, SPDPriority priority);
-static char* escape_dot(const char *otext);
+static char* escape_dot(const char *text);
 static int isanum(char* str);          
 static char* get_reply(SPDConnection *connection);
 static int get_err_code(char *reply);
@@ -65,8 +61,6 @@ static void xfree(void *ptr);
 static int ret_ok(char *reply);
 static void SPD_DBG(char *format, ...);
 static void* spd_events_handler(void*);
-static _SPDString spd_string_append(_SPDString str, char *tail, int bytes);
-static _SPDString spd_string_new(void);
 
 pthread_mutex_t spd_logging_mutex;
 
@@ -1421,90 +1415,58 @@ xfree(void *ptr)
         free(ptr);
 }
 
-static _SPDString
-spd_string_new(void)
-{
-    _SPDString result;
-    
-    result.bytes=1024;
-    result.str=malloc(result.bytes);
-    result.str[0]='\0';
-    
-    return result;
-}
-
-static _SPDString
-spd_string_append(_SPDString str, char *tail, int bytes)
-{
-    if (tail == NULL) return str;
-    
-    while ((strlen(str.str)+strlen(tail))>= str.bytes){
-       str.bytes *= 2;
-       str.str = realloc(str.str, str.bytes);
-    }
-
-    if (bytes != -1)
-       strncat(str.str, tail, bytes);
-    else
-       strcat(str.str, tail);
-
-    return str;
-}   
-
+/*
+ * escape_dot: Replace . with .. at the start of lines.
+ * @text: text to escape
+ * @Returns: An allocated string, containing the escaped text.
+ */
 static char*
 escape_dot(const char *text)
 {
-    _SPDString result;
-    size_t text_len;
-    int pos;
-    char *place;
-
-    result=spd_string_new();
-
-    if (text == NULL) return NULL;
-    text_len = strlen(text);
-
-    pos = 0;
-    if (text_len == 0){
-       return result.str;
-    }
-    /*If text contains only a dot, escape it*/
-    else if (text_len==1 && text[0]=='.'){
-       result = spd_string_append(result, "..", -1);
-       return result.str;
-    }
-    /*Escape the leading '.\r\n', if present*/
-    else if (text_len >=3){
-       if (!strncmp(text, ".\r\n", 3)){
-           result = spd_string_append(result, "..", -1);
-           pos += 1;
-       }
+    size_t orig_len = 0;
+    const char *orig_end;
+    char *result = NULL;
+    char *result_ptr;
+    static const char *ESCAPED_DOTLINE = "\r\n..";
+    static const size_t ESCAPED_DOTLINELEN = 4;
+    static const size_t DOTLINELEN = 3;
+
+    if (text == NULL)
+        return NULL;
+
+orig_len = strlen(text);
+    orig_end = text + orig_len;
+    result = malloc((orig_len * 2 + 1) * sizeof(char));
+
+    if (result == NULL)
+        return NULL;
+
+    result_ptr = result;
+
+    /* We're over-allocating.  Even if we replaced every character
+     * in text with "..", the length of the escaped string can be no more
+     * than orig_len * 2.  We could tighten that upper bound with
+     * a little more work.
+     */
+
+    if ((orig_len >= 1) && (text[0] == '.')) {
+        *(result_ptr++) = '.';
+        *(result_ptr++) = '.';
+        text += 1;
     }
 
-    /* Replace all full \r\n.\r\n sequences */
-    while((place = strstr(&text[pos], "\r\n.\r\n"))){
-       assert (place >= text);
-       int n = place-&text[pos];
-       result = spd_string_append(result, (char*) &text[pos], n);
-       result = spd_string_append(result, "\r\n..", -1);
-       /* Only rewind before the following \r\n to resume search for
-          sequence */
-       pos +=n+3;
-    }
-
-    /* Paste the rest */    
-    result=spd_string_append(result, (char*) &text[pos], -1);
-    
-    /*Escape the trailing '\r\n.' if found by adding an additional dot at the
-      end*/
-    if(strlen(result.str)>=3){
-       if(!strncmp(&result.str[strlen(result.str)-3], "\r\n.", 3)){
-           result=spd_string_append(result, ".", -1);
-           return result.str;
-       }
+    while (text < orig_end) {
+        if ((text[0] == '\r') && (text[1] == '\n') && (text[2] == '.')) {
+            memcpy(result_ptr, ESCAPED_DOTLINE, ESCAPED_DOTLINELEN);
+            result_ptr += ESCAPED_DOTLINELEN;
+            text += DOTLINELEN;
+        } else {
+            *(result_ptr++) = *(text++);
+        }
     }
 
-    return result.str;
+    * result_ptr = '\0';
+    return result;
 }
 
 #ifdef LIBSPEECHD_DEBUG
-- 
1.7.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]