Пример #1
0
 def parse_length(self):
     raw_bytes = self.data[12:13]
     raw_num = bytes_to_uint(raw_bytes, self.byte_order)
     firstb, secondb = raw_num // 16, raw_num % 16
     if secondb != 0 or firstb < 5 or firstb > 15:
         raise InvalidFieldValue()
     self.length = firstb * 4
Пример #2
0
 def parse_length(self):
     raw_bytes = self.data[12:13]
     raw_num = bytes_to_uint(raw_bytes, self.byte_order)
     firstb, secondb = raw_num // 16, raw_num % 16
     if secondb != 0 or firstb < 5 or firstb > 15:
         raise InvalidFieldValue()
     self.length = firstb * 4
Пример #3
0
 def parse_first_byte(self):
     raw_bytes = self.data[:1]
     raw_num = bytes_to_uint(raw_bytes, self.byte_order)
     firstb, secondb = raw_num // 16, raw_num % 16
     if firstb not in [4, 6]:
         raise InvalidFieldValue()
     self.version = firstb
     self.length = secondb * 4
Пример #4
0
 def parse_first_byte(self):
     raw_bytes = self.data[:1]
     raw_num = bytes_to_uint(raw_bytes, self.byte_order)
     firstb, secondb = raw_num // 16, raw_num % 16
     if firstb not in [4, 6]:
         raise InvalidFieldValue()
     self.version = firstb
     self.length = secondb * 4
Пример #5
0
    def parse_scenario(self, raw_city_data):
        """
        Parses the scenario information.
        Args:
            raw_city_data (bytes): Raw data to parse scenario information out of.
        """
        raw_text = raw_city_data["TEXT"]
        raw_scenario = raw_city_data["SCEN"]
        picture = raw_city_data["PICT"]

        for entry in raw_text:
            string_id = entry[: 4]
            raw_string = entry[4 :].decode('ASCII').replace('\r', '\n')
            if string_id == b'\x80\x00\x00\x00':
                self.scenario_text = raw_string
            elif string_id == b'\x81\x00\x00\x00':
                self.scenario_descriptive_text = raw_string
            else:
                print(f"Found unknown TEXT block in input file.\nid: {string_id}, contents: \"{raw_string}\"")
        if self.debug:
            print(f"Scenario:\nShort text: {self.scenario_text}\nDescriptive Text:{self.scenario_descriptive_text}")

        conditions = {}
        offset = 4
        for k, v in self._contents.items():
            conditions[k] = bytes_to_uint(raw_scenario[offset : offset + v])
            offset += v
            if self.debug:
                print(f"Conditions: {conditions}")
            self.scenario_condition = conditions

        header = picture[0 : 4]
        if header != bytearray(b'\x80\x00\x00\x00'):
            print("Scenario PICT parsing failed.")  # todo: exception?
        # Why is the endianness different here? It just is.
        row_length = unpack('<H', picture[4 : 6])[0]  # x dimension of image.
        row_count = unpack('<H', picture[6 : 8])[0]  # y dimension of image.
        image_data = []
        picture_data = picture[8 : ]
        if self.debug:
            print(f"Scenario PICT, {row_length}x{row_count} pixels:")
        for row_idx in range(0, row_count):
            row_start = row_idx * (row_length + 1)
            row = [x for x in picture_data[row_start : row_start + row_length + 1]]
            if row[-1] not in (0, 255):
                row = [0] * row_length
            else:
                row = row[ : -1]
            image_data.append(row)
        # In case the PICT isn't 65x65, like in MALIBU.SCN
        if row_count > 65:
            image_data = image_data[: 65]
        if self.debug:
            for idx, r in enumerate(image_data):
                print(f"{idx}:\n{r}")
        self.scenario_pict = image_data
Пример #6
0
    def parse_answers(self, start_pos):
        pos = start_pos
        for I in range(0, self.answers_rss):
            raw_data_length = self.data[pos+10:pos+12]
            data_length = bytes_to_uint(raw_data_length, self.byte_order)
            answer_length = 12 + data_length

            self.answers.append({
                'name': self.data[pos:pos+2],
                'type': self.data[pos+2:pos+4],
                'class': self.data[pos+4:pos+6],
                'time_to_live': self.data[pos+6:pos+10],
                'data': self.data[pos+12:pos+answer_length],
            })
            pos += answer_length
        return pos
