cwPianoScore.cpp: Added CSV reader.
This commit is contained in:
parent
8e1c3e4b8d
commit
53dfdbc2a5
198
cwPianoScore.cpp
198
cwPianoScore.cpp
@ -6,6 +6,7 @@
|
|||||||
#include "cwPianoScore.h"
|
#include "cwPianoScore.h"
|
||||||
#include "cwMidi.h"
|
#include "cwMidi.h"
|
||||||
#include "cwTime.h"
|
#include "cwTime.h"
|
||||||
|
#include "cwFile.h"
|
||||||
|
|
||||||
namespace cw
|
namespace cw
|
||||||
{
|
{
|
||||||
@ -38,6 +39,189 @@ namespace cw
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned _scan_to_end_of_field( const char* lineBuf, unsigned buf_idx, unsigned bufCharCnt )
|
||||||
|
{
|
||||||
|
for(; buf_idx < bufCharCnt; ++buf_idx )
|
||||||
|
{
|
||||||
|
if( lineBuf[buf_idx] == '"' )
|
||||||
|
{
|
||||||
|
for(++buf_idx; buf_idx < bufCharCnt; ++buf_idx)
|
||||||
|
if( lineBuf[buf_idx] == '"' )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( lineBuf[buf_idx] == ',')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf_idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
rc_t _parse_csv_double( const char* lineBuf, unsigned bfi, unsigned efi, double &valueRef )
|
||||||
|
{
|
||||||
|
errno = 0;
|
||||||
|
valueRef = strtod(lineBuf+bfi,nullptr);
|
||||||
|
if( errno != 0 )
|
||||||
|
return cwLogError(kOpFailRC,"CSV String to number conversion failed.");
|
||||||
|
|
||||||
|
return kOkRC;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t _parse_csv_unsigned( const char* lineBuf, unsigned bfi, unsigned efi, unsigned &valueRef )
|
||||||
|
{
|
||||||
|
rc_t rc;
|
||||||
|
double v;
|
||||||
|
if((rc = _parse_csv_double(lineBuf,bfi,efi,v)) == kOkRC )
|
||||||
|
valueRef = (unsigned)v;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t _parse_csv_line( score_t* p, event_t* e, char* line_buf, unsigned lineBufCharCnt )
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
kMeas_FIdx,
|
||||||
|
kIndex_FIdx,
|
||||||
|
kVoice_FIdx,
|
||||||
|
kLoc_FIdx,
|
||||||
|
kTick_FIdx,
|
||||||
|
kSec_FIdx,
|
||||||
|
kDur_FIdx,
|
||||||
|
kRval_FIdx,
|
||||||
|
kSPitch_FIdx,
|
||||||
|
kDMark_FIdx,
|
||||||
|
kDLevel_FIdx,
|
||||||
|
kStatus_FIdx,
|
||||||
|
kD0_FIdx,
|
||||||
|
kD1_FIdx,
|
||||||
|
kBar_FIdx,
|
||||||
|
kSection_FIdx,
|
||||||
|
kBpm_FIdx,
|
||||||
|
kGrace_FIdx,
|
||||||
|
kPedal_FIdx,
|
||||||
|
kMax_FIdx
|
||||||
|
};
|
||||||
|
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
unsigned bfi = 0;
|
||||||
|
unsigned efi = 0;
|
||||||
|
unsigned field_idx = 0;
|
||||||
|
|
||||||
|
|
||||||
|
for(field_idx=0; field_idx != kMax_FIdx; ++field_idx)
|
||||||
|
{
|
||||||
|
if((efi = _scan_to_end_of_field(line_buf,efi,lineBufCharCnt)) == kInvalidIdx )
|
||||||
|
{
|
||||||
|
rc = cwLogError( rc, "End of field scan failed");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( bfi != efi )
|
||||||
|
{
|
||||||
|
switch( field_idx )
|
||||||
|
{
|
||||||
|
case kLoc_FIdx:
|
||||||
|
rc = _parse_csv_unsigned( line_buf, bfi, efi, e->loc );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kSec_FIdx:
|
||||||
|
rc = _parse_csv_double( line_buf, bfi, efi, e->sec );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kStatus_FIdx:
|
||||||
|
rc = _parse_csv_unsigned( line_buf, bfi, efi, e->status );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kD0_FIdx:
|
||||||
|
rc = _parse_csv_unsigned( line_buf, bfi, efi, e->d0 );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kD1_FIdx:
|
||||||
|
rc = _parse_csv_unsigned( line_buf, bfi, efi, e->d1 );
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bfi = efi + 1;
|
||||||
|
efi = efi + 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
rc_t _parse_csv( score_t* p, const char* fn )
|
||||||
|
{
|
||||||
|
rc_t rc;
|
||||||
|
file::handle_t fH;
|
||||||
|
unsigned line_count = 0;
|
||||||
|
char* lineBufPtr = nullptr;
|
||||||
|
unsigned lineBufCharCnt = 0;
|
||||||
|
|
||||||
|
if((rc = file::open( fH, fn, file::kReadFl )) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError( rc, "Piano score file open failed on '%s'.",cwStringNullGuard(fn));
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((rc = file::lineCount(fH,&line_count)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError( rc, "Line count query failed on '%s'.",cwStringNullGuard(fn));
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for(unsigned line=0; line<line_count; ++line)
|
||||||
|
if( line > 0 ) // skip column title line
|
||||||
|
{
|
||||||
|
event_t* e = mem::allocZ<event_t>();
|
||||||
|
|
||||||
|
if((rc = getLineAuto( fH, &lineBufPtr, &lineBufCharCnt )) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError( rc, "Line read failed on '%s' line number '%i'.",cwStringNullGuard(fn),line+1);
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((rc = _parse_csv_line( p, e, lineBufPtr, lineBufCharCnt )) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError( rc, "Line parse failed on '%s' line number '%i'.",cwStringNullGuard(fn),line+1);
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// assign the UID
|
||||||
|
e->uid = line;
|
||||||
|
|
||||||
|
// link the event into the event list
|
||||||
|
if( p->end != nullptr )
|
||||||
|
p->end->link = e;
|
||||||
|
else
|
||||||
|
p->base = e;
|
||||||
|
|
||||||
|
p->end = e;
|
||||||
|
|
||||||
|
// track the max 'loc' id
|
||||||
|
if( e->loc > p->maxLocId )
|
||||||
|
p->maxLocId = e->loc;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
mem::release(lineBufPtr);
|
||||||
|
file::close(fH);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
rc_t _parse_event_list( score_t* p, const object_t* cfg )
|
rc_t _parse_event_list( score_t* p, const object_t* cfg )
|
||||||
{
|
{
|
||||||
rc_t rc;
|
rc_t rc;
|
||||||
@ -136,11 +320,13 @@ cw::rc_t cw::score::create( handle_t& hRef, const char* fn )
|
|||||||
{
|
{
|
||||||
rc_t rc;
|
rc_t rc;
|
||||||
object_t* cfg = nullptr;
|
object_t* cfg = nullptr;
|
||||||
|
score_t* p = nullptr;
|
||||||
|
|
||||||
if((rc = destroy(hRef)) != kOkRC )
|
if((rc = destroy(hRef)) != kOkRC )
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
// parse the cfg file
|
// parse the cfg file
|
||||||
|
/*
|
||||||
if((rc = objectFromFile( fn, cfg )) != kOkRC )
|
if((rc = objectFromFile( fn, cfg )) != kOkRC )
|
||||||
{
|
{
|
||||||
rc = cwLogError(rc,"Score parse failed on file: '%s'.", fn);
|
rc = cwLogError(rc,"Score parse failed on file: '%s'.", fn);
|
||||||
@ -148,12 +334,22 @@ cw::rc_t cw::score::create( handle_t& hRef, const char* fn )
|
|||||||
}
|
}
|
||||||
|
|
||||||
rc = create(hRef,cfg);
|
rc = create(hRef,cfg);
|
||||||
|
*/
|
||||||
|
|
||||||
errLabel:
|
p = mem::allocZ< score_t >();
|
||||||
|
|
||||||
|
rc = _parse_csv(p,fn);
|
||||||
|
|
||||||
|
hRef.set(p);
|
||||||
|
|
||||||
|
//errLabel:
|
||||||
|
|
||||||
if( cfg != nullptr )
|
if( cfg != nullptr )
|
||||||
cfg->free();
|
cfg->free();
|
||||||
|
|
||||||
|
if( rc != kOkRC )
|
||||||
|
destroy(hRef);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user