| 1 | #!/usr/bin/env python2
 | 
| 2 | """
 | 
| 3 | strings.py
 | 
| 4 | """
 | 
| 5 | from __future__ import print_function
 | 
| 6 | 
 | 
| 7 | import os
 | 
| 8 | from mycpp import mylib
 | 
| 9 | from mycpp.mylib import log
 | 
| 10 | 
 | 
| 11 | from typing import List
 | 
| 12 | 
 | 
| 13 | 
 | 
| 14 | def banner(s):
 | 
| 15 |     # type: (str) -> None
 | 
| 16 |     print('')
 | 
| 17 |     print('=== %s ===' % s)
 | 
| 18 |     print('')
 | 
| 19 | 
 | 
| 20 | 
 | 
| 21 | class Foo(object):
 | 
| 22 | 
 | 
| 23 |     def __init__(self):
 | 
| 24 |         # type: () -> None
 | 
| 25 |         self.s = 'mystr'
 | 
| 26 | 
 | 
| 27 | 
 | 
| 28 | def TestMethods():
 | 
| 29 |     # type: () -> None
 | 
| 30 | 
 | 
| 31 |     s = 'a1bc'
 | 
| 32 | 
 | 
| 33 |     if s.startswith(''):
 | 
| 34 |         print('empty yes')
 | 
| 35 | 
 | 
| 36 |     if s.startswith('a1'):
 | 
| 37 |         print('a1 yes')
 | 
| 38 | 
 | 
| 39 |     if not s.startswith('zz'):
 | 
| 40 |         print('zz no')
 | 
| 41 | 
 | 
| 42 |     if s.endswith(''):
 | 
| 43 |         print('empty yes')
 | 
| 44 | 
 | 
| 45 |     if s.endswith('bc'):
 | 
| 46 |         print('bc yes')
 | 
| 47 | 
 | 
| 48 |     if s.endswith('c'):
 | 
| 49 |         print('bc yes')
 | 
| 50 | 
 | 
| 51 |     if not s.endswith('zzzzzz'):
 | 
| 52 |         print('zzzzzz no')
 | 
| 53 | 
 | 
| 54 |     # This file is out of date!  It thinks it happens in Python 3, but we have
 | 
| 55 |     # it in Python 2.7
 | 
| 56 | 
 | 
| 57 |     # /home/andy/wedge/oils-for-unix.org/pkg/mypy/0.780/mypy/typeshed/stdlib/2/__builtin__.pyi:509: note: "startswith" of "str" defined here
 | 
| 58 | 
 | 
| 59 |     # Fixed here - https://github.com/python/typeshed/blob/main/stdlib/builtins.pyi
 | 
| 60 |     #
 | 
| 61 |     # It can be fixed by patching, gah
 | 
| 62 | 
 | 
| 63 |     # start pos
 | 
| 64 |     #if s.startswith('bc', start=2):
 | 
| 65 |     #    print('bc YES')
 | 
| 66 | 
 | 
| 67 |     # find(s, start, end) can be used to implement TokenStartsWith() and
 | 
| 68 |     # TokenEndsWith(), TokenEquals(), IsPlusEquals(), TokenContains(), etc.
 | 
| 69 | 
 | 
| 70 |     s = 'aaa-bb-cc'
 | 
| 71 |     substrs = [
 | 
| 72 |         'aa',
 | 
| 73 |         'b',
 | 
| 74 |         'z',
 | 
| 75 |         'aaaa',  # too long
 | 
| 76 |         '',
 | 
| 77 |     ]
 | 
| 78 |     for substr in substrs:
 | 
| 79 |         for start in xrange(0, len(s)):
 | 
| 80 |             pos = s.find(substr, start)
 | 
| 81 |             print('%s find %s start:%d => %d' % (s, substr, start, pos))
 | 
| 82 | 
 | 
| 83 |     print('---')
 | 
| 84 | 
 | 
| 85 |     for substr in substrs:
 | 
| 86 |         for end in xrange(0, len(s)):
 | 
| 87 |             pos = s.find(substr, 0, end)
 | 
| 88 |             print('%s find %s end:%d => %d' % (s, substr, end, pos))
 | 
| 89 | 
 | 
| 90 |     print('---')
 | 