Пример #7
0
    def parse_answers(self, start_pos):
        pos = start_pos
        for I in range(0, self.answers_rss):
            raw_data_length = self.data[pos + 10:pos + 12]
            data_length = bytes_to_uint(raw_data_length, self.byte_order)
            answer_length = 12 + data_length

            self.answers.append({
                'name':
                self.data[pos:pos + 2],
                'type':
                self.data[pos + 2:pos + 4],
                'class':
                self.data[pos + 4:pos + 6],
                'time_to_live':
                self.data[pos + 6:pos + 10],
                'data':
                self.data[pos + 12:pos + answer_length],
            })
            pos += answer_length
        return pos
Пример #8
0
 def parse_captured_size(self):
     raw_bytes = self.header[12:16]
     self.seconds = bytes_to_uint(raw_bytes, self.byte_order)
Пример #9
0
 def parse_saved_size(self):
     raw_bytes = self.header[8:12]
     self.saved_size = bytes_to_uint(raw_bytes, self.byte_order)
Пример #10
0
 def parse_total(self):
     raw_bytes = self.data[2:4]
     raw_num = bytes_to_uint(raw_bytes, self.byte_order)
     if raw_num < 20 or raw_num > 65535:
         return InvalidFieldValue()
     self.total = raw_num
Пример #11
0
 def parse_answers_rss(self):
     raw_bytes = self.data[6:8]
     self.answers_rss = bytes_to_uint(raw_bytes, self.byte_order)
Пример #12
0
 def parse_data_length(self):
     raw_bytes = self.data[4:6]
     self.data_length = bytes_to_uint(raw_bytes, self.byte_order)
Пример #13
0
 def parse_source_port(self):
     raw_bytes = self.data[:2]
     self.source_port = bytes_to_uint(raw_bytes, self.byte_order)
Пример #14
0
 def parse_protocol(self):
     raw_bytes = self.data[9:10]
     self.protocol = bytes_to_uint(raw_bytes, self.byte_order)
Пример #15
0
 def parse_answers_rss(self):
     raw_bytes = self.data[6:8]
     self.answers_rss = bytes_to_uint(raw_bytes, self.byte_order)
Пример #16
0
 def parse_questions(self):
     raw_bytes = self.data[4:6]
     self.questions = bytes_to_uint(raw_bytes, self.byte_order)
Пример #17
0
 def parse_data_length(self):
     raw_bytes = self.data[4:6]
     self.data_length = bytes_to_uint(raw_bytes, self.byte_order)
Пример #18
0
 def parse_destination_port(self):
     raw_bytes = self.data[2:4]
     self.destination_port = bytes_to_uint(raw_bytes, self.byte_order)
Пример #19
0
 def parse_source_port(self):
     raw_bytes = self.data[:2]
     self.source_port = bytes_to_uint(raw_bytes, self.byte_order)
Пример #20
0
 def parse_saved_size(self):
     raw_bytes = self.header[8:12]
     self.saved_size = bytes_to_uint(raw_bytes, self.byte_order)
Пример #21
0
 def parse_protocol(self):
     raw_bytes = self.data[9:10]
     self.protocol = bytes_to_uint(raw_bytes, self.byte_order)
Пример #22
0
 def parse_link_layer_type(self):
     raw_bytes = self.header[20:24]
     self.link_layer_type = bytes_to_uint(raw_bytes, self.byte_order)
Пример #23
0
 def parse_total(self):
     raw_bytes = self.data[2:4]
     raw_num = bytes_to_uint(raw_bytes, self.byte_order)
     if raw_num < 20 or raw_num > 65535:
         return InvalidFieldValue()
     self.total = raw_num
Пример #24
0
 def parse_time_offset(self):
     raw_bytes = self.header[8:12]
     self.time_offset = bytes_to_uint(raw_bytes, self.byte_order)
Пример #25
0
 def parse_snapshot_length(self):
     raw_bytes = self.header[16:20]
     self.snapshot_length = bytes_to_uint(raw_bytes, self.byte_order)
Пример #26
0
 def parse_time_offset(self):
     raw_bytes = self.header[8:12]
     self.time_offset = bytes_to_uint(raw_bytes, self.byte_order)
Пример #27
0
 def parse_destination_port(self):
     raw_bytes = self.data[2:4]
     self.destination_port = bytes_to_uint(raw_bytes, self.byte_order)
Пример #28
0
 def parse_snapshot_length(self):
     raw_bytes = self.header[16:20]
     self.snapshot_length = bytes_to_uint(raw_bytes, self.byte_order)
Пример #29
0
 def parse_questions(self):
     raw_bytes = self.data[4:6]
     self.questions = bytes_to_uint(raw_bytes, self.byte_order)
Пример #30
0
 def parse_link_layer_type(self):
     raw_bytes = self.header[20:24]
     self.link_layer_type = bytes_to_uint(raw_bytes, self.byte_order)
Пример #31
0
    def parse_scenario(self, raw_city_data):
        """
        Parses the scenario information.
        Args:
            raw_city_data (bytes): Raw data to parse scenario information out of.
        """
        self.is_scenario = True

        raw_text = raw_city_data["TEXT"]
        raw_scenario = raw_city_data["SCEN"]
        picture = raw_city_data["PICT"]

        for entry in raw_text:
            string_id = entry[:4]
            raw_string = entry[4:].decode('ASCII').replace('\r', '\n')
            if string_id == b'\x80\x00\x00\x00':
                self.scenario_text = raw_string
            elif string_id == b'\x81\x00\x00\x00':
                self.scenario_descriptive_text = raw_string
            else:
                print(
                    f"Found unknown TEXT block in input file.\nid: {string_id}, contents: \"{raw_string}\""
                )
        if self.debug:
            print(
                f"Scenario:\nShort text: {self.scenario_text}\nDescriptive Text:{self.scenario_descriptive_text}"
            )

        conditions = {}
        offset = 4
        contents = collections.OrderedDict((
            ("disaster_type", 2),
            ("distater_x_location", 1),
            ("disaster_y_location", 1),
            ("time_limit_months", 2),
            ("city_size_goal", 4),
            ("residential_goal", 4),
            ("commercial_goal", 4),
            ("industrial_goal", 4),
            ("cash_flow_goal-bonds", 4),
            ("land_value_goal", 4),
            ("pollution_limit", 4),
            ("traffic_limit", 4),
            ("crime_limit", 4),
            ("build_item_one", 1),
            ("build_item_two", 1),
            ("item_one_tiles", 2),
            ("item_two_tiles", 2),
        ))
        for k, v in contents.items():
            conditions[k] = bytes_to_uint(raw_scenario[offset:offset + v])
            offset += v
            if self.debug:
                print(f"Conditions: {conditions}")
            self.scenario_condition = conditions

        header = picture[0:4]
        if header != bytearray(b'\x80\x00\x00\x00'):
            print("Scenario PICT parsing failed.")  # todo: exception?
        # Why is the endianness different here? It just is.
        row_length = unpack('<H', picture[4:6])[0]  # x dimension of image.
        row_count = unpack('<H', picture[6:8])[0]  # y dimension of image.
        image_data = []
        picture_data = picture[8:]
        if self.debug:
            print(f"Scenario PICT, {row_length}x{row_count} pixels:")
        for row_idx in range(0, row_count):
            row_start = row_idx * (row_length + 1)
            row = [
                x for x in picture_data[row_start:row_start + row_length + 1]
            ]
            if row[-1] != 255:
                row = [0] * row_length
            else:
                row = row[:-1]
            image_data.append(row)
        if self.debug:
            for idx, r in enumerate(image_data):
                print(f"{idx}:\n{r}")
        self.scenario_pict = image_data
Пример #32
0
 def parse_captured_size(self):
     raw_bytes = self.header[12:16]
     self.seconds = bytes_to_uint(raw_bytes, self.byte_order)