1 | /* $Id: kHtmlPC.cpp,v 1.2 2000-02-12 17:55:03 bird Exp $ */
|
---|
2 | /*
|
---|
3 | * kHtmlPC - Special-purpose HTML/SQL preprocessor.
|
---|
4 | *
|
---|
5 | * Copyright (c) 1999 knut st. osmundsen
|
---|
6 | *
|
---|
7 | */
|
---|
8 |
|
---|
9 | /*******************************************************************************
|
---|
10 | * Defined Constants *
|
---|
11 | *******************************************************************************/
|
---|
12 | #define ErrorDescCase(errorcode) case errorcode: return formatMessage(#errorcode)
|
---|
13 | #define TAG_PARAMETER_LIST \
|
---|
14 | const kTag &tag, \
|
---|
15 | kLIFO<kFileEntry> &lifoFile, \
|
---|
16 | kLIFO<kFileEntry> &lifoUsed, \
|
---|
17 | kLIFO<kVariableEntry> &lifoVar, \
|
---|
18 | kLIFO2<kSqlEntry, kVariableEntry> &lifoSql, \
|
---|
19 | kFileEntry * &pCurFile, \
|
---|
20 | int &i, \
|
---|
21 | FILE *phLog
|
---|
22 |
|
---|
23 | #define TAG_PARAMETERS tag, lifoFile, lifoUsed, lifoVar, lifoSql, pCurFile, i, phLog
|
---|
24 | #define TAG_PARAMETER_LIST_UNREF \
|
---|
25 | int f = phLog || i || pCurFile || &lifoFile || \
|
---|
26 | &lifoUsed || &lifoVar || &lifoSql || &tag; \
|
---|
27 | f = f
|
---|
28 |
|
---|
29 | #ifdef __EMX__
|
---|
30 | #define max(a,b) (((a) > (b)) ? (a) : (b))
|
---|
31 | #define min(a,b) (((a) < (b)) ? (a) : (b))
|
---|
32 | #define _System
|
---|
33 | #endif
|
---|
34 |
|
---|
35 | #define TRUE 1
|
---|
36 | #define FALSE 0
|
---|
37 | #define CCHMAXPATH 260
|
---|
38 |
|
---|
39 |
|
---|
40 | /*******************************************************************************
|
---|
41 | * Structures and Typedefs *
|
---|
42 | *******************************************************************************/
|
---|
43 | typedef unsigned long BOOL;
|
---|
44 | typedef struct _POINTL
|
---|
45 | {
|
---|
46 | long x;
|
---|
47 | long y;
|
---|
48 | } POINTL, *PPOINTL;
|
---|
49 |
|
---|
50 |
|
---|
51 | /*******************************************************************************
|
---|
52 | * Header Files *
|
---|
53 | *******************************************************************************/
|
---|
54 | #include <stdio.h>
|
---|
55 | #include <stdlib.h>
|
---|
56 | #include <string.h>
|
---|
57 | #include <signal.h>
|
---|
58 | #include <malloc.h>
|
---|
59 | #ifdef __EMX__
|
---|
60 | #include <math.h>
|
---|
61 | #undef _NAN
|
---|
62 | static double _NAN = (0.0/0.0);
|
---|
63 | #else
|
---|
64 | #include <float.h>
|
---|
65 | #endif
|
---|
66 | #include <assert.h>
|
---|
67 | /* gifdraw */
|
---|
68 | extern "C"
|
---|
69 | {
|
---|
70 | #include "gd/gd.h"
|
---|
71 | #include "gd/gdfontg.h"
|
---|
72 | #include "gd/gdfontl.h"
|
---|
73 | #include "gd/gdfonts.h"
|
---|
74 | /* Y wrappers; LB = origo at Left Botton corner */
|
---|
75 | #define gdImageLineLB(im,x1,y1,x2,y2,cl) gdImageLine(im,x1,gdImageSY(im)-(y1),x2,gdImageSY(im)-(y2),cl)
|
---|
76 | #define gdImageStringLB(im,f,x,y,s,cl) gdImageString(im,f,x,gdImageSY(im)-(y),s,cl)
|
---|
77 | #define gdImageStringUpLB(im,f,x,y,s,cl) gdImageStringUp(im,f,x,gdImageSY(im)-(y),s,cl)
|
---|
78 | }
|
---|
79 |
|
---|
80 | #include "kLIFO.h"
|
---|
81 | #include "kList.h"
|
---|
82 | #include "kHtmlPC.h"
|
---|
83 | #include "db.h"
|
---|
84 |
|
---|
85 | /*@Struct***********************************************************************
|
---|
86 | * Structures and Typedefs *
|
---|
87 | *******************************************************************************/
|
---|
88 | typedef struct _GraphCallBackParameters
|
---|
89 | {
|
---|
90 | kGraph *pGraph;
|
---|
91 | kGraphDataSet *pDataSet;
|
---|
92 | kGraphData *pData;
|
---|
93 | kGraph::enmType enmTypeCd;
|
---|
94 | long lSeqNbr;
|
---|
95 | char *pszLegend;
|
---|
96 | char *pszColor;
|
---|
97 | } GRAPHCALLBACKPARAM, *PGRAPHCALLBACKPARAM;
|
---|
98 |
|
---|
99 |
|
---|
100 |
|
---|
101 | /*******************************************************************************
|
---|
102 | * Global Variables *
|
---|
103 | *******************************************************************************/
|
---|
104 | static FILE *phLog = NULL;
|
---|
105 |
|
---|
106 |
|
---|
107 | /*******************************************************************************
|
---|
108 | * Internal Functions *
|
---|
109 | *******************************************************************************/
|
---|
110 | extern "C" void handler(int sig);
|
---|
111 | static void syntax(void);
|
---|
112 | static void openLog(void);
|
---|
113 | static void closeLog(void);
|
---|
114 | static unsigned long processFile(const char *pszFilename/*, const POPTIONS pOptions*/);
|
---|
115 | static unsigned long tagEndkSql(TAG_PARAMETER_LIST);
|
---|
116 | static unsigned long tagkSql(TAG_PARAMETER_LIST);
|
---|
117 | static unsigned long tagkTemplate(TAG_PARAMETER_LIST, FILE * &phFile);
|
---|
118 | static unsigned long tagkInclude(TAG_PARAMETER_LIST);
|
---|
119 | static unsigned long tagkGraph(TAG_PARAMETER_LIST);
|
---|
120 | static unsigned long tagkDefine(TAG_PARAMETER_LIST);
|
---|
121 | static unsigned long tagkUndef(TAG_PARAMETER_LIST);
|
---|
122 | static unsigned long tagkIf(TAG_PARAMETER_LIST);
|
---|
123 | static unsigned long tagkElse(TAG_PARAMETER_LIST);
|
---|
124 | static unsigned long tagkEndif(TAG_PARAMETER_LIST);
|
---|
125 |
|
---|
126 | static BOOL rebuildFileLIFO(kLIFO<kFileEntry> &lifoFile, kLIFO<kFileEntry> &lifoUsed, const kFileEntry *pFileEntryTop);
|
---|
127 | static char *dupeString(const char *psz);
|
---|
128 | #if 0
|
---|
129 | inline char upcase(char ch);
|
---|
130 | static char *stristr(const char *pszStr, const char *pszSubStr);
|
---|
131 | static char *trim(char *psz);
|
---|
132 | static char *ltrim(char *psz);
|
---|
133 | static const char *ltrim(const char *psz);
|
---|
134 | static char *ltrimL(char *psz);
|
---|
135 | #endif
|
---|
136 | static const char *ltrimL(const char *psz);
|
---|
137 | static long _System dbFetchCallBack(const char *pszValue, const char *pszFieldName, void *pvUser);
|
---|
138 | long _System dbDataSetCallBack(const char *pszValue, const char *pszFieldName, void *pvUser);
|
---|
139 | long _System dbGraphCallBack(const char *pszValue, const char *pszFieldName, void *pvUser);
|
---|
140 |
|
---|
141 |
|
---|
142 | /**
|
---|
143 | * Main function.
|
---|
144 | * @returns Number of errors
|
---|
145 | * @param argc Argument count.
|
---|
146 | * @param argv Argument array.
|
---|
147 | */
|
---|
148 | int main(int argc, char **argv)
|
---|
149 | {
|
---|
150 | int argi;
|
---|
151 | BOOL fFatal = FALSE;
|
---|
152 | unsigned long ulRc = 0;
|
---|
153 | char *pszHost = "localhost";
|
---|
154 | char *pszDatabase = "Odin32";
|
---|
155 | char *pszUser = "root";
|
---|
156 | char *pszPasswd = "";
|
---|
157 |
|
---|
158 | /* signal handler */
|
---|
159 | if (SIG_ERR == signal(SIGBREAK, handler)
|
---|
160 | || SIG_ERR == signal(SIGTERM, handler)
|
---|
161 | || SIG_ERR == signal(SIGINT, handler)
|
---|
162 | )
|
---|
163 | fprintf(stderr, "Error installing signalhandler...");
|
---|
164 |
|
---|
165 |
|
---|
166 | /**************************************************************************
|
---|
167 | * parse arguments.
|
---|
168 | * options: -h or -? help
|
---|
169 | * -d:<dbname> Database name
|
---|
170 | * -p:<passwd> Password
|
---|
171 | * -u:<user> Userid
|
---|
172 | * -h:<host> Hostname/IP-address
|
---|
173 | **************************************************************************/
|
---|
174 | if (argc == 1)
|
---|
175 | syntax();
|
---|
176 | argi = 1;
|
---|
177 | while (argi < argc && !fFatal)
|
---|
178 | {
|
---|
179 | if(argv[argi][0] == '-' || argv[argi][0] == '/')
|
---|
180 | {
|
---|
181 | switch (argv[argi][1])
|
---|
182 | {
|
---|
183 | case 'd':
|
---|
184 | case 'D':
|
---|
185 | if (argv[argi][2] == ':')
|
---|
186 | pszDatabase = &argv[argi][3];
|
---|
187 | else
|
---|
188 | fprintf(stderr, "warning: option '-d:' requires database name.\n");
|
---|
189 | break;
|
---|
190 |
|
---|
191 | case 'h':
|
---|
192 | case 'H':
|
---|
193 | if (argv[argi][2] == ':')
|
---|
194 | {
|
---|
195 | pszHost = &argv[argi][3];
|
---|
196 | break;
|
---|
197 | }
|
---|
198 | case '?':
|
---|
199 | syntax();
|
---|
200 | return 0;
|
---|
201 |
|
---|
202 | case 'p':
|
---|
203 | case 'P':
|
---|
204 | if (argv[argi][2] == ':')
|
---|
205 | pszPasswd = &argv[argi][3];
|
---|
206 | else
|
---|
207 | fprintf(stderr, "warning: option '-p:' requires password.\n");
|
---|
208 | break;
|
---|
209 |
|
---|
210 | case 'u':
|
---|
211 | case 'U':
|
---|
212 | if (argv[argi][2] == ':')
|
---|
213 | pszUser = &argv[argi][3];
|
---|
214 | else
|
---|
215 | fprintf(stderr, "error: option '-u:' requires userid.\n");
|
---|
216 | break;
|
---|
217 |
|
---|
218 | /*
|
---|
219 | options.fSomeOption = argv[argi][2] != '-';
|
---|
220 | break;
|
---|
221 | */
|
---|
222 |
|
---|
223 | default:
|
---|
224 | fprintf(stderr, "incorrect parameter. (argi=%d, argv[argi]=%s)\n", argi, argv[argi]);
|
---|
225 | fFatal = TRUE;
|
---|
226 | break;
|
---|
227 | }
|
---|
228 | }
|
---|
229 | else
|
---|
230 | {
|
---|
231 | if (phLog == NULL)
|
---|
232 | openLog();
|
---|
233 | if (dbConnect(pszHost, pszUser, pszPasswd, pszDatabase))
|
---|
234 | {
|
---|
235 | ulRc += processFile(argv[argi]/*, &options*/);
|
---|
236 | dbDisconnect();
|
---|
237 | }
|
---|
238 | else
|
---|
239 | fprintf(phLog, "Error connecting to database.\n");
|
---|
240 | }
|
---|
241 | argi++;
|
---|
242 | }
|
---|
243 |
|
---|
244 | /* close the log */
|
---|
245 | closeLog();
|
---|
246 |
|
---|
247 | /* warn if error during processing. */
|
---|
248 | if (!fFatal)
|
---|
249 | fprintf(stderr, "kHTMLPreCompiler compleated with %ld error%s and %ld warning%s.\n",
|
---|
250 | ulRc & 0x0000ffffUL, (ulRc & 0x0000ffffUL) != 1 ? "s" : "",
|
---|
251 | ulRc >> 16, (ulRc >> 16) != 1 ? "s" : ""
|
---|
252 | );
|
---|
253 | return (int)(ulRc & 0x0000ffff);
|
---|
254 | }
|
---|
255 |
|
---|
256 |
|
---|
257 | /**
|
---|
258 | * signal handler....
|
---|
259 | * @param sig
|
---|
260 | * @remark Needs to flush files before termination. (debugging purpose)
|
---|
261 | */
|
---|
262 | void handler(int sig)
|
---|
263 | {
|
---|
264 | fprintf(stderr, "\n\t!signal %d!\n", sig);
|
---|
265 | flushall();
|
---|
266 | dbDisconnect();
|
---|
267 | exit(-1);
|
---|
268 | }
|
---|
269 |
|
---|
270 | /**
|
---|
271 | * Display syntax.
|
---|
272 | */
|
---|
273 | static void syntax(void)
|
---|
274 | {
|
---|
275 | printf("\n"
|
---|
276 | "kHtmlPC v%01d.%02d - General-purpose HTML precompiler.\n"
|
---|
277 | "-------------------------------------------------\n"
|
---|
278 | "syntax: kHtmlPc.exe [-h|-?] [options] [file1 [file2 [..]]\n"
|
---|
279 | "\n"
|
---|
280 | " -h or -? Syntax help. (this)\n"
|
---|
281 | " -h:<hostname> Database server hostname. default: localhost\n"
|
---|
282 | " -u:<username> Username on the server. default: root\n"
|
---|
283 | " -p:<password> Password. default: <empty>\n"
|
---|
284 | " -d:<database> Database to use. default: Odin32\n"
|
---|
285 | "\n"
|
---|
286 | "\n"
|
---|
287 | "Copyright (c) 1999 knut st. osmundsen (knut.stange.osmundsen@pmsc.no)",
|
---|
288 | VER_MAJOR, VER_MINOR
|
---|
289 | );
|
---|
290 | }
|
---|
291 |
|
---|
292 |
|
---|
293 | /**
|
---|
294 | * Opens log file. Currently this we don't use a logfile, stderr is our logfile.
|
---|
295 | */
|
---|
296 | static void openLog(void)
|
---|
297 | {
|
---|
298 | #if 0
|
---|
299 | if (phLog == NULL)
|
---|
300 | {
|
---|
301 | phLog = fopen("APIImport.Log", "w");
|
---|
302 | if (phLog == NULL)
|
---|
303 | {
|
---|
304 | fprintf(stderr,"error occured while opening log file - will use stderr instead.\n");
|
---|
305 | phLog = stderr;
|
---|
306 | }
|
---|
307 | }
|
---|
308 | #else
|
---|
309 | phLog = stderr;
|
---|
310 | #endif
|
---|
311 | }
|
---|
312 |
|
---|
313 |
|
---|
314 | /**
|
---|
315 | * Closes the log.
|
---|
316 | */
|
---|
317 | static void closeLog(void)
|
---|
318 | {
|
---|
319 | if (phLog != stderr && phLog != NULL)
|
---|
320 | fclose(phLog);
|
---|
321 | }
|
---|
322 |
|
---|
323 |
|
---|
324 | /**
|
---|
325 | * Preprocesses a file.
|
---|
326 | * @returns high word Number of warnings.
|
---|
327 | * low word Number of errors;
|
---|
328 | * @param pszFilename Pointer to filename.
|
---|
329 | * @param pOption Pointer to the option struct.
|
---|
330 | * @remark Big function!
|
---|
331 | */
|
---|
332 | static unsigned long processFile(const char *pszFilename/*, const POPTIONS pOptions*/)
|
---|
333 | {
|
---|
334 | unsigned long ulRc = 0;
|
---|
335 | unsigned long ulRc2;
|
---|
336 | FILE *phFile = NULL; /* Current output file. */
|
---|
337 | kLIFO<kFileEntry> lifoFile, lifoUsed;
|
---|
338 | kLIFO<kVariableEntry> lifoVar; /* tags not implemented yet... */
|
---|
339 | kLIFO2<kSqlEntry, kVariableEntry> lifoSql;
|
---|
340 | kFileEntry *pCurFile;
|
---|
341 | const kVariableEntry *pVariable = NULL;
|
---|
342 | const char *psz;
|
---|
343 | char szVariable[81];
|
---|
344 |
|
---|
345 | /* open initial file */
|
---|
346 | try
|
---|
347 | {
|
---|
348 | pCurFile = new kFileEntry(pszFilename);
|
---|
349 | }
|
---|
350 | catch (int errorcode)
|
---|
351 | {
|
---|
352 | fprintf(phLog, "error opening initial file. errorcode = %d\n", errorcode);
|
---|
353 | return 0x00000001;
|
---|
354 | }
|
---|
355 |
|
---|
356 | /* loop on pCurFile */
|
---|
357 | while (pCurFile != NULL)
|
---|
358 | {
|
---|
359 | /* loop on curFile->pszCurrent */
|
---|
360 | while (pCurFile->pszCurrent != NULL && *pCurFile->pszCurrent != '\0')
|
---|
361 | {
|
---|
362 | /*********/
|
---|
363 | /* !kTag */
|
---|
364 | /*********/
|
---|
365 | if (pCurFile->pszCurrent[0] == '<' && pCurFile->pszCurrent[1] == '!')
|
---|
366 | { /* find end, replace variables and switch tag type. */
|
---|
367 | char szTag[1024];
|
---|
368 | BOOL fQuote = FALSE;
|
---|
369 | int i = 0, j = 0;
|
---|
370 |
|
---|
371 | /* copy tag and insert variables */
|
---|
372 | while ((fQuote || pCurFile->pszCurrent[i] != '>') && pCurFile->pszCurrent[i] != '\0'
|
---|
373 | && j < (int)sizeof(szTag))
|
---|
374 | {
|
---|
375 | fQuote = fQuote ? pCurFile->pszCurrent[i] != '"' : pCurFile->pszCurrent[i] == '"';
|
---|
376 | /* variable? */
|
---|
377 | if (pCurFile->pszCurrent[i] == '$' && pCurFile->pszCurrent[i+1] == '(')
|
---|
378 | {
|
---|
379 | psz = pCurFile->pszCurrent + i + 2;
|
---|
380 | while (*psz != ')' && *psz != '\0' && (psz - &pCurFile->pszCurrent[i]) < (int)(sizeof(szVariable)-1))
|
---|
381 | psz++;
|
---|
382 | if (*psz == ')')
|
---|
383 | {
|
---|
384 | strncpy(&szVariable[0], pCurFile->pszCurrent + i + 2, psz - &pCurFile->pszCurrent[i] - 2);
|
---|
385 | szVariable[psz - &pCurFile->pszCurrent[i] - 2] = '\0';
|
---|
386 |
|
---|
387 | pVariable = lifoSql.findSub(&szVariable[0]);
|
---|
388 | if (pVariable == NULL)
|
---|
389 | pVariable = lifoVar.find(&szVariable[0]);
|
---|
390 |
|
---|
391 | if (pVariable != NULL)
|
---|
392 | {
|
---|
393 | if(j + strlen(pVariable->getValue()) < sizeof(szTag))
|
---|
394 | { /* copy variable value */
|
---|
395 | strcpy(&szTag[j], pVariable->getValue());
|
---|
396 | j += strlen(&szTag[j]) - 1;
|
---|
397 | i += psz - &pCurFile->pszCurrent[i];
|
---|
398 | }
|
---|
399 | else
|
---|
400 | { /* warning - complain, skip and continue */
|
---|
401 | fprintf(phLog, "%s(%ld) : warning: Variable '%s' out of space, increase the size of szTag.\n",
|
---|
402 | pCurFile->getFilename(), pCurFile->getLineNumber()+1, &szVariable[0]);
|
---|
403 | szTag[j] = pCurFile->pszCurrent[i];
|
---|
404 | }
|
---|
405 | }
|
---|
406 | else
|
---|
407 | { /* warning - complain, skip and continue */
|
---|
408 | fprintf(phLog, "%s(%ld) : warning: Variable '%s' not defined.\n",
|
---|
409 | pCurFile->getFilename(), pCurFile->getLineNumber()+1, &szVariable[0]);
|
---|
410 | szTag[j] = pCurFile->pszCurrent[i];
|
---|
411 | }
|
---|
412 | }
|
---|
413 | else
|
---|
414 | { /* error - complain, skip and continue. */
|
---|
415 | fprintf(phLog, "%s(%ld) : error: Missing left parenthese on variable expression\n",
|
---|
416 | pCurFile->getFilename(), pCurFile->getLineNumber()+1);
|
---|
417 | szTag[j] = pCurFile->pszCurrent[i];
|
---|
418 | }
|
---|
419 | }
|
---|
420 | else
|
---|
421 | szTag[j] = pCurFile->pszCurrent[i];
|
---|
422 | /* next */
|
---|
423 | i++;
|
---|
424 | j++;
|
---|
425 | }
|
---|
426 |
|
---|
427 |
|
---|
428 | /* copy ok? */
|
---|
429 | if (j < (int)sizeof(szTag) && pCurFile->pszCurrent[i] == '>')
|
---|
430 | {
|
---|
431 | szTag[j++] = '>';
|
---|
432 | szTag[j] = '\0';
|
---|
433 | i++;
|
---|
434 | try
|
---|
435 | {
|
---|
436 | /* try create tag object */
|
---|
437 | kTag tag(&szTag[0]);
|
---|
438 |
|
---|
439 | /* check for warning */
|
---|
440 | if (tag.queryWarning() != NULL)
|
---|
441 | fprintf(phLog, "%s(%ld) : warning: tag warning - %s.\n",
|
---|
442 | pCurFile->getFilename(), pCurFile->getLineNumber()+1, tag.queryWarning());
|
---|
443 |
|
---|
444 |
|
---|
445 | /**************/
|
---|
446 | /**************/
|
---|
447 | /* tag switch */
|
---|
448 | /**************/
|
---|
449 | /**************/
|
---|
450 | ulRc2 = 0;
|
---|
451 | if (tag.isTag("!kSql")) /* !kSql */
|
---|
452 | ulRc2 = tagkSql(TAG_PARAMETERS);
|
---|
453 | else if (tag.isTag("!/kSql")) /* !/kSql */
|
---|
454 | ulRc2 = tagEndkSql(TAG_PARAMETERS);
|
---|
455 | else if (tag.isTag("!kTemplate")) /* !kTemplate */
|
---|
456 | ulRc2 = tagkTemplate(TAG_PARAMETERS, phFile);
|
---|
457 | else if (tag.isTag("!kInclude")) /* !kInclude */
|
---|
458 | ulRc2 = tagkInclude(TAG_PARAMETERS);
|
---|
459 | else if (tag.isTag("!kGraph")) /* !kGraph */
|
---|
460 | ulRc2 = tagkGraph(TAG_PARAMETERS);
|
---|
461 | else if (tag.isTag("!kDefine")) /* !kDefine */
|
---|
462 | ulRc2 = tagkDefine(TAG_PARAMETERS);
|
---|
463 | else if (tag.isTag("!kUndef")) /* !kUndef */
|
---|
464 | ulRc2 = tagkUndef(TAG_PARAMETERS);
|
---|
465 | else if (tag.isTag("!kIf")) /* !kIf */
|
---|
466 | ulRc2 = tagkIf(TAG_PARAMETERS);
|
---|
467 | else if (tag.isTag("!kElse")) /* !kElse */
|
---|
468 | ulRc2 = tagkElse(TAG_PARAMETERS);
|
---|
469 | else if (tag.isTag("!kEndif")) /* !kEndif */
|
---|
470 | ulRc2 = tagkEndif(TAG_PARAMETERS);
|
---|
471 | else
|
---|
472 | {
|
---|
473 | if (phFile != NULL)
|
---|
474 | fputc(*pCurFile->pszCurrent, phFile); /* if this proove to be very slow, we'll have to buffer writes better. */
|
---|
475 | pCurFile->pszCurrent++;
|
---|
476 | }
|
---|
477 |
|
---|
478 | /* if error occurred - skip and continue. */
|
---|
479 | if ((ulRc2 & 0x0000ffff) != 0)
|
---|
480 | {
|
---|
481 | if (phFile != NULL)
|
---|
482 | fputc(*pCurFile->pszCurrent, phFile); /* if this proove to be very slow, we'll have to buffer writes better. */
|
---|
483 | pCurFile->pszCurrent++;
|
---|
484 | }
|
---|
485 | ulRc += ulRc2;
|
---|
486 | }
|
---|
487 | catch (kError::enmErrors enmErrorCd)
|
---|
488 | {
|
---|
489 | fprintf(phLog, "%s(%ld) : error: tag error - %s.\n",
|
---|
490 | pCurFile->getFilename(), pCurFile->getLineNumber()+1, kError::queryDescription(enmErrorCd));
|
---|
491 | if (phFile != NULL)
|
---|
492 | fputc(*pCurFile->pszCurrent, phFile); /* if this proove to be very slow, we'll have to buffer writes better. */
|
---|
493 | pCurFile->pszCurrent++;
|
---|
494 | ulRc += 0x00000001;
|
---|
495 | }
|
---|
496 | }
|
---|
497 | else
|
---|
498 | {
|
---|
499 | fprintf(phLog, "%s(%ld) : error: error occurred extracting tag.\n\tPossible reasons: unbalanced quotes, missing '>',...\n",
|
---|
500 | pCurFile->getFilename(), pCurFile->getLineNumber()+1);
|
---|
501 | if (phFile != NULL)
|
---|
502 | fputc(*pCurFile->pszCurrent, phFile); /* if this proove to be very slow, we'll have to buffer writes better. */
|
---|
503 | pCurFile->pszCurrent++;
|
---|
504 | ulRc += 0x00000001;
|
---|
505 | }
|
---|
506 |
|
---|
507 | }
|
---|
508 | /*************/
|
---|
509 | /*************/
|
---|
510 | /* VARIABLE */
|
---|
511 | /*************/
|
---|
512 | /*************/
|
---|
513 | else if (pCurFile->pszCurrent[0] == '$' && pCurFile->pszCurrent[1] == '(')
|
---|
514 | {
|
---|
515 | psz = pCurFile->pszCurrent + 2;
|
---|
516 | while (*psz != ')' && *psz != '\0' && (psz - pCurFile->pszCurrent) < (int)(sizeof(szVariable)-1))
|
---|
517 | psz++;
|
---|
518 | if (*psz == ')')
|
---|
519 | {
|
---|
520 | strncpy(&szVariable[0], pCurFile->pszCurrent+2, psz - pCurFile->pszCurrent-2);
|
---|
521 | szVariable[psz - pCurFile->pszCurrent - 2] = '\0';
|
---|
522 |
|
---|
523 | pVariable = lifoSql.findSub(&szVariable[0]);
|
---|
524 | if (pVariable == NULL)
|
---|
525 | pVariable = lifoVar.find(&szVariable[0]);
|
---|
526 |
|
---|
527 | if (pVariable != NULL)
|
---|
528 | {
|
---|
529 | /* write variable */
|
---|
530 | if (phFile != NULL)
|
---|
531 | fwrite(pVariable->getValue(), strlen(pVariable->getValue()), 1, phFile);
|
---|
532 | }
|
---|
533 | else
|
---|
534 | { /* warning - complain, skip and continue */
|
---|
535 | fprintf(phLog, "%s(%ld) : warning: Variable '%s' not defined.\n",
|
---|
536 | pCurFile->getFilename(), pCurFile->getLineNumber()+1, &szVariable[0]);
|
---|
537 | if (phFile != NULL)
|
---|
538 | fwrite(pCurFile->pszCurrent, psz - pCurFile->pszCurrent + 1, 1, phFile);
|
---|
539 | ulRc += 0x00010000;
|
---|
540 | }
|
---|
541 | pCurFile->pszCurrent = psz + 1;
|
---|
542 | }
|
---|
543 | else
|
---|
544 | { /* error - complain, skip and continue. */
|
---|
545 | fprintf(phLog, "%s(%ld) : error: Missing left parenthese on variable expression\n",
|
---|
546 | pCurFile->getFilename(), pCurFile->getLineNumber()+1);
|
---|
547 | if (phFile != NULL)
|
---|
548 | fputc(*pCurFile->pszCurrent, phFile); /* if this proove to be very slow, we'll have to buffer writes better. */
|
---|
549 | pCurFile->pszCurrent++;
|
---|
550 | ulRc += 0x00000001;
|
---|
551 | }
|
---|
552 | }
|
---|
553 | else
|
---|
554 | { /* next */
|
---|
555 | if (phFile != NULL)
|
---|
556 | fputc(*pCurFile->pszCurrent, phFile); /* if this proove to be very slow, we'll have to buffer writes better. */
|
---|
557 | pCurFile->pszCurrent++;
|
---|
558 | }
|
---|
559 | }
|
---|
560 |
|
---|
561 |
|
---|
562 | /* resume processing of parent file */
|
---|
563 | kFileEntry *pFE = lifoFile.pop();
|
---|
564 | if (pFE != NULL)
|
---|
565 | {
|
---|
566 | assert(pFE == pCurFile->queryParent());
|
---|
567 | pFE->pszCurrent = pCurFile->queryParentPointer();
|
---|
568 | }
|
---|
569 | lifoUsed.push(pCurFile);
|
---|
570 | pCurFile = pFE;
|
---|
571 | }
|
---|
572 |
|
---|
573 | /* close file */
|
---|
574 | if (phFile != NULL)
|
---|
575 | fclose(phFile);
|
---|
576 |
|
---|
577 | return ulRc;
|
---|
578 | }
|
---|
579 |
|
---|
580 |
|
---|
581 | /**
|
---|
582 | * Tag function - kSql.
|
---|
583 | * @returns low word: number of errors
|
---|
584 | * high word: number of warnings
|
---|
585 | * @remark See TAG_PARAMETER_LIST for parameters.
|
---|
586 | * Use TAG_PARAMETERS when calling this function.
|
---|
587 | */
|
---|
588 | static unsigned long tagkSql(TAG_PARAMETER_LIST)
|
---|
589 | {
|
---|
590 | unsigned long ulRc = 0;
|
---|
591 |
|
---|
592 | try
|
---|
593 | {
|
---|
594 | lifoSql.push(new kSqlEntry(tag, &pCurFile->pszCurrent[i], pCurFile));
|
---|
595 | pCurFile->pszCurrent += i;
|
---|
596 | }
|
---|
597 | catch (kError::enmErrors enmErrorCd)
|
---|
598 | {
|
---|
599 | fprintf(phLog, "%s(%ld) : error: kSql tag - %s (errorcode=%d)\n",
|
---|
600 | pCurFile->getFilename(), pCurFile->getLineNumber()+1,
|
---|
601 | kError::queryDescription(enmErrorCd), enmErrorCd);
|
---|
602 | /* fake entry */
|
---|
603 | if (enmErrorCd != kError::error_invalid_tag)
|
---|
604 | lifoSql.push(new kSqlEntry());
|
---|
605 | TAG_PARAMETER_LIST_UNREF;
|
---|
606 | }
|
---|
607 |
|
---|
608 | return ulRc;
|
---|
609 | }
|
---|
610 |
|
---|
611 |
|
---|
612 | /**
|
---|
613 | * Tag function - /kSql.
|
---|
614 | * @returns low word: number of errors
|
---|
615 | * high word: number of warnings
|
---|
616 | * @remark See TAG_PARAMETER_LIST for parameters.
|
---|
617 | * Use TAG_PARAMETERS when calling this function.
|
---|
618 | */
|
---|
619 | static unsigned long tagEndkSql(TAG_PARAMETER_LIST)
|
---|
620 | {
|
---|
621 | unsigned long ulRc = 0;
|
---|
622 | kSqlEntry *pCurSql;
|
---|
623 |
|
---|
624 | pCurSql = lifoSql.pop();
|
---|
625 | if (pCurSql != NULL)
|
---|
626 | {
|
---|
627 | if (!pCurSql->eof())
|
---|
628 | {
|
---|
629 | if (pCurSql->fetch())
|
---|
630 | {
|
---|
631 | if (pCurSql->queryFileEntry() != NULL)
|
---|
632 | {
|
---|
633 | /* three cases: current file, lifoFile or lifoUsed */
|
---|
634 | if (pCurSql->queryFileEntry() == pCurFile)
|
---|
635 | { /* 1. current file */
|
---|
636 | pCurFile->pszCurrent = pCurSql->queryBackTrackPos();
|
---|
637 | }
|
---|
638 | else if (lifoFile.exists(pCurSql->queryFileEntry()))
|
---|
639 | { /* 2. lifoFile */
|
---|
640 | lifoFile.popPush(pCurSql->queryFileEntry(), lifoUsed);
|
---|
641 | pCurFile = lifoFile.pop();
|
---|
642 | if (pCurFile != NULL)
|
---|
643 | pCurFile->pszCurrent = pCurSql->queryBackTrackPos();
|
---|
644 | else
|
---|
645 | {
|
---|
646 | fprintf(phLog, "fatal internal error(%s, %ld, %s, %d): kSqlEntry - pCurFile == NULL\n",
|
---|
647 | pCurFile->getFilename(), pCurFile->getLineNumber()+1, __FILE__, __LINE__);
|
---|
648 | return (unsigned long)~0;
|
---|
649 | }
|
---|
650 | }
|
---|
651 | else if (lifoUsed.exists(pCurSql->queryFileEntry()))
|
---|
652 | { /* 3. lifoUsed */
|
---|
653 | lifoFile.popPush(NULL, lifoUsed);
|
---|
654 | assert(lifoFile.isEmpty());
|
---|
655 | if (rebuildFileLIFO(lifoFile, lifoUsed, pCurSql->queryFileEntry()))
|
---|
656 | {
|
---|
657 | pCurFile = lifoFile.pop(); assert(pCurFile == pCurSql->queryFileEntry());
|
---|
658 | pCurFile->pszCurrent = pCurSql->queryBackTrackPos();
|
---|
659 | }
|
---|
660 | else
|
---|
661 | {
|
---|
662 | fprintf(phLog, "fatal internal error(%s, %ld, %s, %d): rebuildLIFO failed\n",
|
---|
663 | pCurFile->getFilename(), pCurFile->getLineNumber()+1, __FILE__, __LINE__);
|
---|
664 | return (unsigned long)~0;
|
---|
665 | }
|
---|
666 | }
|
---|
667 | else
|
---|
668 | {
|
---|
669 | fprintf(phLog, "internal error(%s, %ld, %s, %d): pFileEntry == NULL\n",
|
---|
670 | pCurFile->getFilename(), pCurFile->getLineNumber()+1, __FILE__, __LINE__);
|
---|
671 | pCurSql = lifoSql.pop(); /* neutralize the push below */
|
---|
672 | }
|
---|
673 |
|
---|
674 | lifoSql.push(pCurSql);
|
---|
675 | pCurSql = NULL;
|
---|
676 | }
|
---|
677 | else
|
---|
678 | {
|
---|
679 | fprintf(phLog, "internal error(%s, %ld, %s, %d): kSqlEntry - pFileEntry == NULL\n",
|
---|
680 | pCurFile->getFilename(), pCurFile->getLineNumber()+1, __FILE__, __LINE__);
|
---|
681 | pCurFile->pszCurrent += i;
|
---|
682 | }
|
---|
683 | }
|
---|
684 | else
|
---|
685 | {
|
---|
686 | fprintf(phLog, "%s(%ld) : error: sql error, %s\n",
|
---|
687 | pCurFile->getFilename(), pCurFile->getLineNumber()+1,
|
---|
688 | pCurSql->querySqlLastError());
|
---|
689 | pCurFile->pszCurrent += i;
|
---|
690 | }
|
---|
691 | }
|
---|
692 |
|
---|
693 | /* finished processing this tag? then delete it! */
|
---|
694 | if (pCurSql != NULL)
|
---|
695 | {
|
---|
696 | delete pCurSql;
|
---|
697 | pCurFile->pszCurrent += i;
|
---|
698 | }
|
---|
699 | }
|
---|
700 | else
|
---|
701 | {
|
---|
702 | fprintf(phLog, "%s(%ld) : error: unexpected '/kSql' tag.\n",
|
---|
703 | pCurFile->getFilename(), pCurFile->getLineNumber()+1);
|
---|
704 | pCurFile->pszCurrent += i;
|
---|
705 | TAG_PARAMETER_LIST_UNREF;
|
---|
706 | }
|
---|
707 |
|
---|
708 | return ulRc;
|
---|
709 | }
|
---|
710 |
|
---|
711 |
|
---|
712 | /**
|
---|
713 | * Tag function - kTemplate.
|
---|
714 | * @returns low word: number of errors
|
---|
715 | * high word: number of warnings
|
---|
716 | * @param phFile Reference to current output file.
|
---|
717 | * @remark See TAG_PARAMETER_LIST for parameters.
|
---|
718 | * Use TAG_PARAMETERS when calling this function.
|
---|
719 | */
|
---|
720 | static unsigned long tagkTemplate(TAG_PARAMETER_LIST, FILE * &phFile)
|
---|
721 | {
|
---|
722 | unsigned long ulRc = 0;
|
---|
723 | const char *pszFilename;
|
---|
724 |
|
---|
725 | /* verify parameters */
|
---|
726 | if (tag.getParameterCount() > 1 && tag.getParameterCount() == 0)
|
---|
727 | {
|
---|
728 | fprintf(phLog, "%s(%ld) : warning: kTemplate - incorrect number of parameters.\n",
|
---|
729 | pCurFile->getFilename(), pCurFile->getLineNumber()+1);
|
---|
730 | ulRc += 0x00010000;
|
---|
731 | }
|
---|
732 |
|
---|
733 | pszFilename = tag.queryParameter("filename");
|
---|
734 | if (pszFilename != NULL)
|
---|
735 | {
|
---|
736 | if (phFile != NULL)
|
---|
737 | fclose(phFile);
|
---|
738 |
|
---|
739 | phFile = fopen(pszFilename, "wb");
|
---|
740 | if (phFile != NULL)
|
---|
741 | fprintf(phLog, "%s(%ld) : info: new output file, '%s'.\n",
|
---|
742 | pCurFile->getFilename(), pCurFile->getLineNumber()+1, pszFilename);
|
---|
743 | else
|
---|
744 | {
|
---|
745 | fprintf(phLog, "%s(%ld) : error: kTemplate - error opening output file '%s'.\n",
|
---|
746 | pCurFile->getFilename(), pCurFile->getLineNumber()+1, pszFilename);
|
---|
747 | ulRc += 0x00000001;
|
---|
748 | }
|
---|
749 | }
|
---|
750 | else
|
---|
751 | {
|
---|
752 | fprintf(phLog, "%s(%ld) : error: kTemplate - filename is missing.\n",
|
---|
753 | pCurFile->getFilename(), pCurFile->getLineNumber()+1);
|
---|
754 | ulRc += 0x00000001;
|
---|
755 | TAG_PARAMETER_LIST_UNREF;
|
---|
756 | }
|
---|
757 |
|
---|
758 | pCurFile->pszCurrent += i;
|
---|
759 |
|
---|
760 | return ulRc;
|
---|
761 | }
|
---|
762 |
|
---|
763 |
|
---|
764 | /**
|
---|
765 | * Tag function - kInclude.
|
---|
766 | * @returns low word: number of errors
|
---|
767 | * high word: number of warnings
|
---|
768 | * @remark See TAG_PARAMETER_LIST for parameters.
|
---|
769 | * Use TAG_PARAMETERS when calling this function.
|
---|
770 | */
|
---|
771 | static unsigned long tagkInclude(TAG_PARAMETER_LIST)
|
---|
772 | {
|
---|
773 | unsigned long ulRc = 0;
|
---|
774 |
|
---|
775 | try
|
---|
776 | {
|
---|
777 | lifoFile.push(pCurFile);
|
---|
778 | pCurFile = new kFileEntry(tag, pCurFile->pszCurrent+i, pCurFile);
|
---|
779 | }
|
---|
780 | catch (kError::enmErrors enmErrorCd)
|
---|
781 | {
|
---|
782 | fprintf(phLog, "%s(%ld) : error: kInclude - %s\n",
|
---|
783 | pCurFile->getFilename(), pCurFile->getLineNumber()+1,
|
---|
784 | kError::queryDescription(enmErrorCd));
|
---|
785 | pCurFile = lifoFile.pop();
|
---|
786 | ulRc = 0x00000001;
|
---|
787 | TAG_PARAMETER_LIST_UNREF;
|
---|
788 | }
|
---|
789 |
|
---|
790 | return ulRc;
|
---|
791 | }
|
---|
792 |
|
---|
793 |
|
---|
794 | /**
|
---|
795 | * Tag function - kGraph.
|
---|
796 | * @returns low word: number of errors
|
---|
797 | * high word: number of warnings
|
---|
798 | * @remark See TAG_PARAMETER_LIST for parameters.
|
---|
799 | * Use TAG_PARAMETERS when calling this function.
|
---|
800 | */
|
---|
801 | static unsigned long tagkGraph(TAG_PARAMETER_LIST)
|
---|
802 | {
|
---|
803 | unsigned long ulRc = 0;
|
---|
804 | /**
|
---|
805 | * Tag description:
|
---|
806 | * <!kGraph filename="graph.gif" type=<lines|...> [subtype=<normal|...>]
|
---|
807 | * data="sql x,y,color,legend from...."
|
---|
808 | * data="sql x,y,color,legend from...."
|
---|
809 | * data="sql x,y,color,legend from...."
|
---|
810 | * ...
|
---|
811 | * >
|
---|
812 | * [] = optional
|
---|
813 | */
|
---|
814 | try
|
---|
815 | {
|
---|
816 | kGraph graph(tag);
|
---|
817 | graph.showWarnings(phLog, pCurFile);
|
---|
818 | graph.save();
|
---|
819 | }
|
---|
820 | catch (kError::enmErrors emnErrorCd)
|
---|
821 | {
|
---|
822 | fprintf(phLog, "%s(%ld) : error: kGraph - %s.\n",
|
---|
823 | pCurFile->getFilename(), pCurFile->getLineNumber()+1,
|
---|
824 | kError::queryDescription(emnErrorCd));
|
---|
825 | ulRc = 0x00000001;
|
---|
826 | TAG_PARAMETER_LIST_UNREF;
|
---|
827 | }
|
---|
828 | pCurFile->pszCurrent += i;
|
---|
829 |
|
---|
830 | return ulRc;
|
---|
831 | }
|
---|
832 |
|
---|
833 |
|
---|
834 | /**
|
---|
835 | * Tag function - kDefine.
|
---|
836 | * @returns low word: number of errors
|
---|
837 | * high word: number of warnings
|
---|
838 | * @remark See TAG_PARAMETER_LIST for parameters.
|
---|
839 | * Use TAG_PARAMETERS when calling this function.
|
---|
840 | */
|
---|
841 | static unsigned long tagkDefine(TAG_PARAMETER_LIST)
|
---|
842 | {
|
---|
843 | unsigned long ulRc = 0;
|
---|
844 |
|
---|
845 | fprintf(phLog, "%s(%ld) : error: kDefine - This tag is not implemented yet.\n",
|
---|
846 | pCurFile->getFilename(), pCurFile->getLineNumber()+1);
|
---|
847 | ulRc = 0x00000001;
|
---|
848 | TAG_PARAMETER_LIST_UNREF;
|
---|
849 |
|
---|
850 | return ulRc;
|
---|
851 | }
|
---|
852 |
|
---|
853 |
|
---|
854 | /**
|
---|
855 | * Tag function - kUndef.
|
---|
856 | * @returns low word: number of errors
|
---|
857 | * high word: number of warnings
|
---|
858 | * @remark See TAG_PARAMETER_LIST for parameters.
|
---|
859 | * Use TAG_PARAMETERS when calling this function.
|
---|
860 | */
|
---|
861 | static unsigned long tagkUndef(TAG_PARAMETER_LIST)
|
---|
862 | {
|
---|
863 | unsigned long ulRc = 0;
|
---|
864 |
|
---|
865 | fprintf(phLog, "%s(%ld) : error: kUndef - This tag is not implemented yet.\n",
|
---|
866 | pCurFile->getFilename(), pCurFile->getLineNumber()+1);
|
---|
867 | ulRc = 0x00000001;
|
---|
868 | TAG_PARAMETER_LIST_UNREF;
|
---|
869 |
|
---|
870 | return ulRc;
|
---|
871 | }
|
---|
872 |
|
---|
873 |
|
---|
874 | /**
|
---|
875 | * Tag function - kIf.
|
---|
876 | * @returns low word: number of errors
|
---|
877 | * high word: number of warnings
|
---|
878 | * @remark See TAG_PARAMETER_LIST for parameters.
|
---|
879 | * Use TAG_PARAMETERS when calling this function.
|
---|
880 | */
|
---|
881 | static unsigned long tagkIf(TAG_PARAMETER_LIST)
|
---|
882 | {
|
---|
883 | unsigned long ulRc = 0;
|
---|
884 |
|
---|
885 | fprintf(phLog, "%s(%ld) : error: kIf - This tag is not implemented yet.\n",
|
---|
886 | pCurFile->getFilename(), pCurFile->getLineNumber()+1);
|
---|
887 | ulRc = 0x00000001;
|
---|
888 | TAG_PARAMETER_LIST_UNREF;
|
---|
889 |
|
---|
890 | return ulRc;
|
---|
891 | }
|
---|
892 |
|
---|
893 |
|
---|
894 | /**
|
---|
895 | * Tag function - kElse.
|
---|
896 | * @returns low word: number of errors
|
---|
897 | * high word: number of warnings
|
---|
898 | * @remark See TAG_PARAMETER_LIST for parameters.
|
---|
899 | * Use TAG_PARAMETERS when calling this function.
|
---|
900 | */
|
---|
901 | static unsigned long tagkElse(TAG_PARAMETER_LIST)
|
---|
902 | {
|
---|
903 | unsigned long ulRc = 0;
|
---|
904 |
|
---|
905 | fprintf(phLog, "%s(%ld) : error: kElse - This tag is not implemented yet.\n",
|
---|
906 | pCurFile->getFilename(), pCurFile->getLineNumber()+1);
|
---|
907 | ulRc = 0x00000001;
|
---|
908 | TAG_PARAMETER_LIST_UNREF;
|
---|
909 |
|
---|
910 | return ulRc;
|
---|
911 | }
|
---|
912 |
|
---|
913 |
|
---|
914 | /**
|
---|
915 | * Tag function - kEndif.
|
---|
916 | * @returns low word: number of errors
|
---|
917 | * high word: number of warnings
|
---|
918 | * @remark See TAG_PARAMETER_LIST for parameters.
|
---|
919 | * Use TAG_PARAMETERS when calling this function.
|
---|
920 | */
|
---|
921 | static unsigned long tagkEndif(TAG_PARAMETER_LIST)
|
---|
922 | {
|
---|
923 | unsigned long ulRc = 0;
|
---|
924 |
|
---|
925 | fprintf(phLog, "%s(%ld) : error: kEndif - This tag is not implemented yet.\n",
|
---|
926 | pCurFile->getFilename(), pCurFile->getLineNumber()+1);
|
---|
927 | ulRc = 0x00000001;
|
---|
928 | TAG_PARAMETER_LIST_UNREF;
|
---|
929 |
|
---|
930 | return ulRc;
|
---|
931 | }
|
---|
932 |
|
---|
933 |
|
---|
934 | #if 0
|
---|
935 | /**
|
---|
936 | * Tag function - k.
|
---|
937 | * @returns low word: number of errors
|
---|
938 | * high word: number of warnings
|
---|
939 | * @remark See TAG_PARAMETER_LIST for parameters.
|
---|
940 | * Use TAG_PARAMETERS when calling this function.
|
---|
941 | */
|
---|
942 | static unsigned long tagk(TAG_PARAMETER_LIST)
|
---|
943 | {
|
---|
944 | unsigned long ulRc = 0;
|
---|
945 |
|
---|
946 | TAG_PARAMETER_LIST_UNREF;
|
---|
947 |
|
---|
948 | return ulRc;
|
---|
949 | }
|
---|
950 | #endif
|
---|
951 |
|
---|
952 |
|
---|
953 | /**
|
---|
954 | * Rebuild a fileentry based on a given file entry.
|
---|
955 | * @returns success indicator. TRUE / FALSE.
|
---|
956 | * @param lifoFile Target.
|
---|
957 | * @param lifoUsed Source.
|
---|
958 | * @param pFileEntryTop New to file entry.
|
---|
959 | * @remark Recusive.
|
---|
960 | */
|
---|
961 | static BOOL rebuildFileLIFO(kLIFO<kFileEntry> &lifoFile, kLIFO<kFileEntry> &lifoUsed, const kFileEntry *pFileEntryTop)
|
---|
962 | {
|
---|
963 | /* base case */
|
---|
964 | if (pFileEntryTop == NULL)
|
---|
965 | return TRUE;
|
---|
966 | /* general case */
|
---|
967 | pFileEntryTop = lifoUsed.get(pFileEntryTop);
|
---|
968 | if (pFileEntryTop != NULL && rebuildFileLIFO(lifoFile, lifoUsed, pFileEntryTop->queryParent()))
|
---|
969 | lifoFile.push((kFileEntry*)pFileEntryTop);
|
---|
970 | else
|
---|
971 | return FALSE;
|
---|
972 | return TRUE;
|
---|
973 | }
|
---|
974 |
|
---|
975 |
|
---|
976 | /**
|
---|
977 | * Duplicates a string.
|
---|
978 | * @returns Pointer to stringcopy. Remeber to delete this!
|
---|
979 | * @param psz Pointer to string to duplicate.
|
---|
980 | */
|
---|
981 | static char *dupeString(const char *psz)
|
---|
982 | {
|
---|
983 | char *pszDupe;
|
---|
984 | if (psz == NULL)
|
---|
985 | return NULL;
|
---|
986 | pszDupe = new char[strlen(psz)+1];
|
---|
987 | return strcpy(pszDupe, psz);
|
---|
988 | }
|
---|
989 |
|
---|
990 |
|
---|
991 | #if 0 // not used
|
---|
992 | /**
|
---|
993 | * Upcases a char.
|
---|
994 | * @returns Upper case of the char given in ch.
|
---|
995 | * @param ch Char to capitalize.
|
---|
996 | */
|
---|
997 | inline char upcase(char ch)
|
---|
998 | {
|
---|
999 | return ch >= 'a' && ch <= 'z' ? (char)(ch - ('a' - 'A')) : ch;
|
---|
1000 | }
|
---|
1001 |
|
---|
1002 |
|
---|
1003 | /**
|
---|
1004 | * Searches for a substring in a string.
|
---|
1005 | * @returns Pointer to start of substring when found, NULL when not found.
|
---|
1006 | * @param pszStr String to be searched.
|
---|
1007 | * @param pszSubStr String to be searched.
|
---|
1008 | * @remark Depends on the upcase function.
|
---|
1009 | */
|
---|
1010 | static char *stristr(const char *pszStr, const char *pszSubStr)
|
---|
1011 | {
|
---|
1012 | int cchSubStr = strlen(pszSubStr);
|
---|
1013 | int i = 0;
|
---|
1014 |
|
---|
1015 | while (*pszStr != '\0' && i < cchSubStr)
|
---|
1016 | {
|
---|
1017 | i = 0;
|
---|
1018 | while (i < cchSubStr && pszStr[i] != '\0' &&
|
---|
1019 | (upcase(pszStr[i]) == upcase(pszSubStr[i])))
|
---|
1020 | i++;
|
---|
1021 | pszStr++;
|
---|
1022 | }
|
---|
1023 |
|
---|
1024 | return (char*)(*pszStr != '\0' ? pszStr - 1 : NULL);
|
---|
1025 | }
|
---|
1026 |
|
---|
1027 |
|
---|
1028 | /**
|
---|
1029 | * Trims a string, that is removing blank spaces at start and end.
|
---|
1030 | * @returns Pointer to first non-blank char.
|
---|
1031 | * @param psz Pointer to string.
|
---|
1032 | * @result Blank at end of string is removed. ('\0' is moved to the left.)
|
---|
1033 | */
|
---|
1034 | static char *trim(char *psz)
|
---|
1035 | {
|
---|
1036 | int i;
|
---|
1037 | if (psz == NULL)
|
---|
1038 | return NULL;
|
---|
1039 | while (*psz == ' ')
|
---|
1040 | psz++;
|
---|
1041 | i = strlen(psz) - 1;
|
---|
1042 | while (i >= 0 && psz[i] == ' ')
|
---|
1043 | i--;
|
---|
1044 | psz[i+1] = '\0';
|
---|
1045 | return psz;
|
---|
1046 | }
|
---|
1047 |
|
---|
1048 |
|
---|
1049 | /**
|
---|
1050 | * Trims left side of a string; that is removing blank spaces at start.
|
---|
1051 | * @returns Pointer to first non-blank char.
|
---|
1052 | * @param psz Pointer to string.
|
---|
1053 | * @remark non-const edtion.
|
---|
1054 | */
|
---|
1055 | static char *ltrim(char *psz)
|
---|
1056 | {
|
---|
1057 | while (*psz == ' ')
|
---|
1058 | psz++;
|
---|
1059 | return psz;
|
---|
1060 | }
|
---|
1061 |
|
---|
1062 |
|
---|
1063 | /**
|
---|
1064 | * Trims left side of a string; that is removing blank spaces.
|
---|
1065 | * @returns Pointer to first non-blank char.
|
---|
1066 | * @param psz Pointer to string.
|
---|
1067 | * @remark const edtion.
|
---|
1068 | */
|
---|
1069 | static const char *ltrim(const char *psz)
|
---|
1070 | {
|
---|
1071 | while (*psz == ' ')
|
---|
1072 | psz++;
|
---|
1073 | return psz;
|
---|
1074 | }
|
---|
1075 |
|
---|
1076 |
|
---|
1077 | /**
|
---|
1078 | * Trims left side of a string; that is removing blank spaces, new lines and tabs.
|
---|
1079 | * @returns Pointer to first non-blank char.
|
---|
1080 | * @param psz Pointer to string.
|
---|
1081 | * @remark non-const edtion.
|
---|
1082 | */
|
---|
1083 | static char *ltrimL(char *psz)
|
---|
1084 | {
|
---|
1085 | while (*psz == ' ' || *psz == '\t' || *psz == '\r' || *psz == '\n')
|
---|
1086 | psz++;
|
---|
1087 | return psz;
|
---|
1088 | }
|
---|
1089 | #endif
|
---|
1090 |
|
---|
1091 | /**
|
---|
1092 | * Trims left side of a string; that is removing blank spaces, new lines and tabs.
|
---|
1093 | * @returns Pointer to first non-blank char.
|
---|
1094 | * @param psz Pointer to string.
|
---|
1095 | * @remark const edtion.
|
---|
1096 | */
|
---|
1097 | static const char *ltrimL(const char *psz)
|
---|
1098 | {
|
---|
1099 | while (*psz == ' ' || *psz == '\t' || *psz == '\r' || *psz == '\n')
|
---|
1100 | psz++;
|
---|
1101 | return psz;
|
---|
1102 | }
|
---|
1103 |
|
---|
1104 |
|
---|
1105 | /**
|
---|
1106 | * Formats a raw message to a readable message.
|
---|
1107 | * @returns Pointer to a static data field containing the formatted message.
|
---|
1108 | * @param pszMsg message to format.
|
---|
1109 | */
|
---|
1110 | const char *kError::formatMessage(const char *pszMsg)
|
---|
1111 | {
|
---|
1112 | static char szData[256];
|
---|
1113 | int i = 0;
|
---|
1114 |
|
---|
1115 | /* skip first word */
|
---|
1116 | while (*pszMsg != '_' && *pszMsg != '\0')
|
---|
1117 | pszMsg++;
|
---|
1118 | if (pszMsg != '\0')
|
---|
1119 | {
|
---|
1120 | pszMsg++;
|
---|
1121 | do
|
---|
1122 | {
|
---|
1123 | if (*pszMsg == '_')
|
---|
1124 | szData[i++] = ' ';
|
---|
1125 | else
|
---|
1126 | szData[i++] = *pszMsg;
|
---|
1127 | } while (*pszMsg++ != '\0');
|
---|
1128 |
|
---|
1129 | strcat(&szData[0], ".");
|
---|
1130 | }
|
---|
1131 | else
|
---|
1132 | szData[0] = '\0';
|
---|
1133 |
|
---|
1134 | return &szData[0];
|
---|
1135 | }
|
---|
1136 |
|
---|
1137 |
|
---|
1138 | /**
|
---|
1139 | * Give a description of an error code.
|
---|
1140 | * @returns "Read only"/const string. Never NULL.
|
---|
1141 | * @param emnError Error code.
|
---|
1142 | */
|
---|
1143 | const char *kError::queryDescription(kError::enmErrors enmError)
|
---|
1144 | {
|
---|
1145 | switch (enmError)
|
---|
1146 | {
|
---|
1147 | case error_sql_failed:
|
---|
1148 | return kSqlEntry::querySqlLastError();
|
---|
1149 |
|
---|
1150 | ErrorDescCase(no_error );
|
---|
1151 | ErrorDescCase(error_unexpected_end_of_string );
|
---|
1152 | ErrorDescCase(error_unexpected_eot );
|
---|
1153 | ErrorDescCase(error_invalid_tag_start_char );
|
---|
1154 | ErrorDescCase(error_invalid_tagname );
|
---|
1155 | ErrorDescCase(error_invalid_tag );
|
---|
1156 | ErrorDescCase(error_no_filename );
|
---|
1157 | ErrorDescCase(error_unexpected_eof );
|
---|
1158 | ErrorDescCase(error_unbalanced_quotes );
|
---|
1159 | ErrorDescCase(error_eot_not_found );
|
---|
1160 | ErrorDescCase(error_opening_file );
|
---|
1161 | ErrorDescCase(error_determing_file_size );
|
---|
1162 | ErrorDescCase(error_new_failed );
|
---|
1163 | ErrorDescCase(error_reading_file );
|
---|
1164 | ErrorDescCase(error_incorrect_number_of_parameters );
|
---|
1165 | ErrorDescCase(error_missing_sql );
|
---|
1166 | ErrorDescCase(error_invalid_sql_tag );
|
---|
1167 | ErrorDescCase(error_opening_output_file );
|
---|
1168 | ErrorDescCase(error_graph_to_small );
|
---|
1169 | ErrorDescCase(error_graph_type_must_be_specified_before_data );
|
---|
1170 | ErrorDescCase(error_data_param_is_missing_value );
|
---|
1171 | ErrorDescCase(error_type_param_is_missing_value );
|
---|
1172 | ErrorDescCase(error_invalid_type );
|
---|
1173 | ErrorDescCase(error_filename_param_is_missing_value );
|
---|
1174 | ErrorDescCase(error_width_cx_param_is_missing_value );
|
---|
1175 | ErrorDescCase(error_height_cy_param_is_missing_value );
|
---|
1176 | ErrorDescCase(error_graph_type_is_missing );
|
---|
1177 | ErrorDescCase(error_graph_subtype_is_invalid );
|
---|
1178 | ErrorDescCase(error_filename_is_missing );
|
---|
1179 | ErrorDescCase(error_no_data );
|
---|
1180 | ErrorDescCase(error_invalid_dimentions );
|
---|
1181 | ErrorDescCase(error_data_param_is_missing_sql_statement );
|
---|
1182 | ErrorDescCase(error_xstart_param_is_missing_value );
|
---|
1183 | ErrorDescCase(error_xend_param_is_missing_value );
|
---|
1184 | ErrorDescCase(error_ystart_param_is_missing_value );
|
---|
1185 | ErrorDescCase(error_yend_param_is_missing_value );
|
---|
1186 |
|
---|
1187 | ErrorDescCase(warning_illegal_string_char );
|
---|
1188 | ErrorDescCase(warning_too_many_parameters );
|
---|
1189 | ErrorDescCase(warning_unexpected_end_of_string );
|
---|
1190 | ErrorDescCase(warning_unexpected_eot );
|
---|
1191 | ErrorDescCase(warning_failed_to_open_background_image );
|
---|
1192 | ErrorDescCase(warning_failed_to_load_background_image );
|
---|
1193 | ErrorDescCase(warning_invalid_sub_type );
|
---|
1194 | ErrorDescCase(warning_title_param_is_missing_value );
|
---|
1195 | ErrorDescCase(warning_titlex_param_is_missing_value );
|
---|
1196 | ErrorDescCase(warning_titley_param_is_missing_value );
|
---|
1197 | ErrorDescCase(warning_invalid_parameter );
|
---|
1198 | ErrorDescCase(warning_legend_is_not_implemented_yet );
|
---|
1199 | ErrorDescCase(warning_failed_to_convert_date );
|
---|
1200 | ErrorDescCase(warning_invalid_color_value );
|
---|
1201 | ErrorDescCase(warning_to_many_fields_in_data_sql );
|
---|
1202 | ErrorDescCase(warning_pie_not_implemented_yet );
|
---|
1203 | ErrorDescCase(warning_negative_values_are_not_supported_yet );
|
---|
1204 | ErrorDescCase(warning_background_param_is_missing_value );
|
---|
1205 | ErrorDescCase(warning_backgroundcolor_is_invalid );
|
---|
1206 | ErrorDescCase(warning_backgroundcolor_param_is_missing_value );
|
---|
1207 | ErrorDescCase(warning_foregroundcolor_is_invalid );
|
---|
1208 | ErrorDescCase(warning_foregroundcolor_param_is_missing_value );
|
---|
1209 | ErrorDescCase(warning_axiscolor_is_invalid );
|
---|
1210 | ErrorDescCase(warning_axiscolor_param_is_missing_value );
|
---|
1211 | }
|
---|
1212 | return "unknown error";
|
---|
1213 | }
|
---|
1214 |
|
---|
1215 |
|
---|
1216 | /**
|
---|
1217 | * Query for a warning.
|
---|
1218 | * @returns Const pointer to warning description. NULL if no warning.
|
---|
1219 | */
|
---|
1220 | const char *kTag::queryWarning(void)
|
---|
1221 | {
|
---|
1222 | return enmWarning != kError::no_error ? kError::queryDescription(enmWarning) : NULL;
|
---|
1223 | }
|
---|
1224 |
|
---|
1225 |
|
---|
1226 | /**
|
---|
1227 | * Anayses an tag: get tagname and parameters (if any).
|
---|
1228 | * @param pszTag Pointer to tag buffer.
|
---|
1229 | * @sketch
|
---|
1230 | * @remark Throws kError::emnErrors on error.
|
---|
1231 | */
|
---|
1232 | void kTag::analyseTag(const char *pszTag) throw(kError::enmErrors)
|
---|
1233 | {
|
---|
1234 | char *psz = &szTag[0];
|
---|
1235 |
|
---|
1236 | /* skip blanks at start */
|
---|
1237 | while (*pszTag == ' ')
|
---|
1238 | pszTag++;
|
---|
1239 |
|
---|
1240 | /* tagname */
|
---|
1241 | if (*pszTag++ != '<')
|
---|
1242 | throw(kError::error_invalid_tag_start_char);
|
---|
1243 | pszTag = copyTag(psz, pszTag);
|
---|
1244 | pszTagname = psz;
|
---|
1245 | psz += strlen(psz) + 1;
|
---|
1246 |
|
---|
1247 | /* parameters */
|
---|
1248 | if (strncmp(pszTagname, "!--", 3) != 0) /* ignore comments */
|
---|
1249 | {
|
---|
1250 | try
|
---|
1251 | {
|
---|
1252 | pszTag = ltrimL(pszTag);
|
---|
1253 | while (*pszTag != '>' && *pszTag != '\0' && cParameters < TAG_MAX_PARAMETERS)
|
---|
1254 | {
|
---|
1255 | /* parametername */
|
---|
1256 | pszTag = copyParameterName(psz, pszTag);
|
---|
1257 | apszParameters[cParameters] = psz;
|
---|
1258 | psz += strlen(psz) + 1;
|
---|
1259 |
|
---|
1260 | /* parametervalue */
|
---|
1261 | apszValues[cParameters] = NULL;
|
---|
1262 | pszTag = ltrimL(pszTag);
|
---|
1263 | if (*pszTag == '=')
|
---|
1264 | {
|
---|
1265 | pszTag = ltrimL(pszTag + 1);
|
---|
1266 | if (*pszTag != '\"')
|
---|
1267 | pszTag = copyParameterValue1(psz, pszTag);
|
---|
1268 | else
|
---|
1269 | pszTag = copyParameterValue2(psz, pszTag);
|
---|
1270 | apszValues[cParameters] = psz;
|
---|
1271 | psz += strlen(psz) + 1;
|
---|
1272 | }
|
---|
1273 |
|
---|
1274 | /* parameter finished - next */
|
---|
1275 | cParameters++;
|
---|
1276 | pszTag = ltrimL(pszTag);
|
---|
1277 | }
|
---|
1278 |
|
---|
1279 | /* check for warnings */
|
---|
1280 | if (*pszTag != '>' && cParameters >= TAG_MAX_PARAMETERS)
|
---|
1281 | throw(kError::warning_too_many_parameters);
|
---|
1282 | if (*pszTag != '>')
|
---|
1283 | throw(kError::warning_unexpected_eot);
|
---|
1284 | }
|
---|
1285 | catch (kError::enmErrors enmErrorCd)
|
---|
1286 | {
|
---|
1287 | /* no fatal error --> warning */
|
---|
1288 | enmWarning = enmErrorCd;
|
---|
1289 | }
|
---|
1290 | }
|
---|
1291 | }
|
---|
1292 |
|
---|
1293 |
|
---|
1294 | /**
|
---|
1295 | * Copy a tagname.
|
---|
1296 | * @returns Pointer to first char after the tag. (pszFrom)
|
---|
1297 | * @param pszTo Pointer to target.
|
---|
1298 | * @param pszFrom Pointer to value string.
|
---|
1299 | * @remark Throws kError::emnErrors on error, fatal for this object.
|
---|
1300 | */
|
---|
1301 | const char *kTag::copyTag(char *pszTo, const char *pszFrom) throw(kError::enmErrors)
|
---|
1302 | {
|
---|
1303 | const char *psz = pszTo;
|
---|
1304 |
|
---|
1305 | /* checks for errors */
|
---|
1306 | if (*pszFrom == '>')
|
---|
1307 | throw(kError::error_unexpected_eot);
|
---|
1308 |
|
---|
1309 | /* skip to start of tagname */
|
---|
1310 | while (*pszFrom == ' ')
|
---|
1311 | pszFrom++;
|
---|
1312 |
|
---|
1313 | /* copy string */
|
---|
1314 | while (
|
---|
1315 | (*pszFrom >= 'a' && *pszFrom <= 'z') ||
|
---|
1316 | (*pszFrom >= 'A' && *pszFrom <= 'Z') ||
|
---|
1317 | (*pszFrom >= '0' && *pszFrom <= '9') ||
|
---|
1318 | *pszFrom == '/' ||
|
---|
1319 | *pszFrom == '!' || *pszFrom == '-' //<!--> and <!k...>
|
---|
1320 | )
|
---|
1321 | *pszTo++ = *pszFrom++;
|
---|
1322 | *pszTo = '\0';
|
---|
1323 |
|
---|
1324 | /* checks for errors */
|
---|
1325 | if (*pszFrom == '\0')
|
---|
1326 | throw(kError::error_unexpected_eot);
|
---|
1327 | if (*pszFrom != '>' && *pszFrom != ' ' && strncmp("!--", psz, 3) != 0) //<!--aasdfv-->
|
---|
1328 | throw(kError::error_invalid_tagname);
|
---|
1329 |
|
---|
1330 | return pszFrom;
|
---|
1331 | }
|
---|
1332 |
|
---|
1333 |
|
---|
1334 | /**
|
---|
1335 | * Copy a
|
---|
1336 | * @returns Pointer to first char after the tag. (pszFrom)
|
---|
1337 | * @param pszTo Pointer to target.
|
---|
1338 | * @param pszFrom Pointer to value string.
|
---|
1339 | * @remark Throws kError::emnErrors on error, fatal for this object.
|
---|
1340 | */
|
---|
1341 | const char *kTag::copyParameterName(char *pszTo, const char *pszFrom) throw(kError::enmErrors)
|
---|
1342 | {
|
---|
1343 | /* checks for errors */
|
---|
1344 | if (*pszFrom == '>')
|
---|
1345 | throw(kError::warning_unexpected_eot);
|
---|
1346 |
|
---|
1347 | /* skip to start of parameter name */
|
---|
1348 | while (*pszFrom == ' ')
|
---|
1349 | pszFrom++;
|
---|
1350 |
|
---|
1351 | /* copy string */
|
---|
1352 | while (
|
---|
1353 | (*pszFrom >= 'a' && *pszFrom <= 'z') ||
|
---|
1354 | (*pszFrom >= 'A' && *pszFrom <= 'Z') ||
|
---|
1355 | (*pszFrom >= '0' && *pszFrom <= '9')
|
---|
1356 | )
|
---|
1357 | *pszTo++ = *pszFrom++;
|
---|
1358 | *pszTo = '\0';
|
---|
1359 |
|
---|
1360 | /* checks for errors */
|
---|
1361 | if (*pszFrom == '\0')
|
---|
1362 | throw(kError::warning_unexpected_eot);
|
---|
1363 |
|
---|
1364 | return pszFrom;
|
---|
1365 | }
|
---|
1366 |
|
---|
1367 |
|
---|
1368 | /**
|
---|
1369 | * Copy a simple parameter value. A simple parameter value is not enclosed in "".
|
---|
1370 | * @returns Pointer to first char after the value. (pszFrom)
|
---|
1371 | * @param pszTo Pointer to target.
|
---|
1372 | * @param pszFrom Pointer to value string.
|
---|
1373 | * @remark Throws kError::emnErrors on warning, do not continue analysis.
|
---|
1374 | */
|
---|
1375 | const char *kTag::copyParameterValue1(char *pszTo, const char *pszFrom) throw(kError::enmErrors)
|
---|
1376 | {
|
---|
1377 | /* skip to start of parameter value */
|
---|
1378 | while (*pszFrom == ' ')
|
---|
1379 | pszFrom++;
|
---|
1380 |
|
---|
1381 | /* copy string */
|
---|
1382 | while (
|
---|
1383 | (*pszFrom >= 'a' && *pszFrom <= 'z') ||
|
---|
1384 | (*pszFrom >= 'A' && *pszFrom <= 'Z') ||
|
---|
1385 | (*pszFrom >= '0' && *pszFrom <= '9') ||
|
---|
1386 | *pszFrom == '.' || *pszFrom == ','
|
---|
1387 | )
|
---|
1388 | *pszTo++ = *pszFrom++;
|
---|
1389 | *pszTo = '\0';
|
---|
1390 |
|
---|
1391 | /* check for warnings */
|
---|
1392 | if (*pszFrom == '\0')
|
---|
1393 | throw(kError::warning_unexpected_eot);
|
---|
1394 | if (*pszFrom != ' ' && *pszFrom != '>' && *pszFrom != '\n' && *pszFrom != '\r')
|
---|
1395 | throw(kError::warning_illegal_string_char);
|
---|
1396 |
|
---|
1397 | return pszFrom;
|
---|
1398 | }
|
---|
1399 |
|
---|
1400 |
|
---|
1401 | /**
|
---|
1402 | * Copy an enclosed parameter value. Enclosed in "".
|
---|
1403 | * @returns Pointer to first char after the value. (pszFrom)
|
---|
1404 | * @param pszTo Pointer to target.
|
---|
1405 | * @param pszFrom Pointer to value string.
|
---|
1406 | * @remark Throws kError::emnErrors on warning, do not continue analysis.
|
---|
1407 | */
|
---|
1408 | const char *kTag::copyParameterValue2(char *pszTo, const char *pszFrom) throw(kError::enmErrors)
|
---|
1409 | {
|
---|
1410 | /* skip to start " */
|
---|
1411 | while (*pszFrom != '\"' && *pszFrom != '>' && *pszFrom != '\0')
|
---|
1412 | pszFrom++;
|
---|
1413 | if (*pszFrom != '\"')
|
---|
1414 | throw(kError::error_unexpected_end_of_string);
|
---|
1415 | pszFrom++;
|
---|
1416 |
|
---|
1417 | /* copy string */
|
---|
1418 | while (*pszFrom != '\"' /*&& *pszFrom != '>'*/ && *pszFrom != '\0')
|
---|
1419 | *pszTo++ = *pszFrom++;
|
---|
1420 | *pszTo = '\0';
|
---|
1421 |
|
---|
1422 | /* check for warnings */
|
---|
1423 | if (*pszFrom != '\"')
|
---|
1424 | throw(kError::warning_unexpected_end_of_string);
|
---|
1425 |
|
---|
1426 | return pszFrom + 1;
|
---|
1427 | }
|
---|
1428 |
|
---|
1429 |
|
---|
1430 | /**
|
---|
1431 | * Is this the correct tag?
|
---|
1432 | * @returns TRUE pszTagname matches this->pszTagname, else FALSE.
|
---|
1433 | * @param pszTagname Name to match.
|
---|
1434 | */
|
---|
1435 | BOOL kTag::isTag(const char *pszTagname) const
|
---|
1436 | {
|
---|
1437 | if (pszTagname == NULL)
|
---|
1438 | return FALSE;
|
---|
1439 | return stricmp(pszTagname, this->pszTagname) == 0;
|
---|
1440 | }
|
---|
1441 |
|
---|
1442 |
|
---|
1443 | /**
|
---|
1444 | * Constructor.
|
---|
1445 | * @param pszTag Pointer to tag to analyse.
|
---|
1446 | * @remark Throws kError::emnErrors on warning, do not continue analysis.
|
---|
1447 | */
|
---|
1448 | kTag::kTag(const char *pszTag) throw(kError::enmErrors)
|
---|
1449 | : pszTagname(NULL), cParameters(0), enmWarning(kError::no_error)
|
---|
1450 | {
|
---|
1451 | analyseTag(pszTag);
|
---|
1452 | }
|
---|
1453 |
|
---|
1454 |
|
---|
1455 | /**
|
---|
1456 | * Destructor.
|
---|
1457 | */
|
---|
1458 | kTag::~kTag(void)
|
---|
1459 | {
|
---|
1460 | }
|
---|
1461 |
|
---|
1462 |
|
---|
1463 | /**
|
---|
1464 | * Gets the tag name.
|
---|
1465 | * @returns Const pointer to tag name. Not NULL.
|
---|
1466 | */
|
---|
1467 | const char *kTag::getTagname(void) const
|
---|
1468 | {
|
---|
1469 | return pszTagname;
|
---|
1470 | }
|
---|
1471 |
|
---|
1472 |
|
---|
1473 | /**
|
---|
1474 | * Gets the number of parameters found for this tag.
|
---|
1475 | * @returns Number of parameters. -1 on error (should never occur!).
|
---|
1476 | */
|
---|
1477 | unsigned long kTag::getParameterCount(void) const
|
---|
1478 | {
|
---|
1479 | return cParameters;
|
---|
1480 | }
|
---|
1481 |
|
---|
1482 |
|
---|
1483 | /**
|
---|
1484 | * Seek for the value of a given parameter.
|
---|
1485 | * @returns "Readonly"/const pointer to value. NULL if no value or parameter not found.
|
---|
1486 | * @param pszParameter Pointer to parameter name.
|
---|
1487 | * @remark Parameters are case insensitive!
|
---|
1488 | */
|
---|
1489 | const char *kTag::queryParameter(const char *pszParameter) const
|
---|
1490 | {
|
---|
1491 | unsigned int i = 0;
|
---|
1492 | while (i < cParameters && stricmp(apszParameters[i], pszParameter) != 0)
|
---|
1493 | i++;
|
---|
1494 | return i < cParameters ? apszValues[i]: NULL;
|
---|
1495 | }
|
---|
1496 |
|
---|
1497 |
|
---|
1498 | /**
|
---|
1499 | * Checks if a parameter exists.
|
---|
1500 | * @returns TRUE: exists, FALSE: does not exist.
|
---|
1501 | * @param pszParameter Pointer to parameter name.
|
---|
1502 | * @remark Parameters are case insensitive!
|
---|
1503 | */
|
---|
1504 | BOOL kTag::queryExists(const char *pszParameter) const
|
---|
1505 | {
|
---|
1506 | unsigned int i = 0;
|
---|
1507 | while (i < cParameters && stricmp(apszParameters[i], pszParameter) != 0)
|
---|
1508 | i++;
|
---|
1509 | return i < cParameters;
|
---|
1510 | }
|
---|
1511 |
|
---|
1512 |
|
---|
1513 | /**
|
---|
1514 | * Gets the parameter name for the given parameter number.
|
---|
1515 | * @returns Pointer to "readonly"/const parametername. NULL if outof range.
|
---|
1516 | * @param ulOrdinal Parameter number. 0-based.
|
---|
1517 | */
|
---|
1518 | const char *kTag::queryParameterName(unsigned long ulOrdinal) const
|
---|
1519 | {
|
---|
1520 | return ulOrdinal < cParameters ? apszParameters[ulOrdinal] : NULL;
|
---|
1521 | }
|
---|
1522 |
|
---|
1523 |
|
---|
1524 | /**
|
---|
1525 | * Gets the value for the given parameter number.
|
---|
1526 | * @returns Pointer to "readonly"/const parameter value. NULL if outof range or no value.
|
---|
1527 | * @param ulOrdinal Parameter number. 0-based.
|
---|
1528 | * @remark Return value NULL doesn't have to be an error, the parameter may not have a value!
|
---|
1529 | */
|
---|
1530 | const char *kTag::queryParameterValue(unsigned long ulOrdinal) const
|
---|
1531 | {
|
---|
1532 | return ulOrdinal < cParameters ? apszValues[ulOrdinal] : NULL;
|
---|
1533 | }
|
---|
1534 |
|
---|
1535 |
|
---|
1536 | /**
|
---|
1537 | * Opens and reads a file into memory.
|
---|
1538 | * @param pszFilename Pointer to input filename.
|
---|
1539 | * @remark throws error code (enum).
|
---|
1540 | */
|
---|
1541 | void kFileEntry::openAndReadFile(const char *pszFilename) throw (kError::enmErrors)
|
---|
1542 | {
|
---|
1543 | FILE *phFile;
|
---|
1544 |
|
---|
1545 | phFile = fopen(pszFilename, "rb");
|
---|
1546 | if (phFile == NULL)
|
---|
1547 | throw(kError::error_opening_file);
|
---|
1548 | if (fseek(phFile, 0, SEEK_END) == 0 &&
|
---|
1549 | (cbFile = ftell(phFile)) != 0 &&
|
---|
1550 | fseek(phFile, 0, SEEK_SET) == 0
|
---|
1551 | )
|
---|
1552 | {
|
---|
1553 | pszFile = new char[cbFile+1];
|
---|
1554 | if (pszFile != NULL)
|
---|
1555 | {
|
---|
1556 | memset(pszFile, 0, (size_t)(cbFile+1));
|
---|
1557 | if (fread(pszFile, cbFile, 1, phFile) != 1)
|
---|
1558 | {
|
---|
1559 | fclose(phFile);
|
---|
1560 | throw(kError::error_reading_file);
|
---|
1561 | }
|
---|
1562 | fclose(phFile);
|
---|
1563 | }
|
---|
1564 | else
|
---|
1565 | {
|
---|
1566 | fclose(phFile);
|
---|
1567 | throw(kError::error_new_failed);
|
---|
1568 | }
|
---|
1569 | }
|
---|
1570 | else
|
---|
1571 | {
|
---|
1572 | fclose(phFile);
|
---|
1573 | throw(kError::error_determing_file_size);
|
---|
1574 | }
|
---|
1575 | }
|
---|
1576 |
|
---|
1577 |
|
---|
1578 | /**
|
---|
1579 | * Creates a file entry object.
|
---|
1580 | * @param pszFilename Pointer input filename.
|
---|
1581 | * @sketch Open file.
|
---|
1582 | * Find file length.
|
---|
1583 | * Read file into memory.
|
---|
1584 | * @remark throws error code enum.
|
---|
1585 | */
|
---|
1586 | kFileEntry::kFileEntry(const char *pszFilename) throw (kError::enmErrors) : pParent(NULL), pszParent(NULL)
|
---|
1587 | {
|
---|
1588 | openAndReadFile(pszFilename);
|
---|
1589 | strcpy(&szFilename[0], pszFilename);
|
---|
1590 | pszCurrent = pszFile;
|
---|
1591 | }
|
---|
1592 |
|
---|
1593 |
|
---|
1594 | /**
|
---|
1595 | * Create a file entry object with parent from a include statement.
|
---|
1596 | * @parma tag Reference to tag object.
|
---|
1597 | * @param pszParent Current pointer in parent file.
|
---|
1598 | * @param pParent Pointer to current file entry.
|
---|
1599 | * @sketch Open and read file into memory.
|
---|
1600 | * Copy filename.
|
---|
1601 | * Set current pointer.
|
---|
1602 | * @remark throws error code enum.
|
---|
1603 | * TODO - use not fully implemented.
|
---|
1604 | */
|
---|
1605 | kFileEntry::kFileEntry(const kTag &tag, const char *pszParent, const kFileEntry *pParent) throw (kError::enmErrors)
|
---|
1606 | : pParent(pParent), pszParent(pszParent)
|
---|
1607 | {
|
---|
1608 | const char *pszFilename;
|
---|
1609 |
|
---|
1610 | /* verify tag */
|
---|
1611 | if (stricmp(tag.getTagname(), "!kInclude"))
|
---|
1612 | throw(kError::error_invalid_tag);
|
---|
1613 |
|
---|
1614 | /* verify parameters */
|
---|
1615 | if (tag.getParameterCount() != 1)
|
---|
1616 | throw(kError::error_incorrect_number_of_parameters);
|
---|
1617 |
|
---|
1618 | /* get filename */
|
---|
1619 | pszFilename = tag.queryParameter("filename");
|
---|
1620 | if (pszFilename == NULL)
|
---|
1621 | throw(kError::error_no_filename);
|
---|
1622 |
|
---|
1623 | /* copy filename */
|
---|
1624 | strcpy(&szFilename[0], pszFilename);
|
---|
1625 |
|
---|
1626 | /* open and read file */
|
---|
1627 | openAndReadFile(&szFilename[0]);
|
---|
1628 | pszCurrent = pszFile;
|
---|
1629 | }
|
---|
1630 |
|
---|
1631 |
|
---|
1632 | /**
|
---|
1633 | * Destroys the file entry object.
|
---|
1634 | */
|
---|
1635 | kFileEntry::~kFileEntry()
|
---|
1636 | {
|
---|
1637 | delete pszFile;
|
---|
1638 | pszCurrent = NULL;
|
---|
1639 |
|
---|
1640 | }
|
---|
1641 |
|
---|
1642 |
|
---|
1643 | /**
|
---|
1644 | * Get linenumber.
|
---|
1645 | * @returns linenumber, -1 on error
|
---|
1646 | * @remark 0 based.
|
---|
1647 | */
|
---|
1648 | long kFileEntry::getLineNumber(void) const
|
---|
1649 | {
|
---|
1650 | long cLines = 0;
|
---|
1651 | char *psz = pszFile;
|
---|
1652 |
|
---|
1653 | while (psz < pszCurrent && *psz != '\0')
|
---|
1654 | {
|
---|
1655 | if (*psz == '\n')
|
---|
1656 | cLines++;
|
---|
1657 | psz++;
|
---|
1658 | }
|
---|
1659 |
|
---|
1660 | return cLines;
|
---|
1661 | }
|
---|
1662 |
|
---|
1663 |
|
---|
1664 | /**
|
---|
1665 | * Creates a variable entry object.
|
---|
1666 | */
|
---|
1667 | kVariableEntry::kVariableEntry(const char *pszName, const char *pszValue)
|
---|
1668 | {
|
---|
1669 | this->pszName = dupeString(pszName);
|
---|
1670 | this->pszValue = dupeString(pszValue);
|
---|
1671 | }
|
---|
1672 |
|
---|
1673 |
|
---|
1674 | /**
|
---|
1675 | * Destroys the variable entry object.
|
---|
1676 | */
|
---|
1677 | kVariableEntry::~kVariableEntry()
|
---|
1678 | {
|
---|
1679 | if (pszName != NULL)
|
---|
1680 | delete pszName;
|
---|
1681 | if (pszValue != NULL)
|
---|
1682 | delete pszValue;
|
---|
1683 | }
|
---|
1684 |
|
---|
1685 |
|
---|
1686 | /**
|
---|
1687 | * Executes the sql query present in pszSql.
|
---|
1688 | * @remark Throws error code.
|
---|
1689 | */
|
---|
1690 | void kSqlEntry::dbExecuteQuery(void) throw (kError::enmErrors)
|
---|
1691 | {
|
---|
1692 | pres = ::dbExecuteQuery(pszSql);
|
---|
1693 | if (pres != NULL)
|
---|
1694 | {
|
---|
1695 | cRows = dbQueryResultRows(pres);
|
---|
1696 | dbFetch();
|
---|
1697 | }
|
---|
1698 | else
|
---|
1699 | throw(kError::error_sql_failed);
|
---|
1700 | }
|
---|
1701 |
|
---|
1702 |
|
---|
1703 | /**
|
---|
1704 | * Fetch next row of results.
|
---|
1705 | * @returns success indicator. TRUE / FASLE.
|
---|
1706 | * @result lifoVariables are destroyed.
|
---|
1707 | */
|
---|
1708 | BOOL kSqlEntry::dbFetch(void)
|
---|
1709 | {
|
---|
1710 | BOOL fRc = FALSE;
|
---|
1711 |
|
---|
1712 | lifoVariables.destroy();
|
---|
1713 |
|
---|
1714 | if (cRows != 0)
|
---|
1715 | {
|
---|
1716 | cRows--;
|
---|
1717 | fRc = ::dbFetch(pres, dbFetchCallBack, (void*)&lifoVariables);
|
---|
1718 | }
|
---|
1719 |
|
---|
1720 | return fRc;
|
---|
1721 | }
|
---|
1722 |
|
---|
1723 |
|
---|
1724 | /**
|
---|
1725 | * Callback function used when receiving data from a dbFetch call.
|
---|
1726 | * This function creates a new kVariableEntry from the input, and pushes it
|
---|
1727 | * onto the variable lifo.
|
---|
1728 | * @returns 0 success, -1 error.
|
---|
1729 | * @param pszValue Field value. Used as variable value.
|
---|
1730 | * @param pszFieldName Field name. Used as variable name.
|
---|
1731 | * @param pvUser Pointer to user defined data, here a variable lifo.
|
---|
1732 | */
|
---|
1733 | static long _System dbFetchCallBack(const char *pszValue, const char *pszFieldName, void *pvUser)
|
---|
1734 | {
|
---|
1735 | kLIFO<kVariableEntry> *plifoVar = (kLIFO<kVariableEntry> *) pvUser;
|
---|
1736 | kVariableEntry *pVarEntry;
|
---|
1737 |
|
---|
1738 | if (pszFieldName == NULL)
|
---|
1739 | return -1;
|
---|
1740 | if (pszValue == NULL)
|
---|
1741 | pszValue = "-NULL-";
|
---|
1742 | pVarEntry = new kVariableEntry(pszFieldName, pszValue);
|
---|
1743 | if (pVarEntry != NULL)
|
---|
1744 | plifoVar->push(pVarEntry);
|
---|
1745 | else
|
---|
1746 | return -1;
|
---|
1747 | return 0;
|
---|
1748 | }
|
---|
1749 |
|
---|
1750 |
|
---|
1751 | /**
|
---|
1752 | * Frees the database result.
|
---|
1753 | * @remark Called during destruction of object.
|
---|
1754 | */
|
---|
1755 | void kSqlEntry::dbFreeResult(void)
|
---|
1756 | {
|
---|
1757 | if (pres != NULL)
|
---|
1758 | {
|
---|
1759 | ::dbFreeResult(pres);
|
---|
1760 | pres = NULL;
|
---|
1761 | }
|
---|
1762 | }
|
---|
1763 |
|
---|
1764 |
|
---|
1765 | /**
|
---|
1766 | * Creates a dummy sql entry.
|
---|
1767 | */
|
---|
1768 | kSqlEntry::kSqlEntry() :
|
---|
1769 | pszSql(NULL), pres(NULL), cRows(0), pFileEntry(pFileEntry), pszCurrent(pszCurrent)
|
---|
1770 | {
|
---|
1771 | }
|
---|
1772 |
|
---|
1773 |
|
---|
1774 | /**
|
---|
1775 | * Interpret the <!kSql ...> tag and creates an sql entry object from it.
|
---|
1776 | * @param pszCurrent Current pointer into the file entry object.
|
---|
1777 | * @param pFileEntry Pointer to current file entry object.
|
---|
1778 | * @remark throws error code.
|
---|
1779 | */
|
---|
1780 | kSqlEntry::kSqlEntry(const kTag &tag, const char *pszCurrent, const kFileEntry *pFileEntry) throw (kError::enmErrors)
|
---|
1781 | : pszSql(NULL), pres(NULL), cRows(0), pFileEntry(pFileEntry), pszCurrent(pszCurrent)
|
---|
1782 | {
|
---|
1783 | const char *pszSql;
|
---|
1784 |
|
---|
1785 | /* verify tag */
|
---|
1786 | if (!tag.isTag("!kSql"))
|
---|
1787 | throw(kError::error_invalid_tag);
|
---|
1788 | if (!tag.queryExists("sql"))
|
---|
1789 | throw(kError::error_missing_sql);
|
---|
1790 | if (tag.getParameterCount() > 1)
|
---|
1791 | throw(kError::error_incorrect_number_of_parameters);
|
---|
1792 |
|
---|
1793 | /* get sql */
|
---|
1794 | pszSql = tag.queryParameter("sql");
|
---|
1795 | if (pszSql == NULL || strlen(pszSql) == 0)
|
---|
1796 | throw(kError::error_invalid_sql_tag);
|
---|
1797 |
|
---|
1798 | this->pszSql = dupeString(pszSql);
|
---|
1799 | if (this->pszSql == NULL)
|
---|
1800 | throw(kError::error_new_failed);
|
---|
1801 |
|
---|
1802 | /* execute sql */
|
---|
1803 | dbExecuteQuery();
|
---|
1804 | }
|
---|
1805 |
|
---|
1806 |
|
---|
1807 | /**
|
---|
1808 | * Destructor.
|
---|
1809 | */
|
---|
1810 | kSqlEntry::~kSqlEntry()
|
---|
1811 | {
|
---|
1812 | if (pszSql != NULL)
|
---|
1813 | delete pszSql;
|
---|
1814 | dbFreeResult();
|
---|
1815 | }
|
---|
1816 |
|
---|
1817 |
|
---|
1818 | /**
|
---|
1819 | * Equal operator. Comapres this object with a key string.
|
---|
1820 | * @returns TRUE if equal, FALSE if not equal.
|
---|
1821 | * @param psz Pointer to key string.
|
---|
1822 | */
|
---|
1823 | BOOL kSqlEntry::operator ==(const char *psz) const
|
---|
1824 | {
|
---|
1825 | return lifoVariables.find(psz) != NULL;
|
---|
1826 | }
|
---|
1827 |
|
---|
1828 |
|
---|
1829 | /**
|
---|
1830 | * Fetches the next set of data.
|
---|
1831 | * @returns Success indicator. TRUE / FALSE.
|
---|
1832 | */
|
---|
1833 | BOOL kSqlEntry::fetch(void)
|
---|
1834 | {
|
---|
1835 | return dbFetch();
|
---|
1836 | }
|
---|
1837 |
|
---|
1838 |
|
---|
1839 | /**
|
---|
1840 | * Finds a kVariableEntry matching a given key.
|
---|
1841 | * @returns Const pointer to variable node or NULL (if not found).
|
---|
1842 | * @param pszKey Key to match.
|
---|
1843 | */
|
---|
1844 | const kVariableEntry *kSqlEntry::find(const char *pszKey) const
|
---|
1845 | {
|
---|
1846 | return lifoVariables.find(pszKey);
|
---|
1847 | }
|
---|
1848 |
|
---|
1849 |
|
---|
1850 | /**
|
---|
1851 | * Checks if a node exists.
|
---|
1852 | * @returns TRUE - node exists, FALSE - node does not exist.
|
---|
1853 | * @param pVariableEntry Pointer to node/entry.
|
---|
1854 | */
|
---|
1855 | BOOL kSqlEntry::exists(const kVariableEntry *pVariableEntry) const
|
---|
1856 | {
|
---|
1857 | return lifoVariables.exists(pVariableEntry);
|
---|
1858 | }
|
---|
1859 |
|
---|
1860 |
|
---|
1861 | /**
|
---|
1862 | * Gets last sql error.
|
---|
1863 | * @returns Pointer to readonly string describing the error.
|
---|
1864 | */
|
---|
1865 | const char *kSqlEntry::querySqlLastError(void)
|
---|
1866 | {
|
---|
1867 | return dbGetLastErrorDesc();
|
---|
1868 | }
|
---|
1869 |
|
---|
1870 |
|
---|
1871 | /**
|
---|
1872 | * Finds an item in the sublist of the nodes.. Matching a given key.
|
---|
1873 | * @returns Pointer to subnode if found.
|
---|
1874 | * @param pszKey Key to match.
|
---|
1875 | * @remark uses the const EntryEntry *find(const char *pszKey) const; function.
|
---|
1876 | */
|
---|
1877 | template <class kEntry, class kEntryEntry>
|
---|
1878 | const kEntryEntry *kLIFO2<kEntry, kEntryEntry>::findSub(const char *pszKey) const
|
---|
1879 | {
|
---|
1880 | const kEntry *pE = pTop;
|
---|
1881 | const kEntryEntry *pEE = NULL;
|
---|
1882 |
|
---|
1883 | while (pE != NULL && (pEE = pE->find(pszKey)) == NULL)
|
---|
1884 | pE = (const kEntry*)pE->getNext();
|
---|
1885 |
|
---|
1886 | return pEE;
|
---|
1887 | }
|
---|
1888 |
|
---|
1889 |
|
---|
1890 | /**
|
---|
1891 | * Checks if an item exists.
|
---|
1892 | * @returns TRUE - exists, FALSE - doesn't exists
|
---|
1893 | * @param pEntryEntry Pointer to sub not which is to exists.
|
---|
1894 | * @remark uses the BOOL exist(const char *pszKey) const; function.
|
---|
1895 | */
|
---|
1896 | template <class kEntry, class kEntryEntry>
|
---|
1897 | BOOL kLIFO2<kEntry, kEntryEntry>::existsSub(const kEntryEntry *pEntryEntry) const
|
---|
1898 | {
|
---|
1899 | kEntry *pE = pTop;
|
---|
1900 | BOOL f= FALSE;
|
---|
1901 |
|
---|
1902 | while (pE != NULL && !(f = pE->exists(pEntryEntry)))
|
---|
1903 | pE = (kEntry *)pE->getNext();
|
---|
1904 |
|
---|
1905 | return f;
|
---|
1906 | }
|
---|
1907 |
|
---|
1908 |
|
---|
1909 | /**
|
---|
1910 | * BOOL operator.
|
---|
1911 | */
|
---|
1912 | BOOL kGraphData::operator==(const kGraphData &entry) const
|
---|
1913 | {
|
---|
1914 | return rdX == entry.rdX;
|
---|
1915 | }
|
---|
1916 |
|
---|
1917 |
|
---|
1918 | /**
|
---|
1919 | * BOOL operator.
|
---|
1920 | */
|
---|
1921 | BOOL kGraphData::operator!=(const kGraphData &entry) const
|
---|
1922 | {
|
---|
1923 | return rdX != entry.rdX;
|
---|
1924 | }
|
---|
1925 |
|
---|
1926 |
|
---|
1927 | /**
|
---|
1928 | * BOOL operator.
|
---|
1929 | */
|
---|
1930 | BOOL kGraphData::operator< (const kGraphData &entry) const
|
---|
1931 | {
|
---|
1932 | return rdX < entry.rdX;
|
---|
1933 | }
|
---|
1934 |
|
---|
1935 |
|
---|
1936 | /**
|
---|
1937 | * BOOL operator.
|
---|
1938 | */
|
---|
1939 | BOOL kGraphData::operator<=(const kGraphData &entry) const
|
---|
1940 | {
|
---|
1941 | return rdX <= entry.rdX;
|
---|
1942 | }
|
---|
1943 |
|
---|
1944 |
|
---|
1945 | /**
|
---|
1946 | * BOOL operator.
|
---|
1947 | */
|
---|
1948 | BOOL kGraphData::operator> (const kGraphData &entry) const
|
---|
1949 | {
|
---|
1950 | return rdX > entry.rdX;
|
---|
1951 | }
|
---|
1952 |
|
---|
1953 |
|
---|
1954 | /**
|
---|
1955 | * BOOL operator.
|
---|
1956 | */
|
---|
1957 | BOOL kGraphData::operator>=(const kGraphData &entry) const
|
---|
1958 | {
|
---|
1959 | return rdX >= entry.rdX;
|
---|
1960 | }
|
---|
1961 |
|
---|
1962 |
|
---|
1963 | /**
|
---|
1964 | * Adds a warning to the list of warnings.
|
---|
1965 | * @param enmErrorCd Warning code.
|
---|
1966 | */
|
---|
1967 | void kGraphDataSet::addWarning(kError::enmErrors enmErrorCd)
|
---|
1968 | {
|
---|
1969 | if (plistWarnings != NULL)
|
---|
1970 | plistWarnings->insert(new kWarningEntry(enmErrorCd));
|
---|
1971 | else
|
---|
1972 | assert(!"internal error");
|
---|
1973 | }
|
---|
1974 |
|
---|
1975 |
|
---|
1976 | /**
|
---|
1977 | * Constructs an empty dataset.
|
---|
1978 | * @remark Throws kError::enmErrors
|
---|
1979 | */
|
---|
1980 | kGraphDataSet::kGraphDataSet() throw(kError::enmErrors)
|
---|
1981 | : rdCount(_NAN), ulColor(0xffffffffUL), clrColor(-1), pszLegend(NULL),
|
---|
1982 | fXDate(FALSE), plistWarnings(NULL)
|
---|
1983 | {
|
---|
1984 | }
|
---|
1985 |
|
---|
1986 |
|
---|
1987 | /**
|
---|
1988 | * Constructs a dataset from a sql statement and a given graph type.
|
---|
1989 | * @param pszSql Sql-statement which gives us the data.
|
---|
1990 | * @param enmTypeCd This is the integer value of the graph type.
|
---|
1991 | * @param plistWarnings Pointer to warning list.
|
---|
1992 | * @remark Throws kError::enmErrors
|
---|
1993 | */
|
---|
1994 | kGraphDataSet::kGraphDataSet(const char *pszSql, int enmTypeCd,
|
---|
1995 | kSortedList<kWarningEntry> *plistWarnings) throw(kError::enmErrors)
|
---|
1996 | : rdCount(_NAN), ulColor(0xffffffffUL), clrColor(-1), pszLegend(NULL),
|
---|
1997 | fXDate(FALSE), plistWarnings(plistWarnings)
|
---|
1998 | {
|
---|
1999 | void *pres;
|
---|
2000 | if (pszSql == NULL || strlen(pszSql) == 0) throw(kError::error_data_param_is_missing_sql_statement);
|
---|
2001 | if (enmTypeCd == kGraph::unknown) throw(kError::error_graph_type_must_be_specified_before_data);
|
---|
2002 |
|
---|
2003 | switch (enmTypeCd)
|
---|
2004 | {
|
---|
2005 | case kGraph::lines:
|
---|
2006 | {
|
---|
2007 | pres = ::dbExecuteQuery(pszSql);
|
---|
2008 | if (pres != NULL)
|
---|
2009 | {
|
---|
2010 | GRAPHCALLBACKPARAM Param = {NULL, this, NULL, (kGraph::enmType)enmTypeCd, 0};
|
---|
2011 | while (::dbFetch(pres, dbDataSetCallBack, (void*)&Param))
|
---|
2012 | Param.lSeqNbr = 0;
|
---|
2013 | }
|
---|
2014 | else
|
---|
2015 | throw(kError::error_sql_failed);
|
---|
2016 | break;
|
---|
2017 | }
|
---|
2018 |
|
---|
2019 | case kGraph::pie:
|
---|
2020 | addWarning(kError::warning_pie_not_implemented_yet);
|
---|
2021 |
|
---|
2022 | default:
|
---|
2023 | break;
|
---|
2024 | }
|
---|
2025 | }
|
---|
2026 |
|
---|
2027 |
|
---|
2028 | /**
|
---|
2029 | * Callback function used when receiving data.
|
---|
2030 | * @returns 0 success, -1 error.
|
---|
2031 | * @param pszValue Field value. Used as variable value.
|
---|
2032 | * @param pszFieldName Field name. Used as variable name.
|
---|
2033 | * @param pvUser Pointer to user defined data, here a variable lifo.
|
---|
2034 | */
|
---|
2035 | long _System dbDataSetCallBack(const char *pszValue, const char *pszFieldName, void *pvUser)
|
---|
2036 | {
|
---|
2037 | PGRAPHCALLBACKPARAM pParam = (PGRAPHCALLBACKPARAM)pvUser;
|
---|
2038 |
|
---|
2039 | assert(pParam != NULL);
|
---|
2040 |
|
---|
2041 | switch (pParam->enmTypeCd)
|
---|
2042 | {
|
---|
2043 | case kGraph::lines:
|
---|
2044 | {
|
---|
2045 | switch (pParam->lSeqNbr)
|
---|
2046 | {
|
---|
2047 | case 0:
|
---|
2048 | pParam->pData = new kGraphData;
|
---|
2049 | /* date test */
|
---|
2050 | if (strlen(pszValue) == (4+1+2+1+2) && pszValue[4] == '-' && pszValue[7] == '-')
|
---|
2051 | {
|
---|
2052 | strcpy(&pParam->pData->szXDate[0], pszValue);
|
---|
2053 | pParam->pData->rdX = kGraph::dateToDbl(&pParam->pData->szXDate[0]);
|
---|
2054 | pParam->pDataSet->fXDate = TRUE;
|
---|
2055 | }
|
---|
2056 | else
|
---|
2057 | {
|
---|
2058 | pParam->pData->szXDate[0] = '\0';
|
---|
2059 | pParam->pData->rdX = atol(pszValue);
|
---|
2060 | }
|
---|
2061 | pParam->pDataSet->listData.insert(pParam->pData);
|
---|
2062 | break;
|
---|
2063 |
|
---|
2064 | case 1:
|
---|
2065 | pParam->pData->rdY = atol(pszValue);
|
---|
2066 | break;
|
---|
2067 |
|
---|
2068 | case 2:
|
---|
2069 | if (pszFieldName == NULL || stricmp(pszFieldName, "legend") != 0)
|
---|
2070 | pParam->pDataSet->setColor(pszValue);
|
---|
2071 | else
|
---|
2072 | pParam->pDataSet->setLegend(pszValue);
|
---|
2073 | break;
|
---|
2074 |
|
---|
2075 | case 3:
|
---|
2076 | if (pszFieldName == NULL || stricmp(pszFieldName, "color") != 0)
|
---|
2077 | pParam->pDataSet->setLegend(pszValue);
|
---|
2078 | else
|
---|
2079 | pParam->pDataSet->setColor(pszValue);
|
---|
2080 | break;
|
---|
2081 |
|
---|
2082 | default:
|
---|
2083 | pParam->pDataSet->addWarning(kError::warning_to_many_fields_in_data_sql);
|
---|
2084 | }
|
---|
2085 | break;
|
---|
2086 | }
|
---|
2087 |
|
---|
2088 | case kGraph::pie:
|
---|
2089 | default:
|
---|
2090 | break;
|
---|
2091 | }
|
---|
2092 |
|
---|
2093 | pParam->lSeqNbr++;
|
---|
2094 | return 0;
|
---|
2095 | }
|
---|
2096 |
|
---|
2097 |
|
---|
2098 | /**
|
---|
2099 | * Destructor.
|
---|
2100 | */
|
---|
2101 | kGraphDataSet::~kGraphDataSet(void)
|
---|
2102 | {
|
---|
2103 | if (pszLegend != NULL) delete pszLegend;
|
---|
2104 | }
|
---|
2105 |
|
---|
2106 |
|
---|
2107 | /**
|
---|
2108 | * Find max X value in set.
|
---|
2109 | * @returns max X value. 0.0 if empty set.
|
---|
2110 | */
|
---|
2111 | double kGraphDataSet::maxX(void) const
|
---|
2112 | {
|
---|
2113 | double rdRet = _NAN;
|
---|
2114 | kGraphData *p = listData.getFirst();
|
---|
2115 |
|
---|
2116 | while (p != NULL)
|
---|
2117 | {
|
---|
2118 | if (rdRet < p->rdX || rdRet != rdRet)
|
---|
2119 | rdRet = p->rdX;
|
---|
2120 | p = (kGraphData*)p->getNext();
|
---|
2121 | }
|
---|
2122 |
|
---|
2123 | return rdRet == rdRet ? rdRet : 0.0;
|
---|
2124 | }
|
---|
2125 |
|
---|
2126 |
|
---|
2127 | /**
|
---|
2128 | * Find min X value in set.
|
---|
2129 | * @returns min X value. 0.0 if empty set.
|
---|
2130 | */
|
---|
2131 | double kGraphDataSet::minX(void) const
|
---|
2132 | {
|
---|
2133 | double rdRet = _NAN;
|
---|
2134 | kGraphData *p = listData.getFirst();
|
---|
2135 |
|
---|
2136 | while (p != NULL)
|
---|
2137 | {
|
---|
2138 | if (rdRet > p->rdX || rdRet != rdRet)
|
---|
2139 | rdRet = p->rdX;
|
---|
2140 | p = (kGraphData*)p->getNext();
|
---|
2141 | }
|
---|
2142 |
|
---|
2143 | return rdRet == rdRet ? rdRet : 0.0;
|
---|
2144 | }
|
---|
2145 |
|
---|
2146 |
|
---|
2147 | /**
|
---|
2148 | * Find max Y value in set.
|
---|
2149 | * @returns max Y value. 0.0 if empty set.
|
---|
2150 | */
|
---|
2151 | double kGraphDataSet::maxY(void) const
|
---|
2152 | {
|
---|
2153 | double rdRet = _NAN;
|
---|
2154 | kGraphData *p = listData.getFirst();
|
---|
2155 |
|
---|
2156 | while (p != NULL)
|
---|
2157 | {
|
---|
2158 | if (rdRet < p->rdY || rdRet != rdRet)
|
---|
2159 | rdRet = p->rdY;
|
---|
2160 | p = (kGraphData*)p->getNext();
|
---|
2161 | }
|
---|
2162 |
|
---|
2163 | return rdRet == rdRet ? rdRet : 0.0;
|
---|
2164 | }
|
---|
2165 |
|
---|
2166 |
|
---|
2167 | /**
|
---|
2168 | * Find min Y value in set.
|
---|
2169 | * @returns min Y value. 0.0 if empty set.
|
---|
2170 | */
|
---|
2171 | double kGraphDataSet::minY(void) const
|
---|
2172 | {
|
---|
2173 | double rdRet = _NAN;
|
---|
2174 | kGraphData *p = listData.getFirst();
|
---|
2175 |
|
---|
2176 | while (p != NULL)
|
---|
2177 | {
|
---|
2178 | if (rdRet > p->rdY || rdRet != rdRet)
|
---|
2179 | rdRet = p->rdY;
|
---|
2180 | p = (kGraphData*)p->getNext();
|
---|
2181 | }
|
---|
2182 |
|
---|
2183 | return rdRet == rdRet ? rdRet : 0.0;
|
---|
2184 | }
|
---|
2185 |
|
---|
2186 |
|
---|
2187 | /**
|
---|
2188 | * Sets the ulColor data member. This
|
---|
2189 | * @param pszColor Pointer to color string. That is "#RRGGBB".
|
---|
2190 | */
|
---|
2191 | void kGraphDataSet::setColor(const char *pszColor)
|
---|
2192 | {
|
---|
2193 | if (ulColor != 0xffffffffUL)
|
---|
2194 | return;
|
---|
2195 |
|
---|
2196 | if (*pszColor == '#')
|
---|
2197 | {
|
---|
2198 | ulColor = 0;
|
---|
2199 | for (int i = 1; i < 7; i++)
|
---|
2200 | {
|
---|
2201 | ulColor = ulColor << 4;
|
---|
2202 | if (pszColor[i] >= '0' && pszColor[i] <= '9')
|
---|
2203 | ulColor |= pszColor[i] - '0';
|
---|
2204 | else if (pszColor[i] >= 'A' && pszColor[i] <= 'F')
|
---|
2205 | ulColor |= pszColor[i] - 'A' + 0xa;
|
---|
2206 | else if (pszColor[i] >= 'a' && pszColor[i] <= 'f')
|
---|
2207 | ulColor |= pszColor[i] - 'a' + 0xa;
|
---|
2208 | else
|
---|
2209 | addWarning(kError::warning_invalid_color_value);
|
---|
2210 | }
|
---|
2211 | }
|
---|
2212 | else
|
---|
2213 | addWarning(kError::warning_invalid_color_value);
|
---|
2214 | }
|
---|
2215 |
|
---|
2216 |
|
---|
2217 | /**
|
---|
2218 | * Allocates color and set the clrColor datamember.
|
---|
2219 | * @param pGraph Pointer to gifdraw image structure.
|
---|
2220 | */
|
---|
2221 | void kGraphDataSet::setColor(gdImagePtr pGraph)
|
---|
2222 | {
|
---|
2223 | if (clrColor == -1)
|
---|
2224 | clrColor = gdImageColorAllocate(pGraph,
|
---|
2225 | (int)(0xFF & (ulColor >> 16)),
|
---|
2226 | (int)(0xFF & (ulColor >> 8)),
|
---|
2227 | (int)(0xFF & ulColor));
|
---|
2228 | }
|
---|
2229 |
|
---|
2230 |
|
---|
2231 | /**
|
---|
2232 | * Sets the legend string.
|
---|
2233 | * @param pszLegend Legend.
|
---|
2234 | */
|
---|
2235 | void kGraphDataSet::setLegend(const char *pszLegend)
|
---|
2236 | {
|
---|
2237 | if (this->pszLegend == NULL)
|
---|
2238 | this->pszLegend = dupeString(pszLegend);
|
---|
2239 | }
|
---|
2240 |
|
---|
2241 |
|
---|
2242 | /**
|
---|
2243 | * Analyses the tag and executes SQL statements.
|
---|
2244 | * @param tag Tag.
|
---|
2245 | * @remark Throws kError::enmErrors
|
---|
2246 | */
|
---|
2247 | void kGraph::analyseTag(const kTag &tag) throw(kError::enmErrors)
|
---|
2248 | {
|
---|
2249 | int cArgs, i;
|
---|
2250 | const char *pszName;
|
---|
2251 | const char *pszValue;
|
---|
2252 | /*const char *psz;
|
---|
2253 | long l;
|
---|
2254 | unsigned long ul;*/
|
---|
2255 |
|
---|
2256 | /* tagname */
|
---|
2257 | if (stricmp(tag.getTagname(), "!kGraph") != 0)
|
---|
2258 | throw(kError::error_invalid_tagname);
|
---|
2259 |
|
---|
2260 | /* parameters */
|
---|
2261 | i = 0;
|
---|
2262 | cArgs = (int)tag.getParameterCount();
|
---|
2263 | while (i < cArgs)
|
---|
2264 | {
|
---|
2265 | pszName = tag.queryParameterName(i);
|
---|
2266 | pszValue = tag.queryParameterValue(i);
|
---|
2267 |
|
---|
2268 | if (stricmp(pszName, "data") == 0)
|
---|
2269 | {
|
---|
2270 | if ((int)enmTypeCd == unknown) throw(kError::error_graph_type_must_be_specified_before_data);
|
---|
2271 | if (pszValue == NULL || strlen(pszValue) == 0) throw(kError::error_data_param_is_missing_value);
|
---|
2272 | #if 0
|
---|
2273 | listDataSets.insert(new kGraphDataSet(pszValue, enmTypeCd, &listWarnings));
|
---|
2274 | #else
|
---|
2275 | fetchData(pszValue);
|
---|
2276 | #endif
|
---|
2277 | }
|
---|
2278 | else if (stricmp(pszName, "type") == 0)
|
---|
2279 | {
|
---|
2280 | if (pszValue == NULL) throw(kError::error_type_param_is_missing_value);
|
---|
2281 | if (stricmp(pszValue, "lines") == 0)
|
---|
2282 | enmTypeCd = lines;
|
---|
2283 | else if (stricmp(pszValue, "pie") == 0)
|
---|
2284 | enmTypeCd = pie;
|
---|
2285 | else
|
---|
2286 | throw(kError::error_invalid_type);
|
---|
2287 |
|
---|
2288 | }
|
---|
2289 | else if (stricmp(pszName, "subtype") == 0)
|
---|
2290 | {
|
---|
2291 | if (pszValue != NULL && stricmp(pszValue, "normal") == 0)
|
---|
2292 | enmSubTypeCd = normal;
|
---|
2293 | else
|
---|
2294 | addWarning(kError::warning_invalid_sub_type);
|
---|
2295 | }
|
---|
2296 | else if (stricmp(pszName, "filename") == 0)
|
---|
2297 | {
|
---|
2298 | if (pszValue == NULL || strlen(pszValue) == 0) throw(kError::error_filename_param_is_missing_value);
|
---|
2299 | pszFilename = dupeString(pszValue);
|
---|
2300 | }
|
---|
2301 | else if (stricmp(pszName, "title") == 0)
|
---|
2302 | {
|
---|
2303 | if (pszValue != NULL)
|
---|
2304 | pszTitle = dupeString(pszValue);
|
---|
2305 | else
|
---|
2306 | addWarning(kError::warning_title_param_is_missing_value);
|
---|
2307 | }
|
---|
2308 | else if (stricmp(pszName, "titlex") == 0)
|
---|
2309 | {
|
---|
2310 | if (pszValue != NULL)
|
---|
2311 | pszTitleX = dupeString(pszValue);
|
---|
2312 | else
|
---|
2313 | addWarning(kError::warning_titlex_param_is_missing_value);
|
---|
2314 | }
|
---|
2315 | else if (stricmp(pszName, "titley") == 0)
|
---|
2316 | {
|
---|
2317 | if (pszValue != NULL)
|
---|
2318 | pszTitleY = dupeString(pszValue);
|
---|
2319 | else
|
---|
2320 | addWarning(kError::warning_titley_param_is_missing_value);
|
---|
2321 | }
|
---|
2322 | else if (stricmp(pszName, "legend") == 0)
|
---|
2323 | {
|
---|
2324 | fLegend = pszValue == NULL || stricmp(pszValue, "yes") == 0;
|
---|
2325 | }
|
---|
2326 | else if (stricmp(pszName, "width") == 0 || stricmp(pszName, "cx") == 0)
|
---|
2327 | {
|
---|
2328 | if (pszValue == NULL || strlen(pszValue) == 0) throw(kError::error_width_cx_param_is_missing_value);
|
---|
2329 | cX = atol(pszValue);
|
---|
2330 | if (cX < 100)
|
---|
2331 | throw(kError::error_graph_to_small);
|
---|
2332 | }
|
---|
2333 | else if (stricmp(pszName, "height") == 0 || stricmp(pszName, "cy") == 0)
|
---|
2334 | {
|
---|
2335 | if (pszValue == NULL || strlen(pszValue) == 0) throw(kError::error_height_cy_param_is_missing_value);
|
---|
2336 | cY = atol(pszValue);
|
---|
2337 | if (cY < 100)
|
---|
2338 | throw(kError::error_graph_to_small);
|
---|
2339 | }
|
---|
2340 | else if (stricmp(pszName, "startx") == 0 || stricmp(pszName, "minx") == 0)
|
---|
2341 | {
|
---|
2342 | if (pszValue == NULL || strlen(pszValue) == 0) throw(kError::error_xstart_param_is_missing_value);
|
---|
2343 | if (isDate(pszValue))
|
---|
2344 | rdStartX = dateToDbl(pszValue);
|
---|
2345 | else
|
---|
2346 | rdStartX = (double)atol(pszValue); /* TODO: real value not supported */
|
---|
2347 | }
|
---|
2348 | else if (stricmp(pszName, "endx") == 0 || stricmp(pszName, "maxx") == 0)
|
---|
2349 | {
|
---|
2350 | if (pszValue == NULL || strlen(pszValue) == 0) throw(kError::error_xend_param_is_missing_value);
|
---|
2351 | if (isDate(pszValue))
|
---|
2352 | rdEndX = dateToDbl(pszValue);
|
---|
2353 | else
|
---|
2354 | rdEndX = (double)atol(pszValue); /* TODO: real value not supported */
|
---|
2355 | }
|
---|
2356 | else if (stricmp(pszName, "starty") == 0 || stricmp(pszName, "miny") == 0)
|
---|
2357 | {
|
---|
2358 | if (pszValue == NULL || strlen(pszValue) == 0) throw(kError::error_ystart_param_is_missing_value);
|
---|
2359 | rdStartY = (double)atol(pszValue); /* TODO: real value not supported */
|
---|
2360 | }
|
---|
2361 | else if (stricmp(pszName, "endy") == 0 || stricmp(pszName, "maxy") == 0)
|
---|
2362 | {
|
---|
2363 | if (pszValue == NULL || strlen(pszValue) == 0) throw(kError::error_yend_param_is_missing_value);
|
---|
2364 | rdEndY = (double)atol(pszValue); /* TODO: real value not supported */
|
---|
2365 | }
|
---|
2366 | else if (stricmp(pszName, "background") == 0)
|
---|
2367 | {
|
---|
2368 | if (pszValue != NULL)
|
---|
2369 | {
|
---|
2370 | if (pszValue[0] == '#')
|
---|
2371 | ulBGColor = readColor(pszValue);
|
---|
2372 | else
|
---|
2373 | pszBackground = dupeString(pszValue);
|
---|
2374 | }
|
---|
2375 | else
|
---|
2376 | addWarning(kError::warning_background_param_is_missing_value);
|
---|
2377 | }
|
---|
2378 | else if (stricmp(pszName, "backgroundcolor") == 0)
|
---|
2379 | {
|
---|
2380 | if (pszValue != NULL)
|
---|
2381 | {
|
---|
2382 | if (pszValue[0] == '#')
|
---|
2383 | ulBGColor = readColor(pszValue);
|
---|
2384 | else
|
---|
2385 | addWarning(kError::warning_backgroundcolor_is_invalid);
|
---|
2386 | }
|
---|
2387 | else
|
---|
2388 | addWarning(kError::warning_backgroundcolor_param_is_missing_value);
|
---|
2389 | }
|
---|
2390 | else if (stricmp(pszName, "foregroundcolor") == 0)
|
---|
2391 | {
|
---|
2392 | if (pszValue != NULL)
|
---|
2393 | {
|
---|
2394 | if (pszValue[0] == '#')
|
---|
2395 | ulFGColor = readColor(pszValue);
|
---|
2396 | else
|
---|
2397 | addWarning(kError::warning_foregroundcolor_is_invalid);
|
---|
2398 | }
|
---|
2399 | else
|
---|
2400 | addWarning(kError::warning_foregroundcolor_param_is_missing_value);
|
---|
2401 | }
|
---|
2402 | else if (stricmp(pszName, "axiscolor") == 0)
|
---|
2403 | {
|
---|
2404 | if (pszValue != NULL)
|
---|
2405 | {
|
---|
2406 | if (pszValue[0] == '#')
|
---|
2407 | ulAxisColor = readColor(pszValue);
|
---|
2408 | else
|
---|
2409 | addWarning(kError::warning_axiscolor_is_invalid);
|
---|
2410 | }
|
---|
2411 | else
|
---|
2412 | addWarning(kError::warning_axiscolor_param_is_missing_value);
|
---|
2413 | }
|
---|
2414 | else
|
---|
2415 | addWarning(kError::warning_invalid_parameter);
|
---|
2416 |
|
---|
2417 | /* next */
|
---|
2418 | i++;
|
---|
2419 | }
|
---|
2420 |
|
---|
2421 | /* check that required parameters are present */
|
---|
2422 | if ((int)enmTypeCd == unknown) throw(kError::error_graph_type_is_missing);
|
---|
2423 | if ((int)enmSubTypeCd != normal) throw(kError::error_graph_subtype_is_invalid);
|
---|
2424 | if (pszFilename == NULL) throw(kError::error_filename_is_missing);
|
---|
2425 | if (listDataSets.getFirst() == NULL) throw(kError::error_no_data);
|
---|
2426 | if (cX < 50 || cY < 40) throw(kError::error_invalid_dimentions);
|
---|
2427 |
|
---|
2428 | #if 0
|
---|
2429 | /* Check for date X values */
|
---|
2430 | fXDate = listDataSets.getFirst()->getXDate();
|
---|
2431 | #endif
|
---|
2432 | }
|
---|
2433 |
|
---|
2434 |
|
---|
2435 | /**
|
---|
2436 | * Fetches data for multiple data sets.
|
---|
2437 | * @param pszSql Pointer to sql statement.
|
---|
2438 | */
|
---|
2439 | void kGraph::fetchData(const char *pszSql) throw(kError::enmErrors)
|
---|
2440 | {
|
---|
2441 | void *pres;
|
---|
2442 |
|
---|
2443 | switch (enmTypeCd)
|
---|
2444 | {
|
---|
2445 | case kGraph::lines:
|
---|
2446 | {
|
---|
2447 | pres = ::dbExecuteQuery(pszSql);
|
---|
2448 | if (pres != NULL)
|
---|
2449 | {
|
---|
2450 | kGraphDataSet *pDataSet = NULL;
|
---|
2451 | GRAPHCALLBACKPARAM Param = {this, NULL, NULL, enmTypeCd, 0, NULL, NULL};
|
---|
2452 | while (::dbFetch(pres, dbGraphCallBack, (void*)&Param))
|
---|
2453 | {
|
---|
2454 | /* find correct dataset: legend present - allways; else first time only.*/
|
---|
2455 | if (Param.pszLegend != NULL || pDataSet == NULL)
|
---|
2456 | pDataSet = findOrCreateDataSet(Param.pszLegend);
|
---|
2457 | assert(pDataSet != NULL);
|
---|
2458 |
|
---|
2459 | pDataSet->setLegend(Param.pszLegend);
|
---|
2460 | pDataSet->setColor(Param.pszColor);
|
---|
2461 | pDataSet->listData.insert(Param.pData);
|
---|
2462 |
|
---|
2463 | /* next */
|
---|
2464 | Param.lSeqNbr = 0;
|
---|
2465 | Param.pData = NULL;
|
---|
2466 | if (Param.pszColor != NULL)
|
---|
2467 | {
|
---|
2468 | delete Param.pszColor;
|
---|
2469 | Param.pszColor = NULL;
|
---|
2470 | }
|
---|
2471 | if (Param.pszLegend != NULL)
|
---|
2472 | {
|
---|
2473 | delete Param.pszLegend;
|
---|
2474 | Param.pszLegend = NULL;
|
---|
2475 | }
|
---|
2476 | }
|
---|
2477 | if (Param.pData != NULL) delete Param.pData;
|
---|
2478 | if (Param.pszColor != NULL) delete Param.pszColor;
|
---|
2479 | if (Param.pszLegend != NULL) delete Param.pszLegend;
|
---|
2480 | }
|
---|
2481 | else
|
---|
2482 | throw(kError::error_sql_failed);
|
---|
2483 | break;
|
---|
2484 | }
|
---|
2485 |
|
---|
2486 | case kGraph::pie:
|
---|
2487 | addWarning(kError::warning_pie_not_implemented_yet);
|
---|
2488 |
|
---|
2489 | default:
|
---|
2490 | break;
|
---|
2491 | }
|
---|
2492 | }
|
---|
2493 |
|
---|
2494 |
|
---|
2495 |
|
---|
2496 | /**
|
---|
2497 | * Callback function used when receiving data.
|
---|
2498 | * @returns 0 success, -1 error.
|
---|
2499 | * @param pszValue Field value. Used as variable value.
|
---|
2500 | * @param pszFieldName Field name. Used as variable name.
|
---|
2501 | * @param pvUser Pointer to user defined data, here a variable lifo.
|
---|
2502 | */
|
---|
2503 | long _System dbGraphCallBack(const char *pszValue, const char *pszFieldName, void *pvUser)
|
---|
2504 | {
|
---|
2505 | PGRAPHCALLBACKPARAM pParam = (PGRAPHCALLBACKPARAM)pvUser;
|
---|
2506 |
|
---|
2507 | assert(pParam != NULL);
|
---|
2508 |
|
---|
2509 | switch (pParam->enmTypeCd)
|
---|
2510 | {
|
---|
2511 | case kGraph::lines:
|
---|
2512 | {
|
---|
2513 | switch (pParam->lSeqNbr)
|
---|
2514 | {
|
---|
2515 | case 0:
|
---|
2516 | pParam->pData = new kGraphData;
|
---|
2517 | /* date test */
|
---|
2518 | if (strlen(pszValue) == (4+1+2+1+2) && pszValue[4] == '-' && pszValue[7] == '-')
|
---|
2519 | {
|
---|
2520 | strcpy(&pParam->pData->szXDate[0], pszValue);
|
---|
2521 | pParam->pData->rdX = kGraph::dateToDbl(&pParam->pData->szXDate[0]);
|
---|
2522 | pParam->pGraph->fXDate = TRUE;
|
---|
2523 | }
|
---|
2524 | else
|
---|
2525 | {
|
---|
2526 | pParam->pData->szXDate[0] = '\0';
|
---|
2527 | pParam->pData->rdX = atol(pszValue);
|
---|
2528 | }
|
---|
2529 | break;
|
---|
2530 |
|
---|
2531 | case 1:
|
---|
2532 | pParam->pData->rdY = atol(pszValue);
|
---|
2533 | break;
|
---|
2534 |
|
---|
2535 | case 2:
|
---|
2536 | if (pszFieldName == NULL || stricmp(pszFieldName, "legend") != 0)
|
---|
2537 | pParam->pszColor = dupeString(pszValue);
|
---|
2538 | else
|
---|
2539 | pParam->pszLegend = dupeString(pszValue);
|
---|
2540 | break;
|
---|
2541 |
|
---|
2542 | case 3:
|
---|
2543 | if (pszFieldName == NULL || stricmp(pszFieldName, "color") != 0)
|
---|
2544 | pParam->pszLegend = dupeString(pszValue);
|
---|
2545 | else
|
---|
2546 | pParam->pszColor = dupeString(pszValue);
|
---|
2547 | break;
|
---|
2548 |
|
---|
2549 | default:
|
---|
2550 | pParam->pGraph->addWarning(kError::warning_to_many_fields_in_data_sql);
|
---|
2551 | }
|
---|
2552 | break;
|
---|
2553 | }
|
---|
2554 |
|
---|
2555 | case kGraph::pie:
|
---|
2556 | default:
|
---|
2557 | break;
|
---|
2558 | }
|
---|
2559 |
|
---|
2560 | pParam->lSeqNbr++;
|
---|
2561 | return 0;
|
---|
2562 | }
|
---|
2563 |
|
---|
2564 |
|
---|
2565 | /**
|
---|
2566 | * Finds or creates an dataset for the given legend (id).
|
---|
2567 | * @returns Pointer to DataSet. (NULL only when new failes.)
|
---|
2568 | * @param pszLegend DataSet identifier. NULL is allowed.
|
---|
2569 | */
|
---|
2570 | kGraphDataSet *kGraph::findOrCreateDataSet(const char *pszLegend) throw(kError::enmErrors)
|
---|
2571 | {
|
---|
2572 | kGraphDataSet *p;
|
---|
2573 |
|
---|
2574 | if (pszLegend != NULL)
|
---|
2575 | {
|
---|
2576 | p = listDataSets.getFirst();
|
---|
2577 | while (p != NULL && *p != pszLegend)
|
---|
2578 | p = (kGraphDataSet *)p->getNext();
|
---|
2579 | }
|
---|
2580 | else
|
---|
2581 | p = NULL;
|
---|
2582 |
|
---|
2583 |
|
---|
2584 | if (p == NULL)
|
---|
2585 | listDataSets.insert(p = new kGraphDataSet());
|
---|
2586 |
|
---|
2587 | return p;
|
---|
2588 | }
|
---|
2589 |
|
---|
2590 |
|
---|
2591 | /**
|
---|
2592 | * Draw the base structure of the graph.
|
---|
2593 | */
|
---|
2594 | void kGraph::createBaseGraph(void) throw(kError::enmErrors)
|
---|
2595 | {
|
---|
2596 | POINTL ptl;
|
---|
2597 | char szMax[32];
|
---|
2598 |
|
---|
2599 | pGraph = gdImageCreate(cX, cY);
|
---|
2600 |
|
---|
2601 | /* background? */
|
---|
2602 | if (pszBackground != NULL)
|
---|
2603 | {
|
---|
2604 | gdImagePtr pBackground;
|
---|
2605 | FILE *phFile;
|
---|
2606 | phFile = fopen(pszBackground, "rb");
|
---|
2607 | if (phFile)
|
---|
2608 | {
|
---|
2609 | pBackground = gdImageCreateFromGif(phFile);
|
---|
2610 | if (pBackground != NULL)
|
---|
2611 | {
|
---|
2612 | gdImageCopyResized(pGraph, pBackground,
|
---|
2613 | 0, 0, //destination low left corner
|
---|
2614 | 0, 0, //source low left corner
|
---|
2615 | cX, cY, //destination width and height
|
---|
2616 | gdImageSX(pBackground), //source width
|
---|
2617 | gdImageSY(pBackground) //source height
|
---|
2618 | );
|
---|
2619 | gdImageDestroy(pBackground);
|
---|
2620 | }
|
---|
2621 | else
|
---|
2622 | addWarning(kError::warning_failed_to_load_background_image);
|
---|
2623 | fclose(phFile);
|
---|
2624 | }
|
---|
2625 | else
|
---|
2626 | addWarning(kError::warning_failed_to_open_background_image);
|
---|
2627 | }
|
---|
2628 |
|
---|
2629 | /* calc base coordinates */
|
---|
2630 | ptlOrigo.x = max(2 + (fXDate ? 5 : 0)*6, (long)(cX*0.05));
|
---|
2631 | _itoa((int)maxY(), &szMax[0], 10);
|
---|
2632 | ptlOrigo.y = max((long)(2 + strlen(&szMax[0])*6), (long)(cY*0.05));
|
---|
2633 | if (pszTitleX) ptlOrigo.y += 16;
|
---|
2634 | if (pszTitleY) ptlOrigo.x += 16;
|
---|
2635 | ptlYEnd.x = ptlOrigo.x;
|
---|
2636 | ptlYEnd.y = cY - ptlOrigo.y - (pszTitle ? max(20, (long)(cY*0.10)) : 0);
|
---|
2637 | ptlXEnd.x = cX - ptlOrigo.x;
|
---|
2638 | ptlXEnd.y = ptlOrigo.y;
|
---|
2639 |
|
---|
2640 | if (fLegend)
|
---|
2641 | {
|
---|
2642 | addWarning(kError::warning_legend_is_not_implemented_yet);
|
---|
2643 | ptlXEnd.x -= (long)(cX * 0.20);
|
---|
2644 | }
|
---|
2645 |
|
---|
2646 | /* allocate default colors */
|
---|
2647 | setColors();
|
---|
2648 |
|
---|
2649 | /* draw axsis */
|
---|
2650 | if (pszTitleX)
|
---|
2651 | gdImageStringLB(pGraph, gdFontGiant,
|
---|
2652 | (int)(ptlOrigo.x + (ptlXEnd.x - ptlOrigo.x)/2.0 - strlen(pszTitleX)*9/2.0),
|
---|
2653 | max(2, (int)(cY*0.01))+ 16,
|
---|
2654 | pszTitleX, clrForeground);
|
---|
2655 | if (pszTitleY)
|
---|
2656 | gdImageStringUpLB(pGraph, gdFontGiant,
|
---|
2657 | max(2, (int)(cX*0.01)),
|
---|
2658 | (int)(ptlOrigo.y + (ptlYEnd.y - ptlOrigo.y)/2.0 - strlen(pszTitleY)*9/2.0),
|
---|
2659 | pszTitleY, clrForeground);
|
---|
2660 | if (pszTitle)
|
---|
2661 | {
|
---|
2662 | ptl.x = (long)(cX/2.0 - strlen(pszTitle)*9/2.0);
|
---|
2663 | ptl.y = cY - max(5, (int)(cY*0.02));
|
---|
2664 | gdImageStringLB(pGraph, gdFontGiant, (int)ptl.x, (int)ptl.y, pszTitle, clrForeground);
|
---|
2665 | gdImageLineLB(pGraph, (int)ptl.x - 3, (int)ptl.y - 18,
|
---|
2666 | (int)ptl.x + strlen(pszTitle)*9 + 5, (int)ptl.y - 18, clrForeground);
|
---|
2667 | }
|
---|
2668 |
|
---|
2669 |
|
---|
2670 | gdImageLineLB(pGraph, (int)ptlOrigo.x, (int)ptlOrigo.y-2, (int)ptlYEnd.x, (int)ptlYEnd.y+3, clrAxis);
|
---|
2671 | gdImageLineLB(pGraph, (int)ptlYEnd.x+2, (int)ptlYEnd.y, (int)ptlYEnd.x, (int)ptlYEnd.y+3, clrAxis);
|
---|
2672 | gdImageLineLB(pGraph, (int)ptlYEnd.x-2, (int)ptlYEnd.y, (int)ptlYEnd.x, (int)ptlYEnd.y+3, clrAxis);
|
---|
2673 |
|
---|
2674 | gdImageLineLB(pGraph, (int)ptlOrigo.x-2, (int)ptlOrigo.y, (int)ptlXEnd.x+3, (int)ptlXEnd.y, clrAxis);
|
---|
2675 | gdImageLineLB(pGraph, (int)ptlXEnd.x, (int)ptlXEnd.y+2, (int)ptlXEnd.x+3, (int)ptlXEnd.y, clrAxis);
|
---|
2676 | gdImageLineLB(pGraph, (int)ptlXEnd.x, (int)ptlXEnd.y-2, (int)ptlXEnd.x+3, (int)ptlXEnd.y, clrAxis);
|
---|
2677 |
|
---|
2678 |
|
---|
2679 | /* scale - x */
|
---|
2680 | char szData[20];
|
---|
2681 | double rdMin, rdMax, rd, rdD;
|
---|
2682 | int cTags;
|
---|
2683 |
|
---|
2684 | rdMax = maxX();
|
---|
2685 | rdMin = minX();
|
---|
2686 |
|
---|
2687 | if (fXDate)
|
---|
2688 | {
|
---|
2689 | if (!kGraph::dblToDate(rdMin, &szData[0]))
|
---|
2690 | addWarning(kError::warning_failed_to_convert_date);
|
---|
2691 | }
|
---|
2692 | else
|
---|
2693 | sprintf(&szData[0], "%1.*f", rdMax > 10 ? 0 : 1, rdMin);
|
---|
2694 | gdImageStringLB(pGraph, gdFontSmall,
|
---|
2695 | (int)(ptlOrigo.x - strlen(&szData[0])*6/2.0),
|
---|
2696 | (int)(ptlOrigo.y - 3),
|
---|
2697 | &szData[0], clrForeground);
|
---|
2698 | if (fXDate)
|
---|
2699 | {
|
---|
2700 | if (!kGraph::dblToDate(rdMax, &szData[0]))
|
---|
2701 | addWarning(kError::warning_failed_to_convert_date);
|
---|
2702 | }
|
---|
2703 | else
|
---|
2704 | sprintf(&szData[0], "%1.*f", rdMax > 10 ? 0 : 1, rdMax);
|
---|
2705 | gdImageStringLB(pGraph, gdFontSmall,
|
---|
2706 | (int)(ptlXEnd.x - strlen(&szData[0])*6/2.0),
|
---|
2707 | (int)(ptlOrigo.y - 3),
|
---|
2708 | &szData[0], clrForeground);
|
---|
2709 |
|
---|
2710 | rd = strlen(&szData[0])*6 + 20; //length of on scale tag
|
---|
2711 | cTags = (int)((ptlXEnd.x - ptlOrigo.x) / rd); //max number of tags
|
---|
2712 | if (cTags > 0)
|
---|
2713 | {
|
---|
2714 | rdD = rdMax - rdMin;
|
---|
2715 | if (rd > 10)
|
---|
2716 | rdD = (int)(rdD/cTags);
|
---|
2717 | else
|
---|
2718 | rdD = ((int)(rdD/cTags*10))/10;
|
---|
2719 | rd = rdMin + rdD;
|
---|
2720 | while (rdD > 0.0 && (rd + rdD) <= rdMax)
|
---|
2721 | {
|
---|
2722 | int x = (int)(ptlOrigo.x + (ptlXEnd.x - ptlOrigo.x)/(rdMax-rdMin)*(rd - rdMin));
|
---|
2723 | if (fXDate)
|
---|
2724 | {
|
---|
2725 | if (!kGraph::dblToDate(rd, &szData[0]))
|
---|
2726 | addWarning(kError::warning_failed_to_convert_date);
|
---|
2727 | }
|
---|
2728 | else
|
---|
2729 | sprintf(&szData[0], "%1.*f", rdMax > 10 ? 0 : 1, rd);
|
---|
2730 | gdImageStringLB(pGraph, gdFontSmall, x - (int)(strlen(&szData[0])*6/2.0), (int)(ptlOrigo.y - 3),
|
---|
2731 | &szData[0], clrForeground);
|
---|
2732 | gdImageLineLB(pGraph, x, (int)(ptlOrigo.y - 1), x, (int)(ptlOrigo.y + 1), clrAxis);
|
---|
2733 |
|
---|
2734 | /* next */
|
---|
2735 | rd += rdD;
|
---|
2736 | }
|
---|
2737 | }
|
---|
2738 |
|
---|
2739 | /* scale - y */
|
---|
2740 | rdMax = maxY();
|
---|
2741 | rdMin = minY();
|
---|
2742 |
|
---|
2743 | sprintf(&szData[0], "%1.*f", rdMax > 10 ? 0 : 1, rdMin);
|
---|
2744 | gdImageStringLB(pGraph, gdFontSmall,
|
---|
2745 | (int)(ptlOrigo.x - 3 - strlen(&szData[0])*6),
|
---|
2746 | (int)(ptlOrigo.y + 8/2 + 2),
|
---|
2747 | &szData[0], clrForeground);
|
---|
2748 | sprintf(&szData[0], "%1.*f", rdMax > 10 ? 0 : 1, rdMax);
|
---|
2749 | gdImageStringLB(pGraph, gdFontSmall,
|
---|
2750 | (int)(ptlOrigo.x - 3 - strlen(&szData[0])*6),
|
---|
2751 | (int)(ptlYEnd.y + 8/2),
|
---|
2752 | &szData[0], clrForeground);
|
---|
2753 |
|
---|
2754 | rd = 14 + 10; //length of on scale tag
|
---|
2755 | cTags = (int)((ptlYEnd.y - ptlOrigo.y) / rd); //max number of tags
|
---|
2756 | if (cTags > 0)
|
---|
2757 | {
|
---|
2758 | rdD = rdMax - rdMin;
|
---|
2759 | if (rd > 10)
|
---|
2760 | rdD = (int)(rdD/cTags);
|
---|
2761 | else
|
---|
2762 | rdD = ((int)(rdD/cTags*10))/10;
|
---|
2763 | rd = rdMin + rdD;
|
---|
2764 | while (rdD > 0.0 && (rd + rdD) <= rdMax)
|
---|
2765 | {
|
---|
2766 | int y = (int)(ptlOrigo.y + (ptlYEnd.y - ptlOrigo.y)/(rdMax-rdMin)*(rd - rdMin));
|
---|
2767 | sprintf(&szData[0], "%1.*f", rdMax > 10 ? 0 : 1, rd);
|
---|
2768 | gdImageStringLB(pGraph, gdFontSmall,
|
---|
2769 | (int)(ptlOrigo.x - 3 - strlen(&szData[0])*6),
|
---|
2770 | y + 8/2,
|
---|
2771 | &szData[0], clrForeground);
|
---|
2772 | gdImageLineLB(pGraph, (int)(ptlOrigo.x - 1), y, (int)(ptlOrigo.x + 1), y, clrAxis);
|
---|
2773 |
|
---|
2774 | /* next */
|
---|
2775 | rd += rdD;
|
---|
2776 | }
|
---|
2777 | }
|
---|
2778 | }
|
---|
2779 |
|
---|
2780 |
|
---|
2781 | /**
|
---|
2782 | * Draw all lines.
|
---|
2783 | */
|
---|
2784 | void kGraph::drawLines(void) throw(kError::enmErrors)
|
---|
2785 | {
|
---|
2786 | kGraphDataSet *pDataSet;
|
---|
2787 |
|
---|
2788 | assert((int)enmTypeCd == (int)lines);
|
---|
2789 |
|
---|
2790 | pDataSet = listDataSets.getFirst();
|
---|
2791 | while (pDataSet != NULL)
|
---|
2792 | {
|
---|
2793 | pDataSet->setColor(pGraph);
|
---|
2794 | drawLine(pDataSet);
|
---|
2795 |
|
---|
2796 | /* next */
|
---|
2797 | pDataSet = (kGraphDataSet *)pDataSet->getNext();
|
---|
2798 | }
|
---|
2799 | }
|
---|
2800 |
|
---|
2801 |
|
---|
2802 | /**
|
---|
2803 | * Draws a line for the given data set.
|
---|
2804 | * @param pDataSet Pointer to the dataset for the line.
|
---|
2805 | * @remark not implemented.
|
---|
2806 | */
|
---|
2807 | void kGraph::drawLine(const kGraphDataSet *pDataSet) throw(kError::enmErrors)
|
---|
2808 | {
|
---|
2809 | BOOL fFirstTime = TRUE;
|
---|
2810 | int xPrev = 0; /* don't have to initialized, but it removes gcc warning (release) */
|
---|
2811 | int yPrev = 0; /* don't have to initialized, but it removes gcc warning (release) */
|
---|
2812 | double rdMinX = minX();
|
---|
2813 | double rdMinY = minY();
|
---|
2814 | double rdDX = maxX() - rdMinX;
|
---|
2815 | double rdDY = maxY() - rdMinY;
|
---|
2816 |
|
---|
2817 | kGraphData *p = pDataSet->listData.getFirst();
|
---|
2818 |
|
---|
2819 | if (rdDX != 0.0 && rdDY != 0.0)
|
---|
2820 | {
|
---|
2821 | while (p != NULL)
|
---|
2822 | {
|
---|
2823 | int x, y;
|
---|
2824 |
|
---|
2825 | x = (int)(ptlOrigo.x + ((ptlXEnd.x - ptlOrigo.x)/rdDX * (p->rdX - rdMinX)));
|
---|
2826 | y = (int)(ptlOrigo.y + ((ptlYEnd.y - ptlOrigo.y)/rdDY * (p->rdY - rdMinY)));
|
---|
2827 | if (fFirstTime)
|
---|
2828 | {
|
---|
2829 | xPrev = x;
|
---|
2830 | yPrev = y;
|
---|
2831 | fFirstTime = FALSE;
|
---|
2832 | }
|
---|
2833 | gdImageLineLB(pGraph, xPrev, yPrev, x, y, pDataSet->getColor());
|
---|
2834 |
|
---|
2835 | /* next */
|
---|
2836 | p = (kGraphData*)p->getNext();
|
---|
2837 | xPrev = x;
|
---|
2838 | yPrev = y;
|
---|
2839 | }
|
---|
2840 | }
|
---|
2841 | }
|
---|
2842 |
|
---|
2843 |
|
---|
2844 | /**
|
---|
2845 | * Draws the legend.
|
---|
2846 | * @remark not implemented.
|
---|
2847 | */
|
---|
2848 | void kGraph::drawLegend(void) throw(kError::enmErrors)
|
---|
2849 | {
|
---|
2850 | if (fLegend == FALSE)
|
---|
2851 | return;
|
---|
2852 |
|
---|
2853 | /* TODO */
|
---|
2854 | }
|
---|
2855 |
|
---|
2856 |
|
---|
2857 | /**
|
---|
2858 | * Converts an ISO date to days.
|
---|
2859 | * @returns Returns days after Christ, year 0.
|
---|
2860 | * @param pszDate Pointer to ISO date string.
|
---|
2861 | * @remark pszDate should be an ISO date, if not an exception may occur.
|
---|
2862 | * Use isDate to check it is an ISO date.
|
---|
2863 | */
|
---|
2864 | double kGraph::dateToDbl(const char *pszDate)
|
---|
2865 | {
|
---|
2866 | double rdRet = dbDateToDaysAfterChrist(pszDate);
|
---|
2867 | return rdRet != -1 ? rdRet : _NAN;
|
---|
2868 | }
|
---|
2869 |
|
---|
2870 |
|
---|
2871 | /**
|
---|
2872 | * Converts days to an ISO date.
|
---|
2873 | * @returns Success indicator. TRUE / FALSE.
|
---|
2874 | * @param rdDate Date in double, (really days from year 0).
|
---|
2875 | * @param pszDate Pointer to result buffer. Will hold ISO date string on successful return.
|
---|
2876 | */
|
---|
2877 | BOOL kGraph::dblToDate(double rdDate, char *pszDate)
|
---|
2878 | {
|
---|
2879 | if (rdDate != rdDate)
|
---|
2880 | return FALSE;
|
---|
2881 | return dbDaysAfterChristToDate((signed long)rdDate, pszDate);
|
---|
2882 | }
|
---|
2883 |
|
---|
2884 |
|
---|
2885 | /**
|
---|
2886 | * Checks if the given text string is an ISO date.
|
---|
2887 | * @returns TRUE - if date, else FALSE.
|
---|
2888 | * @param pszDate Possible ISO date string.
|
---|
2889 | */
|
---|
2890 | BOOL kGraph::isDate(const char *pszDate)
|
---|
2891 | {
|
---|
2892 | return strlen(pszDate) == 10 && pszDate[4] == '-' && pszDate[7] == '-';
|
---|
2893 | }
|
---|
2894 |
|
---|
2895 |
|
---|
2896 | /**
|
---|
2897 | * frees all storage.
|
---|
2898 | * @remark Called only at destruction. (That is destructor or when contruction failes.)
|
---|
2899 | */
|
---|
2900 | void kGraph::destroy(void)
|
---|
2901 | {
|
---|
2902 | if (pGraph != NULL) gdImageDestroy(pGraph);
|
---|
2903 | if (pszFilename != NULL) delete pszFilename;
|
---|
2904 | if (pszTitle != NULL) delete pszTitle;
|
---|
2905 | if (pszTitleX != NULL) delete pszTitleX;
|
---|
2906 | if (pszTitleY != NULL) delete pszTitleY;
|
---|
2907 | if (pszBackground != NULL) delete pszBackground;
|
---|
2908 | }
|
---|
2909 |
|
---|
2910 |
|
---|
2911 | /**
|
---|
2912 | * Adds a warning to the list of warnings.
|
---|
2913 | * @param enmErrorCd Warning code.
|
---|
2914 | */
|
---|
2915 | void kGraph::addWarning(kError::enmErrors enmErrorCd)
|
---|
2916 | {
|
---|
2917 | listWarnings.insert(new kWarningEntry(enmErrorCd));
|
---|
2918 | }
|
---|
2919 |
|
---|
2920 |
|
---|
2921 | /**
|
---|
2922 | * Finds the max X value in all data sets.
|
---|
2923 | * @returns max X value. 0.0 if no sets
|
---|
2924 | */
|
---|
2925 | double kGraph::maxX(void)
|
---|
2926 | {
|
---|
2927 | if (rdMaxX != rdMaxX)
|
---|
2928 | {
|
---|
2929 | /* first time */
|
---|
2930 | if (rdEndX != rdEndX)
|
---|
2931 | { /* not spesified by user */
|
---|
2932 | kGraphDataSet *p = listDataSets.getFirst();
|
---|
2933 |
|
---|
2934 | while (p != NULL)
|
---|
2935 | {
|
---|
2936 | double rd = p->maxX();
|
---|
2937 | if (rdMaxX < rd || rdMaxX != rdMaxX)
|
---|
2938 | rdMaxX = rd;
|
---|
2939 | p = (kGraphDataSet*)p->getNext();
|
---|
2940 | }
|
---|
2941 |
|
---|
2942 | rdMaxX = rdMaxX == rdMaxX ? rdMaxX : 0.0;
|
---|
2943 | }
|
---|
2944 | else /* spesified by user */
|
---|
2945 | rdMaxX = rdEndX;
|
---|
2946 | }
|
---|
2947 |
|
---|
2948 | return rdMaxX;
|
---|
2949 | }
|
---|
2950 |
|
---|
2951 |
|
---|
2952 | /**
|
---|
2953 | * Finds the min X value in all data sets.
|
---|
2954 | * @returns min X value. 0.0 if no sets
|
---|
2955 | * @remark Addjusts value if close to 0.
|
---|
2956 | */
|
---|
2957 | double kGraph::minX(void)
|
---|
2958 | {
|
---|
2959 | if (rdMinX != rdMinX)
|
---|
2960 | {
|
---|
2961 | /* first time */
|
---|
2962 | if (rdStartX != rdStartX)
|
---|
2963 | { /* not spesified by user */
|
---|
2964 | kGraphDataSet *p = listDataSets.getFirst();
|
---|
2965 |
|
---|
2966 | while (p != NULL)
|
---|
2967 | {
|
---|
2968 | double rd = p->minX();
|
---|
2969 | if (rdMinX > rd || rdMinX != rdMinX)
|
---|
2970 | rdMinX = rd;
|
---|
2971 | p = (kGraphDataSet*)p->getNext();
|
---|
2972 | }
|
---|
2973 |
|
---|
2974 | /* addjustment */
|
---|
2975 | if (rdMinX != rdMinX)
|
---|
2976 | rdMinX = fXDate ? maxX() - 1.0 : 0.0;
|
---|
2977 | else if (rdMinX >= 0.0)
|
---|
2978 | rdMinX = fXDate ? rdMinX : 0.0;
|
---|
2979 | else
|
---|
2980 | {
|
---|
2981 | /* TODO negative values are not supported yet. */
|
---|
2982 | addWarning(kError::warning_negative_values_are_not_supported_yet);
|
---|
2983 | rdMinX = 0.0;
|
---|
2984 | }
|
---|
2985 | }
|
---|
2986 | else /* spesified by user */
|
---|
2987 | rdMinX = rdStartX;
|
---|
2988 | }
|
---|
2989 |
|
---|
2990 | return rdMinX;
|
---|
2991 | }
|
---|
2992 |
|
---|
2993 |
|
---|
2994 | /**
|
---|
2995 | * Finds the max Y value in all data sets.
|
---|
2996 | * @returns max Y value. 0.0 if no sets
|
---|
2997 | */
|
---|
2998 | double kGraph::maxY(void)
|
---|
2999 | {
|
---|
3000 | if (rdMaxY != rdMaxY)
|
---|
3001 | {
|
---|
3002 | /* first time */
|
---|
3003 | if (rdEndY != rdEndY)
|
---|
3004 | { /* not spesified by user */
|
---|
3005 | kGraphDataSet *p = listDataSets.getFirst();
|
---|
3006 |
|
---|
3007 | while (p != NULL)
|
---|
3008 | {
|
---|
3009 | double rd = p->maxY();
|
---|
3010 | if (rdMaxY < rd || rdMaxY != rdMaxY)
|
---|
3011 | rdMaxY = rd;
|
---|
3012 | p = (kGraphDataSet*)p->getNext();
|
---|
3013 | }
|
---|
3014 |
|
---|
3015 | rdMaxY = rdMaxY == rdMaxY ? rdMaxY : 0.0;
|
---|
3016 | }
|
---|
3017 | else /* spesified by user */
|
---|
3018 | rdMaxY = rdEndY;
|
---|
3019 | }
|
---|
3020 |
|
---|
3021 | return rdMaxY;
|
---|
3022 | }
|
---|
3023 |
|
---|
3024 |
|
---|
3025 | /**
|
---|
3026 | * Finds the min Y value in all data sets.
|
---|
3027 | * @returns min Y value. 0.0 if no sets
|
---|
3028 | * @remark Addjusts value if close to 0.
|
---|
3029 | */
|
---|
3030 | double kGraph::minY(void)
|
---|
3031 | {
|
---|
3032 | if (rdMinY != rdMinY)
|
---|
3033 | {
|
---|
3034 | /* first time */
|
---|
3035 | if (rdStartY != rdStartY)
|
---|
3036 | { /* not spesified by user */
|
---|
3037 | kGraphDataSet *p = listDataSets.getFirst();
|
---|
3038 |
|
---|
3039 | while (p != NULL)
|
---|
3040 | {
|
---|
3041 | double rd = p->minY();
|
---|
3042 | if (rdMinY > rd || rdMinY != rdMinY)
|
---|
3043 | rdMinY = rd;
|
---|
3044 | p = (kGraphDataSet*)p->getNext();
|
---|
3045 | }
|
---|
3046 |
|
---|
3047 | /* addjustment */
|
---|
3048 | if (rdMinY != rdMinY)
|
---|
3049 | rdMinY = 0.0;
|
---|
3050 | else if (rdMinY >= 0.0)
|
---|
3051 | rdMinY = 0.0;
|
---|
3052 | else
|
---|
3053 | { /* TODO negative values are not supported yet. */
|
---|
3054 | addWarning(kError::warning_negative_values_are_not_supported_yet);
|
---|
3055 | rdMinY = 0.0;
|
---|
3056 | }
|
---|
3057 | }
|
---|
3058 | else /* spesified by user */
|
---|
3059 | rdMinY = rdStartY;
|
---|
3060 | }
|
---|
3061 |
|
---|
3062 | return rdMinY;
|
---|
3063 | }
|
---|
3064 |
|
---|
3065 |
|
---|
3066 | /**
|
---|
3067 | * Reads a color parameter.
|
---|
3068 | * @returns 24Bit RGB color value.
|
---|
3069 | * @param pszColor Pointer to color string. That is "#RRGGBB".
|
---|
3070 | */
|
---|
3071 | unsigned long kGraph::readColor(const char *pszColor)
|
---|
3072 | {
|
---|
3073 | unsigned long ulColor = 0xffffff;
|
---|
3074 |
|
---|
3075 | if (*pszColor == '#')
|
---|
3076 | {
|
---|
3077 | ulColor = 0;
|
---|
3078 | for (int i = 1; i < 7; i++)
|
---|
3079 | {
|
---|
3080 | ulColor = ulColor << 4;
|
---|
3081 | if (pszColor[i] >= '0' && pszColor[i] <= '9')
|
---|
3082 | ulColor |= pszColor[i] - '0';
|
---|
3083 | else if (pszColor[i] >= 'A' && pszColor[i] <= 'F')
|
---|
3084 | ulColor |= pszColor[i] - 'A' + 0xa;
|
---|
3085 | else if (pszColor[i] >= 'a' && pszColor[i] <= 'f')
|
---|
3086 | ulColor |= pszColor[i] - 'a' + 0xa;
|
---|
3087 | else
|
---|
3088 | addWarning(kError::warning_invalid_color_value);
|
---|
3089 | }
|
---|
3090 | }
|
---|
3091 | else
|
---|
3092 | addWarning(kError::warning_invalid_color_value);
|
---|
3093 |
|
---|
3094 | return ulColor;
|
---|
3095 | }
|
---|
3096 |
|
---|
3097 |
|
---|
3098 | /**
|
---|
3099 | * Allocates a color in the image.
|
---|
3100 | * @returns GifDraw Color.
|
---|
3101 | * @param ulColor 24Bit RGB color value.
|
---|
3102 | */
|
---|
3103 | int kGraph::setColor(unsigned long ulColor)
|
---|
3104 | {
|
---|
3105 | return gdImageColorAllocate(pGraph,
|
---|
3106 | (int)(0xFF & (ulColor >> 16)),
|
---|
3107 | (int)(0xFF & (ulColor >> 8)),
|
---|
3108 | (int)(0xFF & ulColor));
|
---|
3109 | }
|
---|
3110 |
|
---|
3111 |
|
---|
3112 | /**
|
---|
3113 | * Allocates/sets default colors.
|
---|
3114 | */
|
---|
3115 | void kGraph::setColors(void)
|
---|
3116 | {
|
---|
3117 | clrBackground = setColor(ulBGColor != ~0UL ? ulBGColor : 0x00000000UL); /* vitally important that this is done first! */
|
---|
3118 | clrForeground = setColor(ulFGColor != ~0UL ? ulFGColor : 0x0000FF00UL);
|
---|
3119 | clrAxis = setColor(ulAxisColor != ~0UL ? ulAxisColor : 0x00808080UL);
|
---|
3120 | }
|
---|
3121 |
|
---|
3122 |
|
---|
3123 | /**
|
---|
3124 | * Constructor.
|
---|
3125 | * @remark Throws kError::enmError on error.
|
---|
3126 | */
|
---|
3127 | kGraph::kGraph(const kTag &tag) throw(kError::enmErrors)
|
---|
3128 | : pGraph(NULL), enmTypeCd(unknown), enmSubTypeCd(normal),
|
---|
3129 | pszFilename(NULL), pszTitle(NULL), pszTitleX(NULL),
|
---|
3130 | pszTitleY(NULL), pszBackground(NULL), fLegend(FALSE),
|
---|
3131 | cX(~0L), cY(~0L),
|
---|
3132 | rdStartX(_NAN), rdEndX(_NAN), rdStartY(_NAN), rdEndY(_NAN),
|
---|
3133 | fXDate(FALSE),
|
---|
3134 | ulBGColor(~0UL), ulFGColor(~0UL), ulAxisColor(~0UL),
|
---|
3135 | rdMaxX(_NAN), rdMinX(_NAN), rdMaxY(_NAN), rdMinY(_NAN)
|
---|
3136 | {
|
---|
3137 | try
|
---|
3138 | {
|
---|
3139 | analyseTag(tag);
|
---|
3140 | createBaseGraph();
|
---|
3141 | if (fLegend)
|
---|
3142 | drawLegend();
|
---|
3143 | drawLines();
|
---|
3144 | }
|
---|
3145 | catch (kError::enmErrors enmErrorCd)
|
---|
3146 | {
|
---|
3147 | destroy();
|
---|
3148 | throw(enmErrorCd);
|
---|
3149 | }
|
---|
3150 | }
|
---|
3151 |
|
---|
3152 |
|
---|
3153 | /**
|
---|
3154 | * Destructor.
|
---|
3155 | * @remark calls destroy().
|
---|
3156 | */
|
---|
3157 | kGraph::~kGraph(void)
|
---|
3158 | {
|
---|
3159 | destroy();
|
---|
3160 | }
|
---|
3161 |
|
---|
3162 |
|
---|
3163 | /**
|
---|
3164 | * Saves the graph to the filename specified in the tag.
|
---|
3165 | * @returns Errorcode.
|
---|
3166 | */
|
---|
3167 | kError::enmErrors kGraph::save(void)
|
---|
3168 | {
|
---|
3169 | FILE *phFileOut;
|
---|
3170 |
|
---|
3171 | assert(pGraph != NULL);
|
---|
3172 | assert(pszFilename != NULL);
|
---|
3173 |
|
---|
3174 | phFileOut = fopen(pszFilename, "wb");
|
---|
3175 | if (phFileOut != NULL)
|
---|
3176 | {
|
---|
3177 | gdImageGif(pGraph, phFileOut);
|
---|
3178 | fclose(phFileOut);
|
---|
3179 | }
|
---|
3180 | else
|
---|
3181 | return kError::error_opening_output_file;
|
---|
3182 | return kError::no_error;
|
---|
3183 | }
|
---|
3184 |
|
---|
3185 |
|
---|
3186 | /**
|
---|
3187 | * Prints warnings.
|
---|
3188 | * @returns Number of warnings.
|
---|
3189 | * @param phLog Pointer to log file handle.
|
---|
3190 | */
|
---|
3191 | unsigned long kGraph::showWarnings(FILE *phLog, const kFileEntry *pCurFile)
|
---|
3192 | {
|
---|
3193 | unsigned long cWarnings = 0;
|
---|
3194 | kWarningEntry *p = listWarnings.getFirst();
|
---|
3195 |
|
---|
3196 | while (p != NULL)
|
---|
3197 | {
|
---|
3198 | cWarnings++;
|
---|
3199 | fprintf(phLog, "%s(%ld) : warning: kGraph - %s\n",
|
---|
3200 | pCurFile->getFilename(), pCurFile->getLineNumber()+1,
|
---|
3201 | kError::queryDescription(p->getWarningCode()));
|
---|
3202 | p = (kWarningEntry*)p->getNext();
|
---|
3203 | }
|
---|
3204 |
|
---|
3205 | return cWarnings;
|
---|
3206 | }
|
---|
3207 |
|
---|
3208 |
|
---|
3209 | /* include template code */
|
---|
3210 | #include "kLIFO.cpp"
|
---|
3211 | #include "kList.cpp"
|
---|
3212 |
|
---|
3213 | #ifdef __EMX__
|
---|
3214 | template class kLIFO<kSqlEntry>;
|
---|
3215 | #endif
|
---|
3216 |
|
---|