#include "gdcmMrProtocol.h"
#include <map>
#include <string>
#if defined(_MSC_VER) && (_MSC_VER < 1900)
#define snprintf _snprintf
#endif
namespace gdcm
{
struct MrProtocol::Element {
};
using MyMapType = std::map<std::string, std::string>;
struct MrProtocol::Internals {
MyMapType mymap;
std::string csastr;
int version;
};
static inline bool starts_with(const std::string& s1, const std::string& s2)
{
return s2.size() <= s1.size() && s1.compare(0, s2.size(), s2) == 0;
}
MrProtocol::MrProtocol()
{
Pimpl = new MrProtocol::Internals;
}
bool MrProtocol::Load( const ByteValue * bv, const char * csastr, int version )
{
if( bv )
{
std::string str(bv->GetPointer(), bv->GetLength());
std::istringstream is(str);
std::string s;
Pimpl->version = version;
if( csastr ) Pimpl->csastr = csastr;
else Pimpl->csastr = "";
MyMapType &mymap = Pimpl->mymap;
mymap.clear();
static const char begin[] = "### ASCCONV BEGIN ";
static const char begin2[] = "\"### ASCCONV BEGIN ";
static const char end[] = "### ASCCONV END ###";
bool hasstarted = false;
while( std::getline(is, s ) )
{
if( !hasstarted )
{
s.erase(0, s.find_first_not_of(' '));
hasstarted = starts_with(s, begin) || starts_with(s, begin2);
if( hasstarted ) {
if( version == -1 ) {
static const char vers[] = "version=";
std::string::size_type p = s.find(vers);
if ( p != std::string::npos) {
const char *v = s.c_str() + p + sizeof(vers) - 1;
Pimpl->version = atoi(v);
}
}
continue; }
}
if( !hasstarted ) continue;
if( starts_with(s, end) ) break;
std::string::size_type pos = s.find( '=' );
if( pos != std::string::npos )
{
std::string sub1 = s.substr(0, pos);
sub1.erase( sub1.find_last_not_of(" \t") + 1);
std::string sub2 = s.substr(pos+1); sub2.erase( 0, sub2.find_first_not_of(" \t"));
mymap.insert( MyMapType::value_type(sub1, sub2) );
}
else
{
}
}
}
else
{
Pimpl->version = 0;
Pimpl->csastr = "";
Pimpl->mymap.clear();
return false;
}
return true;
}
MrProtocol::~MrProtocol()
{
delete Pimpl;
}
int MrProtocol::GetVersion() const
{
return Pimpl->version;
}
static inline std::string trim(std::string str)
{
str.erase(0, str.find_first_not_of('"'));
str.erase(str.find_last_not_of('"')+1);
return str;
}
void MrProtocol::Print(std::ostream &os) const
{
{
os << Pimpl->csastr << " / Version: " << Pimpl->version << std::endl;
os << std::endl;
MyMapType &mymap = Pimpl->mymap;
for( MyMapType::const_iterator it = mymap.begin();
it != mymap.end(); ++it)
{
os << it->first << " : " << trim(std::string(it->second)) << std::endl;
}
}
}
const char * MrProtocol::GetMrProtocolByName(const char *name) const
{
if( name )
{
MyMapType &mymap = Pimpl->mymap;
MyMapType::const_iterator it = mymap.find ( name );
if( it == mymap.end() ) return nullptr;
return it->second.c_str();
}
return nullptr;
}
bool MrProtocol::FindMrProtocolByName(const char *name) const
{
if( name )
{
MyMapType &mymap = Pimpl->mymap;
MyMapType::const_iterator it = mymap.find ( name );
if( it != mymap.end() ) return true;
}
return false;
}
bool MrProtocol::GetSliceArray( MrProtocol::SliceArray & sa ) const
{
sa.Slices.clear();
static const char saSize[] = "sSliceArray.lSize";
const char * sizestr = GetMrProtocolByName(saSize);
if( sizestr == nullptr ) return false;
const int size = atoi( sizestr );
sa.Slices.resize( size );
char buf[512];
static const char templ1[] = "sSliceArray.asSlice[%d].sPosition.%s";
static const char templ2[] = "sSliceArray.asSlice[%d].sNormal.%s";
static const char *dir[3] = { "dSag", "dCor", "dTra"};
for( int i = 0; i < size; ++i )
{
Slice & slice = sa.Slices[i];
{
double v[3];
for( int j = 0; j < 3; ++j )
{
snprintf( buf, sizeof(buf), templ1, i, dir[j] );
const char * valstr = GetMrProtocolByName(buf);
double val = 0.0;
if( valstr ) val = atof( valstr );
v[j] = val;
}
Vector3 & pos = slice.Position;
pos.dSag = v[0];
pos.dCor = v[1];
pos.dTra = v[2];
}
{
double v[3];
for( int j = 0; j < 3; ++j )
{
snprintf( buf, sizeof(buf), templ2, i, dir[j] );
const char * valstr = GetMrProtocolByName(buf);
double val = 0.0;
if( valstr ) val = atof( valstr );
v[j] = val;
}
Vector3 & pos = slice.Normal;
pos.dSag = v[0];
pos.dCor = v[1];
pos.dTra = v[2];
}
}
return true;
}
}