]> git.sur5r.net Git - cc65/commitdiff
Added "strrchr" optimizaion a matching unit test and tiny unit test framework. (Docum...
authorIrgendwerA8 <c.krueger.b@web.de>
Sun, 26 Feb 2017 19:03:05 +0000 (20:03 +0100)
committerIrgendwerA8 <c.krueger.b@web.de>
Sun, 26 Feb 2017 19:03:05 +0000 (20:03 +0100)
include/unittest.h [new file with mode: 0644]
libsrc/common/strrchr.s
testcode/lib/strcat-test.c
testcode/lib/strrchr-test.c [new file with mode: 0644]

diff --git a/include/unittest.h b/include/unittest.h
new file mode 100644 (file)
index 0000000..a58bbb9
--- /dev/null
@@ -0,0 +1,89 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                               unittest.h                                  */
+/*                                                                           */
+/*                        Unit test helper macros                            */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 2017 Christian Krueger                                                       */
+/*                                                                           */
+/* This software is provided 'as-is', without any expressed or implied       */
+/* warranty.  In no event will the authors be held liable for any damages    */
+/* arising from the use of this software.                                    */
+/*                                                                           */
+/* Permission is granted to anyone to use this software for any purpose,     */
+/* including commercial applications, and to alter it and redistribute it    */
+/* freely, subject to the following restrictions:                            */
+/*                                                                           */
+/* 1. The origin of this software must not be misrepresented; you must not   */
+/*    claim that you wrote the original software. If you use this software   */
+/*    in a product, an acknowledgment in the product documentation would be  */
+/*    appreciated but is not required.                                       */
+/* 2. Altered source versions must be plainly marked as such, and must not   */
+/*    be misrepresented as being the original software.                      */
+/* 3. This notice may not be removed or altered from any source              */
+/*    distribution.                                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef _UNITTEST_H
+#define _UNITTEST_H
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef COMMA
+#define COMMA ,
+#endif
+
+#define TEST   int main(void) \
+                               {\
+                                       printf("%s: ",__FILE__);
+
+#define ENDTEST                printf("Passed\n"); \
+                                       return EXIT_SUCCESS; \
+                               }
+
+#define ASSERT_IsTrue(a,b)                                     if (!(a)) \
+                                                                                       {\
+                                                                                               printf("Fail at line %d:\n",__LINE__);\
+                                                                                               printf(b);\
+                                                                                               printf("\n");\
+                                                                                               printf("Expected status should be true but wasn't!\n");\
+                                                                                               exit(EXIT_FAILURE);\
+                                                                                       }
+
+#define ASSERT_IsFalse(a,b)                                    if ((a)) \
+                                                                                       {\
+                                                                                               printf("Fail at line %d:\n",__LINE__);\
+                                                                                               printf(b);\
+                                                                                               printf("\n");\
+                                                                                               printf("Expected status should be false but wasn't!\n");\
+                                                                                               exit(EXIT_FAILURE);\
+                                                                                       }
+
+#define ASSERT_AreEqual(a,b,c,d)                       if ((a) != (b)) \
+                                                                                       {\
+                                                                                               printf("Fail at line %d:\n",__LINE__);\
+                                                                                               printf(d);\
+                                                                                               printf("\n");\
+                                                                                               printf("Expected value: "c", but is "c"!\n", (a), (b));\
+                                                                                               exit(EXIT_FAILURE);\
+                                                                                       }
+
+#define ASSERT_AreNotEqual(a,b,c,d)                    if ((a) == (b)) \
+                                                                                       {\
+                                                                                               printf("Fail at line %d:\n",__LINE__);\
+                                                                                               printf(d);\
+                                                                                               printf("\n");\
+                                                                                               printf("Expected value not: "c", but is "c"!\n", (a), (b));\
+                                                                                               exit(EXIT_FAILURE);\
+                                                                                       }
+
+/* End of unittest.h */
+#endif
+
+
+
+
index bd7389e7614762bbf47c78f64c99bf0a92c57750..3e4fb0810beb949fc3a100b436d42f738e14e38a 100644 (file)
@@ -1,47 +1,41 @@
 ;
 ; Ullrich von Bassewitz, 31.05.1998
+; Christian Krueger: 2013-Aug-01, optimization
 ;
 ; char* strrchr (const char* s, int c);
 ;
 
         .export         _strrchr
         .import         popax
-        .importzp       ptr1, ptr2, tmp1
+        .importzp       ptr1, tmp1, tmp2
 
 _strrchr:
-        sta     tmp1            ; Save c
-        jsr     popax           ; get s
-        sta     ptr1
-        stx     ptr1+1
-        lda     #0              ; function result = NULL
-        sta     ptr2
-        sta     ptr2+1
-        tay
-
-L1:     lda     (ptr1),y        ; get next char
-        beq     L3              ; jump if end of string
-        cmp     tmp1            ; found?
-        bne     L2              ; jump if no
-
-; Remember a pointer to the character
-
-        tya
-        clc
-        adc     ptr1
-        sta     ptr2
-        lda     ptr1+1
-        adc     #$00
-        sta     ptr2+1
-
-; Next char
-
-L2:     iny
-        bne     L1
-        inc     ptr1+1
-        bne     L1              ; jump always
-
-; Return the pointer to the last occurrence
-
-L3:     lda     ptr2
-        ldx     ptr2+1
+        sta tmp1        ; Save c
+        jsr popax       ; get s
+        tay             ; low byte to y
+        stx ptr1+1
+        ldx #0          ; default function result is NULL, X is high byte...
+        stx tmp2        ; tmp2 is low-byte
+        stx ptr1        ; low-byte of source string is in Y, so clear real one... 
+   
+testChar:
+        lda (ptr1),y    ; get char
+        beq finished    ; jump if end of string
+        cmp tmp1        ; found?
+        bne nextChar    ; jump if no
+
+charFound:
+        sty tmp2        ; y has low byte of location, save it
+        ldx ptr1+1      ; x holds high-byte of result
+
+nextChar:
+        iny
+        bne testChar
+        inc ptr1+1
+        bne testChar    ; here like bra...
+
+; return the pointer to the last occurrence
+
+finished:
+        lda tmp2        ; high byte in X is already correct...
         rts
index edd614fc4b37e8cec2ecbec8e7c6a1624fedb087..fdc98728844afa79bbb24d53f5e714b792660191 100644 (file)
@@ -1,5 +1,4 @@
-#include <stdio.h>
-#include <stdlib.h>
+#include <unittest.h>
 #include <string.h>
 
 #define SourceStringSize 257                            // test correct page passing (>256)
@@ -8,65 +7,38 @@ static char SourceString[SourceStringSize+1];         // +1 room for terminating null
 static char DestinationString[2*SourceStringSize+1];    // will contain two times the source buffer
 
 
-int main (void)
+TEST
 {
     unsigned i,j;
     char*    p;
-
-    /* Print a header */
-    printf ("strcat(): ");
-
+    
     for (i=0; i < SourceStringSize; ++i)
       SourceString[i] = (i%128)+1;
 
     SourceString[i] = 0;
 
-    if (strlen(SourceString) != SourceStringSize)
-    {
-        printf ("Fail: Source string initialization or 'strlen()' problem!\n");
-        printf ("Expected length: %u but is %u!\n", SourceStringSize, strlen(SourceString));
-        exit (EXIT_FAILURE);
-    }
+    ASSERT_AreEqual(SourceStringSize, strlen(SourceString), "%u", "Source string initialization or 'strlen()' problem!");
 
     /* Ensure empty destination string */
     DestinationString[0] = 0;
 
-    if (strlen(DestinationString) != 0)
-    {
-        printf ("Fail: Destination string initialization or 'strlen()' problem!\n");
-        printf ("Expected length: %u but is %u!\n", 0, strlen(DestinationString));
-        exit (EXIT_FAILURE);
-    }
-
+    ASSERT_AreEqual(0, strlen(DestinationString), "%u", "Destination string initialization or 'strlen()' problem!");
+    
     /* Test concatenation to empty buffer */
 
-    p = strcat(DestinationString, SourceString);
-
-    if (strlen(DestinationString) != SourceStringSize)
-    {
-        printf ("Fail: String concatenation to empty buffer!\n");
-        printf ("Expected length: %u but is %u!\n", SourceStringSize, strlen(DestinationString));
-        exit (EXIT_FAILURE);
-    }    
-
+    strcat(DestinationString, SourceString);
+    
+    ASSERT_AreEqual(SourceStringSize, strlen(DestinationString), "%u", "Unexpected string length while string concatenation to empty buffer!");
+    
     /* Test concatenation to non empty buffer */
 
     p = strcat(DestinationString, SourceString);
 
-    if (strlen(DestinationString) != 2*SourceStringSize)
-    {
-        printf ("Fail: String concatenation to non-empty buffer!\n");
-        printf ("Expected length: %u but is %u!\n", 2*SourceStringSize, strlen(DestinationString));
-        exit (EXIT_FAILURE);
-    }   
+    ASSERT_AreEqual(2*SourceStringSize, strlen(DestinationString), "%u", "Unexpected string length while string concatenation to non-empty buffer!");
 
     /* Test return value */
 
-    if (p != DestinationString)
-    {
-        printf ("Invalid return value!\n");
-        exit (EXIT_FAILURE);
-    }   
+    ASSERT_IsTrue(p == DestinationString,"Invalid return value!");
 
     /* Test contents */
 
@@ -76,18 +48,9 @@ int main (void)
             unsigned position = j*SourceStringSize+i;
             unsigned current = DestinationString[position];
             unsigned expected = (i%128)+1;
-            if (current != expected)
-            {
-                printf ("Fail: Unexpected destination buffer contents at position %u!\n", position);
-                printf ("Expected %u, but is %u!\n", expected, current);
-                exit (EXIT_FAILURE);
-            }
+           ASSERT_AreEqual(expected, current, "%u", "Unexpected destination buffer contents at position %u!\n" COMMA position);
         }
-
-    /* Test passed */
-    printf ("Passed\n");
-    return EXIT_SUCCESS;
 }
