From 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 Mon Sep 17 00:00:00 2001 From: git perforce import user Date: Tue, 25 Oct 2016 12:29:14 -0600 Subject: Initial commit: PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167] --- APEX_1.4/shared/external/src/htmltable.cpp | 3663 ++++++++++++++++++++++++++++ 1 file changed, 3663 insertions(+) create mode 100644 APEX_1.4/shared/external/src/htmltable.cpp (limited to 'APEX_1.4/shared/external/src/htmltable.cpp') diff --git a/APEX_1.4/shared/external/src/htmltable.cpp b/APEX_1.4/shared/external/src/htmltable.cpp new file mode 100644 index 00000000..7bd26a1e --- /dev/null +++ b/APEX_1.4/shared/external/src/htmltable.cpp @@ -0,0 +1,3663 @@ +/* + * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + + +#include "htmltable.h" + +#if PX_WINDOWS_FAMILY // only compile this source code for windows! + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#pragma warning(disable:4267 4127) + +#define USE_CPP 0 +#define USE_EXCEL 0 + +#pragma warning(disable:4996 4702) // Disable Microsof'ts freaking idiotic 'warnings' not to use standard ANSI C stdlib and string functions! + +#include "htmltable.h" + +#if PX_LINUX +#define stricmp(a,b) strcasecmp(a,b) +#define _vsnprintf vsnprintf +#define _mkdir(a) mkdir(a, 0) +#endif + +namespace HTMLTABLE_NVSHARE +{ + +using namespace nvidia; + +#pragma warning(disable:4100) + +class MemHeader +{ +public: + MemHeader *mNext; + MemHeader *mPrevious; + size_t mLength; + const char *mTag; + const char *mFile; + int mLineno; +}; + +class MemTracker +{ +public: + MemTracker(void) + { + mCount = 0; + mTotal = 0; + mRoot = 0; + } + + ~MemTracker(void) + { + } + + void * memAlloc(size_t len,const char *tag,const char *file,int lineno) + { + MemHeader *mh = (MemHeader *)::malloc(len+sizeof(MemHeader)); + mh->mNext = mRoot; + mh->mPrevious = 0; + if ( mRoot ) mRoot->mPrevious = mh; + mRoot = mh; + mh->mLength = len; + mh->mTag = tag; + mh->mFile = file; + mh->mLineno = lineno; + mCount++; + mTotal+=len; + mh++; + return mh; + } + + void memFree(void *mem) + { + MemHeader *mh = (MemHeader *)mem; + mh--; + + MemHeader *prev = mh->mPrevious; + MemHeader *next = mh->mNext; + + if ( prev ) + { + prev->mNext = next; + } + else + { + assert( mRoot == mh ); + mRoot = next; + } + if ( next ) + { + next->mPrevious = prev; + } + mCount--; + mTotal-=mh->mLength; + + assert(mCount>=0); + assert(mTotal>=0); + + ::free(mh); + } + + int getMemoryUsage(void) + { + int c = 0; + int t = 0; + + MemHeader *mh = mRoot; + MemHeader *prev = 0; + while ( mh ) + { + c++; + t+=mh->mLength; + assert( mh->mPrevious == prev ); + prev = mh; + mh = mh->mNext; + } + + assert( c == mCount ); + assert( t == mTotal ); + + return mTotal; + } + +private: + int mCount; + int mTotal; + MemHeader *mRoot; +}; + +static MemTracker gMemTracker; + +#define HTML_NEW(x) new ( gMemTracker.memAlloc(sizeof(x),#x,__FILE__,__LINE__) )x +#define HTML_DELETE(y,x) if ( x ) { x->~y(); gMemTracker.memFree(x); } + +#define HTML_MALLOC(x) gMemTracker.memAlloc(x,__FILE__,__FILE__,__LINE__) +#define HTML_FREE(x) gMemTracker.memFree(x) + + +static char * lastDot(char *src) +{ + char *ret = 0; + + char *dot = strchr(src,'.'); + while ( dot ) + { + ret = dot; + dot = strchr(dot+1,'.'); + } + return ret; +} + + +static char * lastSlash(char *src) // last forward or backward slash character, null if none found. +{ + char *ret = 0; + + char *dot = strchr(src,'\\'); + if ( dot == 0 ) + dot = strchr(src,'/'); + while ( dot ) + { + ret = dot; + dot = strchr(ret+1,'\\'); + if ( dot == 0 ) + dot = strchr(ret+1,'/'); + } + return ret; +} + +static inline const char * tf(bool v) +{ + const char *ret = "false"; + if ( v ) ret = "true"; + return ret; +} + +class QuickSortPointers +{ +public: + void qsort(void **base,int num); // perform the qsort. +protected: + // -1 less, 0 equal, +1 greater. + virtual int compare(void **p1,void **p2) = 0; +private: + void inline swap(char **a,char **b); +}; + + +void QuickSortPointers::swap(char **a,char **b) +{ + char *tmp; + + if ( a != b ) + { + tmp = *a; + *a++ = *b; + *b++ = tmp; + } +} + + +void QuickSortPointers::qsort(void **b,int num) +{ + char *lo,*hi; + char *mid; + char *bottom, *top; + int size; + char *lostk[30], *histk[30]; + int stkptr; + char **base = (char **)b; + + if (num < 2 ) return; + + stkptr = 0; + + lo = (char *)base; + hi = (char *)base + sizeof(char **) * (num-1); + +nextone: + + size = (int)(hi - lo) / (int)sizeof(char**) + 1; + + mid = lo + (size / 2) * sizeof(char **); + swap((char **)mid,(char **)lo); + bottom = lo; + top = hi + sizeof(char **); + + for (;;) + { + do + { + bottom += sizeof(char **); + } while (bottom <= hi && compare((void **)bottom,(void **)lo) <= 0); + + do + { + top -= sizeof(char **); + } while (top > lo && compare((void **)top,(void **)lo) >= 0); + + if (top < bottom) break; + + swap((char **)bottom,(char **)top); + + } + + swap((char **)lo,(char **)top); + + if ( top - 1 - lo >= hi - bottom ) + { + if (lo + sizeof(char **) < top) + { + lostk[stkptr] = lo; + histk[stkptr] = top - sizeof(char **); + stkptr++; + } + if (bottom < hi) + { + lo = bottom; + goto nextone; + } + } + else + { + if ( bottom < hi ) + { + lostk[stkptr] = bottom; + histk[stkptr] = hi; + stkptr++; + } + if (lo + sizeof(char **) < top) + { + hi = top - sizeof(char **); + goto nextone; /* do small recursion */ + } + } + + stkptr--; + + if (stkptr >= 0) + { + lo = lostk[stkptr]; + hi = histk[stkptr]; + goto nextone; + } + return; +} + + +//*** Including my 'FILE_INTERFACE' wrapper that supposed an STDIO style interface to read and write buffers. +class FILE_INTERFACE; + + +FILE_INTERFACE * fi_fopen(const char *fname,const char *spec,void *mem=0,size_t len=0); +void fi_fclose(FILE_INTERFACE *file); +size_t fi_fread(void *buffer,size_t size,size_t count,FILE_INTERFACE *fph); +size_t fi_fwrite(const void *buffer,size_t size,size_t count,FILE_INTERFACE *fph); +size_t fi_fprintf(FILE_INTERFACE *fph,const char *fmt,...); +size_t fi_fflush(FILE_INTERFACE *fph); +size_t fi_fseek(FILE_INTERFACE *fph,size_t loc,size_t mode); +size_t fi_ftell(FILE_INTERFACE *fph); +size_t fi_fputc(char c,FILE_INTERFACE *fph); +size_t fi_fputs(const char *str,FILE_INTERFACE *fph); +size_t fi_feof(FILE_INTERFACE *fph); +size_t fi_ferror(FILE_INTERFACE *fph); +void * fi_getMemBuffer(FILE_INTERFACE *fph,size_t &outputLength); // return the buffer and length of the file. + + +#define DEFAULT_BUFFER_SIZE 8192 + +#if defined(LINUX) +# define _stricmp(a,b) strcasecmp((a),(b)) +#endif + +class FILE_INTERFACE +{ +public: + FILE_INTERFACE(const char *fname,const char *spec,void *mem,size_t len) + { + mMyAlloc = false; + mRead = true; // default is read access. + mFph = 0; + mData = (char *) mem; + mLen = len; + mLoc = 0; + + if ( spec && _stricmp(spec,"wmem") == 0 ) + { + mRead = false; + if ( mem == 0 || len == 0 ) + { + mData = (char *)HTML_MALLOC(DEFAULT_BUFFER_SIZE); + mLen = DEFAULT_BUFFER_SIZE; + mMyAlloc = true; + } + } + + if ( mData == 0 ) + { + mFph = fopen(fname,spec); + } + + strncpy(mName,fname,512); + } + + ~FILE_INTERFACE(void) + { + if ( mMyAlloc ) + { + HTML_FREE(mData); + } + if ( mFph ) + { + fclose(mFph); + } + } + + size_t read(char *data,size_t size) + { + size_t ret = 0; + if ( (mLoc+size) <= mLen ) + { + memcpy(data, &mData[mLoc], size ); + mLoc+=size; + ret = 1; + } + return ret; + } + + size_t write(const char *data,size_t size) + { + size_t ret = 0; + + if ( (mLoc+size) >= mLen && mMyAlloc ) // grow it + { + size_t newLen = mLen*2; + if ( size > newLen ) newLen = size+mLen; + + char *data = (char *)HTML_MALLOC(newLen); + memcpy(data,mData,mLoc); + HTML_FREE(mData); + mData = data; + mLen = newLen; + } + + if ( (mLoc+size) <= mLen ) + { + memcpy(&mData[mLoc],data,size); + mLoc+=size; + ret = 1; + } + return ret; + } + + size_t read(void *buffer,size_t size,size_t count) + { + size_t ret = 0; + if ( mFph ) + { + ret = fread(buffer,size,count,mFph); + } + else + { + char *data = (char *)buffer; + for (size_t i=0; i= mLen ) + ret = 1; + } + return ret; + } + + size_t error(void) + { + size_t ret = 0; + if ( mFph ) + { + ret = (size_t)ferror(mFph); + } + return ret; + } + + + FILE *mFph; + char *mData; + size_t mLen; + size_t mLoc; + bool mRead; + char mName[512]; + bool mMyAlloc; + +}; + +FILE_INTERFACE * fi_fopen(const char *fname,const char *spec,void *mem,size_t len) +{ + FILE_INTERFACE *ret = 0; + + ret = HTML_NEW(FILE_INTERFACE)(fname,spec,mem,len); + + if ( mem == 0 && ret->mData == 0) + { + if ( ret->mFph == 0 ) + { + HTML_DELETE(FILE_INTERFACE,ret); + ret = 0; + } + } + + return ret; +} + +void fi_fclose(FILE_INTERFACE *file) +{ + HTML_DELETE(FILE_INTERFACE,file); +} + +size_t fi_fread(void *buffer,size_t size,size_t count,FILE_INTERFACE *fph) +{ + size_t ret = 0; + if ( fph ) + { + ret = fph->read(buffer,size,count); + } + return ret; +} + +size_t fi_fwrite(const void *buffer,size_t size,size_t count,FILE_INTERFACE *fph) +{ + size_t ret = 0; + if ( fph ) + { + ret = fph->write(buffer,size,count); + } + return ret; +} + +size_t fi_fprintf(FILE_INTERFACE *fph,const char *fmt,...) +{ + size_t ret = 0; + + char buffer[2048]; + buffer[2047] = 0; + _vsnprintf(buffer,2047, fmt, (char *)(&fmt+1)); + + if ( fph ) + { + ret = fph->writeString(buffer); + } + + return ret; +} + + +size_t fi_fflush(FILE_INTERFACE *fph) +{ + size_t ret = 0; + if ( fph ) + { + ret = fph->flush(); + } + return ret; +} + + +size_t fi_fseek(FILE_INTERFACE *fph,size_t loc,size_t mode) +{ + size_t ret = 0; + if ( fph ) + { + ret = fph->seek(loc,mode); + } + return ret; +} + +size_t fi_ftell(FILE_INTERFACE *fph) +{ + size_t ret = 0; + if ( fph ) + { + ret = fph->tell(); + } + return ret; +} + +size_t fi_fputc(char c,FILE_INTERFACE *fph) +{ + size_t ret = 0; + if ( fph ) + { + ret = fph->myputc(c); + } + return ret; +} + +size_t fi_fputs(const char *str,FILE_INTERFACE *fph) +{ + size_t ret = 0; + if ( fph ) + { + ret = fph->writeString(str); + } + return ret; +} + +size_t fi_feof(FILE_INTERFACE *fph) +{ + size_t ret = 0; + if ( fph ) + { + ret = fph->eof(); + } + return ret; +} + +size_t fi_ferror(FILE_INTERFACE *fph) +{ + size_t ret = 0; + if ( fph ) + { + ret = fph->error(); + } + return ret; +} + +void * fi_getMemBuffer(FILE_INTERFACE *fph,size_t &outputLength) +{ + outputLength = 0; + void * ret = 0; + if ( fph ) + { + ret = fph->mData; + outputLength = fph->mLoc; + } + return ret; +} + + +//**** Probably a little bit overkill, but I have just copy pasted my 'InPlaceParser' to handle the comma seperated value lines, since it handles quotated strings and whitspace automatically. + +class InPlaceParserInterface +{ +public: + virtual int ParseLine(int lineno,int argc,const char **argv) =0; // return TRUE to continue parsing, return FALSE to abort parsing process + virtual bool preParseLine(int /*lineno*/,const char * /*line */) { return false; }; // optional chance to pre-parse the line as raw data. If you return 'true' the line will be skipped assuming you snarfed it. +}; + +enum SeparatorType +{ + ST_DATA, // is data + ST_HARD, // is a hard separator + ST_SOFT, // is a soft separator + ST_EOS, // is a comment symbol, and everything past this character should be ignored + ST_LINE_FEED +}; + +class InPlaceParser +{ +public: + InPlaceParser(void) + { + Init(); + } + + InPlaceParser(char *data,int len) + { + Init(); + SetSourceData(data,len); + } + + InPlaceParser(const char *fname) + { + Init(); + SetFile(fname); + } + + ~InPlaceParser(void); + + void Init(void) + { + mQuoteChar = 34; + mData = 0; + mLen = 0; + mMyAlloc = false; + for (int i=0; i<256; i++) + { + mHard[i] = ST_DATA; + mHardString[i*2] = (char)i; + mHardString[i*2+1] = 0; + } + mHard[0] = ST_EOS; + mHard[32] = ST_SOFT; + mHard[9] = ST_SOFT; + mHard[13] = ST_LINE_FEED; + mHard[10] = ST_LINE_FEED; + } + + void SetFile(const char *fname); + + void SetSourceData(char *data,int len) + { + mData = data; + mLen = len; + mMyAlloc = false; + }; + + int Parse(const char *str,InPlaceParserInterface *callback); // returns true if entire file was parsed, false if it aborted for some reason + int Parse(InPlaceParserInterface *callback); // returns true if entire file was parsed, false if it aborted for some reason + + int ProcessLine(int lineno,char *line,InPlaceParserInterface *callback); + + const char ** GetArglist(char *source,int &count); // convert source string into an arg list, this is a destructive parse. + + void SetHardSeparator(char c) // add a hard separator + { + mHard[c] = ST_HARD; + } + + void SetHard(char c) // add a hard separator + { + mHard[c] = ST_HARD; + } + + void SetSoft(char c) // add a hard separator + { + mHard[c] = ST_SOFT; + } + + + void SetCommentSymbol(char c) // comment character, treated as 'end of string' + { + mHard[c] = ST_EOS; + } + + void ClearHardSeparator(char c) + { + mHard[c] = ST_DATA; + } + + + void DefaultSymbols(void); // set up default symbols for hard seperator and comment symbol of the '#' character. + + bool EOS(char c) + { + if ( mHard[c] == ST_EOS ) + { + return true; + } + return false; + } + + void SetQuoteChar(char c) + { + mQuoteChar = c; + } + + bool HasData( void ) const + { + return ( mData != 0 ); + } + + void setLineFeed(char c) + { + mHard[c] = ST_LINE_FEED; + } + + bool isLineFeed(char c) + { + if ( mHard[c] == ST_LINE_FEED ) return true; + return false; + } + +private: + + inline char * AddHard(int &argc,const char **argv,char *foo); + inline bool IsHard(char c); + inline char * SkipSpaces(char *foo); + inline bool IsWhiteSpace(char c); + inline bool IsNonSeparator(char c); // non seperator,neither hard nor soft + + bool mMyAlloc; // whether or not *I* allocated the buffer and am responsible for deleting it. + char *mData; // ascii data to parse. + int mLen; // length of data + SeparatorType mHard[256]; + char mHardString[256*2]; + char mQuoteChar; +}; + +//================================================================================== +void InPlaceParser::SetFile(const char *fname) +{ + if ( mMyAlloc ) + { + HTML_FREE(mData); + } + mData = 0; + mLen = 0; + mMyAlloc = false; + + FILE *fph = fopen(fname,"rb"); + if ( fph ) + { + fseek(fph,0L,SEEK_END); + mLen = ftell(fph); + fseek(fph,0L,SEEK_SET); + + if ( mLen ) + { + mData = (char *) HTML_MALLOC(sizeof(char)*(mLen+1)); + int read = (int)fread(mData,(size_t)mLen,1,fph); + if ( !read ) + { + HTML_FREE(mData); + mData = 0; + } + else + { + mData[mLen] = 0; // zero byte terminate end of file marker. + mMyAlloc = true; + } + } + fclose(fph); + } +} + +//================================================================================== +InPlaceParser::~InPlaceParser(void) +{ + if ( mMyAlloc ) + { + HTML_FREE(mData); + } +} + +#define MAXARGS 512 + +//================================================================================== +bool InPlaceParser::IsHard(char c) +{ + return mHard[c] == ST_HARD; +} + +//================================================================================== +char * InPlaceParser::AddHard(int &argc,const char **argv,char *foo) +{ + while ( IsHard(*foo) ) + { + const char *hard = &mHardString[*foo*2]; + if ( argc < MAXARGS ) + { + argv[argc++] = hard; + } + ++foo; + } + return foo; +} + +//================================================================================== +bool InPlaceParser::IsWhiteSpace(char c) +{ + return mHard[c] == ST_SOFT; +} + +//================================================================================== +char * InPlaceParser::SkipSpaces(char *foo) +{ + while ( !EOS(*foo) && IsWhiteSpace(*foo) ) + ++foo; + return foo; +} + +//================================================================================== +bool InPlaceParser::IsNonSeparator(char c) +{ + return ( !IsHard(c) && !IsWhiteSpace(c) && c != 0 ); +} + +//================================================================================== +int InPlaceParser::ProcessLine(int lineno,char *line,InPlaceParserInterface *callback) +{ + int ret = 0; + + const char *argv[MAXARGS]; + int argc = 0; + + char *foo = line; + + while ( !EOS(*foo) && argc < MAXARGS ) + { + foo = SkipSpaces(foo); // skip any leading spaces + + if ( EOS(*foo) ) + break; + + if ( *foo == mQuoteChar ) // if it is an open quote + { + ++foo; + if ( argc < MAXARGS ) + { + argv[argc++] = foo; + } + while ( !EOS(*foo) && *foo != mQuoteChar ) + ++foo; + if ( !EOS(*foo) ) + { + *foo = 0; // replace close quote with zero byte EOS + ++foo; + } + } + else + { + foo = AddHard(argc,argv,foo); // add any hard separators, skip any spaces + + if ( IsNonSeparator(*foo) ) // add non-hard argument. + { + bool quote = false; + if ( *foo == mQuoteChar ) + { + ++foo; + quote = true; + } + + if ( argc < MAXARGS ) + { + argv[argc++] = foo; + } + + if ( quote ) + { + while (*foo && *foo != mQuoteChar ) + ++foo; + if ( *foo ) + *foo = 32; + } + + // continue..until we hit an eos .. + while ( !EOS(*foo) ) // until we hit EOS + { + if ( IsWhiteSpace(*foo) ) // if we hit a space, stomp a zero byte, and exit + { + *foo = 0; + ++foo; + break; + } + else if ( IsHard(*foo) ) // if we hit a hard separator, stomp a zero byte and store the hard separator argument + { + const char *hard = &mHardString[*foo*2]; + *foo = 0; + if ( argc < MAXARGS ) + { + argv[argc++] = hard; + } + ++foo; + break; + } + ++foo; + } // end of while loop... + } + } + } + + if ( argc ) + { + ret = callback->ParseLine(lineno, argc, argv ); + } + + return ret; +} + + +int InPlaceParser::Parse(const char *str,InPlaceParserInterface *callback) // returns true if entire file was parsed, false if it aborted for some reason +{ + int ret = 0; + + mLen = (int)strlen(str); + if ( mLen ) + { + mData = (char *)HTML_MALLOC((size_t)mLen+1); + strcpy(mData,str); + mMyAlloc = true; + ret = Parse(callback); + } + return ret; +} + +//================================================================================== +// returns true if entire file was parsed, false if it aborted for some reason +//================================================================================== +int InPlaceParser::Parse(InPlaceParserInterface *callback) +{ + int ret = 0; + assert( callback ); + if ( mData ) + { + int lineno = 0; + + char *foo = mData; + char *begin = foo; + + while ( *foo ) + { + if ( isLineFeed(*foo) ) + { + ++lineno; + *foo = 0; + if ( *begin ) // if there is any data to parse at all... + { + bool snarfed = callback->preParseLine(lineno,begin); + if ( !snarfed ) + { + int v = ProcessLine(lineno,begin,callback); + if ( v ) + ret = v; + } + } + + ++foo; + if ( *foo == 10 ) + ++foo; // skip line feed, if it is in the carraige-return line-feed format... + begin = foo; + } + else + { + ++foo; + } + } + + lineno++; // lasst line. + + int v = ProcessLine(lineno,begin,callback); + if ( v ) + ret = v; + } + return ret; +} + +//================================================================================== +void InPlaceParser::DefaultSymbols(void) +{ + SetHardSeparator(','); + SetHardSeparator('('); + SetHardSeparator(')'); + SetHardSeparator('='); + SetHardSeparator('['); + SetHardSeparator(']'); + SetHardSeparator('{'); + SetHardSeparator('}'); + SetCommentSymbol('#'); +} + +//================================================================================== +// convert source string into an arg list, this is a destructive parse. +//================================================================================== +const char ** InPlaceParser::GetArglist(char *line,int &count) +{ + const char **ret = 0; + + static const char *argv[MAXARGS]; + int argc = 0; + + char *foo = line; + + while ( !EOS(*foo) && argc < MAXARGS ) + { + foo = SkipSpaces(foo); // skip any leading spaces + + if ( EOS(*foo) ) + break; + + if ( *foo == mQuoteChar ) // if it is an open quote + { + ++foo; + if ( argc < MAXARGS ) + { + argv[argc++] = foo; + } + while ( !EOS(*foo) && *foo != mQuoteChar ) + ++foo; + if ( !EOS(*foo) ) + { + *foo = 0; // replace close quote with zero byte EOS + ++foo; + } + } + else + { + foo = AddHard(argc,argv,foo); // add any hard separators, skip any spaces + + if ( IsNonSeparator(*foo) ) // add non-hard argument. + { + bool quote = false; + if ( *foo == mQuoteChar ) + { + ++foo; + quote = true; + } + + if ( argc < MAXARGS ) + { + argv[argc++] = foo; + } + + if ( quote ) + { + while (*foo && *foo != mQuoteChar ) + ++foo; + if ( *foo ) + *foo = 32; + } + + // continue..until we hit an eos .. + while ( !EOS(*foo) ) // until we hit EOS + { + if ( IsWhiteSpace(*foo) ) // if we hit a space, stomp a zero byte, and exit + { + *foo = 0; + ++foo; + break; + } + else if ( IsHard(*foo) ) // if we hit a hard separator, stomp a zero byte and store the hard separator argument + { + const char *hard = &mHardString[*foo*2]; + *foo = 0; + if ( argc < MAXARGS ) + { + argv[argc++] = hard; + } + ++foo; + break; + } + ++foo; + } // end of while loop... + } + } + } + + count = argc; + if ( argc ) + { + ret = argv; + } + + return ret; +} + +static bool numeric(char c) +{ + bool ret = false; + + if ( (c >= '0' && c <= '9' ) || c == ',' || c == '.' || c == 32) + { + ret = true; + } + return ret; +} + +static bool isNumeric(const std::string &str) +{ + bool ret = true; + + if ( str.size() == 0 ) + { + ret = false; + } + else + { + const char *scan = str.c_str(); + if ( *scan == '-' ) scan++; + while ( *scan ) + { + if ( !numeric(*scan) ) + { + ret = false; + break; + } + scan++; + } + } + return ret; +} + +#define MAXNUMERIC 32 // JWR support up to 16 32 character long numeric formated strings +#define MAXFNUM 16 + +static char gFormat[MAXNUMERIC*MAXFNUM]; +static int gIndex=0; + +const char * formatNumber(int number) // JWR format this integer into a fancy comma delimited string +{ + char * dest = &gFormat[gIndex*MAXNUMERIC]; + gIndex++; + if ( gIndex == MAXFNUM ) gIndex = 0; + + char scratch[512]; + +#if defined (LINUX_GENERIC) || defined(LINUX) || defined (__CELLOS_LV2__) + snprintf(scratch, 10, "%d", number); +#else + itoa(number,scratch,10); +#endif + + char *source = scratch; + char *str = dest; + unsigned int len = (unsigned int)strlen(scratch); + if ( scratch[0] == '-' ) + { + *str++ = '-'; + source++; + len--; + } + for (unsigned int i=0; i 0 ) + { + len--; + while ( len ) + { + if ( fraction[len] == '0' ) + { + fraction[len] = 0; + len--; + } + else + { + break; + } + } + } +} + +float getFloatValue(const char *data) +{ + char temp[512]; + char *dest = temp; + + while ( *data ) + { + char c = *data++; + if ( c != ',' ) + { + *dest++ = c; + } + } + *dest = 0; + float v = (float)atof(temp); + return v; +} + +void getFloat(float v,std::string &ret) +{ + int ivalue = (int)v; + + if ( v == 0 ) + { + ret = "0"; + } + else if ( v == 1 ) + { + ret = "1"; + } + else if ( v == -1 ) + { + ret = "-1"; + } + else if ( ivalue == 0 ) + { + char fraction[512]; + sprintf(fraction,"%0.9f", v ); + stripFraction(fraction); + ret = fraction; + } + else + { + v-=(float)ivalue; + v = fabsf(v); + if (v < 0.00001f ) + v = 0; + + + const char *temp = formatNumber(ivalue); + if ( v != 0 ) + { + char fraction[512]; + sprintf(fraction,"%0.9f", v ); + assert( fraction[0] == '0' ); + assert( fraction[1] == '.' ); + stripFraction(fraction); + char scratch[512]; + sprintf(scratch,"%s%s", temp, &fraction[1] ); + ret = scratch; + } + else + { + ret = temp; + } + } +} + +class SortRequest +{ +public: + SortRequest(void) + { + + } + SortRequest(const char *sort_name,unsigned int primary_key,bool primary_ascending,unsigned int secondary_key,bool secondary_ascending) + { + if ( sort_name ) + mSortName = sort_name; + + mPrimaryKey = primary_key; + mPrimaryAscending = primary_ascending; + mSecondaryKey = secondary_key; + mSecondaryAscending = secondary_ascending; + + } + + + std::string mSortName; + unsigned int mPrimaryKey; + unsigned int mSecondaryKey; + bool mPrimaryAscending:1; + bool mSecondaryAscending:1; +}; + +typedef std::vector< SortRequest > SortRequestVector; + +typedef std::vector< std::string > StringVector; +typedef std::vector< size_t > SizetVector; + +class HtmlRow +{ +public: + HtmlRow(void) + { + mHeader = false; + mFooter = false; + } + ~HtmlRow(void) + { + } + + void setFooter(bool state) + { + mFooter = state; + } + + bool isFooter(void) const { return mFooter; }; + + void setHeader(bool state) + { + mHeader = state; + } + + bool isHeader(void) const { return mHeader; }; + + void clear(void) + { + mRow.clear(); + } + + void addCSV(const char *data,InPlaceParser &parser) + { + if ( data ) + { + size_t len = strlen(data); + if ( len ) + { + char *temp = (char *)HTML_MALLOC(sizeof(char)*(len+1)); + memcpy(temp,data,len+1); + int count; + const char **args = parser.GetArglist(temp,count); + if ( args ) + { + for (int i=0; i csizes[i] ) + { + csizes[i] = mRow[i].size(); + } + } + } + + void getString(size_t index,std::string &str) const + { + if ( index < mRow.size() ) + { + str = mRow[index]; + } + else + { + str.clear(); + } + } + + void htmlRow(FILE_INTERFACE *fph,HtmlTable *table) + { + { + fi_fprintf(fph,""); + + unsigned int column = 1; + + StringVector::iterator i; + for (i=mRow.begin(); i!=mRow.end(); ++i) + { + + unsigned int color = table->getColor(column,mHeader,mFooter); + + const char *str = (*i).c_str(); + + if ( mHeader ) + { + fi_fprintf(fph," %s ", color, str ); + } + else if ( mFooter ) + { + if ( isNumeric(str)) + { + fi_fprintf(fph," %s", color, str ); + } + else + { + fi_fprintf(fph,"%s ", color, str ); + } + } + else + { + if ( isNumeric(str)) + { + fi_fprintf(fph," %s", color, str ); + } + else + { + fi_fprintf(fph,"%s ", color, str ); + } + } + + column++; + } + + fi_fprintf(fph,"\r\n"); + } + } + + void saveExcel(FILE *fph,HtmlTable *table) + { + { + fprintf(fph,""); + + unsigned int column = 1; + + StringVector::iterator i; + for (i=mRow.begin(); i!=mRow.end(); ++i) + { + + unsigned int color = table->getColor(column,mHeader,mFooter); + + const char *str = (*i).c_str(); + + if ( mHeader ) + { + fprintf(fph," %s ", color, str ); + } + else if ( mFooter ) + { + if ( isNumeric(str)) + { + fprintf(fph," %s", color, str ); + } + else + { + fprintf(fph,"%s ", color, str ); + } + } + else + { + if ( isNumeric(str)) + { + fprintf(fph," %s", color, str ); + } + else + { + fprintf(fph,"%s ", color, str ); + } + } + + column++; + } + + fprintf(fph,"\r\n"); + } + } + + void saveCSV(FILE_INTERFACE *fph) + { + size_t count = mRow.size(); + for (size_t i=0; iaddHeader(%c%c%c%c,%c", 34, '%', 's', 34, 34, 34); + } + else + { + fi_fprintf(fph," table->addCSV(%c%c%c%c,%c", 34, '%', 's', 34, 34, 34 ); + } + + size_t count = mRow.size(); + for (size_t i=0; i v2 ) + ret = 1; + } + else + { + ret = stricmp(p1.c_str(),p2.c_str()); + + if ( ret < 0 ) + ret = -1; + else if ( ret > 0 ) + ret = 1; + + } + + if ( !s.mPrimaryAscending ) + { + ret*=-1; + } + + if ( ret == 0 ) + { + std::string p1; // secondary 1 + std::string p2; // secondary 2 + getString(s.mSecondaryKey-1,p1); + r.getString(s.mSecondaryKey-1,p2); + if (isNumeric(p1) && isNumeric(p2) ) + { + float v1 = getFloatValue(p1.c_str()); + float v2 = getFloatValue(p2.c_str()); + if ( v1 < v2 ) + ret = -1; + else if ( v1 > v2 ) + ret = 1; + } + else + { + ret = stricmp(p1.c_str(),p2.c_str()); + + if ( ret < 0 ) + ret = -1; + else if ( ret > 0 ) + ret = 1; + + } + + if ( !s.mSecondaryAscending ) + { + ret*=-1; + } + + } + + return ret; + } + +private: + bool mHeader:1; + bool mFooter:1; + StringVector mRow; +}; + +typedef std::vector< HtmlRow * > HtmlRowVector; + + +static int gTableCount=0; + +class _HtmlTable : public HtmlTable, public QuickSortPointers +{ +public: + _HtmlTable(const char *heading,HtmlDocument *parent); + + + virtual ~_HtmlTable(void) + { +// gTableCount--; +// printf("Destructed _HtmlTable(%08X) Count:%d\r\n", this, gTableCount ); + reset(); + } + + unsigned int getDisplayOrder(void) const { return mDisplayOrder; }; + + + int compare(void **p1,void **p2) + { + HtmlRow **r1 = (HtmlRow **)p1; + HtmlRow **r2 = (HtmlRow **)p2; + + HtmlRow *row1 = r1[0]; + HtmlRow *row2 = r2[0]; + + assert( !row1->isHeader() ); + assert( !row1->isFooter() ); + + assert( !row2->isHeader() ); + assert( !row2->isFooter() ); + + return row1->compare(*row2,mSortRequest); + } + + void BorderASCII(void) + { + UPPER_LEFT_BORDER = '/'; + UPPER_RIGHT_BORDER = '\\'; + + LOWER_LEFT_BORDER = '\\'; + LOWER_RIGHT_BORDER = '/'; + + TOP_SEPARATOR = '-'; + BOTTOM_SEPARATOR = '-'; + TOP_BORDER = '-'; + BOTTOM_BORDER = '-'; + LEFT_BORDER = '|'; + RIGHT_BORDER = '|'; + VERTICAL_SEPARATOR = '|'; + LEFT_SIDE_BORDER = '|'; + RIGHT_SIDE_BORDER = '|'; + CROSS_BORDER = '-'; + } + + void BorderDOS(void) + { + UPPER_LEFT_BORDER = 201; + UPPER_RIGHT_BORDER = 187; + LOWER_LEFT_BORDER = 200; + LOWER_RIGHT_BORDER = 188; + TOP_SEPARATOR = 203; + BOTTOM_SEPARATOR = 202; + TOP_BORDER = 205; + BOTTOM_BORDER = 205; + LEFT_BORDER = 186; + RIGHT_BORDER = 186; + VERTICAL_SEPARATOR = 186; + LEFT_SIDE_BORDER = 204; + RIGHT_SIDE_BORDER = 185; + CROSS_BORDER = 206; + } + + void reset(void) + { + HtmlRowVector::iterator i; + for (i=mBody.begin(); i!=mBody.end(); i++) + { + HtmlRow *row = (*i); + HTML_DELETE(HtmlRow,row); + } + mBody.clear(); + mExcludeTotals.clear(); + mCurrent = 0; + } + + void addString(std::string &str,const char *data) + { + str.push_back(34); + while ( *data ) + { + str.push_back(*data); + data++; + } + str.push_back(34); + } + + void addHeader(const char *fmt,...) + { + char data[8192]; + data[8191] = 0; + _vsnprintf(data,8191, fmt, (char *)(&fmt+1)); + + mParser.ClearHardSeparator(32); + mParser.ClearHardSeparator(9); + + if ( strstr(data,"/") ) + { + std::string sdata = data; + + while ( true ) + { + size_t len = sdata.size(); + + + std::string header1; + std::string header2; + + char *temp = (char *)HTML_MALLOC(sizeof(char)*(len+1)); + memcpy(temp,sdata.c_str(),len+1); + int count; + const char **args = mParser.GetArglist(temp,count); + + if ( args ) + { + for (int i=0; isetHeader(true); + mCurrent->addCSV(header1.c_str(),mParser); + nextRow(); + + if ( strstr(header2.c_str(),"/") ) + { + sdata = header2; // now process header2... + } + else + { + getCurrent(); + mCurrent->setHeader(true); + mCurrent->addCSV(header2.c_str(),mParser); + nextRow(); + break; + } + } + + } + else + { + getCurrent(); + mCurrent->setHeader(true); + mCurrent->addCSV(data,mParser); + nextRow(); + } + } + + void addColumn(const char *data) + { + getCurrent(); + mCurrent->addColumn(data); + } + + void addColumn(float v) + { + std::string str; + getFloat(v,str); + addColumn(str.c_str()); + } + + void addColumnHex(unsigned int v) + { + char scratch[512]; + sprintf(scratch,"$%08X",v); + addColumn(scratch); + } + + + void addColumn(int v) + { + const char *temp = formatNumber(v); + addColumn(temp); + } + + void addColumn(unsigned int v) + { + const char *temp = formatNumber((int)v); + addColumn(temp); + } + + + void addCSV(bool newRow,const char *fmt,...) + { + char data[8192]; + data[8191] = 0; + _vsnprintf(data,8191, fmt, (char *)(&fmt+1)); + + getCurrent(); + mCurrent->addCSV(data,mParser); + if ( newRow ) + { + mCurrent = 0; + } + } + + void nextRow(void) + { + mCurrent = 0; + } + + void getCurrent(void) + { + if ( mCurrent == 0 ) + { + mCurrent = HTML_NEW(HtmlRow); + mBody.push_back(mCurrent); + } + } + + + void printLeft(FILE_INTERFACE *fph,const std::string &str,size_t width) + { + size_t swid = str.size(); + assert( swid <= width ); + + size_t justify = (width-swid)-1; + fi_fprintf(fph,"%c", 32 ); + fi_fprintf(fph,"%s", str.c_str() ); + for (size_t i=0; i width ) + { + width = swid; + } + + size_t count = 0; + + size_t center = (width-swid)/2; + for (size_t i=0; i\r\n"); + fprintf(fph," %s\r\n", mHeading.c_str() ); + + + HtmlRowVector::iterator i; + for (i=mBody.begin(); i!=mBody.end(); i++) + { + HtmlRow *row = (*i); + row->saveExcel(fph,this); + } + + fprintf(fph,"\r\n"); + fprintf(fph,"