| 91 | 
 | 
| 92 |     # empty string test
 | 
| 93 |     for start in xrange(0, 3):
 | 
| 94 |         for end in xrange(0, 3):
 | 
| 95 |             pos = s.find('', start, end)
 | 
| 96 |             print('%s find empty [%d, %d) => %d' % (s, start, end, pos))
 | 
| 97 | 
 | 
| 98 | 
 | 
| 99 | def TestFormat():
 | 
| 100 |     # type: () -> None
 | 
| 101 | 
 | 
| 102 |     banner('TestFormat')
 | 
| 103 | 
 | 
| 104 |     print('foo' + 'bar')
 | 
| 105 |     print('foo' * 3)
 | 
| 106 |     obj = Foo()
 | 
| 107 |     print('foo' + obj.s)
 | 
| 108 | 
 | 
| 109 |     s = 'mystr'
 | 
| 110 |     print('[%s]' % s)
 | 
| 111 | 
 | 
| 112 |     s = 'mystr'
 | 
| 113 |     print('[%s, %s]' % (s, 'abc'))
 | 
| 114 | 
 | 
| 115 |     print('%s: 5%%-100%%' % 'abc')
 | 
| 116 | 
 | 
| 117 |     print('<a href="foo.html">%s</a>' % 'anchor')
 | 
| 118 | 
 | 
| 119 |     print("foo? %d" % ('f' in s))
 | 
| 120 |     print("str? %d" % ('s' in s))
 | 
| 121 | 
 | 
| 122 |     print("int 5d %5d" % 35)
 | 
| 123 | 
 | 
| 124 |     print("'single'")
 | 
| 125 |     print('"double"')
 | 
| 126 | 
 | 
| 127 |     # test escape codes
 | 
| 128 |     print("a\tb\nc\td\n")
 | 
| 129 | 
 | 
| 130 |     x = 'x'
 | 
| 131 |     print("%s\tb\n%s\td\n" % (x, x))
 | 
| 132 | 
 | 
| 133 |     fmt = "%dfoo"
 | 
| 134 |     print(fmt % 10)
 | 
| 135 | 
 | 
| 136 |     fmts = ["foo%d"]
 | 
| 137 |     print(fmts[0] % 10)
 | 
| 138 | 
 | 
| 139 |     print(("foo " + "%s") % "bar")
 | 
| 140 | 
 | 
| 141 |     # NUL bytes
 | 
| 142 |     s = "spam\0%s" % "eggs"
 | 
| 143 | 
 | 
| 144 |     # TODO: There's a bug here -- we get len == 4 in C++, but it should be 9.
 | 
| 145 |     # It's either StrFormat() or the bad JSON literals \u0000
 | 
| 146 |     if 0:
 | 
| 147 |         print("len(s) = %d" % len(s))
 | 
| 148 |         print(s)
 | 
| 149 | 
 | 
| 150 |     s = "foo%s" % "\0bar"
 | 
| 151 |     print("len(s) = %d" % len(s))
 | 
| 152 | 
 | 
| 153 |     print("%o" % 12345)
 | 
| 154 |     print("%17o" % 12345)
 | 
| 155 |     print("%017o" % 12345)
 | 
| 156 | 
 | 
| 157 |     print("%%%d%%%%" % 12345)
 | 
| 158 | 
 | 
| 159 |     print("%r" % "tab\tline\nline\r\n")
 | 
| 160 | 
 | 
| 161 |     s = 'a1b2c3d4e5'
 | 
| 162 |     # Disable step support
 | 
| 163 |     # print(s[0:10:2])
 | 
| 164 |     # print(s[1:10:2])
 | 
| 165 |     print(s.upper())
 | 
| 166 | 
 | 
| 167 | 
 | 
| 168 | def TestByteOperations():
 | 
| 169 |     # type: () -> None
 | 
| 170 |     banner('TestByteOperations')
 | 
| 171 | 
 | 
| 172 |     s = 'foo' * 10
 | 
| 173 | 
 | 
| 174 |     i = 0
 | 
| 175 |     n = len(s)
 | 
| 176 |     total = 0
 | 
| 177 |     total2 = 0
 | 
| 178 |     while i < n:
 | 
| 179 |         byte = ord(s[i])
 | 
