14e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov#    Copyright 2014-2015 ARM Limited
24e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov#
34e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov# Licensed under the Apache License, Version 2.0 (the "License");
44e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov# you may not use this file except in compliance with the License.
54e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov# You may obtain a copy of the License at
64e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov#
74e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov#     http://www.apache.org/licenses/LICENSE-2.0
84e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov#
94e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov# Unless required by applicable law or agreed to in writing, software
104e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov# distributed under the License is distributed on an "AS IS" BASIS,
114e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov# See the License for the specific language governing permissions and
134e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov# limitations under the License.
144e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov#
154e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov
164e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov
174e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov"""
184e6afe960b0540a0e9781bdfbd82352ff157d24Sergei TrofimovRoutines for doing various type conversions. These usually embody some higher-level
194e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimovsemantics than are present in standard Python types (e.g. ``boolean`` will convert the
204e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimovstring ``"false"`` to ``False``, where as non-empty strings are usually considered to be
214e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov``True``).
224e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov
234e6afe960b0540a0e9781bdfbd82352ff157d24Sergei TrofimovA lot of these are intened to stpecify type conversions declaratively in place like
244e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov``Parameter``'s ``kind`` argument. These are basically "hacks" around the fact that Python
254e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimovis not the best language to use for configuration.
264e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov
274e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov"""
284e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimovimport math
294e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov
304e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimovfrom devlib.utils.misc import isiterable, to_identifier, ranges_to_list, list_to_mask
314e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov
324e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov
334e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimovdef identifier(text):
344e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    """Converts text to a valid Python identifier by replacing all
354e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    whitespace and punctuation."""
364e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    return to_identifier(text)
374e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov
384e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov
394e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimovdef boolean(value):
404e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    """
414e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    Returns bool represented by the value. This is different from
424e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    calling the builtin bool() in that it will interpret string representations.
434e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    e.g. boolean('0') and boolean('false') will both yield False.
444e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov
454e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    """
464e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    false_strings = ['', '0', 'n', 'no', 'off']
474e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    if isinstance(value, basestring):
484e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov        value = value.lower()
494e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov        if value in false_strings or 'false'.startswith(value):
504e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov            return False
514e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    return bool(value)
524e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov
534e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov
544e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimovdef integer(value):
554e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    """Handles conversions for string respresentations of binary, octal and hex."""
564e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    if isinstance(value, basestring):
574e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov        return int(value, 0)
584e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    else:
594e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov        return int(value)
604e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov
614e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov
624e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimovdef numeric(value):
634e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    """
644e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    Returns the value as number (int if possible, or float otherwise), or
654e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    raises ``ValueError`` if the specified ``value`` does not have a straight
664e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    forward numeric conversion.
674e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov
684e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    """
694e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    if isinstance(value, int):
704e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov        return value
714e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    try:
724e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov        fvalue = float(value)
734e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    except ValueError:
744e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov        raise ValueError('Not numeric: {}'.format(value))
754e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    if not math.isnan(fvalue) and not math.isinf(fvalue):
764e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov        ivalue = int(fvalue)
774e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov        if ivalue == fvalue:  # yeah, yeah, I know. Whatever. This is best-effort.
784e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov            return ivalue
794e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    return fvalue
804e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov
814e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov
824e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimovclass caseless_string(str):
834e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    """
844e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    Just like built-in Python string except case-insensitive on comparisons. However, the
854e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    case is preserved otherwise.
864e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov
874e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    """
884e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov
894e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    def __eq__(self, other):
904e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov        if isinstance(other, basestring):
914e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov            other = other.lower()
924e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov        return self.lower() == other
934e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov
944e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    def __ne__(self, other):
954e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov        return not self.__eq__(other)
964e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov
974e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    def __cmp__(self, other):
984e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov        if isinstance(basestring, other):
994e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov            other = other.lower()
1004e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov        return cmp(self.lower(), other)
1014e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov
1024e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    def format(self, *args, **kwargs):
1034e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov        return caseless_string(super(caseless_string, self).format(*args, **kwargs))
1044e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov
1054e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov
1064e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimovdef bitmask(value):
1074e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    if isinstance(value, basestring):
1084e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov        value = ranges_to_list(value)
1094e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    if isiterable(value):
1104e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov        value = list_to_mask(value)
1114e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    if not isinstance(value, int):
1124e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov        raise ValueError(value)
1134e6afe960b0540a0e9781bdfbd82352ff157d24Sergei Trofimov    return value
114