Add timestamp offset for block header
[p2pool.git] / SOAPpy / Utilities.py
1 """
2 ################################################################################
3 # Copyright (c) 2003, Pfizer
4 # Copyright (c) 2001, Cayce Ullman.
5 # Copyright (c) 2001, Brian Matthews.
6 #
7 # All rights reserved.
8 #
9 # Redistribution and use in source and binary forms, with or without
10 # modification, are permitted provided that the following conditions are met:
11 # Redistributions of source code must retain the above copyright notice, this
12 # list of conditions and the following disclaimer.
13 #
14 # Redistributions in binary form must reproduce the above copyright notice,
15 # this list of conditions and the following disclaimer in the documentation
16 # and/or other materials provided with the distribution.
17 #
18 # Neither the name of actzero, inc. nor the names of its contributors may
19 # be used to endorse or promote products derived from this software without
20 # specific prior written permission.
21 #
22 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
26 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #
33 ################################################################################
34 """
35
36 ident = '$Id: Utilities.py 1298 2006-11-07 00:54:15Z sanxiyn $'
37 from version import __version__
38
39 import re
40 import string
41 import sys
42 from types import *
43
44 # SOAPpy modules
45 from Errors import *
46
47 ################################################################################
48 # Utility infielders
49 ################################################################################
50 def collapseWhiteSpace(s):
51     return re.sub('\s+', ' ', s).strip()
52
53 def decodeHexString(data):
54     conv = {
55             '0': 0x0, '1': 0x1, '2': 0x2, '3': 0x3, '4': 0x4,
56             '5': 0x5, '6': 0x6, '7': 0x7, '8': 0x8, '9': 0x9,
57             
58             'a': 0xa, 'b': 0xb, 'c': 0xc, 'd': 0xd, 'e': 0xe,
59             'f': 0xf,
60             
61             'A': 0xa, 'B': 0xb, 'C': 0xc, 'D': 0xd, 'E': 0xe,
62             'F': 0xf,
63             }
64     
65     ws = string.whitespace
66
67     bin = ''
68
69     i = 0
70
71     while i < len(data):
72         if data[i] not in ws:
73             break
74         i += 1
75
76     low = 0
77
78     while i < len(data):
79         c = data[i]
80
81         if c in string.whitespace:
82             break
83
84         try:
85             c = conv[c]
86         except KeyError:
87             raise ValueError, \
88                 "invalid hex string character `%s'" % c
89
90         if low:
91             bin += chr(high * 16 + c)
92             low = 0
93         else:
94             high = c
95             low = 1
96
97         i += 1
98
99     if low:
100         raise ValueError, "invalid hex string length"
101
102     while i < len(data):
103         if data[i] not in string.whitespace:
104             raise ValueError, \
105                 "invalid hex string character `%s'" % c
106
107         i += 1
108
109     return bin
110
111 def encodeHexString(data):
112     h = ''
113
114     for i in data:
115         h += "%02X" % ord(i)
116
117     return h
118
119 def leapMonth(year, month):
120     return month == 2 and \
121         year % 4 == 0 and \
122         (year % 100 != 0 or year % 400 == 0)
123
124 def cleanDate(d, first = 0):
125     ranges = (None, (1, 12), (1, 31), (0, 23), (0, 59), (0, 61))
126     months = (0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
127     names = ('year', 'month', 'day', 'hours', 'minutes', 'seconds')
128
129     if len(d) != 6:
130         raise ValueError, "date must have 6 elements"
131
132     for i in range(first, 6):
133         s = d[i]
134
135         if type(s) == FloatType:
136             if i < 5:
137                 try:
138                     s = int(s)
139                 except OverflowError:
140                     if i > 0:
141                         raise
142                     s = long(s)
143
144                 if s != d[i]:
145                     raise ValueError, "%s must be integral" % names[i]
146
147                 d[i] = s
148         elif type(s) == LongType:
149             try: s = int(s)
150             except: pass
151         elif type(s) != IntType:
152             raise TypeError, "%s isn't a valid type" % names[i]
153
154         if i == first and s < 0:
155             continue
156
157         if ranges[i] != None and \
158             (s < ranges[i][0] or ranges[i][1] < s):
159             raise ValueError, "%s out of range" % names[i]
160
161     if first < 6 and d[5] >= 61:
162         raise ValueError, "seconds out of range"
163
164     if first < 2:
165         leap = first < 1 and leapMonth(d[0], d[1])
166
167         if d[2] > months[d[1]] + leap:
168             raise ValueError, "day out of range"
169
170 def debugHeader(title):
171     s = '*** ' + title + ' '
172     print s + ('*' * (72 - len(s)))
173
174 def debugFooter(title):
175     print '*' * 72
176     sys.stdout.flush()