1 | # lognestmonster Copyright (c) 2019 Joshua 'joshuas3' Stockin |
2 | # <https://github.com/JoshuaS3/lognestmonster/>. |
3 |
|
4 |
|
5 | # This file is part of lognestmonster. |
6 |
|
7 | # lognestmonster is free software: you can redistribute it and/or modify |
8 | # it under the terms of the GNU General Public License as published by |
9 | # the Free Software Foundation, either version 3 of the License, or |
10 | # (at your option) any later version. |
11 |
|
12 | # lognestmonster is distributed in the hope that it will be useful, |
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | # GNU General Public License for more details. |
16 |
|
17 | # You should have received a copy of the GNU General Public License |
18 | # along with lognestmonster. If not, see <https://www.gnu.org/licenses/>. |
19 |
|
20 | import struct |
21 | import os |
22 |
|
23 | STATEMENT_START = 0 |
24 | STATEMENT_END = 1 |
25 | EVENT_START = 2 |
26 | EVENT_END = 3 |
27 |
|
28 | def ulonglong(bytestr): |
29 | return struct.unpack("@Q", bytestr)[0] |
30 | def uchar(charv): |
31 | return struct.unpack("@B", charv)[0] |
32 | def ushort(shortv): |
33 | return struct.unpack("@H", shortv)[0] |
34 |
|
35 |
|
36 | class NestableProto: |
37 | parent = None |
38 |
|
39 | class NestProto: |
40 | pushed = [] |
41 |
|
42 | class StatementProto(NestableProto): |
43 | verbosity = 0 |
44 | timestamp = 0 |
45 | pos = 0 |
46 | def __init__(self): |
47 | self.verbosity = 0 |
48 | self.timestamp = 0 |
49 | self.pos = 0 |
50 | self.parent = None |
51 | self.pushed = [] |
52 |
|
53 | class EventProto(NestProto, NestableProto): |
54 | def __init__(self): |
55 | self.parent = None |
56 | self.pushed = [] |
57 |
|
58 |
|
59 | class Reader: |
60 | fd = None |
61 |
|
62 | version = 0 |
63 | timestamp = 0 |
64 |
|
65 | objects = {} |
66 |
|
67 | event_count = 0 |
68 | statement_count = 0 |
69 |
|
70 | file_size = 0 |
71 | position = 0 |
72 |
|
73 | def __init__(self, fd): |
74 | self.fd = fd |
75 |
|
76 | self.version = 0 |
77 | self.timestamp = 0 |
78 |
|
79 | self.objects = {} # key = position in file, value = True for statement, False for event |
80 |
|
81 | self.event_count = 0 |
82 | self.statement_count = 0 |
83 |
|
84 | self.file_size = 0 |
85 | self.position = 0 |
86 |
|
87 | self.size() |
88 | self.scan() |
89 |
|
90 | def size(): |
91 | self.fd.seek(0, os.SEEK_END) # go to end of file and get position |
92 | newsize = self.fd.tell() |
93 | self.fd.seek(self.position) # return to previous position |
94 |
|
95 | diff = self.file_size - newsize |
96 | self.file_size = newsize |
97 | return diff > 0 |
98 |
|
99 | def scan(): # scan for events and statements from self.position to the end of file |
100 | if self.position == 0: # if it's the start of the file, grab version and timestamp |
101 | version_byte = self.fd.read(1) |
102 | self.version = uchar(version_byte) |
103 | timestamp_bytes = self.fd.read(8) |
104 | self.timestamp = ulonglong(timestamp_bytes) |
105 | self.position = self.fd.tell() |
106 |
|
107 | current_statement = None |
108 | current_event = None |
109 | if self.position < self.file_size: |
110 | self.objects[self.position:self.file_size] = None |
111 | while self.position < self.file_size: |
112 | pass |
113 |
|
114 |
|