-
+ENDTEST
 
 
diff --git a/testcode/lib/strrchr-test.c b/testcode/lib/strrchr-test.c
new file mode 100644 (file)
index 0000000..9c1c700
--- /dev/null
@@ -0,0 +1,38 @@
+#include <unittest.h>
+#include <string.h>
+                                                    
+static char TestString[] = "01234567890123456789";     // two times the same string
+static char Found[256];
+
+TEST
+{
+    unsigned len;
+    unsigned i;
+    char*    p;
+
+    len = strlen(TestString)/2;        // test only one half of the string, to find last appearance
+
+    /* Search for all characters in the string, including the terminator */
+    for (i = 0; i < len; ++i)
+    {
+        /* Search for this char */
+        p = strrchr (TestString, TestString[i]);
+        ASSERT_AreEqual(i+len, p-TestString, "%u", "Unexpected location of character '%c' found!" COMMA TestString[i]);
+
+        /* Mark the char as checked */
+        Found[TestString[i]] = 1;
+    }
+
+    /* Search for all other characters and make sure they aren't found */
+    for (i = 0; i < 256; ++i)
+    {
+        if (!Found[i])
+        {
+            p = strrchr (TestString, i);
+            ASSERT_IsFalse(p, "Unexpected location of character '%c' found!" COMMA TestString[i]);
+        }
+    }
+}
+ENDTEST
+
+