#include "IpoptConfig.h"
#include "IpJournalist.hpp"
#include "IpDebug.hpp"
#include <cstdio>
#include <cstring>
namespace Ipopt
{
Journalist::Journalist()
{ }
Journalist::~Journalist()
{
journals_.clear();
}
void Journalist::Printf(
EJournalLevel level,
EJournalCategory category,
const char* pformat,
...
) const
{
va_list ap;
va_start(ap, pformat);
VPrintf(level, category, pformat, ap);
va_end(ap);
}
void Journalist::PrintStringOverLines(
EJournalLevel level,
EJournalCategory category,
Index indent_spaces,
Index max_length,
const std::string& line
) const
{
DBG_ASSERT(indent_spaces + max_length + 1 < 1024);
char buffer[1024];
std::string::size_type last_line_pos = 0;
std::string::size_type last_word_pos = 0;
bool first_line = true;
Index buffer_pos = 0;
while( last_line_pos < line.length() )
{
std::string::size_type line_pos = last_line_pos;
Index curr_length = 0;
while( curr_length < max_length && line_pos < line.length() )
{
buffer[buffer_pos] = line[line_pos];
if( line[line_pos] == ' ' )
{
last_word_pos = line_pos + 1;
}
curr_length++;
buffer_pos++;
line_pos++;
}
if( line_pos == line.length() )
{
buffer[buffer_pos] = '\0';
Printf(level, category, "%s", buffer);
break;
}
if( last_word_pos == last_line_pos )
{
if( line[line_pos] == ' ' )
{
buffer[buffer_pos] = '\0';
last_word_pos = line_pos + 1;
last_line_pos = line_pos + 1;
}
else
{
buffer[buffer_pos - 1] = '-';
buffer[buffer_pos] = '\0';
last_word_pos = line_pos - 1;
last_line_pos = last_word_pos;
}
}
else
{
buffer[buffer_pos - (line_pos - last_word_pos) - 1] = '\0';
last_line_pos = last_word_pos;
}
Printf(level, category, "%s\n", buffer);
if( first_line )
{
for( Index i = 0; i < indent_spaces; i++ )
{
buffer[i] = ' ';
}
first_line = false;
}
buffer_pos = indent_spaces;
}
}
void Journalist::PrintfIndented(
EJournalLevel level,
EJournalCategory category,
Index indent_level,
const char* pformat,
...
) const
{
va_list ap;
va_start(ap, pformat);
VPrintfIndented(level, category, indent_level, pformat, ap);
va_end(ap);
}
void Journalist::VPrintf(
EJournalLevel level,
EJournalCategory category,
const char* pformat,
va_list ap
) const
{
for( Index i = 0; i < (Index) journals_.size(); i++ )
{
if( journals_[i]->IsAccepted(category, level) )
{
#ifdef IPOPT_HAS_VA_COPY
va_list apcopy;
va_copy(apcopy, ap);
journals_[i]->Printf(category, level, pformat, apcopy);
va_end(apcopy);
#else
journals_[i]->Printf(category, level, pformat, ap);
#endif
}
}
}
void Journalist::VPrintfIndented(
EJournalLevel level,
EJournalCategory category,
Index indent_level,
const char* pformat,
va_list ap
) const
{
for( Index i = 0; i < (Index) journals_.size(); i++ )
{
if( journals_[i]->IsAccepted(category, level) )
{
for( Index s = 0; s < indent_level; s++ )
{
journals_[i]->Print(category, level, " ");
}
#ifdef IPOPT_HAS_VA_COPY
va_list apcopy;
va_copy(apcopy, ap);
journals_[i]->Printf(category, level, pformat, apcopy);
va_end(apcopy);
#else
journals_[i]->Printf(category, level, pformat, ap);
#endif
}
}
}
bool Journalist::ProduceOutput(
EJournalLevel level,
EJournalCategory category
) const
{
for( Index i = 0; i < (Index) journals_.size(); i++ )
{
if( journals_[i]->IsAccepted(category, level) )
{
return true;
}
}
return false;
}
bool Journalist::AddJournal(
const SmartPtr<Journal> jrnl
)
{
DBG_ASSERT(IsValid(jrnl));
std::string name = jrnl->Name();
SmartPtr<Journal> temp = GetJournal(name);
DBG_ASSERT(IsNull(temp));
if( IsValid(temp) )
{
return false;
}
journals_.push_back(jrnl);
return true;
}
SmartPtr<Journal> Journalist::AddFileJournal(
const std::string& journal_name,
const std::string& fname,
EJournalLevel default_level,
bool file_append
)
{
SmartPtr<FileJournal> temp = new FileJournal(journal_name, default_level);
if( temp->Open(fname.c_str(), file_append) && AddJournal(GetRawPtr(temp)) )
{
return GetRawPtr(temp);
}
return NULL;
}
void Journalist::FlushBuffer() const
{
for( Index i = 0; i < (Index) journals_.size(); i++ )
{
journals_[i]->FlushBuffer();
}
}
SmartPtr<Journal> Journalist::GetJournal(
const std::string& journal_name
)
{
SmartPtr<Journal> retValue = NULL;
for( Index i = 0; i < (Index) journals_.size(); i++ )
{
SmartPtr<Journal> tmp = journals_[i];
if( tmp->Name() == journal_name )
{
retValue = tmp;
break;
}
}
return retValue;
}
void Journalist::DeleteAllJournals()
{
for( Index i = 0; i < (Index) journals_.size(); i++ )
{
journals_[i] = NULL;
}
journals_.resize(0);
}
Journal::Journal(
const std::string& name,
EJournalLevel default_level
)
: name_(name)
{
for( Index i = 0; i < J_LAST_CATEGORY; i++ )
{
print_levels_[i] = default_level;
}
}
Journal::~Journal()
{ }
std::string Journal::Name()
{
return name_;
}
bool Journal::IsAccepted(
EJournalCategory category,
EJournalLevel level
) const
{
if( print_levels_[(Index) category] >= (Index) level )
{
return true;
}
return false;
}
void Journal::SetPrintLevel(
EJournalCategory category,
EJournalLevel level
)
{
print_levels_[(Index) category] = (Index) level;
}
void Journal::SetAllPrintLevels(
EJournalLevel level
)
{
for( Index category = (Index) J_DBG; category < (Index) J_USER_APPLICATION; category++ )
{
print_levels_[category] = (Index) level;
}
}
FileJournal::FileJournal(
const std::string& name,
EJournalLevel default_level
)
: Journal(name, default_level),
file_(NULL)
{ }
FileJournal::~FileJournal()
{
if( file_ && file_ != stdout && file_ != stderr )
{
fclose(file_);
}
file_ = NULL;
}
bool FileJournal::Open(
const char* fname,
bool fappend
)
{
if( file_ && file_ != stdout && file_ != stderr )
{
fclose(file_);
}
file_ = NULL;
if( strcmp("stdout", fname) == 0 )
{
file_ = stdout;
return true;
}
else if( strcmp("stderr", fname) == 0 )
{
file_ = stderr;
return true;
}
else
{
file_ = fopen(fname, fappend ? "a+" : "w+");
if( file_ )
{
return true;
}
}
return false;
}
void FileJournal::PrintImpl(
EJournalCategory ,
EJournalLevel ,
const char* str
)
{
DBG_START_METH("Journal::Print", 0);
if( file_ )
{
fprintf(file_, "%s", str);
DBG_EXEC(0, fflush(file_));
}
}
void FileJournal::PrintfImpl(
EJournalCategory ,
EJournalLevel ,
const char* pformat,
va_list ap
)
{
DBG_START_METH("Journal::Printf", 0);
if( file_ )
{
vfprintf(file_, pformat, ap);
DBG_EXEC(0, fflush(file_));
}
}
void FileJournal::FlushBufferImpl()
{
if( file_ )
{
fflush(file_);
}
}
StreamJournal::StreamJournal(
const std::string& name,
EJournalLevel default_level
)
: Journal(name, default_level),
os_(NULL)
{
}
void StreamJournal::SetOutputStream(
std::ostream* os
)
{
os_ = os;
}
void StreamJournal::PrintImpl(
EJournalCategory ,
EJournalLevel ,
const char* str
)
{
DBG_START_METH("StreamJournal::PrintImpl", 0);
if( os_ )
{
*os_ << str;
DBG_EXEC(0, *os_ << std::flush);
}
}
void StreamJournal::PrintfImpl(
EJournalCategory ,
EJournalLevel ,
const char* pformat,
va_list ap
)
{
DBG_START_METH("StreamJournal::PrintfImpl", 0);
if( os_ )
{
vsprintf(buffer_, pformat, ap);
*os_ << buffer_;
DBG_EXEC(0, *os_ << std::flush);
}
}
void StreamJournal::FlushBufferImpl()
{
if( os_ )
{
*os_ << std::flush;
}
}
}