[CalendarServer-changes] [13689] PyCalendar/trunk/src/pycalendar

source_changes at macosforge.org source_changes at macosforge.org
Wed Jun 25 11:47:12 PDT 2014


Revision: 13689
          http://trac.calendarserver.org//changeset/13689
Author:   cdaboo at apple.com
Date:     2014-06-25 11:47:12 -0700 (Wed, 25 Jun 2014)
Log Message:
-----------
Performance improvements.

Modified Paths:
--------------
    PyCalendar/trunk/src/pycalendar/stringutils.py
    PyCalendar/trunk/src/pycalendar/utils.py

Added Paths:
-----------
    PyCalendar/trunk/src/pycalendar/tests/test_stringutils.py

Modified: PyCalendar/trunk/src/pycalendar/stringutils.py
===================================================================
--- PyCalendar/trunk/src/pycalendar/stringutils.py	2014-06-25 18:45:45 UTC (rev 13688)
+++ PyCalendar/trunk/src/pycalendar/stringutils.py	2014-06-25 18:47:12 UTC (rev 13689)
@@ -18,51 +18,31 @@
 
 def strduptokenstr(txt, tokens):
 
-    result = None
-    start = 0
+    # First punt over any leading space - this is not common so test the
+    # first character before trying the more expensive strip
+    if txt[0] == " ":
+        txt = txt.lstrip()
+        if not txt:
+            return None, ""
 
-    # First punt over any leading space
-    for s in txt:
-        if s == " ":
-            start += 1
-        else:
-            break
-    else:
-        return None, ""
-
     # Handle quoted string
-    if txt[start] == '\"':
-
-        maxlen = len(txt)
-        # Punt leading quote
-        start += 1
-        end = start
-
-        done = False
-        while not done:
-            if end == maxlen:
-                return None, txt
-
-            if txt[end] == '\"':
-                done = True
-            elif txt[end] == '\\':
-                # Punt past quote
-                end += 2
+    if txt[0] == '\"':
+        skip = False
+        for end, s in enumerate(txt[1:]):
+            if skip:
+                skip = False
+                continue
+            elif s == '\"':
+                return txt[1:end + 1], txt[end + 2:]
             else:
-                end += 1
-            if end >= maxlen:
-                return None, txt
-
-        return txt[start:end], txt[end + 1:]
+                skip = (s == '\\')
+        else:
+            return None, txt
     else:
-        for relend, s in enumerate(txt[start:]):
+        for end, s in enumerate(txt):
             if s in tokens:
-                if relend:
-                    result = txt[start:start + relend]
-                else:
-                    result = ""
-                return result, txt[start + relend:]
-        return txt[start:], ""
+                return txt[0:end], txt[end:]
+        return txt, ""
 
 
 

Added: PyCalendar/trunk/src/pycalendar/tests/test_stringutils.py
===================================================================
--- PyCalendar/trunk/src/pycalendar/tests/test_stringutils.py	                        (rev 0)
+++ PyCalendar/trunk/src/pycalendar/tests/test_stringutils.py	2014-06-25 18:47:12 UTC (rev 13689)
@@ -0,0 +1,47 @@
+##
+#    Copyright (c) 2012-2013 Cyrus Daboo. All rights reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License");
+#    you may not use this file except in compliance with the License.
+#    You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+##
+
+import unittest
+from pycalendar.stringutils import strduptokenstr
+
+class TestStringUtils(unittest.TestCase):
+
+    def test_strduptokenstr(self):
+        """
+        Make sure L{strduptokenstr} copes with all possibilities.
+        """
+
+        data = (
+            # Leading space
+            ("  abc:def", ":;", ("abc", ":def")),
+            ("  \"abc\":def", ":;", ("abc", ":def")),
+            ("   ", ":;", (None, "")),
+
+            # Quoted
+            ("\"abc\":def", ":;", ("abc", ":def")),
+            ("\"ab\\c\":def", ":;", ("ab\\c", ":def")),
+            ("\"ab\\c:def", ":;", (None, "\"ab\\c:def")),
+            ("\"abc\":", ":;", ("abc", ":")),
+            ("\"abc\"", ":;", ("abc", "")),
+
+            # Unuoted
+            ("abc:def", ":;", ("abc", ":def")),
+            ("abc:", ":;", ("abc", ":")),
+            ("abc", ":;", ("abc", "")),
+        )
+
+        for txt, tokens, result in data:
+            self.assertEqual(strduptokenstr(txt, tokens), result)

Modified: PyCalendar/trunk/src/pycalendar/utils.py
===================================================================
--- PyCalendar/trunk/src/pycalendar/utils.py	2014-06-25 18:45:45 UTC (rev 13688)
+++ PyCalendar/trunk/src/pycalendar/utils.py	2014-06-25 18:47:12 UTC (rev 13689)
@@ -201,57 +201,67 @@
     RFC6868 parameter encoding.
     """
 
-    encoded = []
-    last = ''
-    for c in value:
-        if c == '\r':
-            encoded.append('^')
-            encoded.append('n')
-        elif c == '\n':
-            if last != '\r':
-                encoded.append('^')
-                encoded.append('n')
-        elif c == '"':
-            encoded.append('^')
-            encoded.append('\'')
-        elif c == '^':
-            encoded.append('^')
-            encoded.append('^')
-        else:
-            encoded.append(c)
-        last = c
+    # Test for encoded characters first as encoding is expensive and it is better to
+    # avoid doing it if it is not required (which is the common case)
+    encode = False
+    for c in "\r\n\"^":
+        if c in value:
+            encode = True
 
-    return "".join(encoded)
+    if encode:
+        encoded = []
+        last = ''
+        for c in value:
+            if c in "\r\n\"^":
+                if c == '\r':
+                    encoded.append("^n")
+                elif c == '\n':
+                    if last != '\r':
+                        encoded.append("^n")
+                elif c == '"':
+                    encoded.append("^'")
+                elif c == '^':
+                    encoded.append("^^")
+            else:
+                encoded.append(c)
+            last = c
 
+        return "".join(encoded)
+    else:
+        return value
 
 
+
 def decodeParameterValue(value):
     """
     RFC6868 parameter decoding.
     """
 
-    if value is None:
-        return None
-    decoded = []
-    last = ''
-    for c in value:
+    # Test for encoded characters first as decoding is expensive and it is better to
+    # avoid doing it if it is not required (which is the common case)
+    if value is not None and "^" in value:
+        decoded = []
+        last = ''
+        for c in value:
+            if last == '^':
+                if c == 'n':
+                    decoded.append('\n')
+                elif c == '\'':
+                    decoded.append('"')
+                elif c == '^':
+                    decoded.append('^')
+                    c = ''
+                else:
+                    decoded.append('^')
+                    decoded.append(c)
+            elif c != '^':
+                decoded.append(c)
+            last = c
         if last == '^':
-            if c == 'n':
-                decoded.append('\n')
-            elif c == '\'':
-                decoded.append('"')
-            elif c == '^':
-                decoded.append('^')
-                c = ''
-            else:
-                decoded.append('^')
-                decoded.append(c)
-        elif c != '^':
-            decoded.append(c)
-        last = c
-    if last == '^':
-        decoded.append('^')
-    return "".join(decoded)
+            decoded.append('^')
+        return "".join(decoded)
+    else:
+        return value
 
 
 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140625/f02ee0d9/attachment.html>


More information about the calendarserver-changes mailing list