From 6a3b4ee9690e4975b2d6310606d839034e9b89b2 Mon Sep 17 00:00:00 2001 From: Jan Marvin Garbuszus Date: Tue, 18 Jun 2024 00:14:53 +0200 Subject: [PATCH] [xlsb] add data validations --- R/wb_load.R | 21 +++ src/xlsb.cpp | 341 +++++++++++++++++++++++++++++++++++++++++---- src/xlsb_defines.h | 27 ++++ src/xlsb_funs.h | 184 ++++++++++++++++++------ 4 files changed, 502 insertions(+), 71 deletions(-) diff --git a/R/wb_load.R b/R/wb_load.R index 63f5d0c94..c4992893e 100644 --- a/R/wb_load.R +++ b/R/wb_load.R @@ -1571,6 +1571,17 @@ wb_load <- function( ) } + for (i in seq_along(wb$worksheets)) { + if (!wb$is_chartsheet[[i]]) + wb$worksheets[[i]]$extLst <- + stringi::stri_replace_all_fixed( + wb$worksheets[[i]]$extLst, + xti$name_id, + xti$sheets, + vectorize_all = FALSE + ) + } + ### for external references we need to get the required sheet names first # For now this is all a little guess work @@ -1648,6 +1659,16 @@ wb_load <- function( vectorize_all = FALSE ) } + + + if (!wb$is_chartsheet[[i]]) + wb$worksheets[[j]]$dataValidations <- + stringi::stri_replace_all_fixed( + wb$worksheets[[j]]$dataValidations, + nri$name_id, + nri$name, + vectorize_all = FALSE + ) } } diff --git a/src/xlsb.cpp b/src/xlsb.cpp index d80dbd1ec..9fa8fd4c3 100644 --- a/src/xlsb.cpp +++ b/src/xlsb.cpp @@ -2026,6 +2026,7 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo if (debug) Rcpp::Rcout << "." << std::endl; RECORD(x, size, bin, swapit); + if (debug) Rcpp::Rcout << x << ": " << size << std::endl; switch(x) { @@ -2186,6 +2187,7 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo case BrtPane: { + if (debug) Rcpp::Rcout << "BrtPane: " << std::endl; uint8_t flags = 0; uint32_t rwTop = 0, colLeft = 0, pnnAct = 0; double xnumXSplit = 0.0, xnumYSplit = 0.0; @@ -2304,6 +2306,7 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo case BrtPageSetup: { + if (debug) Rcpp::Rcout << "BrtPageSetup: " << std::endl; uint16_t flags = 0; uint32_t iPaperSize = 0, iScale = 0, iRes = 0, iVRes = 0, iCopies = 0, iPageStart = 0, iFitWidth = 0, iFitHeight = 0; @@ -2345,6 +2348,7 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo case BrtPhoneticInfo: { + if (debug) Rcpp::Rcout << "BrtPhoneticInfo: " << std::endl; uint16_t iFnt = 0; uint32_t phType = 0, phAll = 0; iFnt = readbin(iFnt, bin, swapit); @@ -2359,6 +2363,7 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo case BrtBeginHeaderFooter: { + if (debug) Rcpp::Rcout << "BrtBeginHeaderFooter: " << std::endl; uint16_t flags = 0; flags = readbin(flags, bin, swapit); // unused @@ -3060,6 +3065,7 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo case BrtArrFmla: { + if (debug) Rcpp::Rcout << "BrtArrFmla: " << bin.tellg() << std::endl; int is_shared_formula = false; uint8_t flags = 0; @@ -3241,14 +3247,21 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo xnumHeader = Xnum(bin, swapit); xnumFooter = Xnum(bin, swapit); - out << "" << std::endl; + if (xnumLeft < 0 || xnumLeft > 49) Rcpp::stop("xnumLeft size out of bounds"); + if (xnumRight < 0 || xnumRight > 49) Rcpp::stop("xnumRight size out of bounds"); + if (xnumTop < 0 || xnumTop > 49) Rcpp::stop("xnumTop size out of bounds"); + if (xnumBottom < 0 || xnumBottom > 49) Rcpp::stop("xnumBottom size out of bounds"); + if (xnumHeader < 0 || xnumHeader > 49) Rcpp::stop("xnumHeader size out of bounds"); + if (xnumFooter < 0 || xnumFooter > 49) Rcpp::stop("xnumFooter size out of bounds"); + + out << "" << std::endl; break; } @@ -3262,7 +3275,7 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo case BrtDrawing: { - if (debug) Rcpp::Rcout << "" << std::endl; + if (debug) Rcpp::Rcout << "BrtDrawing" << std::endl; std::string stRelId = XLNullableWideString(bin, swapit); out << "" << std::endl; break; @@ -3270,7 +3283,7 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo case BrtLegacyDrawing: { - if (debug) Rcpp::Rcout << "" << std::endl; + if (debug) Rcpp::Rcout << "BrtLegacyDrawing" << std::endl; std::string stRelId = XLNullableWideString(bin, swapit); out << "" << std::endl; break; @@ -3278,7 +3291,7 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo case BrtLegacyDrawingHF: { - if (debug) Rcpp::Rcout << "" << std::endl; + if (debug) Rcpp::Rcout << "BrtLegacyDrawingHF" << std::endl; std::string stRelId = XLNullableWideString(bin, swapit); out << "" << std::endl; break; @@ -3286,7 +3299,7 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo case BrtHLink: { - if (debug) Rcpp::Rcout << "" << std::endl; + if (debug) Rcpp::Rcout << "BrtHLink" << std::endl; std::vector rfx = UncheckedRfX(bin, swapit); std::string relId = XLNullableWideString(bin, swapit); @@ -3313,7 +3326,7 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo case BrtBeginAFilter: { - if (debug) Rcpp::Rcout << "" << std::endl; + if (debug) Rcpp::Rcout << "BrtBeginAFilter" << std::endl; std::vector rfx = UncheckedRfX(bin, swapit); std::string lref = int_to_col(rfx[2] + 1) + std::to_string(rfx[0] + 1); @@ -3336,7 +3349,7 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo case BrtBeginFilterColumn: { - if (debug) Rcpp::Rcout << "" << std::endl; + if (debug) Rcpp::Rcout << "BrtBeginFilterColumn" << std::endl; uint16_t flags = 0; uint32_t dwCol = 0; @@ -3352,7 +3365,7 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo case BrtBeginFilters: { - if (debug) Rcpp::Rcout << "" << std::endl; + if (debug) Rcpp::Rcout << "BrtBeginFilters" << std::endl; // bin.seekg(size, bin.cur); uint32_t fBlank = 0, unused = 0; @@ -3364,7 +3377,7 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo case BrtFilter: { - if (debug) Rcpp::Rcout << "" << std::endl; + if (debug) Rcpp::Rcout << "BrtFilter" << std::endl; std::string rgch = XLWideString(bin, swapit); out << "" << std::endl; // bin.seekg(size, bin.cur); @@ -3373,7 +3386,7 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo case BrtEndFilters: { - if (debug) Rcpp::Rcout << "" << std::endl; + if (debug) Rcpp::Rcout << "BrtEndFilters" << std::endl; out << "" << std::endl; bin.seekg(size, bin.cur); break; @@ -3381,7 +3394,7 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo case BrtColorFilter: { - if (debug) Rcpp::Rcout << "" << std::endl; + if (debug) Rcpp::Rcout << "BrtColorFilter" << std::endl; uint32_t dxfid = 0, fCellColor = 0; dxfid = readbin(dxfid, bin, swapit); fCellColor = readbin(fCellColor, bin, swapit); @@ -3395,6 +3408,7 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo case BrtBeginCustomFilters14: case BrtBeginCustomRichFilters: { + if (debug) Rcpp::Rcout << "BrtBeginCustom..." << std::endl; Rcpp::warning("Custom Filter found. This is not handled."); bin.seekg(size, bin.cur); @@ -3403,6 +3417,7 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo case BrtDynamicFilter: { + if (debug) Rcpp::Rcout << "BrtDynamicFilter" << std::endl; Rcpp::warning("Dynamic Filter found. This is not handled."); bin.seekg(size, bin.cur); break; @@ -3426,7 +3441,7 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo case BrtEndFilterColumn: { - if (debug) Rcpp::Rcout << "" << std::endl; + if (debug) Rcpp::Rcout << "BrtEndFilterColumn" << std::endl; out << "" << std::endl; bin.seekg(size, bin.cur); break; @@ -3502,21 +3517,272 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo } case BrtBeginDVals: - case BrtBeginDVals14: { - Rcpp::warning("Worksheet contains unhandled data validation."); - bin.seekg(size, bin.cur); + if (debug) Rcpp::Rcout << "BrtBeginDVals" << std::endl; + + uint16_t flags = 0; + uint32_t xLeft = 0, yTop = 0, unused3 = 0, idvMac = 0; + + // openxlsx2 does not handle this? + flags = readbin(flags, bin, swapit); + xLeft = readbin(xLeft, bin, swapit); + yTop = readbin(yTop, bin, swapit); + unused3 = readbin(unused3, bin, swapit); + idvMac = readbin(idvMac, bin, swapit); + + if (idvMac > 65534) Rcpp::stop("idvMac to big"); + + out << "" << std::endl; break; } + case BrtDVal: - case BrtDVal14: + { + if (debug) Rcpp::Rcout << "BrtDVal" << std::endl; + + uint32_t flags = 0; + std::vector sqrfx; + std::string strErrorTitle = "", strError = "", strPromptTitle = "", strPrompt = ""; + + flags = readbin(flags, bin, swapit); + + BrtDValFields *fields = (BrtDValFields *)&flags; + + sqrfx = UncheckedSqRfX(bin, swapit); + strErrorTitle = XLNullableWideString(bin, swapit); + strError = XLNullableWideString(bin, swapit); + strPromptTitle = XLNullableWideString(bin, swapit); + strPrompt = XLNullableWideString(bin, swapit); + + int sharedFormula = false; + std::string formula1 = CellParsedFormula(bin, swapit, debug, 0, 0, sharedFormula, has_revision_record); + std::string formula2 = CellParsedFormula(bin, swapit, debug, 0, 0, sharedFormula, has_revision_record); + + std::string lref = int_to_col(sqrfx[3] + 1) + std::to_string(sqrfx[1] + 1); + std::string rref = int_to_col(sqrfx[4] + 1) + std::to_string(sqrfx[2] + 1); + + std::string sqref; + if (lref.compare(rref) == 0) { + sqref = lref; + } else { + sqref = lref + ":" + rref; + } + + out << "valType) << "\" " << + "operator=\"" << typOperator(fields->typOperator) << "\" " << + "allowBlank=\"" << (bool)fields->fAllowBlank << "\" " << + "showInputMessage=\"" << (bool)fields->fShowInputMsg << "\" " << + "showErrorMessage=\"" << (bool)fields->fShowErrorMsg << "\" " << + "sqref=\"" << sqref << "\" >" << + "" << formula1 << "" << + "" << formula2 << "" << + "" << std::endl; + + break; + } + case BrtDValList: - case BrtBeginDCon: - case BrtEndDCon: + { + Rcpp::Rcout << "BrtDValList" << std::endl; + + std::string strDvalList = XLWideString(bin, swapit); + Rcpp::Rcout << strDvalList << std::endl; + + break; + } + case BrtEndDVals: + { + if (debug) Rcpp::Rcout << "BrtEndDVals" << std::endl; + out << "" << std::endl; + bin.seekg(size, bin.cur); + break; + } + + case BrtBeginDVals14: + { + if (debug) Rcpp::Rcout << "BrtBeginDVals14" << std::endl; + // Rcpp::warning("Worksheet contains unhandled data validation."); + + // FRT blank + uint32_t reserved = 0; + reserved = readbin(reserved, bin, swapit); + + // Dvals + uint16_t flags = 0; + uint32_t xLeft = 0, yTop = 0, unused3 = 0, idvMac = 0; + + // openxlsx2 does not handle this? + flags = readbin(flags, bin, swapit); + xLeft = readbin(xLeft, bin, swapit); + yTop = readbin(yTop, bin, swapit); + unused3 = readbin(unused3, bin, swapit); + idvMac = readbin(idvMac, bin, swapit); + + if (idvMac > 65534) Rcpp::stop("idvMac to big"); + + out << "" << std::endl; + + break; + } + + case BrtDVal14: + { + if (debug) Rcpp::Rcout << "BrtDVal14" << std::endl; + + // Start FRTHeader + uint32_t flags_frt = 0; + std::vector frt_sqrefs; + std::vector frt_fmls; + + flags_frt = readbin(flags_frt, bin, swapit); + + FRTHeaderFields *fields_frt = (FRTHeaderFields *)&flags_frt; + + if (fields_frt->fRef) { // but must be 0 + // Rcpp::Rcout << "fRef" << std::endl; + uint32_t cref = 0; + cref = readbin(cref, bin, swapit); + // Rcpp::Rcout << "Refs: " << cref << std::endl; + + for (uint32_t crf = 0; crf < cref; ++crf) { + uint32_t flags_cref = 0; + flags_cref = readbin(flags_cref, bin, swapit); + std::vector rfx_cref = UncheckedRfX(bin, swapit); + } + + } + + if (fields_frt->fSqref) { // must be 1 + // Rcpp::Rcout << "fSqref" << std::endl; + uint32_t csqref = 0; + csqref = readbin(csqref, bin, swapit); + // Rcpp::Rcout << "Sqrefs: " << csqref << std::endl; + + for (uint32_t csqrf = 0; csqrf < csqref; ++csqrf) { + uint32_t flags_csqrf = 0; + flags_csqrf = readbin(flags_csqrf, bin, swapit); + + /* beg move this to function -------------------------------------*/ + std::vector rfx_csqrfx = UncheckedSqRfX(bin, swapit); + + std::string lref = int_to_col(rfx_csqrfx[3] + 1) + std::to_string(rfx_csqrfx[1] + 1); + std::string rref = int_to_col(rfx_csqrfx[4] + 1) + std::to_string(rfx_csqrfx[2] + 1); + + std::string sqref; + if (lref.compare(rref) == 0) { + sqref = lref; + } else { + sqref = lref + ":" + rref; + } + /* end move this to function -------------------------------------*/ + + frt_sqrefs.push_back(sqref); + + } + + } + + if (fields_frt->fFormula) { // 0 or 1 + // Rcpp::Rcout << "fFormula" << std::endl; + uint32_t cformula = 0; + cformula = readbin(cformula, bin, swapit); + // Rcpp::Rcout << "Formulas: " << cformula << std::endl; + + for (uint32_t cfml = 0; cfml < cformula; ++cfml) { + uint32_t flags_cfml = 0; + flags_cfml = readbin(flags_cfml, bin, swapit); + int sharedFormula = false; + std::string frt_fml = FRTParsedFormula(bin, swapit, debug, 0, 0, sharedFormula, has_revision_record); + frt_fmls.push_back(frt_fml); + // Rcpp::Rcout << frt_fmls[cfml] << std::endl; + } + + } + + if (fields_frt->fRelID) { // 0 + // Rcpp::Rcout << "fRelID" << std::endl; + std::string relId = LPWideString(bin, swapit); + } + // End FRTHeader + + uint32_t flags = 0; + std::string strErrorTitle = "", strError = "", strPromptTitle = "", strPrompt = ""; + + flags = readbin(flags, bin, swapit); + + BrtDValFields *fields = (BrtDValFields *)&flags; + + + // if (debug) + // Rprintf("%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", + // (uint32_t)fields->valType, + // (uint32_t)fields->errStyle, + // (uint32_t)fields->unused, + // (uint32_t)fields->fAllowBlank, + // (uint32_t)fields->fSuppressCombo, + // (uint32_t)fields->mdImeMode, + // (uint32_t)fields->fShowInputMsg, + // (uint32_t)fields->fShowErrorMsg, + // (uint32_t)fields->typOperator, + // (uint32_t)fields->fDVMinFmla, + // (uint32_t)fields->fDVMaxFmla + // ); + + strErrorTitle = XLNullableWideString(bin, swapit); + strError = XLNullableWideString(bin, swapit); + strPromptTitle = XLNullableWideString(bin, swapit); + strPrompt = XLNullableWideString(bin, swapit); + + out << "valType) << "\" " << + "operator=\"" << typOperator(fields->typOperator) << "\" " << + "allowBlank=\"" << (bool)fields->fAllowBlank << "\" " << + "showInputMessage=\"" << (bool)fields->fShowInputMsg << "\" " << + "showErrorMessage=\"" << (bool)fields->fShowErrorMsg << "\" " << + // "xr:uid=\"{00000000-0002-0000-0200-000000000000}\" " << + ">"; + + for (size_t len = 0; len < frt_fmls.size(); ++len) { + + out << + "" << + "" << + frt_fmls[len] << + "" << + ""; + } + for (size_t len = 0; len < frt_fmls.size(); ++len) { + + out << + "" << + frt_sqrefs[len] << + ""; + } + + out << "" << std::endl; + + break; + } + case BrtEndDVals14: { + if (debug) Rcpp::Rcout << "BrtEndDVals14" << std::endl; + out << "" << std::endl; + bin.seekg(size, bin.cur); + break; + } + + + case BrtBeginDCon: + case BrtEndDCon: + { + if (debug) Rcpp::Rcout << "BrtBegin/EndDCon" << std::endl; bin.seekg(size, bin.cur); break; } @@ -3677,11 +3943,28 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo } // end unhandled page breaks - // TODO it is not correct to stop here for future records, but we ignore - // this segments currently. Otherwise the calendar_stress.xlsb - // file breaks. Somehow there are new blank cell and row header entries. case BrtFRTBegin: + { + if (debug) Rcpp::Rcout << "BrtFRTBegin" << std::endl; + + // we only handle this for data validation lists. + out << "" << + "" << + std::endl; + + ProductVersion(bin, swapit, debug); + + break; + } + case BrtFRTEnd: + { + if (debug) Rcpp::Rcout << "BrtFRTEnd" << std::endl; + out << "" << std::endl; + bin.seekg(size, bin.cur); + break; + } + case BrtEndSheet: { @@ -3711,6 +3994,7 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo case BrtCellIgnoreEC: case BrtEndCellIgnoreECs: { + if (debug) Rcpp::Rcout << "BrtBeginCell" << std::endl; // Rcpp::warning("Worksheet contains unhandled data validation."); bin.seekg(size, bin.cur); break; @@ -3749,6 +4033,7 @@ int worksheet_bin(std::string filePath, bool chartsheet, std::string outPath, bo case BrtSheetProtectionIso: case BrtCsProtection: { + if (debug) Rcpp::Rcout << "protection" << std::endl; // uint16_t protpwd = 0; // uint32_t fLocked = 0, fObjects = 0; // unhandled diff --git a/src/xlsb_defines.h b/src/xlsb_defines.h index e318a529e..73e762dfd 100644 --- a/src/xlsb_defines.h +++ b/src/xlsb_defines.h @@ -179,6 +179,33 @@ typedef struct { uint16_t unused : 13; } BrtWbPropFields; +typedef struct { + uint8_t valType : 4; + uint8_t errStyle : 3; + bool unused : 1; + bool fAllowBlank : 1; + bool fSuppressCombo : 1; + uint8_t mdImeMode : 8; + bool fShowInputMsg : 1; + bool fShowErrorMsg : 1; + uint8_t typOperator : 4; + bool fDVMinFmla : 1; // only in 14 + bool fDVMaxFmla : 1; // only in 14 + uint8_t reserved : 6; +} BrtDValFields; + +typedef struct { + uint16_t product : 15; + bool reserved : 1; +} FRTVersionFields; + +typedef struct { + bool fRef : 1; + bool fSqref : 1; + bool fFormula : 1; + bool fRelID : 1; + uint32_t reserved : 28; +} FRTHeaderFields; typedef struct { uint8_t columns : 2; diff --git a/src/xlsb_funs.h b/src/xlsb_funs.h index 6006b6a61..e6a3c0d7b 100644 --- a/src/xlsb_funs.h +++ b/src/xlsb_funs.h @@ -243,6 +243,13 @@ std::string PtrStr(std::istream& sas, bool swapit) { return read_xlwidestring(str, sas); } +std::string LPWideString(std::istream& sas, bool swapit) { + uint16_t len = 0; + len = readbin(len, sas, swapit); + std::string str(len, '\0'); + return read_xlwidestring(str, sas); +} + std::string XLWideString(std::istream& sas, bool swapit) { uint32_t len = 0; len = readbin(len, sas, swapit); @@ -568,15 +575,16 @@ std::string RichStr(std::istream& sas, bool swapit) { } void ProductVersion(std::istream& sas, bool swapit, bool debug) { - uint16_t fileVersion = 0, fileProduct = 0; - int8_t fileExtension = 0; - fileVersion = readbin(fileVersion, sas, swapit); - fileProduct = readbin(fileProduct, sas, swapit); + uint16_t version = 0, flags = 0; + version = readbin(version, sas, swapit); // 3586 - x14? + flags = readbin(flags, sas, swapit); // 0 + + FRTVersionFields *fields = (FRTVersionFields *)&flags; - fileExtension = fileProduct & 0x01; - fileProduct = fileProduct & ~static_cast(0x01); - if (debug) Rprintf("ProductVersion: %d: %d: %d\n", fileVersion, fileProduct, fileExtension); + // if (fields->reserved != 0) Rcpp::stop("product version reserved not 0"); + + if (debug) Rprintf("ProductVersion: %d: %d: %d\n", version, fields->product, fields->reserved); } std::vector UncheckedRfX(std::istream& sas, bool swapit) { @@ -1000,6 +1008,34 @@ std::string BErr(std::istream& sas, bool swapit) { return "unknown_ERROR"; } +std::string valType(uint8_t type) { + + if (type == 0x0) return "none"; + if (type == 0x1) return "whole"; + if (type == 0x2) return "decimal"; + if (type == 0x3) return "list"; + if (type == 0x4) return "date"; + if (type == 0x5) return "time"; + if (type == 0x6) return "textLength"; + if (type == 0x7) return "custom"; + + return "unknown_type"; +} + +std::string typOperator(uint8_t oprtr) { + + if (oprtr == 0x0) return "between"; + if (oprtr == 0x1) return "notBetween"; + if (oprtr == 0x2) return "equal"; + if (oprtr == 0x3) return "notEqual"; + if (oprtr == 0x4) return "greaterThan"; + if (oprtr == 0x5) return "lessThan"; + if (oprtr == 0x6) return "greaterThanOrEqual"; + if (oprtr == 0x7) return "lessThanOrEqual"; + + return "unknown_operator"; +} + std::vector Xti(std::istream& sas, bool swapit) { int32_t firstSheet = 0, lastSheet = 0; uint32_t externalLink = 0; @@ -1116,27 +1152,11 @@ std::string parseRPN(const std::string& expression) { return parsedFormula; } +std::string rgce(std::string fml_out, std::istream& sas, bool swapit, bool debug, int col, int row, int &sharedFml, bool has_revision_record, size_t pos, std::vector &ptgextra) { -std::string CellParsedFormula(std::istream& sas, bool swapit, bool debug, int col, int row, int &sharedFml, bool has_revision_record) { - // bool ptg_extra_array = false; - uint32_t cce= 0, cb= 0; - - if (debug) Rcpp::Rcout << "CellParsedFormula: " << sas.tellg() << std::endl; - - cce = readbin(cce, sas, swapit); - if (cce >= 16385) Rcpp::stop("wrong cce size"); - if (debug) Rcpp::Rcout << "cce: " << cce << std::endl; - size_t pos = sas.tellg(); - // sas.seekg(cce, sas.cur); - pos += cce; int8_t val1 = 0; - - // row = 0; - - std::vector ptgextra; - - std::string fml_out; - while((size_t)sas.tellg() < pos) { + // std::vector ptgextra; + while((size_t)sas.tellg() < pos) { if (debug) Rcpp::Rcout << "."; @@ -2048,25 +2068,13 @@ std::string CellParsedFormula(std::istream& sas, bool swapit, bool debug, int co sas.seekg(pos, sas.beg); } + return fml_out; +} - cb = readbin(cb, sas, swapit); // is there a control bit, even if CB is empty? - - if (debug) - Rcpp::Rcout << "cb: " << cb << std::endl; - - pos = sas.tellg(); - // sas.seekg(cce, sas.cur); - - pos += cb; - - if (debug) Rcpp::Rcout << "."; - if (debug) { - Rprintf("Formula cb: %d\n", val1); - Rprintf("%d: %d\n", (int)sas.tellg(), (int)pos); - } - - if (debug) Rcpp::Rcout << "--- formula ---\n" << fml_out << std::endl; +std::string rgcb(std::string fml_out, std::istream& sas, bool swapit, bool debug, int col, int row, int &sharedFml, bool has_revision_record, size_t pos, std::vector &ptgextra) { + int8_t val1 = 0; + // std::vector ptgextra; // RgbExtra for (size_t cntr = 0; cntr < ptgextra.size(); ++cntr) { @@ -2264,6 +2272,49 @@ std::string CellParsedFormula(std::istream& sas, bool swapit, bool debug, int co sas.seekg(pos, sas.beg); } + return fml_out; +} + + +std::string CellParsedFormula(std::istream& sas, bool swapit, bool debug, int col, int row, int &sharedFml, bool has_revision_record) { + // bool ptg_extra_array = false; + uint32_t cce= 0, cb= 0; + std::vector ptgextra; + + if (debug) Rcpp::Rcout << "CellParsedFormula: " << sas.tellg() << std::endl; + + cce = readbin(cce, sas, swapit); + if (cce >= 16385) Rcpp::stop("wrong cce size"); + if (debug) Rcpp::Rcout << "cce: " << cce << std::endl; + + size_t pos = sas.tellg(); + // sas.seekg(cce, sas.cur); + pos += cce; + + std::string fml_out; + + fml_out = rgce(fml_out, sas, swapit, debug, col, row, sharedFml, has_revision_record, pos, ptgextra); + + cb = readbin(cb, sas, swapit); // is there a control bit, even if CB is empty? + + if (debug) + Rcpp::Rcout << "cb: " << cb << std::endl; + + pos = sas.tellg(); + // sas.seekg(cce, sas.cur); + + pos += cb; + + if (debug) Rcpp::Rcout << "."; + if (debug) { + // Rprintf("Formula cb: %d\n", val1); + Rprintf("%d: %d\n", (int)sas.tellg(), (int)pos); + } + + if (debug) Rcpp::Rcout << "--- formula ---\n" << fml_out << std::endl; + + fml_out = rgcb(fml_out, sas, swapit, debug, col, row, sharedFml, has_revision_record, pos, ptgextra); + if (debug) { Rcpp::Rcout << "...fml..." << std::endl; Rcpp::Rcout << fml_out << std::endl; @@ -2274,4 +2325,51 @@ std::string CellParsedFormula(std::istream& sas, bool swapit, bool debug, int co return inflix; } +std::string FRTParsedFormula(std::istream& sas, bool swapit, bool debug, int col, int row, int &sharedFml, bool has_revision_record) { + // bool ptg_extra_array = false; + uint32_t cce= 0, cb= 0; + std::vector ptgextra; + + if (debug) Rcpp::Rcout << "CellParsedFormula: " << sas.tellg() << std::endl; + + cce = readbin(cce, sas, swapit); + if (cce >= 16385) Rcpp::stop("wrong cce size"); + if (debug) Rcpp::Rcout << "cce: " << cce << std::endl; + + cb = readbin(cb, sas, swapit); // is there a control bit, even if CB is empty? + + size_t pos = sas.tellg(); + pos += cce; + + std::string fml_out; + + fml_out = rgce(fml_out, sas, swapit, debug, col, row, sharedFml, has_revision_record, pos, ptgextra); + + if (debug) + Rcpp::Rcout << "cb: " << cb << std::endl; + + pos = sas.tellg(); + pos += cb; + + if (debug) Rcpp::Rcout << "."; + if (debug) { + Rprintf("%d: %d\n", (int)sas.tellg(), (int)pos); + } + + if (debug) Rcpp::Rcout << "--- formula ---\n" << fml_out << std::endl; + + fml_out = rgcb(fml_out, sas, swapit, debug, col, row, sharedFml, has_revision_record, pos, ptgextra); + + if (debug) { + Rcpp::Rcout << "...fml..." << std::endl; + Rcpp::Rcout << fml_out << std::endl; + } + + std::string inflix = parseRPN(fml_out); + + return inflix; +} + + + #endif