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