# include  "tools/cabana/dbc/dbcfile.h" 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <QFile> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <QFileInfo> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <QRegularExpression> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								DBCFile : : DBCFile ( const  QString  & dbc_file_name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  QFile  file ( dbc_file_name ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  ( file . open ( QIODevice : : ReadOnly ) )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    name_  =  QFileInfo ( dbc_file_name ) . baseName ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    filename  =  dbc_file_name ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    // Remove auto save file extension
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( dbc_file_name . endsWith ( AUTO_SAVE_EXTENSION ) )  { 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								      filename . chop ( AUTO_SAVE_EXTENSION . length ( ) ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    parse ( file . readAll ( ) ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  }  else  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    throw  std : : runtime_error ( " Failed to open file. " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								DBCFile : : DBCFile ( const  QString  & name ,  const  QString  & content )  :  name_ ( name ) ,  filename ( " " )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  // Open from clipboard
  
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  parse ( content ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								bool  DBCFile : : save ( )  { 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  assert ( ! filename . isEmpty ( ) ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  ( writeContents ( filename ) )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    cleanupAutoSaveFile ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  true ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  } 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  return  false ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								bool  DBCFile : : saveAs ( const  QString  & new_filename )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  filename  =  new_filename ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  return  save ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								bool  DBCFile : : autoSave ( )  { 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  return  ! filename . isEmpty ( )  & &  writeContents ( filename  +  AUTO_SAVE_EXTENSION ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  DBCFile : : cleanupAutoSaveFile ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  ( ! filename . isEmpty ( ) )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    QFile : : remove ( filename  +  AUTO_SAVE_EXTENSION ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								bool  DBCFile : : writeContents ( const  QString  & fn )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  QFile  file ( fn ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  ( file . open ( QIODevice : : WriteOnly ) )  { 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  file . write ( generateDBC ( ) . toUtf8 ( ) )  > =  0 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  } 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  return  false ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								void  DBCFile : : updateMsg ( const  MessageId  & id ,  const  QString  & name ,  uint32_t  size ,  const  QString  & node ,  const  QString  & comment )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  auto  & m  =  msgs [ id . address ] ; 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  m . address  =  id . address ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  m . name  =  name ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  m . size  =  size ; 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  m . transmitter  =  node . isEmpty ( )  ?  DEFAULT_NODE_NAME  :  node ; 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  m . comment  =  comment ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								cabana : : Msg  * DBCFile : : msg ( uint32_t  address )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  auto  it  =  msgs . find ( address ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  return  it  ! =  msgs . end ( )  ?  & it - > second  :  nullptr ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								cabana : : Msg  * DBCFile : : msg ( const  QString  & name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  auto  it  =  std : : find_if ( msgs . begin ( ) ,  msgs . end ( ) ,  [ & name ] ( auto  & m )  {  return  m . second . name  = =  name ;  } ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  return  it  ! =  msgs . end ( )  ?  & ( it - > second )  :  nullptr ; 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								cabana : : Signal  * DBCFile : : signal ( uint32_t  address ,  const  QString  name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  auto  m  =  msg ( address ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  return  m  ?  ( cabana : : Signal  * ) m - > sig ( name )  :  nullptr ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								void  DBCFile : : parse ( const  QString  & content )  { 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  msgs . clear ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  int  line_num  =  0 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  QString  line ; 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  cabana : : Msg  * current_msg  =  nullptr ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  int  multiplexor_cnt  =  0 ; 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  bool  seen_first  =  false ; 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  QTextStream  stream ( ( QString  * ) & content ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  while  ( ! stream . atEnd ( ) )  { 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    + + line_num ; 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    QString  raw_line  =  stream . readLine ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    line  =  raw_line . trimmed ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    bool  seen  =  true ; 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    try  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      if  ( line . startsWith ( " BO_  " ) )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        multiplexor_cnt  =  0 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        current_msg  =  parseBO ( line ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      }  else  if  ( line . startsWith ( " SG_  " ) )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        parseSG ( line ,  current_msg ,  multiplexor_cnt ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      }  else  if  ( line . startsWith ( " VAL_  " ) )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        parseVAL ( line ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      }  else  if  ( line . startsWith ( " CM_ BO_ " ) )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        parseCM_BO ( line ,  content ,  raw_line ,  stream ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      }  else  if  ( line . startsWith ( " CM_ SG_  " ) )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        parseCM_SG ( line ,  content ,  raw_line ,  stream ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      }  else  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        seen  =  false ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      } 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    }  catch  ( std : : exception  & e )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      throw  std : : runtime_error ( QString ( " [%1:%2]%3: %4 " ) . arg ( filename ) . arg ( line_num ) . arg ( e . what ( ) ) . arg ( line ) . toStdString ( ) ) ; 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( seen )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      seen_first  =  true ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  else  if  ( ! seen_first )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      header  + =  raw_line  +  " \n " ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  } 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  for  ( auto  & [ _ ,  m ]  :  msgs )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    m . update ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								cabana : : Msg  * DBCFile : : parseBO ( const  QString  & line )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  static  QRegularExpression  bo_regexp ( R " (^BO_ (?<address> \ w+)  ( ? < name > \ w + )  * :  ( ? < size > \ w + )  ( ? < transmitter > \ w + ) ) " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  QRegularExpressionMatch  match  =  bo_regexp . match ( line ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  ( ! match . hasMatch ( ) ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    throw  std : : runtime_error ( " Invalid BO_ line format " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  uint32_t  address  =  match . captured ( " address " ) . toUInt ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  ( msgs . count ( address )  >  0 ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    throw  std : : runtime_error ( QString ( " Duplicate message address: %1 " ) . arg ( address ) . toStdString ( ) ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  // Create a new message object
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  cabana : : Msg  * msg  =  & msgs [ address ] ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  msg - > address  =  address ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  msg - > name  =  match . captured ( " name " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  msg - > size  =  match . captured ( " size " ) . toULong ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  msg - > transmitter  =  match . captured ( " transmitter " ) . trimmed ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  return  msg ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  DBCFile : : parseCM_BO ( const  QString  & line ,  const  QString  & content ,  const  QString  & raw_line ,  const  QTextStream  & stream )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  static  QRegularExpression  msg_comment_regexp ( R " (^CM_ BO_ *(?<address> \ w+)  * \ " (?<comment>(?:[^ " \ \ ] | \ \ . ) * ) \ " \ s* ; ) " ); 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  QString  parse_line  =  line ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  ( ! parse_line . endsWith ( " \" ; " ) )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    int  pos  =  stream . pos ( )  -  raw_line . length ( )  -  1 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    parse_line  =  content . mid ( pos ,  content . indexOf ( " \" ; " ,  pos ) ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  auto  match  =  msg_comment_regexp . match ( parse_line ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  ( ! match . hasMatch ( ) ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    throw  std : : runtime_error ( " Invalid message comment format " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  ( auto  m  =  ( cabana : : Msg  * ) msg ( match . captured ( " address " ) . toUInt ( ) ) ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    m - > comment  =  match . captured ( " comment " ) . trimmed ( ) . replace ( " \\ \" " ,  " \" " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  DBCFile : : parseSG ( const  QString  & line ,  cabana : : Msg  * current_msg ,  int  & multiplexor_cnt )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  static  QRegularExpression  sg_regexp ( R " (^SG_ ( \ w+)  :  ( \ d + ) \ | ( \ d + ) @ ( \ d + ) ( [ \ + | \ - ] )  \ ( ( [ 0 - 9. + \ - eE ] + ) , ( [ 0 - 9. + \ - eE ] + ) \ )  \ [ ( [ 0 - 9. + \ - eE ] + ) \ | ( [ 0 - 9. + \ - eE ] + ) \ ]  \ " (.*) \"  (.*)) " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  static  QRegularExpression  sgm_regexp ( R " (^SG_ ( \ w+)  ( \ w + )  * :  ( \ d + ) \ | ( \ d + ) @ ( \ d + ) ( [ \ + | \ - ] )  \ ( ( [ 0 - 9. + \ - eE ] + ) , ( [ 0 - 9. + \ - eE ] + ) \ )  \ [ ( [ 0 - 9. + \ - eE ] + ) \ | ( [ 0 - 9. + \ - eE ] + ) \ ]  \ " (.*) \"  (.*)) " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  ( ! current_msg ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    throw  std : : runtime_error ( " No Message " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  int  offset  =  0 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  auto  match  =  sg_regexp . match ( line ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  ( ! match . hasMatch ( ) )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    match  =  sgm_regexp . match ( line ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    offset  =  1 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  ( ! match . hasMatch ( ) ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    throw  std : : runtime_error ( " Invalid SG_ line format " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  QString  name  =  match . captured ( 1 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  ( current_msg - > sig ( name )  ! =  nullptr ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    throw  std : : runtime_error ( " Duplicate signal name " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  cabana : : Signal  s { } ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  ( offset  = =  1 )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto  indicator  =  match . captured ( 2 ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( indicator  = =  " M " )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      + + multiplexor_cnt ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      // Only one signal within a single message can be the multiplexer switch.
  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      if  ( multiplexor_cnt  > =  2 ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        throw  std : : runtime_error ( " Multiple multiplexor " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      s . type  =  cabana : : Signal : : Type : : Multiplexor ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  else  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      s . type  =  cabana : : Signal : : Type : : Multiplexed ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      s . multiplex_value  =  indicator . mid ( 1 ) . toInt ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  s . name  =  name ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  s . start_bit  =  match . captured ( offset  +  2 ) . toInt ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  s . size  =  match . captured ( offset  +  3 ) . toInt ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  s . is_little_endian  =  match . captured ( offset  +  4 ) . toInt ( )  = =  1 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  s . is_signed  =  match . captured ( offset  +  5 )  = =  " - " ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  s . factor  =  match . captured ( offset  +  6 ) . toDouble ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  s . offset  =  match . captured ( offset  +  7 ) . toDouble ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  s . min  =  match . captured ( 8  +  offset ) . toDouble ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  s . max  =  match . captured ( 9  +  offset ) . toDouble ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  s . unit  =  match . captured ( 10  +  offset ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  s . receiver_name  =  match . captured ( 11  +  offset ) . trimmed ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  current_msg - > sigs . push_back ( new  cabana : : Signal ( s ) ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  DBCFile : : parseCM_SG ( const  QString  & line ,  const  QString  & content ,  const  QString  & raw_line ,  const  QTextStream  & stream )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  static  QRegularExpression  sg_comment_regexp ( R " (^CM_ SG_ *( \ w+)  * ( \ w + )  * \ " ((?:[^ " \ \ ] | \ \ . ) * ) \ " \ s* ; ) " ); 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  QString  parse_line  =  line ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  ( ! parse_line . endsWith ( " \" ; " ) )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    int  pos  =  stream . pos ( )  -  raw_line . length ( )  -  1 ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    parse_line  =  content . mid ( pos ,  content . indexOf ( " \" ; " ,  pos ) ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  auto  match  =  sg_comment_regexp . match ( parse_line ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  ( ! match . hasMatch ( ) ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    throw  std : : runtime_error ( " Invalid CM_ SG_ line format " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  ( auto  s  =  signal ( match . captured ( 1 ) . toUInt ( ) ,  match . captured ( 2 ) ) )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    s - > comment  =  match . captured ( 3 ) . trimmed ( ) . replace ( " \\ \" " ,  " \" " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								void  DBCFile : : parseVAL ( const  QString  & line )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  static  QRegularExpression  val_regexp ( R " (VAL_ ( \ w+)  ( \ w + )  ( \ s * [ - + ] ? [ 0 - 9 ] + \ s + \ " .+? \" [^ ; ] * ) ) " ); 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  auto  match  =  val_regexp . match ( line ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  ( ! match . hasMatch ( ) ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    throw  std : : runtime_error ( " invalid VAL_ line format " ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  if  ( auto  s  =  signal ( match . captured ( 1 ) . toUInt ( ) ,  match . captured ( 2 ) ) )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    QStringList  desc_list  =  match . captured ( 3 ) . trimmed ( ) . split ( ' " ' ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    for  ( int  i  =  0 ;  i  <  desc_list . size ( ) ;  i  + =  2 )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      auto  val  =  desc_list [ i ] . trimmed ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      if  ( ! val . isEmpty ( )  & &  ( i  +  1 )  <  desc_list . size ( ) )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        auto  desc  =  desc_list [ i  +  1 ] . trimmed ( ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        s - > val_desc . push_back ( { val . toDouble ( ) ,  desc } ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								QString  DBCFile : : generateDBC ( )  { 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  QString  dbc_string ,  comment ,  val_desc ; 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  for  ( const  auto  & [ address ,  m ]  :  msgs )  { 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    const  QString  transmitter  =  m . transmitter . isEmpty ( )  ?  DEFAULT_NODE_NAME  :  m . transmitter ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    dbc_string  + =  QString ( " BO_ %1 %2: %3 %4 \n " ) . arg ( address ) . arg ( m . name ) . arg ( m . size ) . arg ( transmitter ) ; 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( ! m . comment . isEmpty ( ) )  { 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								      comment  + =  QString ( " CM_ BO_ %1  \" %2 \" ; \n " ) . arg ( address ) . arg ( QString ( m . comment ) . replace ( " \" " ,  " \\ \" " ) ) ; 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    for  ( auto  sig  :  m . getSignals ( ) )  { 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								      QString  multiplexer_indicator ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      if  ( sig - > type  = =  cabana : : Signal : : Type : : Multiplexor )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        multiplexer_indicator  =  " M  " ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      }  else  if  ( sig - > type  = =  cabana : : Signal : : Type : : Multiplexed )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        multiplexer_indicator  =  QString ( " m%1  " ) . arg ( sig - > multiplex_value ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      } 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								      dbc_string  + =  QString ( "  SG_ %1 %2: %3|%4@%5%6 (%7,%8) [%9|%10]  \" %11 \"  %12 \n " ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        . arg ( sig - > name ) 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        . arg ( multiplexer_indicator ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        . arg ( sig - > start_bit ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        . arg ( sig - > size ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        . arg ( sig - > is_little_endian  ?  ' 1 '  :  ' 0 ' ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        . arg ( sig - > is_signed  ?  ' - '  :  ' + ' ) 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        . arg ( doubleToString ( sig - > factor ) ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        . arg ( doubleToString ( sig - > offset ) ) 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        . arg ( doubleToString ( sig - > min ) ) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        . arg ( doubleToString ( sig - > max ) ) 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        . arg ( sig - > unit ) 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                        . arg ( sig - > receiver_name . isEmpty ( )  ?  DEFAULT_NODE_NAME  :  sig - > receiver_name ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      if  ( ! sig - > comment . isEmpty ( ) )  { 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        comment  + =  QString ( " CM_ SG_ %1 %2  \" %3 \" ; \n " ) . arg ( address ) . arg ( sig - > name ) . arg ( QString ( sig - > comment ) . replace ( " \" " ,  " \\ \" " ) ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      } 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								      if  ( ! sig - > val_desc . empty ( ) )  { 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        QStringList  text ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for  ( auto  & [ val ,  desc ]  :  sig - > val_desc )  { 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								          text  < <  QString ( " %1  \" %2 \" " ) . arg ( val ) . arg ( desc ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        val_desc  + =  QString ( " VAL_ %1 %2 %3; \n " ) . arg ( address ) . arg ( sig - > name ) . arg ( text . join ( "   " ) ) ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    dbc_string  + =  " \n " ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								  } 
 
							 
						 
					
						
							
								
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								  return  header  +  dbc_string  +  comment  +  val_desc ; 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								}