def _generate_era_item(self, era: ZoneEraRaw) -> str: policy_name = era['rules'] if policy_name in ['-', ':']: zone_policy = f"'{policy_name}'" else: zone_policy = f'ZONE_POLICY_{normalize_name(policy_name)}' return self.ZONE_ERA_ITEM.format( raw_line=normalize_raw(era['raw_line']), offset_seconds=era['offset_seconds_truncated'], zone_policy=zone_policy, rules_delta_seconds=era['rules_delta_seconds_truncated'], format=era['format'], # preserve the %s 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'])
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)
def _generate_era_item(self, zone_name: str, era: ZoneEraRaw) -> Tuple[str, int]: rules_policy_name = era['rules'] if rules_policy_name == '-' or rules_policy_name == ':': zone_policy = 'nullptr' else: zone_policy = f'&kPolicy{normalize_name(rules_policy_name)}' offset_code = era['offset_code'] delta_code = era['delta_code_encoded'] delta_code_comment = _get_era_delta_code_comment( offset_seconds=era['offset_seconds_truncated'], delta_seconds=era['rules_delta_seconds_truncated'], scope=self.scope, ) until_year_tiny = era['until_year_tiny'] until_month = era['until_month'] until_day = era['until_day'] until_time_code = era['until_time_code'] until_time_modifier = era['until_time_modifier'] until_time_modifier_comment = _get_time_modifier_comment( time_seconds=era['until_seconds_truncated'], suffix=era['until_time_suffix'], ) format_short = era['format_short'] string_length = len(format_short) + 1 era_item = self.ZONE_INFOS_CPP_ERA_ITEM.format( raw_line=normalize_raw(era['raw_line']), offset_code=offset_code, delta_code=delta_code, delta_code_comment=delta_code_comment, zone_policy=zone_policy, format=format_short, until_year_tiny=until_year_tiny, until_month=until_month, until_day=until_day, until_time_code=until_time_code, until_time_modifier=until_time_modifier, until_time_modifier_comment=until_time_modifier_comment, ) return (era_item, string_length)
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)