File indexing completed on 2025-02-16 09:49:50
0001 0002 /* 0003 File : OriginFile.cpp 0004 Description : Origin file import class 0005 -------------------------------------------------------------------- 0006 SPDX-FileCopyrightText: 2005-2008, 2017-2023 Stefan Gerlach <stefan.gerlach@uni.kn> 0007 SPDX-FileCopyrightText: 2007-2008 Alex Kargovsky <kargovsky*yumr.phys.msu.su> 0008 SPDX-FileCopyrightText: 2007-2008 Ion Vasilief <ion_vasilief*yahoo.fr> 0009 SPDX-License-Identifier: GPL-2.0-or-later 0010 */ 0011 0012 #include "config.h" 0013 #include "OriginFile.h" 0014 0015 #include <fstream> 0016 #include <string> 0017 0018 using namespace std; 0019 0020 OriginFile::OriginFile(const string &fileName) : fileVersion(0), buildVersion(0), ioError(0) 0021 { 0022 ifstream file(fileName.c_str(), ios_base::binary); 0023 0024 if (!file.is_open()) { 0025 ioError = errno; 0026 return; 0027 } 0028 0029 #ifdef GENERATE_CODE_FOR_LOG 0030 FILE *logfile = nullptr; 0031 logfile = fopen("./opjfile.log", "w"); 0032 if (logfile == nullptr) { 0033 ioError = errno; 0034 return; 0035 } 0036 #endif // GENERATE_CODE_FOR_LOG 0037 LOG_PRINT(logfile, "File: %s\n", fileName.c_str()) 0038 0039 string vers; 0040 getline(file, vers); 0041 file.close(); 0042 0043 long majorVersion = strtol(vers.substr(5, 1).c_str(), nullptr, 10); 0044 // char locale_decpoint = vers[6]; 0045 buildVersion = strtol(vers.substr(7).c_str(), nullptr, 10); 0046 // long buildNumber = strtol(vers.substr(12).c_str(),0,10); 0047 0048 // translate version 0049 // see https://www.originlab.com/index.aspx?go=SUPPORT&pid=3325 0050 unsigned int newFileVersion = 0; 0051 if (majorVersion == 3) { 0052 if (buildVersion < 830) 0053 fileVersion = 350; 0054 else 0055 fileVersion = 410; 0056 } else if (buildVersion >= 110 && buildVersion <= 141) // 4.1 0057 fileVersion = 410; 0058 else if (buildVersion <= 210) // 5.0 0059 fileVersion = 500; 0060 else if (buildVersion < 2624) // 6.0 0061 fileVersion = 600; 0062 else if (buildVersion < 2628) // 6.0 SR1 0063 fileVersion = 601; 0064 else if (buildVersion < 2635) // 6.0 SR4 0065 fileVersion = 604; 0066 else if (buildVersion < 2656) // 6.1 0067 fileVersion = 610; 0068 else if (buildVersion < 2659) // 7.0 SR0 (2656-2658) 0069 fileVersion = 700; 0070 else if (buildVersion < 2664) // 7.0 SR1 (2659-2663) 0071 fileVersion = 701; 0072 else if (buildVersion < 2672) // 7.0 SR2 (2664-2671) 0073 fileVersion = 702; 0074 else if (buildVersion < 2673) // 7.0 SR3 (2672-2672) 0075 fileVersion = 703; 0076 else if (buildVersion < 2766) // 7.0 SR4 (2673-2765) 0077 fileVersion = 704; 0078 else if (buildVersion < 2878) // 7.5 (2766-2877) 0079 fileVersion = 750; 0080 else if (buildVersion < 2881) // 8.0 SR0 (2878-2880) 0081 fileVersion = 800; 0082 else if (buildVersion < 2892) // 8.0 SR1,SR2,SR3 (2878-2891) 0083 fileVersion = 801; 0084 else if (buildVersion < 2944) // 8.0 SR4, 8.1 SR1-SR4 (2891-2943) 0085 fileVersion = 810; 0086 else if (buildVersion < 2947) // 8.5 SR0, SR1 (2944-2946) 0087 fileVersion = 850; 0088 else if (buildVersion < 2962) // 8.5.1 SR0, SR1, SR2 0089 fileVersion = 851; 0090 else if (buildVersion < 2980) // 8.6 SR0, SR1, SR2, SR3 0091 fileVersion = 860; 0092 else if (buildVersion < 3025) // 9.0 SR0, SR1, SR2 0093 fileVersion = 900; 0094 else if (buildVersion < 3078) // 9.1 SR0, SR1, SR2, SR3 0095 fileVersion = 910; 0096 else if (buildVersion < 3117) { // 2015 (9.2) SR0, SR1, SR2 0097 fileVersion = 920; 0098 newFileVersion = 20150; 0099 } else if (buildVersion < 3169) { // 2016 (9.3.0) SR0 0100 fileVersion = 930; 0101 newFileVersion = 20160; 0102 } else if (buildVersion < 3172) { // 2016.1 (9.3.1), 2016.2 (9.3.2) SR1, SR2 0103 fileVersion = 931; 0104 newFileVersion = 20161; 0105 } else if (buildVersion < 3225) { // 2017.0 (9.4.0.220) SR0 3224 0106 fileVersion = 940; 0107 newFileVersion = 20170; 0108 } else if (buildVersion < 3228) { // 2017.1 (9.4.1.354), 2017.2 (9.4.2.380) SR1, SR2 3227 0109 fileVersion = 941; 0110 newFileVersion = 20171; 0111 } else if (buildVersion < 3269) { // 2018.0 (9.5.0.193), 2018.1 (9.5.1.195) SR0, SR1 3268 0112 fileVersion = 950; 0113 newFileVersion = 20180; 0114 } else if (buildVersion < 3296) { // 2018b.0 (9.5.5.409) SR0, SR1 3295 0115 fileVersion = 955; 0116 newFileVersion = 20185; 0117 } else if (buildVersion < 3331) { // 2019.0 (9.6.0.172) SR0 3330 0118 fileVersion = 960; 0119 newFileVersion = 20190; 0120 } else if (buildVersion < 3360) { // 2019b.0 (9.6.5.169) SR0 3359 0121 fileVersion = 965; 0122 newFileVersion = 20195; 0123 } else if (buildVersion < 3381) { // 2020.0 (9.7.0.185), 2020.1 (9.7.0.188) SR0, SR1 3380 0124 fileVersion = 970; 0125 newFileVersion = 20200; 0126 } else if (buildVersion < 3426) { // 2020b.0 (9.7.5.184) SR0 3425 0127 fileVersion = 975; 0128 newFileVersion = 20205; 0129 } else if (buildVersion < 3446) { // 2021.0 (9.8.0.200) SR0 3445 0130 fileVersion = 980; 0131 newFileVersion = 20210; 0132 } else if (buildVersion < 3479) { // 2021b.0 (9.8.5.201), 2021b.1 (9.8.5.204), 2021b.2 0133 // (9.8.5.212) SR0, SR1, SR2 3478 0134 fileVersion = 985; 0135 newFileVersion = 20215; 0136 } else if (buildVersion < 3522) { // 2022 (9.90.220) SR0 0137 fileVersion = 990; 0138 newFileVersion = 20220; 0139 } else if (buildVersion < 3523) { // 2022 (9.90.225) SR1 0140 fileVersion = 990; 0141 newFileVersion = 20221; 0142 } else if (buildVersion < 3552) { // 2022b (9.95.167) SR0, OriginViewer 9.9.5 (9.95.63) 3534 0143 fileVersion = 995; 0144 newFileVersion = 20225; 0145 // 2023 does not support OPJ anymore, but newer OriginViewer may do. 0146 } else { 0147 // > 2022b 0148 fileVersion = 1000; 0149 newFileVersion = 20230; 0150 LOG_PRINT(logfile, "Found project version 2023 (10.0.0) or newer\n") 0151 } 0152 0153 if (newFileVersion == 0) { 0154 LOG_PRINT(logfile, "Found project version %.2f\n", fileVersion / 100.0) 0155 } else if (fileVersion < 941) { 0156 LOG_PRINT(logfile, "Found project version %.1f (%.2f)\n", newFileVersion / 10.0, 0157 fileVersion / 100.0) 0158 } 0159 0160 // Close logfile, will be reopened in parser routine. 0161 // There are ways to keep logfile open and pass it to parser routine, 0162 // but I choose to do the same as with 'file', close it and reopen in 'parse' 0163 // routines. 0164 parser.reset(createOriginAnyParser(fileName)); 0165 ioError = 0; 0166 0167 #ifdef GENERATE_CODE_FOR_LOG 0168 fclose(logfile); 0169 #endif 0170 } 0171 0172 bool OriginFile::parse() 0173 { 0174 if (ioError != 0) 0175 return false; 0176 parser->buildVersion = buildVersion; 0177 parser->fileVersion = fileVersion; 0178 return parser->parse(); 0179 } 0180 0181 double OriginFile::version() const 0182 { 0183 return (parser->fileVersion) / 100.0; 0184 } 0185 0186 const tree<Origin::ProjectNode> *OriginFile::project() const 0187 { 0188 return &parser->projectTree; 0189 } 0190 0191 vector<Origin::SpreadColumn>::size_type OriginFile::datasetCount() const 0192 { 0193 return parser->datasets.size(); 0194 } 0195 0196 Origin::SpreadColumn &OriginFile::dataset(vector<Origin::SpreadColumn>::size_type ds) const 0197 { 0198 return parser->datasets[ds]; 0199 } 0200 0201 vector<Origin::SpreadSheet>::size_type OriginFile::spreadCount() const 0202 { 0203 return parser->spreadSheets.size(); 0204 } 0205 0206 Origin::SpreadSheet &OriginFile::spread(vector<Origin::SpreadSheet>::size_type s) const 0207 { 0208 return parser->spreadSheets[s]; 0209 } 0210 0211 vector<Origin::Matrix>::size_type OriginFile::matrixCount() const 0212 { 0213 return parser->matrixes.size(); 0214 } 0215 0216 Origin::Matrix &OriginFile::matrix(vector<Origin::Matrix>::size_type m) const 0217 { 0218 return parser->matrixes[m]; 0219 } 0220 0221 vector<Origin::Function>::size_type OriginFile::functionCount() const 0222 { 0223 return parser->functions.size(); 0224 } 0225 0226 vector<Origin::Function>::difference_type OriginFile::functionIndex(const string &name) const 0227 { 0228 return parser->findFunctionByName(name); 0229 } 0230 0231 Origin::Function &OriginFile::function(vector<Origin::Function>::size_type f) const 0232 { 0233 return parser->functions[f]; 0234 } 0235 0236 vector<Origin::Graph>::size_type OriginFile::graphCount() const 0237 { 0238 return parser->graphs.size(); 0239 } 0240 0241 Origin::Graph &OriginFile::graph(vector<Origin::Graph>::size_type g) const 0242 { 0243 return parser->graphs[g]; 0244 } 0245 0246 vector<Origin::Note>::size_type OriginFile::noteCount() const 0247 { 0248 return parser->notes.size(); 0249 } 0250 0251 Origin::Note &OriginFile::note(vector<Origin::Note>::size_type n) const 0252 { 0253 return parser->notes[n]; 0254 } 0255 0256 vector<Origin::Excel>::size_type OriginFile::excelCount() const 0257 { 0258 return parser->excels.size(); 0259 } 0260 0261 Origin::Excel &OriginFile::excel(vector<Origin::Excel>::size_type e) const 0262 { 0263 return parser->excels[e]; 0264 } 0265 0266 string OriginFile::resultsLogString() const 0267 { 0268 return parser->resultsLog; 0269 } 0270 0271 string liboriginVersionString() 0272 { 0273 return LIBORIGIN_VERSION_STRING; 0274 } 0275 0276 unsigned int liboriginVersion() 0277 { 0278 return LIBORIGIN_VERSION; 0279 } 0280 0281 unsigned int liboriginVersionMajor() 0282 { 0283 return LIBORIGIN_VERSION_MAJOR; 0284 } 0285 0286 unsigned int liboriginVersionMinor() 0287 { 0288 return LIBORIGIN_VERSION_MINOR; 0289 } 0290 0291 unsigned int liboriginVersionPatch() 0292 { 0293 return LIBORIGIN_VERSION_PATCH; 0294 }