通过下列步骤将一个类的输出控制交由OutputCtrlProxy托管:
在类头文件包含output_ctrl
声明中包含宏OUTPUT_CTRL_DECLARE
定义前包含宏OUTPUT_CTRL_DEFINE(className)
增加虚函数void className::Output()const定义
支持的控制
className::SetOutputFlag(OUTPUT_NONE);
不输出
className::SetOutputFlag(OUTPUT_PRINT);
打印
className::SetOutputFlag(OUTPUT_WRITE,OUTPUT_PATH);
写到指定文件
/
output_ctrl.h
/
#ifndef _OUTPUT_CTRL_
#define _OUTPUT_CTRL_
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
using namespace std;
#include "basic_type.h"
#define MAX_CTRL_ENTITY 128
typedef int CtrlId;
typedef enum
{
OUTPUT_NONE,
OUTPUT_PRINT,
OUTPUT_WRITE,
}OutputFlag;
class OutputCtrlProxy
{
public:
static OutputCtrlProxy *Instance();
void SetAllFlag(OutputFlag val);
CtrlId GetCtrlId();
void SetOutputFlag(CtrlId id,OutputFlag val,const char *outputPath=NULL);
void Act(CtrlId id,const char *fmt, ...);
OutputFlag ActFlag(CtrlId id);
protected:
OutputCtrlProxy();
private:
static OutputCtrlProxy *_instance;
ofstream *_outputFile;
int _entityNum;
OutputFlag _flags[MAX_CTRL_ENTITY];
};
/*****************************************************
USER MACRO
*****************************************************/
#define OUTPUT_CTRL_DECLARE \
virtual void Output()const; \
static void SetOutputFlag(OutputFlag val,const char *outputPath=NULL); \
static int GetCtrlId(); \
static int _ctrlId;
#define OUTPUT_CTRL_DEFINE(className) \
int className::_ctrlId = 0; \
int className::GetCtrlId() \
{ \
if(_ctrlId==0) \
{ \
OutputCtrlProxy *p = OutputCtrlProxy::Instance(); \
_ctrlId = p->GetCtrlId(); \
} \
return _ctrlId; \
} \
\
void className::SetOutputFlag(OutputFlag val,const char *outputPath) \
{ \
OutputCtrlProxy *p = OutputCtrlProxy::Instance(); \
p->SetOutputFlag(GetCtrlId(),val,outputPath); \
}
#endif
/
output_ctrl.cpp
/
#include <stdio.h>
#include <stdarg.h>
#include "output_ctrl.h"
OutputCtrlProxy *OutputCtrlProxy::_instance = NULL;
OutputCtrlProxy *OutputCtrlProxy::Instance()
{
if(_instance==0)
{
_instance = new OutputCtrlProxy;
}
return _instance;
}
CtrlId OutputCtrlProxy::GetCtrlId()
{
return ++_entityNum;
}
void OutputCtrlProxy::SetOutputFlag(CtrlId id,OutputFlag val,const char *path)
{
_flags[id-1] = val;
if( val==OUTPUT_WRITE && _outputFile==NULL )
{
if(path!=NULL)
{
_outputFile = new ofstream(path);
}
}
}
void OutputCtrlProxy::Act(CtrlId id,const char *fmt, ...)
{
if( _flags[id-1]!=NULL )
{
char tmpBuffer[1024] = {0};
va_list argptr;
memset(&argptr, 0, sizeof(va_list));
va_start (argptr, fmt);
vsprintf(tmpBuffer, fmt, argptr);
va_end (argptr);
if( _flags[id-1]==OUTPUT_PRINT )
{
printf("%s", tmpBuffer);
}
else if( _flags[id-1]==OUTPUT_WRITE )
{
if(_outputFile!=NULL)
{
_outputFile->write(tmpBuffer,strlen(tmpBuffer));
}
}
}
}
OutputFlag OutputCtrlProxy::ActFlag(CtrlId id)
{
return _flags[id-1];
}
OutputCtrlProxy::OutputCtrlProxy()
{
for(int i=0;i<MAX_CTRL_ENTITY;i++)
{
_flags[i] = OUTPUT_NONE;
}
_entityNum = 0;
_outputFile = NULL;
}
void OutputCtrlProxy::SetAllFlag(OutputFlag val)
{
for(int i=0;i<_entityNum;i++)
{
_flags[i] = OUTPUT_PRINT;
}
_entityNum = 0;
}
/
test_output_ctrl.cpp
/
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "token.h"
#include "TokenDerive.h"
#include "PrecompileBuilder.h"
#define OUTPUT_PATH "E:\\code_analyze\\code\\test_data\\test_output\\output.txt"
class Entity1
{
public:
OUTPUT_CTRL_DECLARE
void Output();
void Output(int printId);
};
OUTPUT_CTRL_DEFINE(Entity1)
void Entity1::Output()const
{
OutputCtrlProxy *p = OutputCtrlProxy::Instance();
p->Act(_ctrlId,"Entity1 output action\n");
}
void Entity1::Output()
{
OutputCtrlProxy *p = OutputCtrlProxy::Instance();
p->Act(_ctrlId,"Entity1 output action\n");
}
void Entity1::Output(int id)
{
OutputCtrlProxy *p = OutputCtrlProxy::Instance();
p->Act(_ctrlId," %d -%s",id,"Entity1 output action\n");
}
class Entity2
{
public:
OUTPUT_CTRL_DECLARE
void Output();
void Output(int printId);
};
OUTPUT_CTRL_DEFINE(Entity2)
void Entity2::Output()const
{
OutputCtrlProxy *p = OutputCtrlProxy::Instance();
p->Act(_ctrlId,"Entity1 output action\n");
}
void Entity2::Output()
{
OutputCtrlProxy *p = OutputCtrlProxy::Instance();
p->Act(_ctrlId,"Entity2 output action\n");
}
void Entity2::Output(int id)
{
OutputCtrlProxy *p = OutputCtrlProxy::Instance();
p->Act(_ctrlId," %d -%s",id,"Entity2 output action\n");
}
void test_ctrl_id()
{
Entity1 e1_1;
Entity1 e1_2;
assert( e1_2.GetCtrlId()==e1_1.GetCtrlId() );
Entity2 e2_1;
Entity2 e2_2;
assert( e2_1.GetCtrlId()==e2_1.GetCtrlId() );
Entity1 e1_3;
assert( e1_3.GetCtrlId()==e1_1.GetCtrlId() );
Entity2 e2_3;
assert( e2_3.GetCtrlId()==e2_1.GetCtrlId() );
}
void test_simple_print()
{
printf("show entity1,don't show entity2\n");
Entity1::SetOutputFlag(OUTPUT_PRINT);
Entity2::SetOutputFlag(OUTPUT_NONE);
Entity1 e1_1,e1_2;
e1_1.Output();
e1_2.Output();
Entity2 e2_1,e2_2;
e2_1.Output();
e2_2.Output();
printf("show entity2,don't show entity1\n");
Entity1::SetOutputFlag(OUTPUT_NONE);
Entity2::SetOutputFlag(OUTPUT_PRINT);
e1_1.Output();
e1_2.Output();
e2_1.Output();
e2_2.Output();
}
void test_complicate_print()
{
int printId = 0;
printf("show entity1,don't show entity2\n");
Entity1::SetOutputFlag(OUTPUT_PRINT);
Entity2::SetOutputFlag(OUTPUT_NONE);
Entity1 e1_1,e1_2;
e1_1.Output(printId++);
e1_2.Output(printId++);
Entity2 e2_1,e2_2;
e2_1.Output(printId++);
e2_2.Output(printId++);
printf("show entity2,don't show entity1\n");
Entity1::SetOutputFlag(OUTPUT_NONE);
Entity2::SetOutputFlag(OUTPUT_PRINT);
e1_1.Output(printId++);
e1_2.Output(printId++);
e2_1.Output(printId++);
e2_2.Output(printId++);
}
void test_print()
{
test_ctrl_id();
test_simple_print();
test_complicate_print();
}
void test_write()
{
int printId = 0;
Entity1 e1_1;
Entity2 e2_1;
Entity1::SetOutputFlag(OUTPUT_PRINT);
e1_1.Output(printId++);
Entity1::SetOutputFlag(OUTPUT_WRITE,OUTPUT_PATH);
e1_1.Output(printId++);
Entity2::SetOutputFlag(OUTPUT_WRITE,OUTPUT_PATH);
e2_1.Output(printId++);
}
void test_output_ctrl()
{
printf("=======test_output_ctrl print=========\n");
test_print();
printf("=======test_output_ctrl write file====\n");
test_write();
}