mirror of
https://git.gfz-potsdam.de/naaice/iphreeqc.git
synced 2025-12-15 16:18:22 +01:00
git-svn-id: svn://136.177.114.72/svn_GW/IPhreeqc/trunk@4106 1feff8c3-07ed-0310-ac33-dd36852eb9cd
456 lines
8.8 KiB
C++
456 lines
8.8 KiB
C++
// SelectedOutput.cpp: implementation of the CSelectedOutput class.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
#if defined(_DEBUG)
|
|
#pragma warning(disable : 4786) // disable truncation warning
|
|
#include <sstream> // std::ostringstream
|
|
#include <windows.h> // ::OutputDebugString
|
|
#endif
|
|
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
|
|
#include "SelectedOutput.hxx"
|
|
#include "phreeqcns.hxx"
|
|
|
|
const size_t RESERVE_ROWS = 80;
|
|
const size_t RESERVE_COLS = 80;
|
|
|
|
|
|
int EndRow(void);
|
|
void AddSelectedOutput(const char* name, const char* format, va_list argptr);
|
|
int warning_msg (const char *err_str);
|
|
|
|
int EndRow(void)
|
|
{
|
|
if (CSelectedOutput::Instance()->GetRowCount() <= 1) {
|
|
// ensure all user_punch headings are included
|
|
for (int i = n_user_punch_index; i < user_punch_count_headings; ++i) {
|
|
CSelectedOutput::Instance()->PushBackEmpty(user_punch_headings[i]);
|
|
}
|
|
}
|
|
return CSelectedOutput::Instance()->EndRow();
|
|
}
|
|
|
|
int PushBackDouble(const char* key, double dVal)
|
|
{
|
|
return CSelectedOutput::Instance()->PushBackDouble(key, dVal);
|
|
}
|
|
|
|
int PushBackLong(const char* key, long lVal)
|
|
{
|
|
return CSelectedOutput::Instance()->PushBackLong(key, lVal);
|
|
}
|
|
|
|
int PushBackString(const char* key, const char* sVal)
|
|
{
|
|
return CSelectedOutput::Instance()->PushBackString(key, sVal);
|
|
}
|
|
|
|
int PushBackEmpty(const char* key)
|
|
{
|
|
return CSelectedOutput::Instance()->PushBackEmpty(key);
|
|
}
|
|
|
|
|
|
void AddSelectedOutput(const char* name, const char* format, va_list argptr)
|
|
{
|
|
int bInt;
|
|
int bDouble;
|
|
int bString;
|
|
|
|
int state;
|
|
int bLongDouble;
|
|
char ch;
|
|
|
|
|
|
/* state values
|
|
0 Haven't found start(%)
|
|
1 Just read start(%)
|
|
2 Just read Flags(-0+ #) (zero or more)
|
|
3 Just read Width
|
|
4 Just read Precision start (.)
|
|
5 Just read Size modifier
|
|
6 Just read Type
|
|
*/
|
|
|
|
if (name == NULL) {
|
|
return;
|
|
}
|
|
|
|
bDouble = 0;
|
|
bInt = 0;
|
|
bString = 0;
|
|
|
|
bLongDouble = 0;
|
|
|
|
state = 0;
|
|
ch = *format++;
|
|
while (ch != '\0') {
|
|
switch (state) {
|
|
case 0: /* looking for Start specification (%) */
|
|
switch (ch) {
|
|
case '%':
|
|
state = 1;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
ch = *format++;
|
|
break;
|
|
case 1: /* reading Flags (zero or more(-,+,0,# or space)) */
|
|
switch (ch) {
|
|
case '-': case '0': case '+': case ' ': case '#':
|
|
ch = *format++;
|
|
break;
|
|
default:
|
|
state = 2;
|
|
break;
|
|
}
|
|
break;
|
|
case 2: /* reading Minimum field width (decimal integer constant) */
|
|
switch (ch) {
|
|
case '.':
|
|
state = 3;
|
|
ch = *format++;
|
|
break;
|
|
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
|
|
ch = *format++;
|
|
break;
|
|
default:
|
|
state = 4;
|
|
break;
|
|
}
|
|
break;
|
|
case 3: /* reading Precision specification (period already read) */
|
|
switch (ch)
|
|
{
|
|
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
|
|
ch = *format++;
|
|
break;
|
|
default:
|
|
state = 4;
|
|
break;
|
|
}
|
|
break;
|
|
case 4: /* reading Size modifier */
|
|
switch (ch)
|
|
{
|
|
case 'l':
|
|
ch = *format++;
|
|
break;
|
|
case 'L':
|
|
bLongDouble = 1;
|
|
ch = *format++;
|
|
break;
|
|
case 'h':
|
|
ch = *format++;
|
|
break;
|
|
}
|
|
state = 5;
|
|
break;
|
|
case 5: /* reading Conversion letter */
|
|
switch (ch) {
|
|
case 'c':
|
|
break;
|
|
case 'd':
|
|
case 'i':
|
|
bInt = 1;
|
|
break;
|
|
case 'n':
|
|
case 'o':
|
|
case 'p':
|
|
break;
|
|
case 's':
|
|
bString = 1;
|
|
break;
|
|
case 'u':
|
|
case 'x':
|
|
case 'X':
|
|
case '%':
|
|
break;
|
|
case 'f':
|
|
case 'e':
|
|
case 'E':
|
|
case 'g':
|
|
case 'G':
|
|
bDouble = 1;
|
|
break;
|
|
default:
|
|
ASSERT(false);
|
|
break;
|
|
}
|
|
ch = '\0'; /* done */
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (bDouble) {
|
|
double valDouble;
|
|
|
|
if (bLongDouble) {
|
|
valDouble = (double)va_arg(argptr, long double);
|
|
}
|
|
else {
|
|
valDouble = va_arg(argptr, double);
|
|
}
|
|
|
|
CSelectedOutput::Instance()->PushBackDouble(name, valDouble);
|
|
}
|
|
else if (bInt) {
|
|
int valInt;
|
|
valInt = va_arg(argptr, int);
|
|
|
|
CSelectedOutput::Instance()->PushBackLong(name, (long)valInt);
|
|
}
|
|
else if (bString) {
|
|
char* valString;
|
|
valString = (char *)va_arg(argptr, char *);
|
|
|
|
CSelectedOutput::Instance()->PushBackString(name, valString);
|
|
}
|
|
else {
|
|
ASSERT(false);
|
|
CSelectedOutput::Instance()->PushBackEmpty(name);
|
|
}
|
|
}
|
|
|
|
// COMMENT: {11/16/2004 10:18:22 PM}CSelectedOutput CSelectedOutput::singleton;
|
|
CSelectedOutput* CSelectedOutput::s_instance = 0;
|
|
|
|
CSelectedOutput* CSelectedOutput::Instance()
|
|
{
|
|
if (s_instance == 0)
|
|
{
|
|
s_instance = new CSelectedOutput;
|
|
}
|
|
return s_instance;
|
|
}
|
|
|
|
void CSelectedOutput::Release()
|
|
{
|
|
if (s_instance)
|
|
{
|
|
delete s_instance;
|
|
s_instance = 0;
|
|
}
|
|
}
|
|
|
|
CSelectedOutput::CSelectedOutput()
|
|
: m_nRowCount(0)
|
|
{
|
|
this->m_arrayVar.reserve(RESERVE_COLS);
|
|
}
|
|
|
|
CSelectedOutput::~CSelectedOutput()
|
|
{
|
|
}
|
|
|
|
void CSelectedOutput::Clear(void)
|
|
{
|
|
this->m_nRowCount = 0;
|
|
this->m_vecVarHeadings.clear();
|
|
this->m_arrayVar.clear();
|
|
this->m_mapHeadingToCol.clear();
|
|
}
|
|
|
|
size_t CSelectedOutput::GetRowCount(void)const
|
|
{
|
|
if (this->GetColCount())
|
|
{
|
|
return this->m_nRowCount + 1; // rows + heading
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
size_t CSelectedOutput::GetColCount(void)const
|
|
{
|
|
return this->m_vecVarHeadings.size();
|
|
}
|
|
|
|
CVar CSelectedOutput::Get(int nRow, int nCol)const
|
|
{
|
|
CVar v;
|
|
this->Get(nRow, nCol, &v);
|
|
return v;
|
|
}
|
|
|
|
VRESULT CSelectedOutput::Get(int nRow, int nCol, VAR* pVAR)const
|
|
{
|
|
if ((size_t)nRow >= this->GetRowCount() || (size_t)nRow < 0) {
|
|
pVAR->type = TT_ERROR;
|
|
pVAR->vresult = VR_INVALIDROW;
|
|
return pVAR->vresult;
|
|
}
|
|
if ((size_t)nCol >= this->GetColCount() || (size_t)nCol < 0) {
|
|
pVAR->type = TT_ERROR;
|
|
pVAR->vresult = VR_INVALIDCOL;
|
|
return pVAR->vresult;
|
|
}
|
|
if (nRow)
|
|
{
|
|
ASSERT((size_t)nRow <= this->m_arrayVar[nCol].size());
|
|
return ::VarCopy(pVAR, &(this->m_arrayVar[nCol])[nRow - 1]);
|
|
}
|
|
else
|
|
{
|
|
return ::VarCopy(pVAR, &(this->m_vecVarHeadings[nCol]));
|
|
}
|
|
}
|
|
|
|
|
|
int CSelectedOutput::EndRow(void)
|
|
{
|
|
if (size_t ncols = this->GetColCount())
|
|
{
|
|
++this->m_nRowCount;
|
|
|
|
// make sure array is full
|
|
for (size_t col = 0; col < ncols; ++col)
|
|
{
|
|
for (size_t row = 0; row < this->m_nRowCount; ++row)
|
|
{
|
|
size_t nrows = this->m_arrayVar[col].size();
|
|
if (nrows < this->m_nRowCount)
|
|
{
|
|
// fill w/ empty
|
|
this->m_arrayVar[col].resize(this->m_nRowCount);
|
|
}
|
|
#if defined(_DEBUG)
|
|
else if (nrows > this->m_nRowCount)
|
|
{
|
|
ASSERT(false);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
// COMMENT: {11/27/2006 7:22:37 PM}#if defined(_DEBUG)
|
|
// COMMENT: {11/27/2006 7:22:37 PM} this->AssertValid();
|
|
// COMMENT: {11/27/2006 7:22:37 PM}#endif
|
|
return 0;
|
|
}
|
|
|
|
int CSelectedOutput::PushBack(const char* key, const CVar& var)
|
|
{
|
|
try
|
|
{
|
|
// check if key is new
|
|
std::map< std::string, size_t >::iterator find;
|
|
find = this->m_mapHeadingToCol.find(std::string(key));
|
|
if (find == this->m_mapHeadingToCol.end())
|
|
{
|
|
// new key(column)
|
|
//
|
|
this->m_mapHeadingToCol.insert(std::map< std::string, size_t >::value_type(std::string(key),
|
|
this->m_mapHeadingToCol.size()) );
|
|
|
|
// add heading
|
|
//
|
|
this->m_vecVarHeadings.push_back(CVar(key));
|
|
|
|
|
|
// add new vector(col)
|
|
//
|
|
this->m_arrayVar.resize(this->m_arrayVar.size() + 1);
|
|
this->m_arrayVar.back().reserve(RESERVE_ROWS);
|
|
|
|
// add empty rows if nec
|
|
if (this->m_nRowCount)
|
|
this->m_arrayVar.back().resize(this->m_nRowCount);
|
|
|
|
this->m_arrayVar.back().push_back(var);
|
|
}
|
|
else
|
|
{
|
|
if (this->m_arrayVar[find->second].size() == this->m_nRowCount) {
|
|
this->m_arrayVar[find->second].push_back(var);
|
|
}
|
|
else {
|
|
ASSERT(this->m_arrayVar[find->second].size() == this->m_nRowCount + 1);
|
|
this->m_arrayVar[find->second].at(this->m_nRowCount) = var;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
catch(...)
|
|
{
|
|
ASSERT(false);
|
|
}
|
|
return 1; // error
|
|
}
|
|
|
|
|
|
int CSelectedOutput::PushBackDouble(const char* key, double value)
|
|
{
|
|
CVar v(value);
|
|
return this->PushBack(key, v);
|
|
}
|
|
|
|
int CSelectedOutput::PushBackLong(const char* key, long value)
|
|
{
|
|
CVar v(value);
|
|
return this->PushBack(key, v);
|
|
}
|
|
|
|
int CSelectedOutput::PushBackString(const char* key, const char* value)
|
|
{
|
|
CVar v(value);
|
|
return this->PushBack(key, v);
|
|
}
|
|
|
|
int CSelectedOutput::PushBackEmpty(const char* key)
|
|
{
|
|
CVar v;
|
|
return this->PushBack(key, v);
|
|
}
|
|
|
|
#if defined(_DEBUG)
|
|
void CSelectedOutput::Dump(const char* heading)
|
|
{
|
|
::OutputDebugStringA(heading);
|
|
std::ostringstream oss;
|
|
oss << *this;
|
|
std::istringstream iss(oss.str());
|
|
std::string line;
|
|
while (std::getline(iss, line)) {
|
|
::OutputDebugStringA(line.c_str());
|
|
::OutputDebugStringA("\n");
|
|
}
|
|
}
|
|
|
|
void CSelectedOutput::AssertValid(void)const
|
|
{
|
|
if (size_t cols = this->GetColCount())
|
|
{
|
|
size_t rows = this->m_arrayVar[0].size();
|
|
for (size_t col = 0; col < cols; ++col)
|
|
{
|
|
ASSERT(rows == this->m_arrayVar[col].size());
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
std::ostream& operator<< (std::ostream &os, const CSelectedOutput &a)
|
|
{
|
|
#if defined(_WIN32)
|
|
os << "CSelectedOutput(rows=" << a.GetRowCount() << ", cols=" << a.GetColCount() << ")\n";
|
|
#endif
|
|
|
|
CVar v;
|
|
for (size_t r = 0; r < a.GetRowCount(); ++r) {
|
|
for (size_t c = 0; c < a.GetColCount(); ++c) {
|
|
a.Get((int)r, (int)c, &v);
|
|
os << v << ", ";
|
|
::VarClear(&v);
|
|
}
|
|
os << "\n";
|
|
}
|
|
os << "\n";
|
|
return os;
|
|
}
|