gecko-dev/lib/libaddr/abtracer.cpp
1998-06-22 21:46:46 +00:00

429 lines
11 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/* file: abtrace.cpp
** Most portions closely derive from public domain IronDoc code and interfaces.
**
** Changes:
** <1> 06Feb1998 first implementation
** <0> 23Dec1997 first interface draft
*/
#ifndef _ABTABLE_
#include "abtable.h"
#endif
#ifndef _ABMODEL_
#include "abmodel.h"
#endif
/*3456789_123456789_123456789_123456789_123456789_123456789_123456789_12345678*/
/* ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- */
#if AB_CONFIG_TRACE_orDEBUG_orPRINT
static const char* ab_Tracer_kClassName /*i*/ = "ab_Tracer";
#endif /* end AB_CONFIG_TRACE_orDEBUG_orPRINT*/
#if AB_CONFIG_TRACE_orDEBUG_orPRINT
static const char* ab_FileTracer_kClassName /*i*/ = "ab_FileTracer";
#endif /* end AB_CONFIG_TRACE_orDEBUG_orPRINT*/
/* ===== ===== ===== ===== ab_Tracer ===== ===== ===== ===== */
// ````` ````` ````` ````` ````` ````` ````` `````
// virtual ab_Object methods
ab_Tracer::~ab_Tracer() /*i*/
{
}
// ````` ````` ````` ````` ````` ````` ````` `````
// non-poly ab_Tracer methods
void ab_Tracer::Trace(ab_Env* ev, const char* inFormat, ...) /*i*/
{
#ifdef AB_CONFIG_TRACE
if ( this->IsOpenObject() )
{
char buf[ AB_Env_kFormatBufferSize ];
va_list args;
va_start(args,inFormat);
PR_vsnprintf(buf, AB_Env_kFormatBufferSize, inFormat, args);
va_end(args);
this->TraceString(ev, buf);
}
#ifdef AB_CONFIG_DEBUG
// presumably this tracer is inside ev, so breaking might recurse:
else this->ObjectPanic("ab_Tracer not open");
#endif /*AB_CONFIG_DEBUG*/
#endif /*AB_CONFIG_TRACE*/
}
ab_Tracer::ab_Tracer(const ab_Usage& inUsage) /*i*/
: ab_Object(inUsage),
mTracer_MethodDepth( 0 )
{
}
/* ===== ===== ===== ===== ab_FileTracer ===== ===== ===== ===== */
// ````` ````` ````` ````` ````` ````` ````` `````
// protected non-poly ab_FileTracer methods
#define ab_FileTracer_kInsetSize /*i*/ 8
#define ab_FileTracer_kBlanksLength /*i*/ 32 /* static blank string length */
void ab_FileTracer::trace_indent(ab_Env* ev) /*i*/
{
// copied almost verbatim from IronDoc sources:
ab_File* file = mFileTracer_File;
if ( file && file->IsOpenObject() )
{
static const char* kBlanks = "<indent . . . . . . . . . . . . . . . . . ";
/* comment to count sections: 12345678 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 */
const char* inset = kBlanks + ab_FileTracer_kInsetSize; /* skip tag */
ab_num count = 0; /* the count of times we write something */
ab_num remaining = mTracer_MethodDepth * 2; /* 2 blanks per indent */
if ( remaining > 1024 ) /* more than some reasonable upper bound? */
remaining = 1024;
if ( remaining ) /* is there any indentation to write? */
{
/* keep looping even if an error has occurred */
while ( remaining ) /* more blanks to write? */
{
ab_num quantum = remaining;
if ( quantum > ab_FileTracer_kBlanksLength )
quantum = ab_FileTracer_kBlanksLength;
if ( count ) /* have we already written at least once? */
file->Write(ev, inset, quantum);
else
file->Write(ev, kBlanks, quantum + ab_FileTracer_kInsetSize);
++count; /* only write the leading indent tag a single time */
remaining -= quantum;
}
file->Write(ev, "/> ", 3); /* end the indent tag */
}
else /* we want to write at least the basic indent tag */
{
file->Write(ev, "<indent /> ", 11); /* empty tag */
/* count length: 12345678901 */
}
}
}
// ````` ````` ````` ````` tags ````` ````` ````` `````
/* :::: ruler for string lengths:- 0123456789012 */
static const char* ab_kTraceTag = "<ab:trace>"; // length 10
#define ab_kTraceTagSize 10
#ifdef XP_MAC
static const char* ab_kTraceEndTag = "</ab:trace>\015";
# define ab_kTraceEndTagSize 12
#else
# if defined(XP_WIN) || defined(XP_OS2)
static const char* ab_kTraceEndTag = "</ab:trace>\015\012";
# define ab_kTraceEndTagSize 13
# else
# ifdef XP_UNIX
static const char* ab_kTraceEndTag = "</ab:trace>\012";
# define ab_kTraceEndTagSize 12
# endif /* XP_UNIX */
# endif /* XP_WIN */
#endif /* XP_MAC */
// ````` ````` ````` ````` tags ````` ````` ````` `````
void ab_FileTracer::trace_string(ab_Env* ev, const char* inMessage, /*i*/
ab_bool inXmlWrap)
{
#ifdef AB_CONFIG_TRACE
// copied closely from IronDoc sources:
ab_File* file = mFileTracer_File;
if ( file && file->IsOpenObject() )
{
this->trace_indent(ev);
if ( inXmlWrap ) // need a leading trace tag?
file->Write(ev, ab_kTraceTag, ab_kTraceTagSize);
file->Write(ev, inMessage, XP_STRLEN(inMessage));
if ( inXmlWrap ) // need a trailing end trace tag?
file->Write(ev, ab_kTraceEndTag, ab_kTraceEndTagSize);
else
file->Write(ev, ab_kNewline, ab_kNewlineSize);
}
#endif /*AB_CONFIG_TRACE*/
}
// ````` ````` ````` ````` ````` ````` ````` `````
// virtual ab_Tracer methods
void ab_FileTracer::TraceString(ab_Env* ev, const char* inMessage) /*i*/
{
#ifdef AB_CONFIG_TRACE
this->trace_string(ev, inMessage, /*inXmlWrap*/ AB_kTrue);
#endif /*AB_CONFIG_TRACE*/
}
void ab_FileTracer::BeginMethod(ab_Env* ev, const char* inClass, /*i*/
const char* inMethod)
{
#ifdef AB_CONFIG_TRACE
if ( this->IsOpenObject() )
{
char buf[ 256 ];
XP_SPRINTF(buf, "<ab:trace method=\"%.48s::%.48s\"> {",
inClass, inMethod);
this->trace_string(ev, buf, /*inXmlWrap*/ AB_kFalse);
++mTracer_MethodDepth;
}
#endif /*AB_CONFIG_TRACE*/
}
void ab_FileTracer::EndMethod(ab_Env* ev) /*i*/
{
#ifdef AB_CONFIG_TRACE
if ( this->IsOpenObject() )
{
if ( mTracer_MethodDepth )
--mTracer_MethodDepth;
else
{
#ifdef AB_CONFIG_DEBUG
this->BreakObject(ev);
#endif /*AB_CONFIG_DEBUG*/
}
this->trace_string(ev, "} </ab:trace>", /*inXmlWrap*/ AB_kFalse);
}
#endif /*AB_CONFIG_TRACE*/
}
void ab_FileTracer::Flush(ab_Env* ev) /*i*/
{
#ifdef AB_CONFIG_TRACE
if ( this->IsOpenObject() )
{
ab_File* file = mFileTracer_File;
if ( file && file->IsOpenObject() )
{
file->Flush(ev);
}
else this->CastAwayConstCloseObject(ev);
}
#endif /*AB_CONFIG_TRACE*/
}
ab_Printer* ab_FileTracer::GetPrinter(ab_Env* ev) /*i*/
{
AB_USED_PARAMS_1(ev);
ab_Printer* outPrinter = 0;
if ( this->IsOpenObject() )
outPrinter = mFileTracer_Printer;
return outPrinter;
}
// ````` ````` ````` ````` ````` ````` ````` `````
// virtual ab_Object methods
char* ab_FileTracer::ObjectAsString(ab_Env* ev, char* outXmlBuf) const /*i*/
{
AB_USED_PARAMS_1(ev);
#if AB_CONFIG_TRACE_orDEBUG_orPRINT
XP_SPRINTF(outXmlBuf,
"<ab:file:tracer:str me=\"^%lX\" md=\"%ld\" f:p=\"^%lX:^%lx\" rc=\"%lu\" a=\"%.9s\" u=\"%.9s\"/>",
(long) this, // me=\"^%lX\"
(long) mTracer_MethodDepth, // md=\"%ld\"
(long) mFileTracer_File, // f:p=\"^%lX
(long) mFileTracer_Printer, // ^%lx\"
(unsigned long) mObject_RefCount, // rc=\"%lu\"
this->GetObjectAccessAsString(), // ac=\"%.9s\"
this->GetObjectUsageAsString() // us=\"%.9s\"
);
#else
*outXmlBuf = 0; /* empty string */
#endif /*AB_CONFIG_TRACE_orDEBUG_orPRINT*/
return outXmlBuf;
}
void ab_FileTracer::CloseObject(ab_Env* ev) /*i*/
{
if ( this->IsOpenObject() )
{
this->MarkClosing();
this->CloseFileTracer(ev);
this->MarkShut();
}
}
void ab_FileTracer::PrintObject(ab_Env* ev, ab_Printer* ioPrinter) const /*i*/
{
#ifdef AB_CONFIG_PRINT
ioPrinter->PutString(ev, "<ab:file:tracer>");
char xmlBuf[ ab_Object_kXmlBufSize + 2 ];
if ( this->IsOpenObject() )
{
ioPrinter->PushDepth(ev); // indent all objects in the list
ioPrinter->NewlineIndent(ev, /*count*/ 1);
ioPrinter->PutString(ev, this->ObjectAsString(ev, xmlBuf));
if ( mFileTracer_File )
{
ioPrinter->NewlineIndent(ev, /*count*/ 1);
mFileTracer_File->PrintObject(ev, ioPrinter);
}
if ( mFileTracer_Printer )
{
ioPrinter->NewlineIndent(ev, /*count*/ 1);
mFileTracer_Printer->PrintObject(ev, ioPrinter);
}
ioPrinter->PopDepth(ev); // stop indentation
}
else // use ab_Object::ObjectAsString() for non-objects:
{
ioPrinter->PutString(ev, this->ab_Object::ObjectAsString(ev, xmlBuf));
}
ioPrinter->NewlineIndent(ev, /*count*/ 1);
ioPrinter->PutString(ev, "</ab:file:tracer>");
#endif /*AB_CONFIG_PRINT*/
}
ab_FileTracer::~ab_FileTracer() /*i*/
{
AB_ASSERT(mFileTracer_File==0);
AB_ASSERT(mFileTracer_Printer==0);
#if AB_CONFIG_TRACE_orDEBUG_orPRINT
ab_Object* obj = mFileTracer_File;
if ( obj )
obj->ObjectNotReleasedPanic(ab_FileTracer_kClassName);
obj = mFileTracer_Printer;
if ( obj )
obj->ObjectNotReleasedPanic(ab_FileTracer_kClassName);
#endif /*AB_CONFIG_TRACE_orDEBUG_orPRINT*/
}
// ````` ````` ````` ````` ````` ````` ````` `````
// public non-poly ab_FileTracer methods
ab_FileTracer::ab_FileTracer(ab_Env* ev, const ab_Usage& inUsage, /*i*/
ab_File* ioFile, ab_Printer* ioPrinter)
: ab_Tracer(inUsage),
mFileTracer_File( 0 ),
mFileTracer_Printer( 0 )
{
ab_Env_BeginMethod(ev, ab_FileTracer_kClassName, ab_FileTracer_kClassName)
if ( ev->Good() )
{
if ( ioFile && ioPrinter )
{
if ( ioFile->AcquireObject(ev) )
{
mFileTracer_File = ioFile;
if ( ioPrinter->AcquireObject(ev) )
mFileTracer_Printer = ioPrinter;
}
}
else ev->NewAbookFault(ab_Object_kFaultNullObjectParameter);
}
ab_Env_EndMethod(ev)
}
void ab_FileTracer::CloseFileTracer(ab_Env* ev) /*i*/
{
ab_Env_BeginMethod(ev, ab_FileTracer_kClassName, "CloseFileTracer")
ab_Object* obj = mFileTracer_File;
if ( obj )
{
mFileTracer_File = 0;
obj->ReleaseObject(ev);
}
obj = mFileTracer_Printer;
if ( obj )
{
mFileTracer_Printer = 0;
obj->ReleaseObject(ev);
}
ab_Env_EndMethod(ev)
}
static ab_FileTracer* ab_FileTracer_g_log_tracer = 0;
/*static*/
ab_FileTracer* ab_FileTracer::GetLogFileTracer(ab_Env* ev)
// standard session file tracer (uses ab_StdioFile::GetLogStdioFile()).
// This tracer instance is used by ab_Env::GetLogFileEnv().
// (Please, never close this tracer instance.)
{
ab_FileTracer* outTracer = 0;
ab_Env_BeginMethod(ev, ab_FileTracer_kClassName, "GetLogFileTracer")
outTracer = ab_FileTracer_g_log_tracer;
if ( !outTracer )
{
ab_StdioFile* file = ab_StdioFile::GetLogStdioFile(ev);
if ( file )
{
ab_Printer* printer = ab_FilePrinter::GetLogFilePrinter(ev);
if ( printer )
{
outTracer = new(*ev)
ab_FileTracer(ev, ab_Usage::kHeap, file, printer);
}
}
if ( outTracer )
{
ab_FileTracer_g_log_tracer = outTracer;
outTracer->AcquireObject(ev);
}
}
if ( outTracer )
{
#ifdef AB_CONFIG_TRACE
if ( ev->DoTrace() )
outTracer->TraceObject(ev);
#endif /*AB_CONFIG_TRACE*/
}
ab_Env_EndMethod(ev)
return outTracer;
}