# Path: pif_ir/bir/objects/metadata_instance.py
# class MetadataInstance(object):
#     required_attributes = ['values', 'visibility']
# 
#     def __init__(self, name, metadata_attrs, bir_structs, buf=None, 
#                  bit_offset=0):
#         check_attributes(name, metadata_attrs, 
#                          MetadataInstance.required_attributes)
# 
#         logging.debug("Adding metadata {0}".format(name))
#         self.name = name
#         self.values = OrderedDict()
#         # FIXME: used for syntactic checking
#         self.visibility = metadata_attrs['visibility']
# 
#         struct_name = metadata_attrs['values']
#         for f_name, f_size in bir_structs[struct_name].fields.items():
#             self.values[f_name] = ValueInstance(f_name, f_size)
# 
#         if buf:
#             self.extract(buf, bit_offset)
# 
#     def __len__(self):
#         return sum([len(fld) for fld in self.values.values()])
# 
#     def __int__(self):
#         value = 0;
#         for fld in self.values.values():
#             value = (value << len(fld)) + int(fld)
#         return value
# 
#     def to_dict(self):
#         return dict([(v.name,int(v)) for v in self.values.values()])
# 
#     def extract(self, buf, bit_offset=0):
#         fld_offset = 0;
#         for fld in self.values.values():
#             fld.extract(buf, bit_offset + fld_offset);
#             fld_offset += len(fld)
# 
#     def serialize(self):
#         byte_list = bytearray(len(self)/8)
#         bit_offset = 0;
#         for fld in self.values.values():
#             fld.update(byte_list, bit_offset)
#             bit_offset += len(fld)
#         return byte_list
# 
#     def get_value(self, value_name):
#         if value_name not in  self.values:
#             return 0
#         return self.values[value_name].value
# 
#     def set_value(self, value_name, value):
#         fld = self.values.get(value_name, None)
#         if fld:
#             fld.value = value
# 
#     def reset_values(self, new_val=0):
#         for fld in self.values.values():
#             fld.value = new_val
# 
# Path: pif_ir/bir/objects/table_entry.py
# class TableEntry(object):
#     def __init__(self, type_, value, key, mask):
#         self.type_ = type_
#         self.value = value
#         self.key = key
#         self.mask = mask
# 
#     def check(self, request):
#         if self.type_ == 'valid':
#             return self._check_valid(request)
#         elif self.type_ == 'exact':
#             return self._check_exact(request)
#         elif self.type_ == 'ternary':
#             return self._check_ternary(request)
#         elif self.type_ == 'lpm':
#             return self._check_lpm(request)
#         logging.warning("unknown TableEntry type")
#         return False
# 
#     def _check_exact(self, request):
#         for fld_name, value in self.key.items():
#             if fld_name not in request.values:
#                 return False
#             elif int(request.get_value(fld_name)) != int(value):
#                 return False
#         return True
# 
#     def _apply_mask(self, fld_name, val):
#         if self.mask == None or fld_name not in self.mask.keys():
#             return int(val)
#         return int(val) & int(self.mask[fld_name])
# 
#     def _check_ternary(self, request):
#         for fld_name, value in self.key.items():
#             if fld_name not in request.values:
#                 return False
#             elif (self._apply_mask(fld_name, request.get_value(fld_name)) !=
#                   self._apply_mask(fld_name, value)):
#                 return False
#         return True
# 
#     def _check_valid(self, request):
#         logging.warning("FIXME: implement TableEntry valid")
#         return False
#     def _check_lpm(self, request):
#         logging.warning("FIXME: implement TableEntry lpm")
#         return False
# 
# Path: pif_ir/bir/utils/exceptions.py
# class BIRTableEntryError(BIRError):
#     """ an entry couldn't be added to table
#     """
#     def __init__(self, name, msg):
#         super(BIRTableEntryError, self).__init__()
#         self.value = "table({}): {}".format(name, msg)
# 
# Path: pif_ir/bir/utils/validate.py
# def check_attributes(obj_name, attributes, required_attributes):
#     for attr in required_attributes:
#         if attr not in attributes:
#             raise BIRYamlAttrError(attr, obj_name)


import logging
from collections import OrderedDict
from pif_ir.bir.objects.metadata_instance import MetadataInstance
from pif_ir.bir.objects.table_entry import TableEntry
from pif_ir.bir.utils.exceptions import BIRTableEntryError
from pif_ir.bir.utils.validate import check_attributes
            raise BIRTableEntryError(self.name, "bad table.add_entry() args")
        logging.debug("Adding entry to {0}".format(self.name))
        self.entries.append(entry)

    def remove_entry(self, key, mask):
        if isinstance(key, MetadataInstance):
            key = key.to_dict()
        if isinstance(mask, MetadataInstance):
            mask = mask.to_dict()
        for pos, ent in enumerate(self.entries):
            if ent.key != key:
                pass
            elif mask != None and ent.mask != mask:
                pass
            else:
                del self.entries[pos]

    def clear(self, entry):
        self.entries = []

    def _handle_hit(self, metadata, table_entry):
        logging.info("Table Match")
        for fld, val in table_entry.value.items():
            if fld in metadata.values.keys():
                metadata.set_value(fld, val)    
            else:
                logging.error("table hit invalid field({})".format(fld))

    def lookup(self, request, response):
        for ent in self.entries:

