pycrate/pycrate_csn1/utils.py

128 lines
3.9 KiB
Python

# -*- coding: UTF-8 -*-
#/**
# * Software Name : pycrate
# * Version : 0.3
# *
# * Copyright 2017. Benoit Michau. ANSSI.
# *
# * This library is free software; you can redistribute it and/or
# * modify it under the terms of the GNU Lesser General Public
# * License as published by the Free Software Foundation; either
# * version 2.1 of the License, or (at your option) any later version.
# *
# * This library is distributed in the hope that it will be useful,
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# * Lesser General Public License for more details.
# *
# * You should have received a copy of the GNU Lesser General Public
# * License along with this library; if not, write to the Free Software
# * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# * MA 02110-1301 USA
# *
# *--------------------------------------------------------
# * File Name : pycrate_csn1/utils.py
# * Created : 2017-06-12
# * Authors : Benoit Michau
# *--------------------------------------------------------
#*/
import re
from pycrate_core.elt import Element
from pycrate_core.utils import *
from pycrate_core.utils import TYPE_UINT as _TYPE_UINT
from pycrate_asn1c.utils import scan_for_comments
from pycrate_asn1c.dictobj import ASN1Dict as CSN1Dict
#------------------------------------------------------------------------------#
# CSN.1 errors
#------------------------------------------------------------------------------#
# generic CSN.1 error
class CSN1Err(PycrateErr):
pass
class CSN1InvalidValueErr(CSN1Err):
pass
#------------------------------------------------------------------------------#
# text processing
#------------------------------------------------------------------------------#
def clean_text(text=''):
"""
processes text to:
remove ASN.1 comments
replace tab with space
remove duplicated spaces
"""
# remove comments
comments = scan_for_comments(text)
if comments:
# get the complementary text to comments, to get the text containing
# the actual definitions
start, defins = 0, []
for (so, eo) in comments:
defins.append( text[start:so] )
start = eo
defins.append( text[start:len(text)] )
text = ''.join(defins)
#
# replace tab and \xa0 with space
text = text.replace('\t', ' ').replace('\xa0', ' ')
# remove duplicated CR
text = re.sub('\n{2,}', '\n', text)
# remove duplicated spaces
text = re.sub(' {2,}', ' ', text)
#
return text
def pythonize_name(name=''):
"""
pythonize CSN.1 object name
"""
# remove any trailing special chars
name = re.sub('[-/\.\s]{1,}$', '', name)
# change space(s) and special character(s) to a single underscore
name = re.sub('[-/\.\s]{1,}', '_', name)
# do not let name starts with a numeric char
if name and name[0] in '0123456789':
name = '_' + name
return name
#------------------------------------------------------------------------------#
# CSN.1 tokens
#------------------------------------------------------------------------------#
_RE_NAME = '[a-zA-Z0-9_\-/ \.]{1,}'
SYNT_RE_NAME = re.compile(
'<\s{0,}(%s)\s{0,}>\s{0,}' % _RE_NAME)
SYNT_RE_REPET = re.compile(
'(?:\(\s{0,}(?:([0-9]{1,})|(\*))\s{0,}\))|(?:\*\s{0,}(?:([0-9]{1,})|(\*)))')
SYNT_RE_VALUE = re.compile(
'([01\s]{1,})|([LH\s]{1,})|(null)')
SYNT_RE_LENREF = re.compile(
'\(\s{0,}val\s{0,}\(\s{0,}(%s)\)\s{0,}\)\s{0,}\&' % _RE_NAME)
#------------------------------------------------------------------------------#
# value conversion
#------------------------------------------------------------------------------#
CSN1T_UINT = _TYPE_UINT
CSN1T_BSTR = 20
def bitstr_to_uint(bitstr):
return int(bitstr, 2)
def uint_to_bitstr(uint, bl):
bs = bin(uint)[2:]
if len(bs) < bl:
return (bl-len(bs)) * '0' + bs
else:
return bs