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 % 164 0
Test Date: 2026-10-11 15:05:20 Functions: 0.0 % 2 0

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

Generated by: LCOV version 2.0-1