blob: eeb26d61c237c926cb2188bb00bea4a234303598 [file] [log] [blame]
Rich Lanea06d0c32013-03-25 08:52:03 -07001# Copyright 2013, Big Switch Networks, Inc.
2#
3# LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
4# the following special exception:
5#
6# LOXI Exception
7#
8# As a special exception to the terms of the EPL, you may distribute libraries
9# generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
10# that copyright and licensing notices generated by LoxiGen are not altered or removed
11# from the LoxiGen Libraries and the notice provided below is (i) included in
12# the LoxiGen Libraries, if distributed in source code form and (ii) included in any
13# documentation for the LoxiGen Libraries, if distributed in binary form.
14#
15# Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
16#
17# You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
18# a copy of the EPL at:
19#
20# http://www.eclipse.org/legal/epl-v10.html
21#
22# Unless required by applicable law or agreed to in writing, software
23# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
24# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
25# EPL for the specific language governing permissions and limitations
26# under the EPL.
27
28"""
29@brief Generic utilities
30
31Intended to be imported into another namespace
32"""
33
Andreas Wundsam2d29c072013-07-16 12:44:03 -070034import functools
Rich Lanea06d0c32013-03-25 08:52:03 -070035import sys
36import of_g
37
38
39################################################################
40#
41# Configuration related
42#
43################################################################
44
45def config_check(str, dictionary = of_g.code_gen_config):
46 """
47 Return config value if in dictionary; else return False.
48 @param str The lookup index
49 @param dictionary The dict to check; use code_gen_config if None
50 """
51
52 if str in dictionary:
53 return dictionary[str]
54
55 return False
56
57################################################################
58#
59# Debug
60#
61################################################################
62
63def debug(obj):
64 """
65 Debug output to the current both the log file and debug output
66 @param out_str The stringified output to write
67 """
68 of_g.loxigen_dbg_file.write(str(obj) + "\n")
69 log(obj)
70
71def log(obj):
72 """
73 Log output to the current global log file
74 @param out_str The stringified output to write
75 """
76 of_g.loxigen_log_file.write(str(obj) + "\n")
Andreas Wundsam2d29c072013-07-16 12:44:03 -070077
78################################################################
79#
80# Memoize
81#
82################################################################
83
84def memoize(obj):
85 """ A function/method decorator that memoizes the result"""
86 cache = obj.cache = {}
87
88 @functools.wraps(obj)
89 def memoizer(*args, **kwargs):
Andreas Wundsamf35ec812013-07-16 13:49:18 -070090 key = args + tuple(kwargs.items())
Andreas Wundsam2d29c072013-07-16 12:44:03 -070091 if key not in cache:
92 cache[key] = obj(*args, **kwargs)
93 return cache[key]
94 return memoizer
95
96################################################################
97#
98# OrderedSet
99#
100################################################################
101
102import collections
103
104class OrderedSet(collections.MutableSet):
105 """
106 A set implementations that retains insertion order. From the receipe
107 http://code.activestate.com/recipes/576694/
108 as referred to in the python documentation
109 """
110
111 def __init__(self, iterable=None):
112 self.end = end = []
113 end += [None, end, end] # sentinel node for doubly linked list
114 self.map = {} # key --> [key, prev, next]
115 if iterable is not None:
116 self |= iterable
117
118 def __len__(self):
119 return len(self.map)
120
121 def __contains__(self, key):
122 return key in self.map
123
124 def add(self, key):
125 if key not in self.map:
126 end = self.end
127 curr = end[1]
128 curr[2] = end[1] = self.map[key] = [key, curr, end]
129
130 def discard(self, key):
131 if key in self.map:
132 key, prev, next = self.map.pop(key)
133 prev[2] = next
134 next[1] = prev
135
136 def __iter__(self):
137 end = self.end
138 curr = end[2]
139 while curr is not end:
140 yield curr[0]
141 curr = curr[2]
142
143 def __reversed__(self):
144 end = self.end
145 curr = end[1]
146 while curr is not end:
147 yield curr[0]
148 curr = curr[1]
149
150 def pop(self, last=True):
151 if not self:
152 raise KeyError('set is empty')
153 key = self.end[1][0] if last else self.end[2][0]
154 self.discard(key)
155 return key
156
157 def __repr__(self):
158 if not self:
159 return '%s()' % (self.__class__.__name__,)
160 return '%s(%r)' % (self.__class__.__name__, list(self))
161
162 def __eq__(self, other):
163 if isinstance(other, OrderedSet):
164 return len(self) == len(other) and list(self) == list(other)
165 return set(self) == set(other)
166
167def find(iterable, func):
168 """
169 find the first item in iterable for which func returns something true'ish.
170 @raise KeyError if no item in iterable fulfills the condition
171 """
172 for i in iterable:
173 if func(i):
174 return i
175 raise KeyError("Couldn't find value that matches: %s" % repr(func))