Browse Source

HPCC-15757 Add non-inplace string replace function to StringBuffer

Signed-off-by: Richard Chapman <rchapman@hpccsystems.com>
Richard Chapman 9 years ago
parent
commit
995cc6409e
4 changed files with 47 additions and 25 deletions
  1. 1 4
      rtl/eclrtl/eclrtl.cpp
  2. 25 21
      system/jlib/jstring.cpp
  3. 2 0
      system/jlib/jstring.hpp
  4. 19 0
      testing/unittests/unittests.cpp

+ 1 - 4
rtl/eclrtl/eclrtl.cpp

@@ -5305,10 +5305,7 @@ void rtlAddExceptionTag(StringBuffer & errorText, const char * tag, const char *
 void rtlSubstituteEmbeddedScript(size32_t &__lenResult, char * &__result, size32_t scriptChars, const char *script, size32_t outFieldsChars, const char *outFields, size32_t searchChars, const char *search)
 {
     StringBuffer result;
-    result.append(rtlUtf8Size(scriptChars, script), script);
-    StringBuffer outFieldsX(rtlUtf8Size(outFieldsChars, outFields), outFields);
-    StringBuffer searchX(rtlUtf8Size(searchChars, search), search);
-    result.replaceString(searchX.str(), outFieldsX.str());
+    ::replaceString(result, rtlUtf8Size(scriptChars, script), script, rtlUtf8Size(searchChars, search), search, rtlUtf8Size(outFieldsChars, outFields), outFields);
     __lenResult = result.length();
     __result = result.detach();
 }

+ 25 - 21
system/jlib/jstring.cpp

@@ -908,41 +908,45 @@ StringBuffer & StringBuffer::replace(char oldChar, char newChar)
     return *this;
 }
 
-// this method will replace all occurrances of "oldStr" with "newStr"
-StringBuffer & StringBuffer::replaceString(const char* oldStr, const char* newStr)
+// Copy source to result, replacing all occurrences of "oldStr" with "newStr"
+StringBuffer &replaceString(StringBuffer & result, size32_t lenSource, const char *source, size32_t lenOldStr, const char* oldStr, size32_t lenNewStr, const char* newStr)
 {
-    if (curLen)
+    if (lenSource)
     {
-        const char* s = str();  // get null terminated version of the string
-        int left = length();
-        int oldStr_len = (size32_t)strlen(oldStr);
-
-        StringBuffer tempbuff;
-
-        while (left >= oldStr_len)
+        size32_t left = lenSource;
+        while (left >= lenOldStr)
         {
-            if ( memcmp(s, oldStr, oldStr_len) == 0)
+            if (memcmp(source, oldStr, lenOldStr)==0)
             {
-                tempbuff.append(newStr);
-                s += oldStr_len;
-                left -= oldStr_len;
+                result.append(lenNewStr, newStr);
+                source += lenOldStr;
+                left -= lenOldStr;
             }
             else
             {
-                tempbuff.append(*s);
-                s++;
+                result.append(*source);
+                source++;
                 left--;
             }
         }
 
         // there are no more possible replacements, make sure we keep the end of the original buffer
-        tempbuff.append(s);
-        
-        //*this = tempbuff;
-        swapWith(tempbuff);
-        
+        result.append(left, source);
     }
+    return result;
+}
 
+// this method will replace all occurrences of "oldStr" with "newStr"
+StringBuffer & StringBuffer::replaceString(const char* oldStr, const char* newStr)
+{
+    if (curLen)
+    {
+        StringBuffer temp;
+        size32_t oldlen = oldStr ? strlen(oldStr) : 0;
+        size32_t newlen = newStr ? strlen(newStr) : 0;
+        ::replaceString(temp, curLen, buffer, oldlen, oldStr, newlen, newStr);
+        swapWith(temp);
+    }
     return *this;
 }
 

+ 2 - 0
system/jlib/jstring.hpp

@@ -401,6 +401,8 @@ extern jlib_decl void decodeXML(ISimpleReadStream &in, StringBuffer &out, unsign
 extern jlib_decl int utf8CharLen(unsigned char ch);
 extern jlib_decl int utf8CharLen(const unsigned char *ch, unsigned maxsize = (unsigned)-1);
 
+extern jlib_decl StringBuffer &replaceString(StringBuffer & result, size32_t lenSource, const char *source, size32_t lenOldStr, const char* oldStr, size32_t lenNewStr, const char* newStr);
+
 inline const char *encodeUtf8XML(const char *x, StringBuffer &ret, unsigned flags=false, unsigned len=(unsigned)-1)
 {
     return encodeXML(x, ret, flags, len, true);

+ 19 - 0
testing/unittests/unittests.cpp

@@ -275,4 +275,23 @@ class InternalStatisticsTest : public CppUnit::TestFixture
 CPPUNIT_TEST_SUITE_REGISTRATION( InternalStatisticsTest );
 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( InternalStatisticsTest, "StatisticsTest" );
 
+//MORE: This can't be included in jlib because of the dll dependency
+class StringBufferTest : public CppUnit::TestFixture
+{
+    CPPUNIT_TEST_SUITE( StringBufferTest  );
+        CPPUNIT_TEST(testReplace);
+    CPPUNIT_TEST_SUITE_END();
+
+    void testReplace()
+    {
+        StringBuffer r ("1 bb c");
+        r.replaceString(" ", "x");
+        ASSERT(streq(r, "1xbbxc"));
+    }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION( StringBufferTest );
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( StringBufferTest, "StringBufferTest" );
+
+
 #endif // _USE_CPPUNIT