|
From: <bc...@wo...> - 2001-02-02 13:08:20
|
[Ype Kingma]
>"""
>stringbuffer.py: mutable string built on java.lang.StringBuffer.
>
>The idea is to save as many string object creations as possible
>while still be about as fast as string's, when implemented
>in Java. This python module is intended as a prototype.
>
>
>The itch:
>
>I needed java.lang.StringBuffer functionality in jython
>on the receiving side of a socket.
>I grew tired of writing:
> buf += sock.recv(maxSize)
>which creates a new buf everytime
>sock.recv(maxSize) is called. Note that sock.recv()
>may return as little as it likes, depending on
>network traffic conditions.
>The alternative of keeping a list of received
>strings did not really appeal to me.
>
>
>The questions:
>
>- This may have been done umpteen times before, when so
> could someone please tell me?
There is a UserString.MutableString class, but it have a diffrent
purpose. A module that wraps a StringBuffer could be usefull as a
standard module.
>- I added the standard string methods.
> Only when these originally return a string I have them put
> the result back into the stringbuffer.
> Methods that return something else work as if they
> were used on a string.
> Is this the right approach? Esp. for split() and friends?
Hard to say. If you haven't already, you can take a look at which
methods in UserString.UserString that returns strings and which that
return UserStrings.
>- I don't know whether I handled python default arguments
> correctly, eg:
>
> def count(self, sub, start = None, end = None):
> if start == None:
> if end == None:
> return str(self).count(sub)
> else:
> return str(self).count(sub, 0, end)
> elif end == None:
> return str(self).count(sub, start)
> else:
> return str(self).count(sub, start, end)
>
> (str(self) should disappear in the java version ...)
That is too much work. UserString simply does:
def count(self, sub, start=0, end=sys.maxint):
return self.data.count(sub, start, end)
Another way to deduce the default values are by looking at the PyString
sources for count(..):
public int count(String sub) {
return count(sub, 0, string.length());
}
public int count(String sub, int start) {
return count(sub, start, string.length());
}
public int count(String sub, int start, int end) {
...
}
The last count method will validate the start/end indexes so the
sys.maxint trick also works.
>- Is an extend() method needed? It is marked as experimental
> in my python 2.0 documentation.
Hard to say. The [].extend() is now used by standard python library so I
think it is safe to say that it will remain. I see no problem with
adding it to stringbuffer and marking it non-experimental.
>- Should slicing be allowed with other steps than 1?
No. I don't see much use for it. After all, strings are not meant as
general sequence. We have real lists for that.
>- pop() also works for slices, is that ok.?
I don't see much use for that either. It's a minor thing.
>Aside: in the sort() method this line gives an internal compiler error:
> l = [self[i] for i in range(len(self))] # internal compiler error:
>name i (jython2.0a3)
>Why?
Because there was an internal compiler error in 2.0alpha3 <wink>. It was
a bug where fast locals in listcomps was not correctly detected.
OTOH, sorting a stringbuffer is bogus. Cute but mostly useless. I'd
rather avoid adding a sort method.
I modified a copy if CPython's test_userstring.py. You should try it, it
caught some typos. It must be run from CPython's ./Lib/test directory.
#!/usr/bin/env python
import sys, string
from test_support import verbose
import string_tests
# UserString is a wrapper around the native builtin string type.
# UserString instances should behave similar to builtin string objects.
# The test cases were in part derived from 'test_string.py'.
from stringbuffer import stringbuffer
if __name__ == "__main__":
verbose = 0
tested_methods = {}
def test(methodname, input, *args):
global tested_methods
tested_methods[methodname] = 1
if verbose:
print '%s.%s(%s) ' % (input, methodname, args),
u = stringbuffer(input)
objects = [input, u, stringbuffer(u)]
res = [""] * 3
for i in range(3):
object = objects[i]
try:
f = getattr(object, methodname)
res[i] = apply(f, args)
except:
res[i] = sys.exc_type
if res[0] != res[1]:
if verbose:
print 'no'
print `input`, f, `res[0]`, "<>", `res[1]`
else:
if verbose:
print 'yes'
if res[1] != res[2]:
if verbose:
print 'no'
print `input`, f, `res[1]`, "<>", `res[2]`
else:
if verbose:
print 'yes'
string_tests.run_method_tests(test)
regards,
finn
|