| 180 |         byte2 = mylib.ByteAt(s, i)
 | 
| 181 | 
 | 
| 182 |         total += byte
 | 
| 183 |         total2 += byte2
 | 
| 184 | 
 | 
| 185 |         i += 1
 | 
| 186 | 
 | 
| 187 |     if total != total2:
 | 
| 188 |         raise AssertionError()
 | 
| 189 | 
 | 
| 190 |     print('total = %d' % total)
 | 
| 191 |     print('total2 = %d' % total2)
 | 
| 192 | 
 | 
| 193 | 
 | 
| 194 | def TestBytes2():
 | 
| 195 |     # type: () -> None
 | 
| 196 | 
 | 
| 197 |     banner('TestBytes2')
 | 
| 198 | 
 | 
| 199 |     b = []  # type: List[int]
 | 
| 200 |     ch = []  # type: List[str]
 | 
| 201 |     for i in xrange(256):
 | 
| 202 |         # Shuffle it a bit, make it a better test
 | 
| 203 |         j = 255 - i
 | 
| 204 |         if j == 2:
 | 
| 205 |             j = 0
 | 
| 206 | 
 | 
| 207 |         b.append(j)
 | 
| 208 |         ch.append(chr(j))
 | 
| 209 | 
 | 
| 210 |     print('len(b) = %d' % len(b))
 | 
| 211 |     print('len(ch) = %d' % len(ch))
 | 
| 212 | 
 | 
| 213 |     all_bytes = ''.join(ch)
 | 
| 214 | 
 | 
| 215 |     b2 = mylib.JoinBytes(b)
 | 
| 216 |     if all_bytes == b2:
 | 
| 217 |         print('EQUAL ==')
 | 
| 218 |     else:
 | 
| 219 |         raise AssertionError('should be equal')
 | 
| 220 | 
 | 
| 221 |     n = len(all_bytes)
 | 
| 222 |     print('len(all_bytes) = %d' % n)
 | 
| 223 |     print('')
 | 
| 224 |     #print('[%s]' % all_bytes)
 | 
| 225 | 
 | 
| 226 |     i = 0
 | 
| 227 |     while i < n:
 | 
| 228 |         byte = mylib.ByteAt(all_bytes, i)
 | 
| 229 |         #log('byte = %d', byte)
 | 
| 230 | 
 | 
| 231 |         if mylib.ByteEquals(byte, '['):
 | 
| 232 |             print('LEFT')
 | 
| 233 |         if mylib.ByteEquals(byte, ']'):
 | 
| 234 |             print('RIGHT')
 | 
| 235 |         if mylib.ByteEquals(byte, '\\'):
 | 
| 236 |             print('BACKSLASH')
 | 
| 237 | 
 | 
| 238 |         # TODO: get rid of JSON crap
 | 
| 239 |         #if mylib.ByteEqualsStr(byte, '\xff'):
 | 
| 240 |         #    print('0xff')
 | 
| 241 | 
 | 
| 242 |         if mylib.ByteEquals(byte, chr(255)):
 | 
| 243 |             print('0xff')
 | 
| 244 | 
 | 
| 245 |         if mylib.ByteInSet(byte, 'abcXYZ'):
 | 
| 246 |             print('abcXYZ')
 | 
| 247 | 
 | 
| 248 |         i += 1
 | 
| 249 | 
 | 
| 250 |     print('')
 | 
| 251 | 
 | 
| 252 | 
 | 
| 253 | def run_tests():
 | 
| 254 |     # type: () -> None
 | 
| 255 | 
 | 
| 256 |     TestFormat()
 | 
| 257 |     TestMethods()
 | 
| 258 |     TestByteOperations()
 | 
| 259 |     TestBytes2()
 | 
| 260 | 
 | 
| 261 | 
 | 
| 262 | def run_benchmarks():
 | 
| 263 |     # type: () -> None
 | 
| 264 |     pass
 | 
| 265 | 
 | 
| 266 | 
 | 
| 267 | if __name__ == '__main__':
 | 
| 268 |     if os.getenv('BENCHMARK'):
 | 
| 269 |         log('Benchmarking...')
 | 
| 270 |         run_benchmarks()
 | 
| 271 |     else:
 | 
| 272 |         run_tests()
 |