OpenRadioss 2025.1.11
OpenRadioss project
Loading...
Searching...
No Matches
checksum_model.cpp
Go to the documentation of this file.
1//Copyright> OpenRadioss
2//Copyright> Copyright (C) 1986-2025 Altair Engineering Inc.
3//Copyright>
4//Copyright> This program is free software: you can redistribute it and/or modify
5//Copyright> it under the terms of the GNU Affero General Public License as published by
6//Copyright> the Free Software Foundation, either version 3 of the License, or
7//Copyright> (at your option) any later version.
8//Copyright>
9//Copyright> This program is distributed in the hope that it will be useful,
10//Copyright> but WITHOUT ANY WARRANTY; without even the implied warranty of
11//Copyright> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12//Copyright> GNU Affero General Public License for more details.
13//Copyright>
14//Copyright> You should have received a copy of the GNU Affero General Public License
15//Copyright> along with this program. If not, see <https://www.gnu.org/licenses/>.
16//Copyright>
17//Copyright>
18//Copyright> Commercial Alternative: Altair Radioss Software
19//Copyright>
20//Copyright> As an alternative to this open-source version, Altair also offers Altair Radioss
21//Copyright> software under a commercial license. Contact Altair to discuss further if the
22//Copyright> commercial version may interest you: https://www.altair.com/radioss/.
23#include <checksum_model.h>
24
25using namespace std;
26
27 // -----------------------------------------------------------------------------------
28 // Function to remove carriage return characters from a string
29 // -----------------------------------------------------------------------------------
30 void MD5Checksum::remove_carriage_return(std::string& line) {
31 line.erase(std::remove(line.begin(), line.end(), '\r'), line.end());
32 }
33
34 // -----------------------------------------------------------------------------------
35 // Tool : Return the separator for the file path according to the OS
36 // output:
37 // separator : "/" for Unix, "\" for Windows
38 // -----------------------------------------------------------------------------------
40 // -----------------------------------------------------------------------------------
41 #ifdef _WIN64
42 return "\\"; // Windows separator
43 #else
44 return "/"; // Unix separator
45 #endif
46 }
47 // -----------------------------------------------------------------------------------
48 // Tool : get directory path from a file path
49 // -----------------------------------------------------------------------------------
50 std::string MD5Checksum::get_path(const std::string& filepath) {
51 // Find the last occurrence of the path separator
52#ifdef _WIN64
53 size_t pos = filepath.find_last_of("/\\");
54 if (pos == std::string::npos) {
55 pos = filepath.find_last_of("/");
56 }
57#else
58 size_t pos = filepath.find_last_of("/");
59#endif
60 if (pos != std::string::npos) {
61 // Extract the substring up to the last separator
62 return filepath.substr(0, pos);
63 }
64 // If no separator is found, return an empty string
65 return "";
66 }
67
68 // ------------------------------------------------------------------------------------------------------------------------
69 void MD5Checksum::new_checksum( string title, list<tuple<int,string, md5_state_t, string>> *md5_states_tmp){
70 // ------------------------------------------------------------------------------------------------------------------------
71 // CHECKSUM/START was met, create a new checksum state
72 // input:
73 // title : title of the checksum
74 // input / output:
75 // md5_states_tmp : list of checksums computed in the file
76 // ------------------------------------------------------------------------------------------------------------------------
77 md5_state_t new_md5;
78 md5_init(&new_md5);
79 string md5_digest(16,'0');
80 md5_states_tmp->push_front(make_tuple(1,title,new_md5,md5_digest));
81 };
82
83 // ------------------------------------------------------------------------------------------------------------------------
84 // Add line to all active MD5 digests
85 // input:
86 // line : string to be added to the checksum
87 // input / output:
88 // md5_states_tmp : list of checksums computed in the file
89 // ------------------------------------------------------------------------------------------------------------------------
90 void MD5Checksum::process_checksum(string line, list<tuple<int,string, md5_state_t, string>> *md5_states_tmp){
91 // ------------------------------------------------------------------------------------------------------------------------
92 for (auto& item : *md5_states_tmp ) {
93 if (get<0>(item) == 1){
94 md5_state_t state = get<2>(item);
95 md5_append( &state, (const md5_byte_t *) line.c_str(), line.length() );
96 get<2>(item) = state;
97 }
98 }
99 };
100
101 // --------------------------------------------------------------------------------------------------------------------
102 // /CHECKSUM/STOP : Finish the MD5 checksum for the first active state
103 // --------------------------------------------------------------------------------------------------------------------
104 // input / output
105 // md5_states_tmp : list of checksums computed in the file
106 // --------------------------------------------------------------------------------------------------------------------
107 void MD5Checksum::end_checksum(list<tuple<int,string, md5_state_t, string>> *md5_states_tmp){
108 // --------------------------------------------------------------------------------------------------------------------
109 int state=-1;
110 for (auto& item : *md5_states_tmp ) {
111 state=get<0>(item);
112 if (state == 1) {
113 get<0>(item) = 0; // Set Active flag to 0
114
115 // Finish the MD5 checksum
116 md5_state_t state = get<2>(item);
117 unsigned char md5[16];
118 md5_finish (&state, md5);
119
120 // Add MD5 in hexadecimal format in tuplet
121 ostringstream formatted_line;
122 for (int i = 0; i < 16; ++i) {
123 formatted_line << hex << setw(2) << setfill('0') << static_cast<int>(md5[i]);
124 }
125 get<3>(item)=formatted_line.str();
126 break;
127 }
128 }
129 };
130
131 // --------------------------------------------------------------------------------------------------------------------
132 // Finalize checksum : After deck file processing : finalize all active checksums (/CHECKSUM/STOP missing)
133 // --------------------------------------------------------------------------------------------------------------------
134 // input / output
135 // md5_states_tmp : list of checksums computed in the file
136 // --------------------------------------------------------------------------------------------------------------------
137 void MD5Checksum::finalize_checksum(list<tuple<int,string, md5_state_t, string>> *md5_states_tmp){
138 // --------------------------------------------------------------------------------------------------------------------
139 int state=-1;
140 for (auto& item : *md5_states_tmp ) {
141 state=get<0>(item);
142 if (state == 1) {
143 get<0>(item) = 0; // Set Active flag to 0
144
145 // Finish the MD5 checksum
146 md5_state_t state = get<2>(item);
147 unsigned char md5[16];
148 md5_finish (&state, md5);
149
150 // Add MD5 in hexadecimal format in tuplet
151 ostringstream formatted_line;
152 for (int i = 0; i < 16; ++i) {
153 formatted_line << hex << setw(2) << setfill('0') << static_cast<int>(md5[i]);
154 }
155 get<3>(item)=formatted_line.str();
156 }
157 }
158 };
159 // -----------------------------------------------------------------------------------------------------------------------------
160 // main checksum computation function
161 // read the input deck line by line , commpute checksums between CHECKSUM/START and CHECKSUM/END
162 // ------------------------------------------------------------------------------------------------------------------------------
163 // input:
164 // filename,string : name of the file to be read
165 // level,int : recursion level (used to limit the number of include files)
166 // output:
167 // md5_states_tmp : list of checksums computed in the file
168 // ------------------------------------------------------------------------------------------------------------------------------
169 int MD5Checksum::file_read(string filename,string deck_directory,int level,list<tuple<int,string, md5_state_t, string>> *md5_states_tmp){
170 // -----------------------------------------------------------------------------------------------------------------------------
171 string chksum_start=( "/CHECKSUM/START");
172 string chksum_end=( "/CHECKSUM/END");
173 string chksum_include=( "#include ");
174 fstream new_file;
175 new_file.open(filename, ios::in);
176
177 // Stop after 15 levels of recursion
178 if (level > 15) return 0;
179
180 if ( !new_file.is_open() ) {
181 return -1;
182 }
183
184 string line;
185 while (getline(new_file, line)) {
186
187 remove_carriage_return(line); // Remove carriage return characters
188 // Search for /CHECKSUM/START keyword
189 if (line == chksum_start) {
190 string title;
191 getline(new_file, title);
192 remove_carriage_return(title); // Remove carriage return characters
193 new_checksum(title,md5_states_tmp);
194 continue;
195 }
196 // Search for /CHECKSUM/END keyword
197 if (line == chksum_end) {
198 end_checksum(md5_states_tmp);
199 continue;
200 }
201
202 string comp=line.substr(0,chksum_include.length());
203 if (comp == chksum_include) {
204 // Process include files
205 string include_file = line.substr(chksum_include.length());
206 if (deck_directory.length() > 0){
207 include_file = deck_directory+separator()+include_file; // Get the path of the file
208 }
209 if (debug){
210 cout << "Include file: " << include_file << endl;
211 }
212 // include_file.erase( remove(include_file.rbegin(), include_file.end(), ' '), include_file.end());
213 // debug cout << "Include file: " << include_file << endl;
214 file_read(include_file,deck_directory, level + 1,md5_states_tmp);
215 continue;
216 }
217
218 if (line[0] == '#') {
219 // Skip comment lines
220 continue;
221 }
222 process_checksum(line,md5_states_tmp);
223
224 }
225 new_file.close();
226 return 0;
227 }
228
229 // --------------------------------------------------------------------------------------------------------
230 // constructor
231 // --------------------------------------------------------------------------------------------------------
233 // --------------------------------------------------------------------------------------------------------
234 {};
235
236 void MD5Checksum::parse(string filenam) {
237 list<tuple<int,string, md5_state_t, string>> md5_states_tmp;
238 string deck_directory = get_path(filenam); // Get the directory of the file
239 file_read(filenam,deck_directory,0,&md5_states_tmp);
240 finalize_checksum(&md5_states_tmp); // Finalize all active checksums
241 // intvert the list to have it in deck order
242 for (const auto& item : md5_states_tmp){
243 md5_states.push_front(item); // Add the checksums to the main list
244 }
245
246 md5_states_tmp.clear(); // Clear the temporary list
247 };
248
249 // --------------------------------------------------------------------------------------------------------
250 // CPP / Fortran interface : Get the number of checksums
251 // --------------------------------------------------------------------------------------------------------
253 // --------------------------------------------------------------------------------------------------------
254 return md5_states.size();
255 }
256
257 // --------------------------------------------------------------------------------------------------------
258 // CPP / Fortran interface : Get the N-th checksum
259 // --------------------------------------------------------------------------------------------------------
260 // input:
261 // N : checksum number to be retrieved
262 // output:
263 // checksum_title : title of the checksum
264 // len_title : length of the checksum title
265 // checksum : checksum value
266 // len_checksum : length of the checksum value
267 // --------------------------------------------------------------------------------------------------------
268 void MD5Checksum::member(int N,char* checksum_title,int *len_title,char* checksum,int *len_checksum) {
269 // --------------------------------------------------------------------------------------------------------
270 int count= md5_states.size();
271 if (N > count) {
272 cout << "Error: N=" << N << " is greater than the number of checksums " << count << endl;
273 checksum[0]='\0';
274 checksum_title[0]='\0';
275 *len_checksum=0;
276 *len_title=0;
277 }else{
278 auto it = md5_states.begin();
279 advance(it, N-1); // Move iterator to the N-th element (0-based index)
280
281 // Copy checksum_title
282 int size_title = get<1>(*it).size();
283 get<1>(*it).copy(checksum_title ,size_title);
284 checksum_title[size_title]='\0';
285 *len_title=size_title;
286
287 // Copy checksum
288 int size_checksum = get<3>(*it).size();
289 get<3>(*it).copy(checksum ,size_checksum);
290 checksum[size_checksum]='\0';
291 *len_checksum=size_checksum;
292
293 // cout << "Member " << *N << " Checksum : " << get<1>(*it) << " " << get<3>(*it) << endl;
294 }
295 }
296
297 // --------------------------------------------------------------------------------------------------------
298 // Get the list of all computed checksums
299 // --------------------------------------------------------------------------------------------------------
300 // output:
301 // computed checksums in hexadecimal format
302 // --------------------------------------------------------------------------------------------------------
304 // --------------------------------------------------------------------------------------------------------
305 list<string> checksums;
306 for (const auto& item : md5_states){
307 if (get<0>(item) == 0){
308 string chksum_item=get<1>(item)+"_"+get<3>(item);
309 checksums.push_back(chksum_item);
310 }
311 }
312 return checksums;
313 }
314
315 // ------------------------
316 // print the checksum list
317 // ------------------------
319 // ------------------------
320 cout << "Checksum list " << endl;
321 cout << "==============" << endl;
322 for (const auto& item : md5_states){
323 if (get<0>(item) == 0){
324 cout << "Checksum : " << get<1>(item) << " " << get<3>(item) << endl;
325 }
326 }
327 }
328
329// End of class MD5Checksum
330
331// ------------------------------------------------------------------------------------------------------------------------
332// C/Fortran interface to the C++ class MD5Checksum
333// The interface is used to create the checksum from the input deck and to read the checksums
334// To be called from Starter.
335
336extern "C" {
337 MD5Checksum * deck_checksum_creation(int len_filename,char filename[]) {
338 int i;
339
340 MD5Checksum * md_compute = new MD5Checksum();
341 char * c_filename = (char*) malloc(len_filename+1);
342 for (i=0; i<len_filename; i++){
343 c_filename[i]=filename[i];
344 }
345 c_filename[len_filename]='\0';
346 string cpp_filename(c_filename);
347
348 md_compute->parse(cpp_filename);
349 return md_compute;
350 }
351
352
354 return md_compute->count();
355 }
356
357 void deck_checksum_read(MD5Checksum * md_compute, int count,char* checksum_title,int *len_title,char* checksum,int *len_checksum) {
358 md_compute->member(count,checksum_title,len_title,checksum,len_checksum);
359 }
360
361}
void deck_checksum_read(MD5Checksum *md_compute, int count, char *checksum_title, int *len_title, char *checksum, int *len_checksum)
int deck_checksum_count(MD5Checksum *md_compute)
MD5Checksum * deck_checksum_creation(int len_filename, char filename[])
std::list< std::tuple< int, std::string, md5_state_t, std::string > > md5_states
void end_checksum(std::list< std::tuple< int, std::string, md5_state_t, std::string > > *md5_states_tmp)
void parse(std::string filenam)
std::list< std::string > get_checksums()
std::string get_path(const std::string &filepath)
void member(int N, char *checksum_title, int *len_title, char *checksum, int *len_checksum)
std::string separator()
void process_checksum(std::string line, std::list< std::tuple< int, std::string, md5_state_t, std::string > > *md5_states_tmp)
int file_read(std::string filename, std::string deck_directory, int level, std::list< std::tuple< int, std::string, md5_state_t, std::string > > *md5_states_tmp)
void finalize_checksum(std::list< std::tuple< int, std::string, md5_state_t, std::string > > *md5_states_tmp)
void new_checksum(std::string title, std::list< std::tuple< int, std::string, md5_state_t, std::string > > *md5_states_tmp)
void remove_carriage_return(std::string &line)
#define N
int comp(int a, int b)