Solved

C++ structure log out

Posted on 2013-12-11
5
274 Views
Last Modified: 2013-12-26
Dear Experts,

I have to write plugin (.dll) that acts on specific hooks (events). When the hook is called, it passes variable of specific structure. it Looks something like this:

int CProc::SymbolsAdd(const StructSymb *symbol) {
   ExtLogger.Out("SYMBOL ADDED %s", SymbolToStr(symbol).c_str());
}
int CProc::SymbolsUpdate(const StructSymb *newsymbol, const StructSymb *oldsymbol) {
   ExtLogger.Out("SYMBOL CHANGED %s", SymbolChangesToStr(newsymbol, oldsymbol).c_str());
}
int CProc::SymbolsDelete(const StructSymb *symbol) {
   ExtLogger.Out("SYMBOL DELETED %s", SymbolToStr(symbol).c_str());
}

Open in new window


struct StructSymb                              
  {
   char              symbol[12];            
   int               type;     
   int               count;                   
   int               count_original;
   int               profit_mode;      
   int               logging;          
   
   ...
   
  };

Open in new window


I have one method (in same CProc class) that takes structure, formats it to string and returns it with prefix of "ADDED" or "DELETED" to ExtLogger. Another method takes new and old structure and compares their members, if they members are different it puts it on the string. This way I get only what was changed on them. Now I'm doing it in most simplest way, which I don't like and I want to change it.
This is what I have as methods for formating:
std::string CProc::SymbolToStr(const StructSymb *symbol)
{
	std::string buffer;
	std::stringstream ss;

	ss << symbol->symbol << " [" << std::endl;
	ss << "\tSymbol\t['" << symbol->type << "'; " << symbol->count << "; '" << symbol->description << "'; " << symbol->count_original << "; " << std::fixed << std::setprecision(1) << (double)100/symbol->mode << ";" << std::endl;
	//end so on...
	
	ss << std::endl;
	buffer = ss.str();

	return(buffer);
}

std::string CProc::SymbolChangesToStr(const StructSymb *newsymbol, const StructSymb *oldsymbol)
{
	std::string buffer;
	std::stringstream ss;
	
	if(newsymbol->count != oldsymbol->count)
		ss << "Count changed from [" << oldsymbol->count << ", " newsymbol->count << "];";
	if(newsymbol->mode != oldsymbol->mode)
		ss << "Mode changed from [" << oldsymbol->mode << ", " newsymbol->mode << "];";
	//end so on...
	
	ss << std::endl;
	buffer = ss.str();

	return(buffer);
}

Open in new window


Structure is much bigger and have different type for members so its even more complex.
Problem that I have is that output is bind to implementation, what I would like to have something like MODEL VIEW approach where "rendering" is taken out of the data it self.
Right now I have hard coded the way data looks, and if I need to change for example to CSV or JSON format, i have to go into each of the hard coded string and reformat it. I wonder what would be the ideal solution for outputting complex structures without having such closed for modification approach. Thank you.

P.S. please ignore sintax mistakes, as I tried to do only pseudo code, real source code compiles and works well, I just need to have better architecture for this problem.
0
Comment
Question by:cjustas
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
5 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 39712024
The concept that you are after seems to be 'serialization' (http://en.wikipedia.org/wiki/Serialization). While C++ does not provide 'native' support for that concept the 'boost' libraries do, see http://www.boost.org/doc/libs/1_46_1/libs/serialization/doc/index.html and http://www.boost.org/doc/libs/1_46_1/libs/serialization/doc/tutorial.html
0
 
LVL 34

Expert Comment

by:sarabande
ID: 39713811
you could provide operator<< for each class/struct like


struct StructSymb                              
  {
   char              symbol[12];            
   int               type;     
   int               count;                   
   int               count_original;
   int               profit_mode;      
   int               logging;          
   
   friend std::ostream & operator<<(std::ostream & os, const StructSymb & s)
   {
         os << "symbol[12]=" << s.symbol << " | "
              << "type=" << type << " | "
              << ...;
        return os;
   }
};

Open in new window



the operator would allow to output your objects to any stream (cout, files, string streams). you even could generate the output operator by means of macros in the cpp file like

BEGIN_STREAM_OPERATOR(StructSymb)
     STREAM_MEMBER(symbol)
     STREAM_MEMBER(type)
     ...
END_STREAM_OPERATOR

Open in new window


the macros would resolve to an implementation of operator<< taking the given class/struct as argument.

Sara
0
 

Author Comment

by:cjustas
ID: 39714040
Both cases are more or less okay, but it covers only straight print out. What about printing only differences between two structures?
0
 
LVL 34

Accepted Solution

by:
sarabande earned 500 total points
ID: 39714406
the macro thing also could be used for differences between objects

#define BEGIN_DIFF_OPERATOR(cls) \
    std::ostream& changes(std::ostream& os, const cls & o1, const cls & o2)\
    { 

#define DIFF_MEMBER(m) \
   if (o1.m != o2.m) \
        os << #m << " changed from " << o1.m << " to " << o2.m << std::endl;

#define END_DIFF_MEMBER return os; }

class B
{
public:
    int a;
    double b;
};


BEGIN_DIFF_OPERATOR(B)
   DIFF_MEMBER(a)
   DIFF_MEMBER(b)
END_DIFF_MEMBER

Open in new window


note, the members would need to have operator== with the above definition of DIFF_MEMBER and need to be public members if the function is not declared friend in the header. but of course you also could make a macro for the header declaration of the function and can add the 'friend' that way. you also could use a DIFF_MEMBER_CHARARR if you have to use strcmp rather than operator== (though I would recommend to using std::string).

Sara
0
 
LVL 34

Expert Comment

by:sarabande
ID: 39740797
cjustas, i don't have any problem if you post your own way to go with the issue and accept that comment as the solution. but i don't want you to accept my comment with an average grade. A C grade is only appropriate if you don't get a serious answer to your questions, what is not the case here. i made some efforts to post a solution for your requirements. you either do honor these efforts with at least a B grade or you may accept another solution. thanks.

Sara

p.s. you can reopen the q. by means of the 'Request Attention' button below your initial post.
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Often, when implementing a feature, you won't know how certain events should be handled at the point where they occur and you'd rather defer to the user of your function or class. For example, a XML parser will extract a tag from the source code, wh…
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

738 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question