diff --git a/scopeprotocols/CSVImportFilter.cpp b/scopeprotocols/CSVImportFilter.cpp index d009f2d3..2ebcd298 100644 --- a/scopeprotocols/CSVImportFilter.cpp +++ b/scopeprotocols/CSVImportFilter.cpp @@ -69,7 +69,7 @@ string CSVImportFilter::GetProtocolName() void CSVImportFilter::OnFileNameChanged() { - auto fname = m_parameters[m_fpname].ToString(); +auto fname = m_parameters[m_fpname].ToString(); if(fname.empty()) return; @@ -103,6 +103,8 @@ void CSVImportFilter::OnFileNameChanged() if(flen != fread(buf, 1, flen, fp)) { LogError("file read error\n"); + delete[] buf; + fclose(fp); return; } buf[flen] = '\0'; //guarantee null termination at end of file @@ -115,15 +117,16 @@ void CSVImportFilter::OnFileNameChanged() vector names; vector< vector > vcolumns; vector timestamps; - bool digilentFormat; + bool digilentFormat = false; size_t nrow = 0; size_t ncols = 0; char* pbuf = buf; char* pend = buf + flen; bool xUnitIsFs = m_parameters[m_xunit].GetIntVal() == Unit::UNIT_FS; - while(true) + + while(pbuf < pend) // Modify loop stop conditions { - nrow ++; + nrow++; //Stop if at end of file char* pline = pbuf; @@ -131,13 +134,15 @@ void CSVImportFilter::OnFileNameChanged() break; //Find first non-blank character in the current line - while(isspace(*pline)) - pline ++; + while(pline < pend && isspace(*pline) && *pline != '\n' && *pline != '\r') + pline++; - //If it's a newline or nul, the line was blank - discard it - if( (*pline == '\0') || (*pline == '\n') || (*pline == '\r') ) + //If we've reached the end or the line starts with newline characters, it's a blank line - discard it + if(pline >= pend || *pline == '\0' || *pline == '\n' || *pline == '\r') { - pbuf ++; + // Skip all consecutive line breaks + while(pbuf < pend && (*pbuf == '\n' || *pbuf == '\r')) + pbuf++; continue; } @@ -145,15 +150,26 @@ void CSVImportFilter::OnFileNameChanged() size_t slen = 0; for(; (pline + slen) < pend; slen++) { - if(pline[slen] == '\0') + char current_char = pline[slen]; + if(current_char == '\0') break; - if( (pline[slen] == '\n') || (pline[slen] == '\r') ) + if(current_char == '\n' || current_char == '\r') { - pline[slen] = '\0'; + // Process \r\n sequence + if(current_char == '\r' && (pline + slen + 1) < pend && pline[slen+1] == '\n') + { + pline[slen] = '\0'; + pline[slen+1] = '\0'; + slen++; // Extra Skip \n + } + else + { + pline[slen] = '\0'; + } break; } } - pbuf += slen; + pbuf += slen + 1; // +1 Skip line breaks //If the line starts with a #, it's a comment. Discard it, but save timestamp metadata if present if(pline[0] == '#') @@ -164,7 +180,6 @@ void CSVImportFilter::OnFileNameChanged() digilentFormat = true; LogTrace("Found Digilent metadata header\n"); } - else if(digilentFormat) { if(s.find("#Date Time: ") == 0) @@ -214,10 +229,12 @@ void CSVImportFilter::OnFileNameChanged() vector headerfields; bool headerRow = false; size_t ncol = 0; - for(size_t i=0; i<=slen; i++) + size_t line_length = strlen(pline); // Use actual string length + + for(size_t i=0; i<=line_length; i++) { //End of field - if( (pline[i] == ',') || (pline[i] == '\n') || (pline[i] == '\r') || (pline[i] == '\0') ) + if(pline[i] == ',' || pline[i] == '\0') { //If this is the first row, check if it's numeric if(names.empty() && timestamps.empty()) @@ -225,14 +242,14 @@ void CSVImportFilter::OnFileNameChanged() //See if it's a header row if(!headerRow) { - for(size_t j=0; pline[j] != '\0'; j++) + for(size_t j=fieldstart; j