# Path: pif_ir/bir/objects/metadata_instance.py
# class MetadataInstance(object):
#     required_attributes = ['values', 'visibility']
# 
#     def __init__(self, name, metadata_attrs, bir_structs, buf=None, 
#                  bit_offset=0):
#         check_attributes(name, metadata_attrs, 
#                          MetadataInstance.required_attributes)
# 
#         logging.debug("Adding metadata {0}".format(name))
#         self.name = name
#         self.values = OrderedDict()
#         # FIXME: used for syntactic checking
#         self.visibility = metadata_attrs['visibility']
# 
#         struct_name = metadata_attrs['values']
#         for f_name, f_size in bir_structs[struct_name].fields.items():
#             self.values[f_name] = ValueInstance(f_name, f_size)
# 
#         if buf:
#             self.extract(buf, bit_offset)
# 
#     def __len__(self):
#         return sum([len(fld) for fld in self.values.values()])
# 
#     def __int__(self):
#         value = 0;
#         for fld in self.values.values():
#             value = (value << len(fld)) + int(fld)
#         return value
# 
#     def to_dict(self):
#         return dict([(v.name,int(v)) for v in self.values.values()])
# 
#     def extract(self, buf, bit_offset=0):
#         fld_offset = 0;
#         for fld in self.values.values():
#             fld.extract(buf, bit_offset + fld_offset);
#             fld_offset += len(fld)
# 
#     def serialize(self):
#         byte_list = bytearray(len(self)/8)
#         bit_offset = 0;
#         for fld in self.values.values():
#             fld.update(byte_list, bit_offset)
#             bit_offset += len(fld)
#         return byte_list
# 
#     def get_value(self, value_name):
#         if value_name not in  self.values:
#             return 0
#         return self.values[value_name].value
# 
#     def set_value(self, value_name, value):
#         fld = self.values.get(value_name, None)
#         if fld:
#             fld.value = value
# 
#     def reset_values(self, new_val=0):
#         for fld in self.values.values():
#             fld.value = new_val
# 
# Path: pif_ir/bir/objects/table_entry.py
# class TableEntry(object):
#     def __init__(self, type_, value, key, mask):
#         self.type_ = type_
#         self.value = value
#         self.key = key
#         self.mask = mask
# 
#     def check(self, request):
#         if self.type_ == 'valid':
#             return self._check_valid(request)
#         elif self.type_ == 'exact':
#             return self._check_exact(request)
#         elif self.type_ == 'ternary':
#             return self._check_ternary(request)
#         elif self.type_ == 'lpm':
#             return self._check_lpm(request)
#         logging.warning("unknown TableEntry type")
#         return False
# 
#     def _check_exact(self, request):
#         for fld_name, value in self.key.items():
#             if fld_name not in request.values:
#                 return False
#             elif int(request.get_value(fld_name)) != int(value):
#                 return False
#         return True
# 
#     def _apply_mask(self, fld_name, val):
#         if self.mask == None or fld_name not in self.mask.keys():
#             return int(val)
#         return int(val) & int(self.mask[fld_name])
# 
#     def _check_ternary(self, request):
#         for fld_name, value in self.key.items():
#             if fld_name not in request.values:
#                 return False
#             elif (self._apply_mask(fld_name, request.get_value(fld_name)) !=
#                   self._apply_mask(fld_name, value)):
#                 return False
#         return True
# 
#     def _check_valid(self, request):
#         logging.warning("FIXME: implement TableEntry valid")
#         return False
#     def _check_lpm(self, request):
#         logging.warning("FIXME: implement TableEntry lpm")
#         return False
# 
# Path: pif_ir/bir/utils/exceptions.py
# class BIRTableEntryError(BIRError):
#     """ an entry couldn't be added to table
#     """
#     def __init__(self, name, msg):
#         super(BIRTableEntryError, self).__init__()
#         self.value = "table({}): {}".format(name, msg)
# 
# Path: pif_ir/bir/utils/validate.py
# def check_attributes(obj_name, attributes, required_attributes):
#     for attr in required_attributes:
#         if attr not in attributes:
#             raise BIRYamlAttrError(attr, obj_name)


# Path: pif_ir/bir/objects/table.py
import logging
from collections import OrderedDict
from pif_ir.bir.objects.metadata_instance import MetadataInstance
from pif_ir.bir.objects.table_entry import TableEntry
from pif_ir.bir.utils.exceptions import BIRTableEntryError
from pif_ir.bir.utils.validate import check_attributes

            raise BIRTableEntryError(self.name, "bad table.add_entry() args")
        logging.debug("Adding entry to {0}".format(self.name))
        self.entries.append(entry)

    def remove_entry(self, key, mask):
        if isinstance(key, MetadataInstance):
            key = key.to_dict()
        if isinstance(mask, MetadataInstance):
            mask = mask.to_dict()
        for pos, ent in enumerate(self.entries):
            if ent.key != key:
                pass
            elif mask != None and ent.mask != mask:
                pass
            else:
                del self.entries[pos]

    def clear(self, entry):
        self.entries = []

    def _handle_hit(self, metadata, table_entry):
        logging.info("Table Match")
        for fld, val in table_entry.value.items():
            if fld in metadata.values.keys():
                metadata.set_value(fld, val)    
            else:
                logging.error("table hit invalid field({})".format(fld))

    def lookup(self, request, response):
        for ent in self.entries:

            if ent.check(request):