\r\n"); + fprintf(fph,"

\r\n"); + fprintf(fph,"

\r\n"); + } + + + void saveSimpleHTML(FILE_INTERFACE *fph) + { + fi_fprintf(fph,"\r\n"); + fi_fprintf(fph," \r\n", mHeading.c_str() ); + + + HtmlRowVector::iterator i; + for (i=mBody.begin(); i!=mBody.end(); i++) + { + HtmlRow *row = (*i); + row->htmlRow(fph,this); + } + + fi_fprintf(fph,"
%s
\r\n"); + fi_fprintf(fph,"

\r\n"); + fi_fprintf(fph,"

\r\n"); + fi_fprintf(fph,"

\r\n"); + } + + void saveCSV(FILE_INTERFACE *fph) + { + fi_fprintf(fph,"%s\r\n", mHeading.c_str() ); + HtmlRowVector::iterator i; + for (i=mBody.begin(); i!=mBody.end(); i++) + { + HtmlRow *row = (*i); + row->saveCSV(fph); + } + fi_fprintf(fph,"\r\n"); + } + + void saveCPP(FILE_INTERFACE *fph) + { + fi_fprintf(fph," if ( 1 )\r\n"); + fi_fprintf(fph," {\r\n"); + fi_fprintf(fph," nvidia::HtmlTable *table = document->createHtmlTable(\"%s\");\r\n", mHeading.c_str() ); + HtmlRowVector::iterator i; + for (i=mBody.begin(); i!=mBody.end(); i++) + { + HtmlRow *row = (*i); + row->saveCPP(fph); + } + + if ( mComputeTotals ) + { + for (size_t i=0; iexcludeTotals(%d);\r\n", mExcludeTotals[i] ); + } + fi_fprintf(fph," table->computeTotals();\r\n"); + } + + + if ( !mSortRequests.empty() ) + { + SortRequestVector::iterator i; + for (i=mSortRequests.begin(); i!=mSortRequests.end(); ++i) + { + SortRequest &sr = (*i); + fi_fprintf(fph," table->addSort(%c%s%c,%d,%s,%d,%s);\r\n", 34, sr.mSortName.c_str(), 34, sr.mPrimaryKey, tf(sr.mPrimaryAscending), sr.mSecondaryKey, tf(sr.mSecondaryAscending) ); + } + } + + fi_fprintf(fph," }\r\n"); + fi_fprintf(fph,"\r\n"); + } + + void sortBody(const SortRequest &sr) + { + mSortRequest = sr; + + size_t rcount = mBody.size(); + int index = 0; + + HtmlRow **rows = (HtmlRow **) HTML_MALLOC(sizeof(HtmlRow *)*rcount); + size_t *indices = (size_t *) HTML_MALLOC(sizeof(size_t)*rcount); + + + for (size_t i=0; iisHeader() ) + { + rows[index] = row; + indices[index] = i; + index++; + } + } + + qsort( (void **)rows,index); + + for (int i=0; i= 2 ) // must have at least one header row and one data row + { + + if ( mSortRequests.size() && type != HST_CPP ) + { + SortRequestVector::iterator i; + for (i=mSortRequests.begin(); i!=mSortRequests.end(); i++) + { + sortBody( (*i) ); + saveInternal(fph,type,(*i).mSortName.c_str()); + } + } + else + { + saveInternal(fph,type,""); + } + } + } + + void saveInternal(FILE_INTERFACE *fph,HtmlSaveType type,const char *secondary_caption) + { + bool totals = false; + + if ( mComputeTotals ) + { + totals = addTotalsRow(); + } + + switch ( type ) + { + case HST_SIMPLE_HTML: + saveSimpleHTML(fph); + break; + case HST_CSV: + saveCSV(fph); + break; + case HST_TEXT: + BorderASCII(); + saveText(fph,secondary_caption); + break; + case HST_TEXT_EXTENDED: + BorderDOS(); + saveText(fph,secondary_caption); + break; + case HST_CPP: + saveCPP(fph); + break; + case HST_XML: + break; + } + + if ( totals ) + { + removeTotalsRow(); + } + } + + bool excluded(size_t c) + { + bool ret = false; + + for (size_t i=0; iisHeader() ) + { + std::string str; + row->getString(column,str); + if ( isNumeric(str) ) + { + float v = getFloatValue(str.c_str()); + ret+=v; + } + } + } + return ret; + } + + bool addTotalsRow(void) + { + bool ret = false; + + if ( mBody.size() >= 2 ) + { + HtmlRow *first_row = 0; + + SizetVector csize; + HtmlRowVector::iterator i; + for (i=mBody.begin(); i!=mBody.end(); i++) + { + HtmlRow *row = (*i); + if ( !row->isHeader() && first_row == 0 ) + { + first_row = row; + } + row->columnSizes(csize); + } + if ( first_row ) + { + HtmlRow *totals = HTML_NEW(HtmlRow); + totals->setFooter(true); + size_t count = csize.size(); + for (size_t i=0; igetString(i,str); + if ( isNumeric(str) ) + { + float v = computeTotal(i); + std::string str; + getFloat(v,str); + totals->addColumn(str.c_str()); + } + else + { + if ( i == 0 ) + { + totals->addColumn("Totals"); + } + else + { + totals->addColumn(""); + } + } + ret = true; + } + else + { + totals->addColumn(""); + } + } + if ( ret ) + { + mBody.push_back(totals); + } + else + { + HTML_DELETE(HtmlRow,totals); + } + } + } + + return ret; + } + + void removeTotalsRow(void) + { + if ( mBody.size() ) + { + size_t index = mBody.size()-1; + HtmlRow *row = mBody[index]; + HTML_DELETE(HtmlRow,row); + HtmlRowVector::iterator i = mBody.end(); + i--; + mBody.erase(i); + } + } + + void saveText(FILE_INTERFACE *fph,const char *secondary_caption) + { + SizetVector csize; + HtmlRowVector::iterator i; + for (i=mBody.begin(); i!=mBody.end(); i++) + { + HtmlRow *row = (*i); + row->columnSizes(csize); + } + + size_t column_count = csize.size(); + size_t column_size = 0; + + for (size_t i=0; i 0 ) + { + printCenter(fph,secondary_caption,column_size); + fi_fprintf(fph," \r\n" ); + } + + + + //***************************************** + // Print the top border + //***************************************** + + fi_fprintf(fph,"%c",UPPER_LEFT_BORDER ); + + for (size_t i=0; igetHtmlTableInterface(); + + return ret; + } + + void computeTotals(void) // compute and display totals of numeric columns when displaying this table. + { + mComputeTotals = true; + } + + void excludeTotals(unsigned int column) + { + mExcludeTotals.push_back(column); + } + + void addSort(const char *sort_name,unsigned int primary_key,bool primary_ascending,unsigned int secondary_key,bool secondary_ascending) // adds a sorted result. You can set up mulitple sort requests for a single table. + { + SortRequest sr(sort_name,primary_key,primary_ascending,secondary_key,secondary_ascending); + mSortRequests.push_back(sr); + } + + void setColumnColor(unsigned int column,unsigned int color) // set a color for a specific column. + { + mColumnColors.push_back(column); + mColumnColors.push_back(color); + } + + void setHeaderColor(unsigned int color) // color for header lines + { + mHeaderColor = color; + } + + void setFooterColor(unsigned int color) // color for footer lines + { + mFooterColor = color; + } + + void setBodyColor(unsigned int color) + { + mBodyColor = color; + } + + unsigned int getColor(unsigned int column,bool isHeader,bool isFooter) + { + + unsigned int ret = mBodyColor; + + if ( isHeader ) + { + ret = mHeaderColor; + } + else if ( isFooter ) + { + ret = mFooterColor; + } + else + { + unsigned int count = unsigned int(mColumnColors.size())/2; + for (unsigned int i=0; i mColumnColors; + HtmlDocument *mParent; + std::string mHeading; + HtmlRow *mCurrent; + HtmlRowVector mBody; + InPlaceParser mParser; + SortRequest mSortRequest; // the current sort request... + SortRequestVector mSortRequests; + + bool mComputeTotals; + std::vector< unsigned int > mExcludeTotals; + + unsigned char UPPER_LEFT_BORDER; + unsigned char UPPER_RIGHT_BORDER; + unsigned char LOWER_LEFT_BORDER; + unsigned char LOWER_RIGHT_BORDER; + unsigned char TOP_SEPARATOR; + unsigned char BOTTOM_SEPARATOR; + unsigned char TOP_BORDER; + unsigned char BOTTOM_BORDER; + unsigned char LEFT_BORDER; + unsigned char RIGHT_BORDER; + unsigned char VERTICAL_SEPARATOR; + unsigned char LEFT_SIDE_BORDER; + unsigned char RIGHT_SIDE_BORDER; + unsigned char CROSS_BORDER; + + +}; + +typedef std::vector< _HtmlTable * > HtmlTableVector; + + +class SortTables : public QuickSortPointers +{ +public: + SortTables(unsigned int tcount,_HtmlTable **tables) + { + qsort((void **)tables,(int)tcount); + } + + virtual int compare(void **p1,void **p2) + { + _HtmlTable **tp1 = (_HtmlTable **)p1; + _HtmlTable **tp2 = (_HtmlTable **)p2; + _HtmlTable *t1 = *tp1; + _HtmlTable *t2 = *tp2; + return (int)t1->getDisplayOrder() - (int)t2->getDisplayOrder(); + } + +}; + +class _HtmlDocument : public HtmlDocument +{ +public: + _HtmlDocument(const char *document_name,HtmlTableInterface *iface) + { + mDisplayOrder = 0; + mInterface = iface; + if ( document_name ) + { + mDocumentName = document_name; + } + } + + virtual ~_HtmlDocument(void) + { + reset(); + } + + unsigned int getDisplayOrder(void) + { + mDisplayOrder++; + return mDisplayOrder; + } + + void reset(void) + { + HtmlTableVector::iterator i; + for (i=mTables.begin(); i!=mTables.end(); i++) + { + HtmlTable *t = (*i); + _HtmlTable *tt = static_cast< _HtmlTable *>(t); + HTML_DELETE(_HtmlTable,tt); + } + mTables.clear(); + } + + + const char * saveDocument(size_t &len,HtmlSaveType type) + { + const char *ret = 0; + + FILE_INTERFACE *fph = fi_fopen("temp", "wmem"); + if ( fph ) + { + + switch ( type ) + { + case HST_SIMPLE_HTML: + fi_fprintf(fph,"\r\n"); + fi_fprintf(fph,"\r\n"); + fi_fprintf(fph,"%s\r\n", mDocumentName.c_str() ); + fi_fprintf(fph,"\r\n"); + break; + case HST_CSV: + break; + case HST_CPP: +#if USE_CPP + fi_fprintf(fph,"#include \r\n"); + fi_fprintf(fph,"#include \r\n"); + fi_fprintf(fph,"#include \r\n"); + fi_fprintf(fph,"#include \r\n"); + fi_fprintf(fph,"\r\n"); + fi_fprintf(fph,"#pragma warning(disable:4996)\r\n"); + fi_fprintf(fph,"\r\n"); + fi_fprintf(fph,"#include \"HtmlTable.h\"\r\n"); + fi_fprintf(fph,"\r\n"); + + + fi_fprintf(fph,"%s\r\n","void testSave(nvidia::HtmlDocument *document,const char *fname,nvidia::HtmlSaveType type)"); + fi_fprintf(fph,"%s\r\n","{"); + fi_fprintf(fph,"%s\r\n"," size_t len;"); + fi_fprintf(fph,"%s\r\n"," const char *data = document->saveDocument(len,type);"); + fi_fprintf(fph,"%s\r\n"," if ( data )"); + fi_fprintf(fph,"%s\r\n"," {"); + fi_fprintf(fph,"%s\r\n"," printf(\"Saving document '%s' which is %d bytes long.\\r\\n\", fname, len );"); + fi_fprintf(fph,"%s\r\n"," FILE *fph = fopen(fname,\"wb\");"); + fi_fprintf(fph,"%s\r\n"," if ( fph )"); + fi_fprintf(fph,"%s\r\n"," {"); + fi_fprintf(fph,"%s\r\n"," fwrite(data,len,1,fph);"); + fi_fprintf(fph,"%s\r\n"," fclose(fph);"); + fi_fprintf(fph,"%s\r\n"," }"); + fi_fprintf(fph,"%s\r\n"," else"); + fi_fprintf(fph,"%s\r\n"," {"); + fi_fprintf(fph,"%s\r\n"," printf(\"Failed to open file for write access.\\r\\n\");"); + fi_fprintf(fph,"%s\r\n"," }"); + fi_fprintf(fph,"%s\r\n"," document->releaseDocumentMemory(data);"); + fi_fprintf(fph,"%s\r\n"," }"); + fi_fprintf(fph,"%s\r\n"," else"); + fi_fprintf(fph,"%s\r\n"," {"); + fi_fprintf(fph,"%s\r\n"," printf(\"Failed to save document %s.\\r\\n\", fname );"); + fi_fprintf(fph,"%s\r\n"," }"); + fi_fprintf(fph,"%s\r\n","}"); + + fi_fprintf(fph,"void html_test(void)\r\n"); + fi_fprintf(fph,"{\r\n"); + fi_fprintf(fph," nvidia::HtmlTableInterface *iface = nvidia::getHtmlTableInterface();\r\n"); + fi_fprintf(fph," nvidia::HtmlDocument *document = iface->createHtmlDocument(\"%s\");\r\n", mDocumentName.c_str() ); +#endif + break; + case HST_TEXT: + case HST_TEXT_EXTENDED: + fi_fprintf(fph,"[%s]\r\n", mDocumentName.c_str() ); + fi_fprintf(fph,"\r\n" ); + break; + default: + assert(0); + } + + if ( !mTables.empty() ) + { + unsigned int tcount = mTables.size(); + _HtmlTable **tables = &mTables[0]; + SortTables st( tcount, tables ); + HtmlTableVector::iterator i; + for (i=mTables.begin(); i!=mTables.end(); ++i) + { + (*i)->save(fph,type); + } + } + + switch ( type ) + { + case HST_SIMPLE_HTML: + fi_fprintf(fph,"\r\n"); + fi_fprintf(fph,"\r\n"); + fi_fprintf(fph,"\r\n"); + break; + case HST_CPP: +#if USE_CPP + fi_fprintf(fph,"%s\r\n"," testSave(document,\"table.txt\", nvidia::HST_TEXT );"); + fi_fprintf(fph,"%s\r\n"," testSave(document,\"table.html\", nvidia::HST_SIMPLE_HTML );"); + fi_fprintf(fph,"%s\r\n"," testSave(document,\"table.cpp\", nvidia::HST_CPP );"); + fi_fprintf(fph,"%s\r\n",""); + fi_fprintf(fph,"%s\r\n",""); + fi_fprintf(fph,"%s\r\n",""); + fi_fprintf(fph,"%s\r\n"," iface->releaseHtmlDocument(document);"); + fi_fprintf(fph,"%s\r\n",""); + fi_fprintf(fph,"%s\r\n","}"); +#endif + break; + case HST_CSV: + break; + case HST_TEXT: + case HST_TEXT_EXTENDED: + fi_fprintf(fph,"\r\n" ); + break; + default: + assert(0); + } + void *data = fi_getMemBuffer(fph,len); + if ( data ) + { + char *temp = (char *)HTML_MALLOC(sizeof(char)*(len+1)); + temp[len] = 0; + memcpy(temp,data,len); + ret = temp; + } + fi_fclose(fph); + } + return ret; + } + + HtmlTable * createHtmlTable(const char *heading) + { + _HtmlTable *ret = HTML_NEW(_HtmlTable)(heading,this); + mTables.push_back(ret); + return ret; + } + + void releaseDocumentMemory(const char *mem) // release memory previously allocated for a document save. + { + HTML_FREE((void *)mem); + } + + + HtmlTableInterface *getHtmlTableInterface(void) + { + return mInterface; + } + + bool saveExcel(const char *fname) // excel format can only be saved directly to files on disk, as it needs to create a sub-directory for the intermediate files. + { + bool ret = false; + + std::string dest_name; + std::string base_name; + std::string root_dir; + + + char scratch[512]; + strcpy(scratch,fname); + char *dot = lastDot(scratch); + if ( dot ) + { + strcpy(scratch,fname); + char *slash = lastSlash(scratch); + if ( slash ) + { + slash++; + char bname[512]; + strcpy(bname,slash); + dest_name = bname; + *slash = 0; + dot = lastDot(bname); + assert(dot); + if ( dot ) + { + char temp[512]; + *dot = 0; + base_name = bname; + root_dir = scratch; + sprintf(temp,"%s%s_files",scratch,bname); + _mkdir(temp); + } + } + else + { + dest_name = fname; + *dot = 0; + base_name = scratch; + char temp[512]; + sprintf(temp,"%s_files", scratch ); + _mkdir(temp); + } + } + + saveExcel(dest_name,base_name,root_dir); + + return ret; + } + + void saveExcel(const std::string &dest_name,const std::string &base_name,std::string &root_dir) + { +#if USE_EXCEL + + char scratch[512]; + sprintf(scratch,"%s%s", root_dir.c_str(), dest_name.c_str() ); + + unsigned int tableCount = unsigned int(mTables.size()); + + FILE *fph = fopen(scratch,"wb"); + + if ( fph ) + { + fprintf(fph,"%s\r\n",""); + fprintf(fph,"%s\r\n",""); + fprintf(fph,"%s\r\n",""); + fprintf(fph,"%s\r\n",""); + fprintf(fph,"%s\r\n",""); + fprintf(fph,"%s\r\n",""); + fprintf(fph,"%s\r\n",""); + fprintf(fph,"\r\n", base_name.c_str()); + fprintf(fph,"\r\n", base_name.c_str()); + fprintf(fph,"\r\n", base_name.c_str()); + fprintf(fph,"%s\r\n",""); + + { + unsigned int index = 0; + HtmlTableVector::iterator i; + for (i=mTables.begin(); i!=mTables.end(); ++i) + { + fprintf(fph,"\r\n", base_name.c_str(), index+1 ); + index++; + } + } + + + fprintf(fph,"%s\r\n",""); + fprintf(fph,"%s\r\n",""); + fprintf(fph,"%s\r\n",""); + fprintf(fph,"%s\r\n",""); + fprintf(fph,"%s\r\n",""); + fprintf(fph,"%s\r\n",""); + fprintf(fph,"%s\r\n",""); + fprintf(fph,"%s\r\n",""); + fprintf(fph," \r\n", base_name.c_str()); + fprintf(fph," \r\n", base_name.c_str()); + fprintf(fph,"%s\r\n"," "); + fprintf(fph,"%s\r\n"," <body>"); + fprintf(fph,"%s\r\n"," <p>This page uses frames, but your browser doesn't support them.</p>"); + fprintf(fph,"%s\r\n"," </body>"); + fprintf(fph,"%s\r\n"," "); + fprintf(fph,"%s\r\n",""); + fprintf(fph,"%s\r\n",""); + fclose(fph); + } + + sprintf(scratch,"%s%s_files\\filelist.xml", root_dir.c_str(), base_name.c_str() ); + fph = fopen(scratch,"wb"); + if ( fph ) + { + + fprintf(fph,"\r\n"); + fprintf(fph," \r\n", dest_name.c_str()); + fprintf(fph," \r\n"); + fprintf(fph," \r\n"); + + for (unsigned int i=0; i\r\n", i+1); + } + + fprintf(fph," \r\n"); + fprintf(fph,"\r\n"); + fclose(fph); + } + + + sprintf(scratch,"%s%s_files\\stylesheet.css", root_dir.c_str(), base_name.c_str() ); + fph = fopen(scratch,"wb"); + if ( fph ) + { + fprintf(fph,"%s\r\n", "tr"); + fprintf(fph,"%s\r\n", " {mso-height-source:auto;}"); + fprintf(fph,"%s\r\n", "col"); + fprintf(fph,"%s\r\n", " {mso-width-source:auto;}"); + fprintf(fph,"%s\r\n", "br"); + fprintf(fph,"%s\r\n", " {mso-data-placement:same-cell;}"); + fprintf(fph,"%s\r\n", ".style0"); + fprintf(fph,"%s\r\n", " {mso-number-format:General;"); + fprintf(fph,"%s\r\n", " text-align:general;"); + fprintf(fph,"%s\r\n", " vertical-align:bottom;"); + fprintf(fph,"%s\r\n", " white-space:nowrap;"); + fprintf(fph,"%s\r\n", " mso-rotate:0;"); + fprintf(fph,"%s\r\n", " mso-background-source:auto;"); + fprintf(fph,"%s\r\n", " mso-pattern:auto;"); + fprintf(fph,"%s\r\n", " color:windowtext;"); + fprintf(fph,"%s\r\n", " font-size:10.0pt;"); + fprintf(fph,"%s\r\n", " font-weight:400;"); + fprintf(fph,"%s\r\n", " font-style:normal;"); + fprintf(fph,"%s\r\n", " text-decoration:none;"); + fprintf(fph,"%s\r\n", " font-family:Arial;"); + fprintf(fph,"%s\r\n", " mso-generic-font-family:auto;"); + fprintf(fph,"%s\r\n", " mso-font-charset:0;"); + fprintf(fph,"%s\r\n", " border:none;"); + fprintf(fph,"%s\r\n", " mso-protection:locked visible;"); + fprintf(fph,"%s\r\n", " mso-style-name:Normal;"); + fprintf(fph,"%s\r\n", " mso-style-id:0;}"); + fprintf(fph,"%s\r\n", "td"); + fprintf(fph,"%s\r\n", " {mso-style-parent:style0;"); + fprintf(fph,"%s\r\n", " padding-top:1px;"); + fprintf(fph,"%s\r\n", " padding-right:1px;"); + fprintf(fph,"%s\r\n", " padding-left:1px;"); + fprintf(fph,"%s\r\n", " mso-ignore:padding;"); + fprintf(fph,"%s\r\n", " color:windowtext;"); + fprintf(fph,"%s\r\n", " font-size:10.0pt;"); + fprintf(fph,"%s\r\n", " font-weight:400;"); + fprintf(fph,"%s\r\n", " font-style:normal;"); + fprintf(fph,"%s\r\n", " text-decoration:none;"); + fprintf(fph,"%s\r\n", " font-family:Arial;"); + fprintf(fph,"%s\r\n", " mso-generic-font-family:auto;"); + fprintf(fph,"%s\r\n", " mso-font-charset:0;"); + fprintf(fph,"%s\r\n", " mso-number-format:General;"); + fprintf(fph,"%s\r\n", " text-align:general;"); + fprintf(fph,"%s\r\n", " vertical-align:bottom;"); + fprintf(fph,"%s\r\n", " border:none;"); + fprintf(fph,"%s\r\n", " mso-background-source:auto;"); + fprintf(fph,"%s\r\n", " mso-pattern:auto;"); + fprintf(fph,"%s\r\n", " mso-protection:locked visible;"); + fprintf(fph,"%s\r\n", " white-space:nowrap;"); + fprintf(fph,"%s\r\n", " mso-rotate:0;}"); + fclose(fph); + } + + sprintf(scratch,"%s%s_files\\tabstrip.htm", root_dir.c_str(), base_name.c_str() ); + fph = fopen(scratch,"wb"); + if ( fph ) + { + fprintf(fph,"\r\n"); + fprintf(fph,"\r\n"); + fprintf(fph,"\r\n"); + fprintf(fph,"\r\n"); + fprintf(fph,"\r\n"); + fprintf(fph,"\r\n", dest_name.c_str()); + fprintf(fph,"\r\n"); + fprintf(fph,"\r\n"); + fprintf(fph,"\r\n"); + fprintf(fph,"\r\n"); + fprintf(fph,"\r\n"); + fprintf(fph,"\r\n"); + fprintf(fph," \r\n"); + for (unsigned int i=0; i Sheet%d \r\n", i+1, i+1); + } + fprintf(fph,"\r\n"); + fprintf(fph," \r\n"); + fprintf(fph,"
\r\n"); + fprintf(fph,"\r\n"); + fprintf(fph,"\r\n"); + fclose(fph); + } + + + { + unsigned int index = 0; + HtmlTableVector::iterator i; + for (i=mTables.begin(); i!=mTables.end(); ++i) + { + _HtmlTable *table = (*i); + sprintf(scratch,"%s%s_files\\sheet%03d.htm", root_dir.c_str(), base_name.c_str(), index+1 ); + fph = fopen(scratch,"wb"); + if ( fph ) + { + + fprintf(fph,"\r\n"); + fprintf(fph,"\r\n"); + fprintf(fph,"\r\n"); + fprintf(fph,"\r\n"); + fprintf(fph,"\r\n"); + fprintf(fph,"\r\n"); + fprintf(fph,"\r\n", dest_name.c_str()); + fprintf(fph,"\r\n"); + fprintf(fph,"\r\n"); + fprintf(fph,"\r\n"); + fprintf(fph,"\r\n"); + fprintf(fph,"\r\n"); + fprintf(fph,"\r\n"); + fprintf(fph,"\r\n"); + fprintf(fph,"\r\n"); + fprintf(fph,"\r\n"); + fprintf(fph,"\r\n"); + table->saveExcel(fph); +/****** + fprintf(fph,"\r\n"); + fprintf(fph," \r\n"); + fprintf(fph," \r\n"); + fprintf(fph," \r\n"); + fprintf(fph," \r\n"); + fprintf(fph," \r\n"); + fprintf(fph," \r\n"); + fprintf(fph," \r\n"); + fprintf(fph," \r\n"); + fprintf(fph," \r\n"); + fprintf(fph," \r\n"); + fprintf(fph," \r\n"); + fprintf(fph," \r\n"); + fprintf(fph," \r\n"); + fprintf(fph," \r\n"); + fprintf(fph," \r\n"); + fprintf(fph," \r\n"); + fprintf(fph," \r\n"); + fprintf(fph," \r\n"); + fprintf(fph," \r\n"); + fprintf(fph,"
ab
12
34
\r\n"); +***/ + fprintf(fph,"\r\n"); + fprintf(fph,"\r\n"); + fprintf(fph,"\r\n"); + fprintf(fph,"\r\n"); + fclose(fph); + } + index++; + } + } + + + +#endif + } + + +private: + unsigned int mDisplayOrder; + std::string mDocumentName; + HtmlTableVector mTables; + HtmlTableInterface *mInterface; +}; + + _HtmlTable::_HtmlTable(const char *heading,HtmlDocument *parent) + { +// gTableCount++; +// printf("Constructed _HtmlTable(%08X) Count:%d\r\n", this,gTableCount ); + + _HtmlDocument *hd = static_cast< _HtmlDocument *>(parent); + mDisplayOrder = hd->getDisplayOrder(); + + mHeaderColor = 0x00FFFF; + mFooterColor = 0xCCFFFF; + mBodyColor = 0xCCFFCC; + + mParent = parent; + if ( heading ) + { + mHeading = heading; + } + mComputeTotals = false; + + mCurrent = 0; + mParser.ClearHardSeparator(32); + mParser.ClearHardSeparator(9); + mParser.SetHard(','); + } + + +class MyHtmlTableInterface : public HtmlTableInterface +{ +public: + + HtmlDocument * createHtmlDocument(const char *document_name) + { + HtmlDocument *ret = 0; + + ret = HTML_NEW(_HtmlDocument)(document_name,this); + + return ret; + } + + void releaseHtmlDocument(HtmlDocument *document) // release a previously created HTML document + { + assert(document); + _HtmlDocument *doc = static_cast< _HtmlDocument *>(document); + HTML_DELETE(_HtmlDocument,doc); + } + + +}; // + +}; // end of namespace + +namespace nvidia +{ +using namespace HTMLTABLE_NVSHARE; + +static MyHtmlTableInterface *gInterface=NULL; + +HtmlTableInterface *getHtmlTableInterface(void) +{ + if ( gInterface == NULL ) + { + gInterface = new MyHtmlTableInterface; + } + return gInterface; +} + +int getHtmlMemoryUsage(void) +{ + return gMemTracker.getMemoryUsage(); +} + +}; + +#endif \ No newline at end of file -- cgit v1.2.3