LCOV - code coverage report
Current view: top level - wibmod/src/WIB1 - AddressTable_fileIO.cpp (source / functions) Coverage Total Hit
Test: code.result Lines: 0.0 % 160 0
Test Date: 2025-12-21 13:07:08 Functions: 0.0 % 2 0

            Line data    Source code
       1              : #include "wibmod/WIB1/AddressTable.hh"
       2              : #include <fstream>
       3              : #include "wibmod/WIB1/AddressTableException.hh"
       4              : #include <boost/tokenizer.hpp> //tokenizer
       5              : #include <stdlib.h>  //strtoul & getenv
       6              : #include <boost/regex.hpp> //regex
       7              : #include <boost/algorithm/string/case_conv.hpp> //to_upper
       8              : 
       9              : 
      10              : #define MAX_FILE_LEVEL 10
      11              : 
      12            0 : void AddressTable::LoadFile(std::string const & fileName,
      13              :                             std::string const & prefix, uint16_t offset){
      14              : 
      15            0 :   std::ifstream inFile(fileName.c_str());
      16            0 :   if (!inFile.is_open()){
      17            0 :     std::string envBasedFileName = fileName;
      18              :     //Try to use address table path if it exists
      19            0 :     if(getenv("WIBMOD_SHARE") != NULL){      
      20            0 :       envBasedFileName=getenv("WIBMOD_SHARE");
      21            0 :       envBasedFileName+="/config/WIB1/tables/";
      22            0 :       envBasedFileName+=fileName;
      23            0 :       inFile.open(envBasedFileName.c_str());
      24              :     }    
      25            0 :     if (!inFile.is_open()){
      26            0 :       BUException::BAD_FILE e;
      27            0 :       e.Append("File not found: ");
      28            0 :       e.Append(envBasedFileName.c_str());
      29            0 :       throw e;        
      30            0 :     }
      31            0 :   }
      32            0 :   const size_t bufferSize = 1000;
      33            0 :   char buffer[bufferSize + 1];
      34            0 :   memset(buffer,0,bufferSize+1);
      35            0 :   uint32_t lineNumber = 1;
      36            0 :   while(! inFile.eof()){    
      37            0 :     inFile.getline(buffer,bufferSize);
      38            0 :     ProcessLine(std::string(buffer),lineNumber,prefix,offset);
      39            0 :     lineNumber++;
      40              :   }
      41            0 : }
      42              : 
      43              : 
      44            0 : void AddressTable::ProcessLine(std::string const & line,size_t lineNumber,
      45              :                                std::string const & prefix, uint16_t offset){
      46              :   //First, ignore commments
      47            0 :   std::string activeLine = line.substr(0,line.find('#'));
      48              :   
      49              : 
      50              :   //Tokenize the activeLine
      51            0 :   boost::char_separator<char> sep(" ");
      52            0 :   boost::tokenizer<boost::char_separator<char> > tokens(activeLine,sep);
      53            0 :   boost::tokenizer<boost::char_separator<char> >::iterator itToken = tokens.begin();
      54              :   
      55              :  
      56              :   //crate a new Item;
      57            0 :   Item * item = new Item;
      58            0 :   size_t iToken = 0;
      59            0 :   for(; itToken != tokens.end(); itToken++){
      60            0 :     switch (iToken){
      61            0 :     case 0:
      62            0 :       {// keep name out of everyone else's scope
      63              :         //Assign name
      64              :         
      65            0 :         std::string name(*itToken);             
      66            0 :         if(!prefix.empty()){
      67              :           //we have a prefix to add on to the name
      68            0 :           name = prefix+std::string(".")+name;
      69              :         }
      70              : 
      71            0 :         while( (name.size() > 0) && ('.' == name[name.size()-1])) {
      72              :           //If the trailing entry is a dot (level marker) drop it as this entry just means the prefix
      73            0 :           name.erase(name.size()-1);
      74              :         }
      75              : 
      76              : 
      77            0 :         if(name.size() == 0){
      78              :           //We have an emtpy name, this is bad and we should throw
      79            0 :           BUException::INVALID_NAME e;
      80            0 :           e.Append("Empty name");
      81            0 :           throw e;        
      82            0 :         }
      83              :         
      84            0 :         boost::to_upper(name);
      85              : 
      86              :         //Assign the name to this item
      87            0 :         item->name.assign(name);
      88            0 :         iToken++;
      89            0 :       }
      90            0 :       break;
      91            0 :     case 1:
      92              :       //Assign address and apply any offset
      93              :       //itToken means we don't have to check for size of string
      94            0 :       item->address = strtoul(itToken->c_str(),NULL,0) + offset;
      95            0 :       iToken++;
      96            0 :       break;
      97            0 :     case 2:
      98              :       
      99              :       //Check if this is an include line
     100            0 :       if(!isdigit((itToken->c_str()[0]))){
     101              :         //we have an include file, append all following tokens together to use as the filename. 
     102            0 :         std::string filename(*itToken);
     103            0 :         itToken++;
     104            0 :         while(itToken != tokens.end()){   
     105            0 :           filename+=" ";
     106            0 :           filename+=*itToken;
     107            0 :           itToken++;
     108              :         }
     109            0 :         fileLevel++;
     110            0 :         if(fileLevel <= MAX_FILE_LEVEL){
     111            0 :           LoadFile(filename,item->name,item->address);              
     112              :         }else{
     113            0 :           BUException::MAX_INCLUDE_FILE_DEPTH e;
     114            0 :           e.Append("File: ");
     115            0 :           e.Append(filename);
     116            0 :           e.Append(" at prefix ");
     117            0 :           e.Append(item->name);
     118            0 :           e.Append(" is too deep\n");
     119            0 :           throw e;
     120            0 :         }
     121            0 :         fileLevel--;
     122              :         //Delete fake partial item
     123            0 :         delete item;
     124              :         //return to move on to the next line of the main file
     125            0 :         return;
     126            0 :       }
     127              : 
     128              :       //Assign mask
     129            0 :       item->mask = strtoul(itToken->c_str(),NULL,0);      
     130              :       //stolen from https://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightParallel
     131              :       //Find the bitshift offset
     132            0 :       {
     133            0 :         unsigned int v = item->mask;      // 32-bit word input to count zero bits on right
     134            0 :         unsigned int c = 32; // c will be the number of zero bits on the right
     135            0 :         v &= -signed(v);
     136            0 :         if (v) {c--;}
     137            0 :         if (v & 0x0000FFFF) {c -= 16;}
     138            0 :         if (v & 0x00FF00FF) {c -= 8;}
     139            0 :         if (v & 0x0F0F0F0F) {c -= 4;}
     140            0 :         if (v & 0x33333333) {c -= 2;}
     141            0 :         if (v & 0x55555555) {c -= 1;}
     142            0 :         item->offset = c;
     143              :       }
     144              : 
     145            0 :       iToken++;      
     146            0 :       break;
     147            0 :     case 3:
     148              :       //Assign mode
     149            0 :       item->mode = 0;
     150              : 
     151              :       //Read
     152            0 :       if(itToken->find('r') != std::string::npos){
     153            0 :         item->mode |= Item::READ;
     154            0 :       }else if (itToken->find('R') != std::string::npos){
     155            0 :         item->mode |= Item::READ;
     156              :       }
     157              : 
     158              :       //Write
     159            0 :       if(itToken->find('w') != std::string::npos){
     160            0 :         item->mode |= Item::WRITE;
     161            0 :       }else if (itToken->find('W') != std::string::npos){
     162            0 :         item->mode |= Item::WRITE;
     163              :       }
     164              : 
     165              :       //Action
     166            0 :       if(itToken->find('a') != std::string::npos){
     167            0 :         item->mode |= Item::ACTION;
     168            0 :       }else if (itToken->find('A') != std::string::npos){
     169            0 :         item->mode |= Item::ACTION;
     170              :       }
     171              : 
     172              :       iToken++;      
     173              :       break;
     174            0 :     default:
     175              :       //parse user arguments
     176              :       //repeated arguments will be over-written
     177              :       
     178              :       //Find if this is an argument or a flag, flags have no equal signs
     179            0 :       if(itToken->find('=') == std::string::npos){
     180              :         //Create an entry for this with no data
     181            0 :         item->user[*itToken];
     182            0 :         iToken++;
     183              :       }else{
     184              :         //Get the name of the user value
     185            0 :         size_t equalSignPos = itToken->find('=');
     186              :         //make sure there isn't a """ before the =
     187            0 :         if(itToken->find('"') != std::string::npos){
     188            0 :           if(itToken->find('"') < equalSignPos){
     189            0 :             BUException::BAD_TOKEN e;
     190            0 :             e.Append("Malformed token : ");
     191            0 :             e.Append(itToken->c_str());
     192            0 :             e.Append(" on line ");        
     193            0 :             char numberBuffer[14] = "\0\0\0\0\0\0\0\0\0\0\0\0";
     194            0 :             snprintf(numberBuffer,12,"%zu\n",lineNumber);
     195            0 :             e.Append(numberBuffer);
     196            0 :             e.Append("Bad line: ");
     197            0 :             e.Append(activeLine);
     198            0 :             e.Append("\n");
     199            0 :             throw e;
     200            0 :           }
     201              :         }
     202              :         //cache the name of the user field
     203            0 :         std::string name = itToken->substr(0,equalSignPos);
     204              :         //Parse the rest of the user value if there is more size
     205            0 :         if(itToken->size()-1 == equalSignPos){
     206            0 :             BUException::BAD_TOKEN e;
     207            0 :             e.Append("Malformed token : ");
     208            0 :             e.Append(itToken->c_str());
     209            0 :             e.Append(" on line ");        
     210            0 :             char numberBuffer[14] = "\0\0\0\0\0\0\0\0\0\0\0\0";
     211            0 :             snprintf(numberBuffer,12,"%zu\n",lineNumber);
     212            0 :             e.Append(numberBuffer);
     213            0 :             throw e;      
     214            0 :         }
     215              :         //star this user field's data (data after the '=' char)
     216            0 :         std::string val = itToken->substr(equalSignPos+1);
     217            0 :         if(val[0] != '"'){
     218              :           //We have a simple entry that has no quotes
     219            0 :           item->user[name] = val;
     220            0 :           iToken++;
     221              :         }else{
     222              :           //We have a quoted value
     223            0 :           val.erase(0,1); //remove the quote
     224              : 
     225              :           //Check if this is still a simple entry, but with quotes        
     226            0 :           if(val.find('"') != std::string::npos){
     227              :             //We have another quote, remove it and everything after it
     228            0 :             val = val.substr(0,val.find('"'));
     229              :           }else{
     230              :             //We have a complicated value
     231            0 :             itToken++;
     232            0 :             while(itToken != tokens.end()){
     233            0 :               val.append(" ");
     234            0 :               val.append(*itToken);
     235            0 :               if((*itToken)[itToken->size() -1] == '"'){              
     236              :                 //stop now that we've reached the closing quote
     237              :                 //remove it from the string
     238            0 :                 val.erase(val.size()-1);
     239              :                 break;
     240              :               }
     241            0 :               iToken++;
     242            0 :               itToken++;
     243              :             }
     244              :           }
     245              :           //convert "\n" to '\n'
     246            0 :           while(val.find("\\n") != std::string::npos){
     247            0 :             val.replace(val.find("\\n"),2,std::string("\n"));
     248              :           }
     249            0 :           item->user[name] = val;
     250              :         }
     251            0 :       }
     252              :       break;
     253              :     }
     254            0 :     if(itToken == tokens.end()){
     255              :       break;
     256              :     }
     257              :   }
     258              : 
     259            0 :   if(iToken >= 4){
     260            0 :     AddEntry(item);
     261              :   }else{
     262            0 :     delete item;
     263              :   }
     264            0 : }
     265              : 
        

Generated by: LCOV version 2.0-1