blob: fa35cb6d998e2baa07037c2fa228401e71560ae2 [file] [log] [blame]
#!/usr/bin/python2.4
#
# Copyright 2011 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Serializes node and string tables. See class comment for more details."""
__author__ = 'bmcquade@google.com (Bryan McQuade)'
def _GetMaxValueForNumBits(num_bits):
"""Return max value for an unsigned integer of width num_bits."""
return 2**num_bits - 1
class TableSerializer(object):
"""TableSerializer serializes the table builders to C code."""
def __init__(self,
component_offset_bits,
child_node_offset_bits,
num_children_bits):
self.max_component_offset = _GetMaxValueForNumBits(
component_offset_bits)
self.max_child_node_offset = _GetMaxValueForNumBits(
child_node_offset_bits)
self.max_num_children = _GetMaxValueForNumBits(num_children_bits)
def SerializeNodeTable(self, node_table_builder, string_table_builder):
"""Generate a C representation of the node table.
Args:
node_table_builder: The node table to use when serializing.
string_table_builder: The string table to use when serializing.
"""
out = []
for node in node_table_builder.GetNodeTable():
component_offset = (
string_table_builder.GetHostnamePartOffset(node.GetName()))
num_children = len(node.GetChildren())
if num_children > 0:
child_node_offset = node_table_builder.GetChildNodeOffset(node)
else:
child_node_offset = 0
if node.IsTerminalNode():
is_root = 1
else:
is_root = 0
if (component_offset > self.max_component_offset or
child_node_offset > self.max_child_node_offset or
num_children > self.max_num_children):
raise OverflowError(
'Values %d %d %d out of range.' %
(component_offset, child_node_offset, num_children))
out.append(r' { %5d, %5d, %5d, %d }, /* %s */' % (
component_offset,
child_node_offset,
num_children,
is_root,
node.GetIdentifier('.')))
return '\n'.join(out)
def SerializeLeafChildNodeTable(self,
node_table_builder,
string_table_builder):
"""Generate a C representation of the leaf node table.
Args:
node_table_builder: The node table to use when serializing.
string_table_builder: The string table to use when serializing.
"""
out = []
for node in node_table_builder.GetLeafNodeTable():
component_offset = (
string_table_builder.GetHostnamePartOffset(node.GetName()))
if component_offset > self.max_component_offset:
raise OverflowError(
'component_offset %d out of range.' % component_offset)
out.append(r'%5d, /* %s */' % (
component_offset, node.GetIdentifier('.')))
return '\n'.join(out)
@staticmethod
def SerializeStringTable(string_table_builder):
"""Generate a C representation of the string table.
Args:
string_table_builder: the string table to use when serializing.
"""
last_newline = 0
out = ['"']
for char in string_table_builder.GetStringTable():
if ord(char) > 127:
raise ValueError("Encountered unexpected multibyte character.")
if char == '\0':
if len(out) - last_newline >= 60:
space_char = '\n'
else:
space_char = ' '
# To prevent the compiler from interpreting subsequent
# characters as part of the hex code, we break the string
# literal.
#
# E.g. [?feet] --> ["\x3f" "feet"] instead of ["\x3ffeet"]
out.extend(['\\', '0', '"', space_char, '"'])
if space_char == '\n':
last_newline = len(out) - 1
else:
out.append(char)
out.append('"')
return ''.join(out)
@staticmethod
def SerializeTestTable(test_table_builder):
"""Generate a C representation of the test table.
Args:
test_table_builder: The test table to use when serializing.
"""
out = []
for host, registry, is_exception_rule in test_table_builder.GetTestTable():
parts = [ 'www', host ]
parts.extend(registry.split('.'))
out.append(r'{ "%s", %d, %d },' % ('.'.join(parts),
len(registry),
is_exception_rule))
return '\n'.join(out)