1 """
2 BINARY2 VOTable encoding.
3
4 BINARY2 is like BINARY, except every record is preceded by a mask which
5 columns are NULL.
6
7 We do not determine any nullvalues any more here.
8
9 Sorry for gratuituously peeking into the guts of enc_binary here. But well,
10 it's family.
11 """
12
13
14
15
16
17
18
19 import datetime
20 import struct
21
22 from gavo import utils
23 from gavo.utils import pgsphere
24 from gavo.votable import coding
25 from gavo.votable import common
26 from gavo.votable import enc_binary
27
28
29 floatNaN = struct.pack("!f", common.NaN)
30 doubleNaN = struct.pack("!d", common.NaN)
31
32
33
35 return enc_binary._makeBitEncoder(field, allowNULL=True)
36
37
39 def makeIntEncoder(field):
40 return [
41 "if val is None:",
42 " val = 0",
43 "tokens.append(struct.pack('%s', val))"%fmtCode]
44 return makeIntEncoder
45
46
48 return [
49 "if val is None:",
50 " val = 0",
51 "else:"
52 " val = ord(val)",
53 "tokens.append(struct.pack('B', val))"]
54
55
57 return [
58 "if val is None:",
59 " tokens.append('\\x00\\x00')",
60 "else:",
61 " coded = val.encode('utf-16be')",
62 " tokens.append(struct.pack('%ds'%len(coded), coded))"]
63
64
66 return [
67 "if isinstance(val, int):",
68 " tokens.append(struct.pack('B', val))",
69 "elif val is None:",
70 " tokens.append('\xff')",
71 "else:",
72 " tokens.append(struct.pack('c', val))"]
73
74
75 _encoders = {
76 "boolean": enc_binary._makeBooleanEncoder,
77 "bit": enc_binary._makeBitEncoder,
78 "unsignedByte": _makeUnsignedByteEncoder,
79 "short": _generateIntEncoderMaker('!h'),
80 "int": _generateIntEncoderMaker('!i'),
81 "long": _generateIntEncoderMaker('!q'),
82 "char": _makeCharEncoder,
83 "unicodeChar": _makeUnicodeCharEncoder,
84 "double": enc_binary._generateFloatEncoderMaker("!d", "doubleNaN"),
85 "float": enc_binary._generateFloatEncoderMaker("!f", "floatNaN"),
86 "doubleComplex": enc_binary._generateComplexEncoderMaker(
87 "!dd", "doubleNaN"),
88 "floatComplex": enc_binary._generateComplexEncoderMaker("!ff", "floatNaN"),
89 }
90
91
93
94
95 src = []
96
97 src.extend(common.getXtypeEncoderCode(field))
98 src.append("val = coding.trimString(val, %s, '\\0')"%repr(field.arraysize))
99
100 if field.datatype=="char":
101 src.extend([
102 'if isinstance(val, unicode):',
103 ' val = val.encode("ascii", "replace")'])
104
105 if field.hasVarLength():
106 src.extend([
107 "tokens.append(struct.pack('!i', len(val)))",
108 ])
109
110 if field.datatype=="unicodeChar":
111 src.append("val = val.encode('utf-16be')")
112 src.append("tokens.append(struct.pack('%ds'%len(val), val))")
113
114 return src
115
116
118 """returns python lines to encode array values of field.
119 """
120 type = field.datatype
121
122
123 if type=="bit":
124 return _makeBitEncoder(field)
125
126 if type=="char" or type=="unicodeChar":
127 return _makeCharArrayEncoder(field)
128
129
130
131
132 padder = '[None]'
133 src = [
134 "fullTokens = tokens",
135 "tokens = []",
136 "if val is None:",
137 " arr = []",
138 "else:",
139 " arr = val",
140 "for val in arr:"
141 ]+common.indentList(_encoders[field.datatype](field), " ")
142
143 src.extend([
144 "fullTokens.append(''.join(tokens))",
145 "tokens = fullTokens"])
146
147 return (common.getXtypeEncoderCode(field)
148 + enc_binary._getArrayShapingCode(field, padder)
149 + src)
150
151
152
154 """returns a sequence of python source lines to encode values described
155 by field into tabledata.
156 """
157 if field.isScalar():
158 return _encoders[field.datatype](field)
159 else:
160 return _getArrayEncoderLines(field)
161
162
164 return [
165 "tokens.append(nullFlags.serializeFromRow(tableRow))"]
166
167
168 -def getPostamble(tableDefinition):
169 return [
170 "return ''.join(tokens)"]
171
172
177