update credits
[LibreOffice.git] / solenv / gdb / libreoffice / tl.py
blob7c18a955543491f8e5d97778790670c4cac78723
1 # -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
3 # This file is part of the LibreOffice project.
5 # This Source Code Form is subject to the terms of the Mozilla Public
6 # License, v. 2.0. If a copy of the MPL was not distributed with this
7 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 import gdb
12 from libreoffice.util import printing
13 from libreoffice.util.string import StringPrinterHelper
15 class StringPrinter(StringPrinterHelper):
16 '''Prints ByteString or UniString'''
18 def __init__(self, typename, val, encoding = None):
19 super(StringPrinter, self).__init__(typename, val, encoding)
21 def valid(self):
22 data = self.val['mpData']
23 # mnRefCount is not a good indicator: it seems there could be
24 # cases where it is negative (-7FFFFFED)
25 return data #and data.dereference()['mnRefCount'] > 0
27 def data(self):
28 assert self.val['mpData']
29 return self.val['mpData'].dereference()['maStr']
31 def length(self):
32 assert self.val['mpData']
33 return self.val['mpData'].dereference()['mnLen']
35 class BigIntPrinter(object):
36 '''Prints big integer'''
38 def __init__(self, typename, val):
39 self.val = val
41 def to_string(self):
42 if self.val['bIsSet']:
43 if self.val['bIsBig']:
44 return self._value()
45 else:
46 return self.val['nVal']
47 else:
48 return "unset %s" % self.typename
50 def _value(self):
51 len = self.val['nLen']
52 digits = self.val['nNum']
53 dsize = digits.dereference().type.sizeof * 8
54 num = 0
55 # The least significant byte is on index 0
56 for i in reversed(range(0, len)):
57 num <<= dsize
58 num += digits[i]
59 return num
61 class ColorPrinter(object):
62 '''Prints color as rgb(r, g, b) or rgba(r, g, b, a)'''
64 def __init__(self, typename, val):
65 self.val = val
67 def to_string(self):
68 color = self.val['mnColor']
69 b = color & 0xff
70 g = (color >> 8) & 0xff
71 r = (color >> 16) & 0xff
72 a = (color >> 24) & 0xff
73 if a:
74 return "rgba(%d, %d, %d, %d)" % (r, g, b, a)
75 else:
76 return "rgb(%d, %d, %d)" % (r, g, b)
78 class FractionPrinter(object):
79 '''Prints fraction'''
81 def __init__(self, typename, val):
82 self.typename = typename
83 self.val = val
85 def to_string(self):
86 numerator = self.val['nNumerator']
87 denominator = self.val['nDenominator']
88 if denominator > 0:
89 return "%d/%d" % (numerator, denominator)
90 else:
91 return "invalid %s" % self.typename
93 class DateTimeImpl(object):
95 def __init__(self, date, time):
96 self.date = date
97 self.time = time
99 def __str__(self):
100 result = ''
101 if self.date:
102 result += str(self.date)
103 if self.time:
104 result += ' '
105 if self.time:
106 result += str(self.time)
107 return result
109 @staticmethod
110 def parse(val):
111 return DateTimeImpl(DateImpl.parse(val), TimeImpl.parse(val))
113 class DateTimePrinter(object):
114 '''Prints date and time'''
116 def __init__(self, typename, val):
117 self.val = val
119 def to_string(self):
120 return str(DateTimeImpl.parse(self.val))
122 class DateImpl(DateTimeImpl):
124 def __init__(self, year, month, day):
125 super(DateImpl, self).__init__(self, None)
126 self.year = year
127 self.month = month
128 self.day = day
130 def __str__(self):
131 return "%d-%d-%d" % (self.year, self.month, self.day)
133 @staticmethod
134 def parse(val):
135 date = val['nDate']
136 d = date % 100
137 m = (date / 100) % 100
138 y = date / 10000
139 return DateImpl(y, m, d)
141 class DatePrinter(object):
142 '''Prints date'''
144 def __init__(self, typename, val):
145 self.val = val
147 def to_string(self):
148 return str(DateImpl.parse(self.val))
150 class TimeImpl(DateTimeImpl):
152 def __init__(self, hour, minute, second, nanosecond = 0):
153 super(TimeImpl, self).__init__(None, self)
154 self.hour = hour
155 self.minute = minute
156 self.second = second
157 self.nanosecond = nanosecond
159 def __str__(self):
160 decimal = ''
161 if self.nanosecond != 0:
162 decimal = '.%09d' % self.nanosecond
163 return "%02d:%02d:%02d%s" % (self.hour, self.minute, self.second, decimal)
165 @staticmethod
166 def parse(val):
167 time = val['nTime']
168 h = time / 10000000000000
169 m = (time / 100000000000) % 100
170 s = (time / 1000000000) % 100
171 ns = time % 1000000000
172 return TimeImpl(h, m, s, ns)
174 class TimePrinter(object):
175 '''Prints time'''
177 def __init__(self, typename, val):
178 self.val = val
180 def to_string(self):
181 return str(TimeImpl.parse(self.val))
183 class IteratorHelper(object):
184 '''Implements a container iterator useable for both 'linear'
185 containers (like DynArray or List) and Tables
188 def __init__(self, block, count, type = None):
189 self.count = count
190 self.type = type
191 self.pos = 0
192 self.block = None
193 self.block_count = 0
194 self.block_pos = 0
195 if block:
196 self._next_block(block)
198 self._check_invariant()
200 def __iter__(self):
201 return self
203 def next(self):
204 if self.pos == self.count:
205 raise StopIteration()
207 if self.block_pos == self.block_count:
208 self._next_block(self.block['pNext'])
210 name = self.name()
211 val = self.value()
212 self.advance()
214 self._check_invariant()
215 return (name, val)
217 def _next_block(self, block):
218 assert block
220 self.block = block.dereference()
221 self.block_pos = 0
222 self.block_count = block['nCount']
224 assert self.block_count <= block['nSize']
225 assert self.block_count + self.pos <= self.count
227 def _check_invariant(self):
228 assert self.count >= 0
229 assert self.pos >= 0
230 assert self.pos <= self.count
231 assert self.block_count >= 0
232 if self.pos < self.count:
233 assert self.block_count > 0
234 assert self.block != None
235 assert self.block_count <= self.count
236 assert self.block_pos >= 0
237 assert self.block_pos <= self.block_count
239 class NoItemType(Exception):
240 pass
242 class ContainerHelper(object):
243 '''Provides support for specialized container printers'''
245 def __init__(self, typename, val, iterator):
246 self.typename = typename
247 self.val = val
248 self.iterator = iterator
250 def to_string(self):
251 size = self.val['nCount']
252 if size > 0:
253 return "%s of length %d" % (self.typename, size)
254 elif size == 0:
255 return "empty %s" % self.typename
256 else:
257 return "invalid %s" % self.typename
259 def children(self):
260 count = self.val.cast(gdb.lookup_type('Container'))['nCount']
261 return self.iterator(self.val['pFirstBlock'], count)
263 class LinearIterator(IteratorHelper):
264 '''Is iterator for 'linear' container'''
266 def __init__(self, block, count, type = None):
267 super(LinearIterator, self).__init__(block, count, type)
269 def name(self):
270 return str(self.pos)
272 def value(self):
273 nodes = self.block['pNodes']#.cast(self.type.pointer())
274 return nodes[self.block_pos]
276 def advance(self):
277 self.pos += 1
278 self.block_pos += 1
280 class LinearContainerPrinter(ContainerHelper):
281 '''Prints 'linear' container, like DynArray or List'''
283 def __init__(self, typename, val):
284 super(LinearContainerPrinter, self).__init__(typename, val, LinearIterator)
286 def display_hint(self):
287 return 'array'
289 class TableIterator(IteratorHelper):
290 '''Is iterator for Table'''
292 def __init__(self, block, count, type = None):
293 super(TableIterator, self).__init__(block, count, type)
294 # ULONG doesn't work on 64-bit for some reason (gdb says it has
295 # size 4 and it's not a typedef to sal_uIntPtr)
296 self._key_type = gdb.lookup_type('sal_uIntPtr')
297 self.is_key = True
299 def name(self):
300 return ''
302 def value(self):
303 nodes = self.block['pNodes']#.cast(self.type.pointer())
304 val = nodes[self.block_pos]
305 if self.is_key:
306 val = str(val.cast(self._key_type))
307 return val
309 def advance(self):
310 self.pos += 1
311 self.block_pos += 1
312 self.is_key = not self.is_key
314 class TablePrinter(ContainerHelper):
315 '''Prints table'''
317 def __init__(self, typename, val):
318 super(TablePrinter, self).__init__(typename, val, TableIterator)
320 def display_hint(self):
321 return 'map'
323 class PointPrinter(object):
324 '''Prints a Point.'''
326 def __init__(self, typename, value):
327 self.typename = typename
328 self.value = value
330 def to_string(self):
331 return "%s" % (self.typename)
333 def children(self):
334 x = self.value['nA']
335 y = self.value['nB']
336 children = [('x', x), ('y', y)]
337 return children.__iter__()
339 class SizePrinter(object):
340 '''Prints a Size.'''
342 def __init__(self, typename, value):
343 self.typename = typename
344 self.value = value
346 def to_string(self):
347 return "%s" % (self.typename)
349 def children(self):
350 width = self.value['nA']
351 height = self.value['nB']
352 children = [('width', width), ('height', height)]
353 return children.__iter__()
355 class RectanglePrinter(object):
356 '''Prints a Rectangle.'''
358 def __init__(self, typename, value):
359 self.typename = typename
360 self.value = value
362 def to_string(self):
363 return "%s" % (self.typename)
365 def children(self):
366 left = self.value['nLeft']
367 top = self.value['nTop']
368 right = self.value['nRight']
369 bottom = self.value['nBottom']
370 children = [('left', left), ('top', top), ('right', right), ('bottom', bottom)]
371 return children.__iter__()
373 printer = None
375 def build_pretty_printers():
376 global printer
378 printer = printing.Printer('libreoffice/tl')
380 # old-style strings
381 printer.add('ByteString', StringPrinter)
382 printer.add('String', lambda name, val: StringPrinter(name, val, 'utf-16'))
384 # old-style containers
385 printer.add('DynArray', LinearContainerPrinter)
386 printer.add('List', LinearContainerPrinter)
387 printer.add('Stack', LinearContainerPrinter)
388 printer.add('Table', TablePrinter)
390 # various types
391 printer.add('BigInt', BigIntPrinter)
392 printer.add('Color', ColorPrinter)
393 printer.add('Fraction', FractionPrinter)
394 printer.add('DateTime', DateTimePrinter)
395 printer.add('Date', DatePrinter)
396 printer.add('Time', TimePrinter)
397 printer.add('Point', PointPrinter)
398 printer.add('Size', SizePrinter)
399 printer.add('Rectangle', RectanglePrinter)
401 def register_pretty_printers(obj):
402 printing.register_pretty_printer(printer, obj)
404 build_pretty_printers()
406 # vim:set shiftwidth=4 softtabstop=4 expandtab: