Ejemplo n.º 1
0
 def _generate_policy_map_items(self, policies_map: PoliciesMap) -> str:
     policy_map_items = ''
     for name, rules in sorted(policies_map.items(),
                               key=lambda x: normalize_name(x[0])):
         policy_map_items += self.ZONE_POLICY_MAP_ITEM.format(
             policyName=normalize_name(name))
     return policy_map_items
Ejemplo n.º 2
0
 def _generate_link_item(self, link_name: str, zone_name: str) -> str:
     return self.ZONE_INFOS_CPP_LINK_ITEM.format(
         scope=self.scope,
         linkFullName=link_name,
         linkNormalizedName=normalize_name(link_name),
         zoneFullName=zone_name,
         zoneNormalizedName=normalize_name(zone_name))
Ejemplo n.º 3
0
 def _generate_info_map_items(self, zones_map: ZonesMap) -> str:
     """Generate a map of (zone_name -> zoneInfo), shorted by name.
     """
     info_map_items = ''
     for zone_name, zones in sorted(zones_map.items(),
                                    key=lambda x: normalize_name(x[0])):
         info_map_items += self.ZONE_INFO_MAP_ITEM.format(
             zoneNormalizedName=normalize_name(zone_name),
             zoneFullName=zone_name)
     return info_map_items
Ejemplo n.º 4
0
    def _generate_link_item(
        self,
        link_name: str,
        zone_name: str,
    ) -> str:
        """Return the Link item.
        """
        ZONE_INFOS_CPP_LINK_ITEM = """\
//---------------------------------------------------------------------------
// Link name: {linkFullName} -> {zoneFullName}
// Strings (bytes): {stringSize} (originally {originalSize})
// Memory (8-bit): {memory8}
// Memory (32-bit): {memory32}
//---------------------------------------------------------------------------

static const char kZoneName{linkNormalizedName}[] {progmem} = \
{compressedName};

const {scope}::ZoneInfo kZone{linkNormalizedName} {progmem} = {{
  kZoneName{linkNormalizedName} /*name*/,
  0x{linkId:08x} /*zoneId*/,
  &kZoneContext /*zoneContext*/,
  {numEras} /*numEras*/,
  kZoneEra{zoneNormalizedName} /*eras*/,
}};

"""
        compressed_name = self.compressed_names[link_name]
        rendered_name = _compressed_name_to_c_string(compressed_name)

        link_name_size = len(compressed_name) + 1
        original_size = len(link_name) + 1
        memory8 = link_name_size + self.SIZEOF_ZONE_INFO_8
        memory32 = link_name_size + self.SIZEOF_ZONE_INFO_32
        link_item = ZONE_INFOS_CPP_LINK_ITEM.format(
            scope=self.scope,
            linkFullName=link_name,
            linkNormalizedName=normalize_name(link_name),
            compressedName=rendered_name,
            linkId=self.link_ids[link_name],
            zoneFullName=zone_name,
            zoneNormalizedName=normalize_name(zone_name),
            stringSize=link_name_size,
            originalSize=original_size,
            memory8=memory8,
            memory32=memory32,
            numEras=len(self.zones_map[zone_name]),
            progmem='ACE_TIME_PROGMEM',
        )

        return link_item
Ejemplo n.º 5
0
    def _generate_info_item(
        self,
        zone_name: str,
        eras: List[ZoneEraRaw],
    ) -> Tuple[str, int]:
        era_items = ''
        string_length = 0
        for era in eras:
            (era_item, length) = self._generate_era_item(zone_name, era)
            era_items += era_item
            string_length += length

        string_length += len(zone_name) + 1
        num_eras = len(eras)
        memory8 = (string_length + num_eras * self.SIZEOF_ZONE_ERA_8 +
                   1 * self.SIZEOF_ZONE_INFO_8)
        memory32 = (string_length + num_eras * self.SIZEOF_ZONE_ERA_32 +
                    1 * self.SIZEOF_ZONE_INFO_32)

        transition_buf_size = self.buf_sizes[zone_name]

        info_item = self.ZONE_INFOS_CPP_INFO_ITEM.format(
            scope=self.scope,
            zoneFullName=zone_name,
            zoneNormalizedName=normalize_name(zone_name),
            zoneId=self.zone_ids[zone_name],
            transitionBufSize=transition_buf_size,
            numEras=num_eras,
            stringLength=string_length,
            memory8=memory8,
            memory32=memory32,
            eraItems=era_items,
            progmem='ACE_TIME_PROGMEM')
        return (info_item, string_length)
Ejemplo n.º 6
0
    def generate_policies_h(self) -> str:
        policy_items = ''
        for name, rules in sorted(self.policies_map.items()):
            policy_items += self.ZONE_POLICIES_H_POLICY_ITEM.format(
                policyName=normalize_name(name), scope=self.scope)

        removed_policy_items = ''
        for name, reasons in sorted(self.removed_policies.items()):
            removed_policy_items += \
                self.ZONE_POLICIES_H_REMOVED_POLICY_ITEM.format(
                    policyName=name,
                    policyReason=', '.join(reasons))

        notable_policy_items = ''
        for name, reasons in sorted(self.notable_policies.items()):
            notable_policy_items += \
                self.ZONE_POLICIES_H_NOTABLE_POLICY_ITEM.format(
                    policyName=name,
                    policyReason=', '.join(reasons))

        return self.ZONE_POLICIES_H_FILE.format(
            invocation=self.invocation,
            tz_files=self.tz_files,
            tz_version=self.tz_version,
            dbNamespace=self.db_namespace,
            dbHeaderNamespace=self.db_header_namespace,
            numPolicies=len(self.policies_map),
            policyItems=policy_items,
            numRemovedPolicies=len(self.removed_policies),
            removedPolicyItems=removed_policy_items,
            numNotablePolicies=len(self.notable_policies),
            notablePolicyItems=notable_policy_items)
Ejemplo n.º 7
0
    def _generate_test_cases(self, test_data: TestData) -> str:
        has_valid_abbrev = self.validation_data['has_valid_abbrev']
        has_valid_dst = self.validation_data['has_valid_dst']
        test_cases = ''
        for zone_name, _ in sorted(test_data.items()):
            normalized_name = normalize_name(zone_name)

            (
                dst_validation_scope,
                dst_validation_comment,
            ) = _get_validation_scope(
                has_valid_dst,
                self.blacklist.get(zone_name),
            )
            (
                abbrev_validation_scope,
                abbrev_validation_comment,
            ) = _get_validation_scope(
                has_valid_abbrev,
                self.blacklist.get(zone_name),
            )

            test_case = f"""\
testF({self.test_class}, {normalized_name}) {{
  assertValid(
     &kZone{normalized_name},
     &kValidationData{normalized_name},
     {dst_validation_scope} /*dstValidationScope{dst_validation_comment}*/,
     {abbrev_validation_scope} \
/*abbrevValidationScope{abbrev_validation_comment}*/);
}}
"""
            test_cases += test_case
        return test_cases
Ejemplo n.º 8
0
    def _generate_infos(self) -> None:
        for zone_name, eras in self.zones_map.items():
            zone_eras: List[ZoneEra] = []
            for era in eras:
                policy_name = era['rules']
                zone_policy: Union[ZonePolicy, str]
                if policy_name in ['-', ':']:
                    zone_policy = policy_name
                else:
                    policy_name = normalize_name(policy_name)
                    zone_policy = self.zone_policies[policy_name]

                # yapf: disable
                zone_eras.append({
                    'offset_seconds': era['offset_seconds_truncated'],
                    'zone_policy': zone_policy,
                    'rules_delta_seconds': era['rules_delta_seconds_truncated'],
                    'format': era['format'],
                    'until_year': era['until_year'],
                    'until_month': era['until_month'],
                    'until_day': era['until_day'],
                    'until_seconds': era['until_seconds_truncated'],
                    'until_time_suffix': era['until_time_suffix'],
                })
                # yapf: enable
            self.zone_infos[zone_name] = {'name': zone_name, 'eras': zone_eras}
Ejemplo n.º 9
0
    def _generate_validation_data_cpp_items(self, test_data: TestData) -> str:
        validation_items = ''
        for zone_name, test_items in sorted(test_data.items()):
            test_items_string = self._generate_validation_data_cpp_test_items(
                zone_name, test_items)
            normalized_name = normalize_name(zone_name)

            validation_item = f"""\
//---------------------------------------------------------------------------
// Zone name: {zone_name}
//---------------------------------------------------------------------------

static const testing::ValidationItem kValidationItems{normalized_name}[] = {{
  //     epoch,  utc,  dst,    y,  m,  d,  h,  m,  s,  abbrev, type
{test_items_string}
}};

const testing::ValidationData kValidationData{normalized_name} = {{
  {len(test_items)} /*numItems*/,
  kValidationItems{normalized_name} /*items*/,
}};

"""
            validation_items += validation_item
        return validation_items
Ejemplo n.º 10
0
 def _generate_validation_data_h_items(self, test_data: TestData) -> str:
     validation_items = ''
     for zone_name, test_items in sorted(test_data.items()):
         validation_items += self.VALIDATION_DATA_H_ITEM.format(
             validationDataClass=self.validation_data_class,
             zoneNormalizedName=normalize_name(zone_name))
     return validation_items
Ejemplo n.º 11
0
    def _generate_validation_data_h_items(self, test_data: TestData) -> str:
        validation_items = ''
        for zone_name, test_items in sorted(test_data.items()):
            normalized_name = normalize_name(zone_name)
            validation_items += f"""\
extern const testing::ValidationData kValidationData{normalized_name};
"""

        return validation_items
Ejemplo n.º 12
0
 def _generate_notable_policy_items(
     self,
     notable_policies: CommentsMap,
 ) -> str:
     notable_policy_items = ''
     for name, reason in sorted(notable_policies.items()):
         notable_policy_items += (self.ZONE_NOTABLE_POLICY_ITEM.format(
             policyName=normalize_name(name), policyReason=reason))
     return notable_policy_items
Ejemplo n.º 13
0
 def _generate_removed_policy_items(
     self,
     removed_policies: CommentsMap,
 ) -> str:
     removed_policy_items = ''
     for name, reason in sorted(removed_policies.items()):
         removed_policy_items += (self.ZONE_REMOVED_POLICY_ITEM.format(
             policyName=normalize_name(name), policyReason=reason))
     return removed_policy_items
Ejemplo n.º 14
0
 def _generate_test_cases(self, test_data: TestData) -> str:
     test_cases = ''
     for zone_name, _ in sorted(test_data.items()):
         test_case = self.TEST_CASE.format(
             dbNamespace=self.db_namespace,
             testClass=self.test_class,
             zoneNormalizedName=normalize_name(zone_name))
         test_cases += test_case
     return test_cases
Ejemplo n.º 15
0
 def _generate_policy_item(self, name: str,
                           rules: List[ZoneRuleRaw]) -> str:
     rule_items = ''
     for rule in rules:
         rule_items += self.ZONE_RULE_ITEM.format(
             policyName=normalize_name(name),
             raw_line=normalize_raw(rule['raw_line']),
             from_year=rule['from_year'],
             to_year=rule['to_year'],
             in_month=rule['in_month'],
             on_day_of_week=rule['on_day_of_week'],
             on_day_of_month=rule['on_day_of_month'],
             at_seconds=rule['at_seconds_truncated'],
             at_time_suffix=rule['at_time_suffix'],
             delta_seconds=rule['delta_seconds_truncated'],
             letter=rule['letter'])
     return self.ZONE_POLICY_ITEM.format(policyName=normalize_name(name),
                                         numRules=len(rules),
                                         ruleItems=rule_items)
Ejemplo n.º 16
0
 def _generate_validation_data_cpp_items(self, test_data: TestData) -> str:
     validation_items = ''
     for zone_name, test_items in sorted(test_data.items()):
         test_items_string = self._generate_validation_data_cpp_test_items(
             zone_name, test_items)
         validation_item = self.VALIDATION_DATA_CPP_ITEM.format(
             validationDataClass=self.validation_data_class,
             zoneFullName=zone_name,
             zoneNormalizedName=normalize_name(zone_name),
             testItems=test_items_string)
         validation_items += validation_item
     return validation_items
Ejemplo n.º 17
0
    def _generate_info_item(
        self,
        zone_name: str,
        eras: List[ZoneEraRaw],
    ) -> str:
        era_items = ''
        for era in eras:
            era_items += self._generate_era_item(era)

        return self.ZONE_INFO_ITEM.format(
            zoneFullName=zone_name,
            zoneNormalizedName=normalize_name(zone_name),
            numEras=len(eras),
            eraItems=era_items)
Ejemplo n.º 18
0
 def generate_registry_cpp(self) -> str:
     zone_registry_items = ''
     for zone_name, eras in sorted(self.zones_map.items()):
         name = normalize_name(zone_name)
         zone_registry_items += f'  &kZone{name}, // {zone_name}\n'
     return self.ZONE_REGISTRY_CPP_FILE.format(
         invocation=self.invocation,
         tz_files=self.tz_files,
         tz_version=self.tz_version,
         scope=self.scope,
         dbNamespace=self.db_namespace,
         dbHeaderNamespace=self.db_header_namespace,
         numZones=len(self.zones_map),
         zoneRegistryItems=zone_registry_items,
         progmem='ACE_TIME_PROGMEM')
Ejemplo n.º 19
0
    def _generate_test_cases(self, test_data: TestData) -> str:
        has_valid_abbrev = self.validation_data['has_valid_abbrev']
        has_valid_dst = self.validation_data['has_valid_dst']
        test_cases = ''
        for zone_name, _ in sorted(test_data.items()):
            normalized_name = normalize_name(zone_name)

            (
                dst_validation_scope,
                dst_validation_comment,
            ) = _get_validation_scope(
                has_valid_dst,
                self.blacklist.get(zone_name),
            )
            (
                abbrev_validation_scope,
                abbrev_validation_comment,
            ) = _get_validation_scope(
                has_valid_abbrev,
                self.blacklist.get(zone_name),
            )

            zone_key = (
                f'&kZone{normalized_name}'
                if self.zone_key_type == 'zoneInfo'
                else f'0x{hash_name(zone_name):08x}'
            )

            test_case = f"""\
testF({self.test_class}, {normalized_name}) {{
  assertValid(
    {zone_key},
    &kValidationData{normalized_name},
    {dst_validation_scope} /*dstValidationScope{dst_validation_comment}*/,
    {abbrev_validation_scope} \
/*abbrevValidationScope{abbrev_validation_comment}*/,
    kZoneBufSize{normalized_name} /*bufSize*/
  );
}}
"""
            test_cases += test_case
        return test_cases
Ejemplo n.º 20
0
    def _generate_info_item(
        self,
        zone_name: str,
        eras: List[ZoneEraRaw],
    ) -> str:
        era_items = ''
        for era in eras:
            era_item = self._generate_era_item(zone_name, era)
            era_items += era_item

        compressed_name = self.compressed_names[zone_name]
        rendered_name = _compressed_name_to_c_string(compressed_name)

        # Calculate memory sizes
        zone_name_size = len(compressed_name) + 1
        format_size = 0
        for era in eras:
            format_size += len(era['format_short']) + 1
        num_eras = len(eras)
        data_size8 = (num_eras * self.SIZEOF_ZONE_ERA_8 +
                      self.SIZEOF_ZONE_INFO_8)
        data_size32 = (num_eras * self.SIZEOF_ZONE_ERA_32 +
                       self.SIZEOF_ZONE_INFO_32)

        string_size = zone_name_size + format_size
        original_size = len(zone_name) + 1 + format_size
        info_item = self.ZONE_INFOS_CPP_INFO_ITEM.format(
            scope=self.scope,
            zoneFullName=zone_name,
            zoneNormalizedName=normalize_name(zone_name),
            compressedName=rendered_name,
            zoneId=self.zone_ids[zone_name],
            numEras=num_eras,
            stringSize=string_size,
            originalSize=original_size,
            memory8=data_size8 + string_size,
            memory32=data_size32 + string_size,
            eraItems=era_items,
            progmem='ACE_TIME_PROGMEM')
        return info_item
Ejemplo n.º 21
0
    def _generate_policies(self) -> None:
        for name, rules in self.policies_map.items():
            policy_rules: List[ZoneRule] = []
            for rule in rules:
                # yapf: disable
                policy_rules.append({
                    'from_year': rule['from_year'],
                    'to_year': rule['to_year'],
                    'in_month': rule['in_month'],
                    'on_day_of_week': rule['on_day_of_week'],
                    'on_day_of_month': rule['on_day_of_month'],
                    'at_seconds': rule['at_seconds_truncated'],
                    'at_time_suffix': rule['at_time_suffix'],
                    'delta_seconds': rule['delta_seconds_truncated'],
                    'letter': rule['letter']
                })
                # yapf: enable

            normalized_name = normalize_name(name)
            self.zone_policies[normalized_name] = {
                'name': name,  # policy name
                'rules': policy_rules
            }
Ejemplo n.º 22
0
    def generate_infos_h(self) -> str:
        info_items = ''
        info_zone_ids = ''
        for zone_name, eras in sorted(self.zones_map.items()):
            info_items += self.ZONE_INFOS_H_INFO_ITEM.format(
                scope=self.scope,
                zoneNormalizedName=normalize_name(zone_name),
                zoneFullName=zone_name,
            )
            info_zone_ids += self.ZONE_INFOS_H_INFO_ZONE_ID.format(
                scope=self.scope,
                zoneNormalizedName=normalize_name(zone_name),
                zoneFullName=zone_name,
                zoneId=self.zone_ids[zone_name],
            )

        removed_info_items = ''
        for zone_name, reasons in sorted(self.removed_zones.items()):
            removed_info_items += self.ZONE_INFOS_H_REMOVED_INFO_ITEM.format(
                zoneFullName=zone_name, reason=', '.join(reasons))

        notable_info_items = ''
        for zone_name, reasons in sorted(self.notable_zones.items()):
            notable_info_items += self.ZONE_INFOS_H_NOTABLE_INFO_ITEM.format(
                zoneFullName=zone_name, reason=', '.join(reasons))

        link_items = ''
        for link_name, zone_name in sorted(self.links_map.items()):
            link_items += self.ZONE_INFOS_H_LINK_ITEM.format(
                scope=self.scope,
                linkNormalizedName=normalize_name(link_name),
                linkFullName=link_name,
                zoneFullName=zone_name)

        removed_link_items = ''
        for link_name, reasons in sorted(self.removed_links.items()):
            removed_link_items += self.ZONE_INFOS_H_REMOVED_LINK_ITEM.format(
                linkFullName=link_name, reason=', '.join(reasons))

        notable_link_items = ''
        for link_name, reasons in sorted(self.notable_links.items()):
            notable_link_items += self.ZONE_INFOS_H_NOTABLE_LINK_ITEM.format(
                linkFullName=link_name, reason=', '.join(reasons))

        return self.ZONE_INFOS_H_FILE.format(
            invocation=self.invocation,
            tz_files=self.tz_files,
            tz_version=self.tz_version,
            scope=self.scope,
            dbNamespace=self.db_namespace,
            dbHeaderNamespace=self.db_header_namespace,
            numInfos=len(self.zones_map),
            infoItems=info_items,
            infoZoneIds=info_zone_ids,
            numLinks=len(self.links_map),
            linkItems=link_items,
            numRemovedInfos=len(self.removed_zones),
            removedInfoItems=removed_info_items,
            numNotableInfos=len(self.notable_zones),
            notableInfoItems=notable_info_items,
            numRemovedLinks=len(self.removed_links),
            removedLinkItems=removed_link_items,
            numNotableLinks=len(self.notable_links),
            notableLinkItems=notable_link_items)
Ejemplo n.º 23
0
    def generate_registry_cpp(self) -> str:

        # Generate only Zones, sorted by zoneId to enable
        # ZoneRegistrar::binarySearchById().
        zone_registry_items = ''
        for zone_name in sorted(
                self.zones_map.keys(),
                key=lambda x: self.zone_ids[x],
        ):
            normalized_name = normalize_name(zone_name)
            zone_id = self.zone_ids[zone_name]
            zone_registry_items += f"""\
  &kZone{normalized_name}, // 0x{zone_id:08x}, {zone_name}
"""

        # Generate Zones and Links, sorted by zoneId.
        zone_and_link_registry_items = ''
        num_zones_and_links = len(self.zones_and_links)
        for zone_name in sorted(
                self.zones_and_links,
                key=lambda x: self.zone_and_link_ids[x],
        ):
            normalized_name = normalize_name(zone_name)
            zone_id = self.zone_and_link_ids[zone_name]
            target_name = self.links_map.get(zone_name)
            if target_name:
                desc_name = f'{zone_name} -> {target_name}'
            else:
                desc_name = zone_name

            zone_and_link_registry_items += f"""\
  &kZone{normalized_name}, // 0x{zone_id:08x}, {desc_name}
"""

        # Generate Link table, sorted by linkId.
        link_registry_items = ''
        for link_name in sorted(
                self.links_map,
                key=lambda x: self.link_ids[x],
        ):
            zone_name = self.links_map[link_name]
            link_id = self.link_ids[link_name]
            zone_id = self.zone_ids[zone_name]

            normalized_link_name = normalize_name(link_name)
            normalized_zone_name = normalize_name(zone_name)

            link_registry_items += f"""\
  {{ kZoneId{normalized_link_name}, kZoneId{normalized_zone_name} }}, \
// 0x{link_id:08x} -> 0x{zone_id:08x}
"""

        return self.ZONE_REGISTRY_CPP_FILE.format(
            invocation=self.invocation,
            tz_files=self.tz_files,
            tz_version=self.tz_version,
            scope=self.scope,
            dbNamespace=self.db_namespace,
            dbHeaderNamespace=self.db_header_namespace,
            numZones=len(self.zones_map),
            numZonesAndLinks=num_zones_and_links,
            numLinks=len(self.links_map),
            zoneRegistryItems=zone_registry_items,
            zoneAndLinkRegistryItems=zone_and_link_registry_items,
            linkRegistryItems=link_registry_items,
            progmem='ACE_TIME_PROGMEM',
        )
Ejemplo n.º 24
0
    def generate_infos_h(self) -> str:
        ZONE_INFOS_H_INFO_ITEM = """\
extern const {scope}::ZoneInfo kZone{zoneNormalizedName}; // {zoneFullName}
"""
        ZONE_INFOS_H_INFO_ZONE_ID = """\
const uint32_t kZoneId{zoneNormalizedName} = 0x{zoneId:08x}; // {zoneFullName}
"""
        ZONE_INFOS_H_BUF_SIZE = """\
const uint8_t kZoneBufSize{zoneNormalizedName} = {bufSize};  // {zoneFullName}
"""
        info_items = ''
        info_zone_ids = ''
        info_buf_sizes = ''
        for zone_name, eras in sorted(self.zones_map.items()):
            normalized_name = normalize_name(zone_name)
            info_items += ZONE_INFOS_H_INFO_ITEM.format(
                scope=self.scope,
                zoneNormalizedName=normalized_name,
                zoneFullName=zone_name,
            )
            info_zone_ids += ZONE_INFOS_H_INFO_ZONE_ID.format(
                zoneNormalizedName=normalized_name,
                zoneFullName=zone_name,
                zoneId=self.zone_ids[zone_name],
            )
            info_buf_sizes += ZONE_INFOS_H_BUF_SIZE.format(
                zoneNormalizedName=normalized_name,
                zoneFullName=zone_name,
                bufSize=self.buf_sizes[zone_name],
            )

        ZONE_INFOS_H_LINK_ITEM = """\
extern const {scope}::ZoneInfo kZone{linkNormalizedName}; \
// {linkFullName} -> {zoneFullName}
"""
        ZONE_INFOS_H_LINK_ID = """\
const uint32_t kZoneId{linkNormalizedName} = 0x{linkId:08x}; // {linkFullName}
"""
        link_items = ''
        link_ids = ''
        for link_name, zone_name in sorted(self.links_map.items()):
            link_items += ZONE_INFOS_H_LINK_ITEM.format(
                scope=self.scope,
                linkNormalizedName=normalize_name(link_name),
                linkFullName=link_name,
                zoneFullName=zone_name)
            link_ids += ZONE_INFOS_H_LINK_ID.format(
                linkNormalizedName=normalize_name(link_name),
                linkFullName=link_name,
                linkId=self.link_ids[link_name],
            )

        ZONE_INFOS_H_REMOVED_INFO_ITEM = """\
// {zoneFullName} ({reason})
"""
        removed_info_items = ''
        for zone_name, reasons in sorted(self.removed_zones.items()):
            removed_info_items += ZONE_INFOS_H_REMOVED_INFO_ITEM.format(
                zoneFullName=zone_name, reason=', '.join(reasons))

        ZONE_INFOS_H_NOTABLE_INFO_ITEM = """\
// {zoneFullName} ({reason})
"""
        notable_info_items = ''
        for zone_name, reasons in sorted(self.notable_zones.items()):
            notable_info_items += ZONE_INFOS_H_NOTABLE_INFO_ITEM.format(
                zoneFullName=zone_name, reason=', '.join(reasons))

        ZONE_INFOS_H_REMOVED_LINK_ITEM = """\
// {linkFullName} ({reason})
"""
        removed_link_items = ''
        for link_name, reasons in sorted(self.removed_links.items()):
            removed_link_items += ZONE_INFOS_H_REMOVED_LINK_ITEM.format(
                linkFullName=link_name, reason=', '.join(reasons))

        ZONE_INFOS_H_NOTABLE_LINK_ITEM = """\
// {linkFullName} ({reason})
"""
        notable_link_items = ''
        for link_name, reasons in sorted(self.notable_links.items()):
            notable_link_items += ZONE_INFOS_H_NOTABLE_LINK_ITEM.format(
                linkFullName=link_name, reason=', '.join(reasons))

        return self.ZONE_INFOS_H_FILE.format(
            invocation=self.invocation,
            tz_files=self.tz_files,
            tz_version=self.tz_version,
            scope=self.scope,
            dbNamespace=self.db_namespace,
            dbHeaderNamespace=self.db_header_namespace,
            numInfos=len(self.zones_map),
            infoItems=info_items,
            zoneIds=info_zone_ids,
            numLinks=len(self.links_map),
            linkItems=link_items,
            linkIds=link_ids,
            numRemovedInfos=len(self.removed_zones),
            removedInfoItems=removed_info_items,
            numNotableInfos=len(self.notable_zones),
            notableInfoItems=notable_info_items,
            numRemovedLinks=len(self.removed_links),
            removedLinkItems=removed_link_items,
            numNotableLinks=len(self.notable_links),
            notableLinkItems=notable_link_items,
            bufSizes=info_buf_sizes,
        )
Ejemplo n.º 25
0
    def _generate_policy_item(
        self,
        name: str,
        rules: List[ZoneRuleRaw],
        indexed_letters: Optional[IndexMap],
    ) -> Tuple[str, int, int]:
        ZONE_POLICIES_CPP_RULE_ITEM = """\
  // {raw_line}
  {{
    {from_year_tiny} /*fromYearTiny*/,
    {to_year_tiny} /*toYearTiny*/,
    {in_month} /*inMonth*/,
    {on_day_of_week} /*onDayOfWeek*/,
    {on_day_of_month} /*onDayOfMonth*/,
    {at_time_code} /*atTimeCode*/,
    {at_time_modifier} /*atTimeModifier ({at_time_modifier_comment})*/,
    {delta_code} /*deltaCode ({delta_code_comment})*/,
    {letter} /*letter{letterComment}*/,
  }},
"""
        ZONE_POLICIES_LETTER_ARRAY = """\
static const char* const kLetters{policyName}[] {progmem} = {{
{letterItems}
}};
"""

        # Generate kZoneRules*[]
        rule_items = ''
        for rule in rules:
            at_time_code = rule['at_time_code']
            at_time_modifier = rule['at_time_modifier']
            at_time_modifier_comment = _get_time_modifier_comment(
                time_seconds=rule['at_seconds_truncated'],
                suffix=rule['at_time_suffix'],
            )
            delta_code = rule['delta_code_encoded']
            delta_code_comment = _get_rule_delta_code_comment(
                delta_seconds=rule['delta_seconds_truncated'],
                scope=self.scope,
            )
            from_year_tiny = rule['from_year_tiny']
            to_year_tiny = rule['to_year_tiny']

            # Single-character 'letter' values are represented as themselves
            # using the C++ 'char' type ('A'-'Z'). But some 'letter' fields hold
            # a multi-character string. We can encode these multi-character
            # strings as an index into an array of NUL-terminated strings.
            # ASCII codes less than 32 (space) are non-printable control
            # characters so they will not collide with the printable characters
            # 'A' - 'Z'. Therefore we can hold to up to 31 multi-character
            # strings per-zone. In practice, for a single zone, the maximum
            # number of multi-character strings that I've seen is 2.
            letter = rule['letter']
            if len(letter) == 1:
                letterComment = ''
                letter = f"'{letter}'"
            elif len(letter) > 1:
                letterComment = f' (index to "{letter}")'
                letter = str(rule['letter_index_per_policy'])
            else:
                raise Exception('len(%s) == 0; should not happen' %
                                rule['letter'])

            rule_items += ZONE_POLICIES_CPP_RULE_ITEM.format(
                raw_line=normalize_raw(rule['raw_line']),
                from_year_tiny=from_year_tiny,
                to_year_tiny=to_year_tiny,
                in_month=rule['in_month'],
                on_day_of_week=rule['on_day_of_week'],
                on_day_of_month=rule['on_day_of_month'],
                at_time_code=at_time_code,
                at_time_modifier=at_time_modifier,
                at_time_modifier_comment=at_time_modifier_comment,
                delta_code=delta_code,
                delta_code_comment=delta_code_comment,
                letter=letter,
                letterComment=letterComment)

        # Generate kLetters*[]
        policy_name = normalize_name(name)
        num_letters = len(indexed_letters) if indexed_letters else 0
        memory_letters8 = 0
        memory_letters32 = 0
        if num_letters:
            assert indexed_letters is not None
            letter_array_ref = f'kLetters{policy_name}'
            letterItems = ''
            for name, index in indexed_letters.items():
                letterItems += f'  /*{index}*/ "{name}",\n'
                memory_letters8 += len(name) + 1 + 2  # NUL terminated
                memory_letters32 += len(name) + 1 + 4  # NUL terminated
            letter_array = ZONE_POLICIES_LETTER_ARRAY.format(
                policyName=policy_name,
                letterItems=letterItems,
                progmem='ACE_TIME_PROGMEM')
        else:
            letter_array_ref = 'nullptr'
            letter_array = ''

        # Calculate the memory consumed by structs and arrays
        num_rules = len(rules)
        memory8 = (1 * self.SIZEOF_ZONE_POLICY_8 +
                   num_rules * self.SIZEOF_ZONE_RULE_8 + memory_letters8)
        memory32 = (1 * self.SIZEOF_ZONE_POLICY_32 +
                    num_rules * self.SIZEOF_ZONE_RULE_32 + memory_letters32)

        policy_item = self.ZONE_POLICIES_CPP_POLICY_ITEM.format(
            scope=self.scope,
            policyName=policy_name,
            numRules=num_rules,
            memory8=memory8,
            memory32=memory32,
            ruleItems=rule_items,
            numLetters=num_letters,
            letterArrayRef=letter_array_ref,
            letterArray=letter_array,
            progmem='ACE_TIME_PROGMEM')

        return (policy_item, memory8, memory32)