Subversion Repositories DevTools

Rev

Rev 2263 | Rev 2269 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2263 kivins 1
//## begin module%1.7%.codegen_version preserve=yes
2
//   Read the documentation to learn more about C++ code generator
3
//   versioning.
4
//## end module%1.7%.codegen_version
5
 
6
//## begin module%420AC16002C1.cm preserve=no
7
//## end module%420AC16002C1.cm
8
 
9
//## begin module%420AC16002C1.cp preserve=no
10
//	C O P Y R I G H T   N O T I C E
11
//	This material is confidential to ERG and may not be disclosed in whole
12
//	or in part to any third party nor used in any manner whatsoever other
13
//	than for the purposes expressly consented to by ERG in writing.
14
//
15
//	This material is also copyright and may not be reproduced, stored in a
16
//	retrieval system or transmitted in any form or by any means in whole or
17
//	in part without the express written consent of ERG.
18
//## end module%420AC16002C1.cp
19
 
20
//## Module: FieldExpression%420AC16002C1; Pseudo Package body
21
//## Subsystem: MASS::Dev::Tools::TxnTestManager::src%41F5A79001E4
22
//## Source file: Z:\MASS_Dev\Tools\TxnTestManager\src\FieldExpression.cpp
23
 
24
//## begin module%420AC16002C1.additionalIncludes preserve=no
25
//## end module%420AC16002C1.additionalIncludes
26
 
27
//## begin module%420AC16002C1.includes preserve=yes
28
#pragma warn -com
29
#include <LoggingMacros.h>
30
#pragma warn +com
31
 
32
#include <vcl.h>
33
#pragma hdrstop
34
//## end module%420AC16002C1.includes
35
 
36
// ICryptographicServerProxy
37
#include "ICryptographicServerProxy.h"
38
// IMessageDigest
39
#include "IMessageDigest.h"
40
// IXmlSchemaWrapperElement
41
#include "IXmlSchemaWrapperElement.h"
42
// TransactionSpecification
43
#include "TransactionSpecification.h"
44
// EvaluationContext
45
#include "EvaluationContext.h"
46
// SequenceCollection
47
#include "SequenceCollection.h"
48
// Sequence
49
#include "Sequence.h"
50
// FieldExpression
51
#include "FieldExpression.h"
52
// DefinedVariable
53
#include "DefinedVariable.h"
54
// DefinedVariableTable
55
#include "DefinedVariableTable.h"
56
//## begin module%420AC16002C1.additionalDeclarations preserve=yes
57
#include <time>
58
#include <locale>
59
#include <sstream>
60
 
61
enum TokenId
62
{
63
	TOKENID_INVALID = 0,
64
	TOKENID_FUNCTION,
65
	TOKENID_VARIABLE,
66
	TOKENID_CONSTANT
67
};
68
enum FunctionId
69
{
70
	EXPRESSIONID_INVALID = 0,
71
	EXPRESSIONID_FORMATVERSION,
72
	EXPRESSIONID_NOW,
73
	EXPRESSIONID_UTCNOW,
74
	EXPRESSIONID_TODAY,
75
	EXPRESSIONID_YESTERDAY,
76
	EXPRESSIONID_TOMORROW,
77
	EXPRESSIONID_RAND,
78
	EXPRESSIONID_UDTYPE,
79
	EXPRESSIONID_UDSUBTYPE,
80
	EXPRESSIONID_ACCOUNTTYPE,
81
	EXPRESSIONID_SEQ,
82
	EXPRESSIONID_KEYVERSION,
83
	EXPRESSIONID_KEYNUMBER,
84
	EXPRESSIONID_MAC,
85
	EXPRESSIONID_SAMID,
86
	EXPRESSIONID_SCENARIO_INDEX,
87
	EXPRESSIONID_HOSTNAME,
2267 kivins 88
	EXPRESSIONID_USERNAME,
89
	EXPRESSIONID_USESEQ,
90
    EXPRESSIONID_SETSHIFTSTART,   
91
    EXPRESSIONID_USESHIFTSTART,
92
    };
2263 kivins 93
struct PredefinedFunction
94
{
95
	const char *	functor;
96
	FunctionId		functionId;
97
};
98
 
99
static const PredefinedFunction functions[] =
100
{
101
	{ "FORMATVERSION",	EXPRESSIONID_FORMATVERSION },
102
	{ "NOW",			EXPRESSIONID_NOW },
103
	{ "UTCNOW",			EXPRESSIONID_UTCNOW },
104
	{ "TODAY",			EXPRESSIONID_TODAY },
105
	{ "YESTERDAY",		EXPRESSIONID_YESTERDAY },
106
	{ "TOMORROW",		EXPRESSIONID_TOMORROW },
107
	{ "RAND",			EXPRESSIONID_RAND },
108
	{ "UDTYPE",			EXPRESSIONID_UDTYPE },
109
	{ "UDSUBTYPE",		EXPRESSIONID_UDSUBTYPE },
110
	{ "ACCOUNTTYPE",	EXPRESSIONID_ACCOUNTTYPE },
111
	{ "SEQ",			EXPRESSIONID_SEQ },
112
	{ "KEYVERSION",		EXPRESSIONID_KEYVERSION },
113
	{ "KEYNUMBER",		EXPRESSIONID_KEYNUMBER },
114
	{ "MAC",			EXPRESSIONID_MAC },
115
	{ "SAMID",			EXPRESSIONID_SAMID },
116
	{ "SCENARIOINDEX",	EXPRESSIONID_SCENARIO_INDEX },
117
	{ "HOSTNAME",		EXPRESSIONID_HOSTNAME },
118
	{ "USERNAME",		EXPRESSIONID_USERNAME },
2267 kivins 119
	{ "USESEQ",			EXPRESSIONID_USESEQ },
120
	{ "SETSHIFTSTART",	EXPRESSIONID_SETSHIFTSTART },
121
	{ "USESHIFTSTART",	EXPRESSIONID_USESHIFTSTART },
2263 kivins 122
	{ 0,				EXPRESSIONID_INVALID }
123
};
124
 
125
static const std::locale myLocale;
126
 
127
const FunctionId & getFunctionId( const std::string & string )
128
{
129
	PredefinedFunction const * where = 0;
130
 
131
	for ( where = functions; where->functor; ++where )
132
	{
133
		if ( string == where->functor )
134
		{
135
			break;
136
		}
137
	}
138
 
139
	return ( where->functionId );
140
}
141
 
142
const bool readExpression( std::istream & stream, std::string & symbol, TokenId & token, EvaluationContext& evaluationContext )
143
{
144
	symbol.erase();
145
 
146
	char character = 0;
147
	while ( stream.get( character ).good() )
148
	{
149
		if ( std::isalnum( character ) || character == '_' )
150
		{
151
			symbol += character;
152
		}
153
		else
154
		{
155
			stream.putback( character );	// Always put this back.
156
 
157
			if ( character == '(' )
158
			{
159
				token = TOKENID_FUNCTION;
160
				return ( true );
161
			}
162
 
163
			break;	// We have read in a lexeme, now tokenise it.
164
		}
165
	}
166
 
167
	// Only do this when we didn't fail reading from the stream.
168
	if ( stream.good() || stream.eof() )
169
	{
170
		token = ( evaluationContext.getSymbolTable().isVariable( symbol, evaluationContext )
171
			? TOKENID_VARIABLE
172
			: TOKENID_CONSTANT );
173
		return ( true );
174
	}
175
 
176
	return ( false );
177
}
178
//## end module%420AC16002C1.additionalDeclarations
179
 
180
 
181
// Class FieldExpression 
182
 
183
FieldExpression::FieldExpression()
184
  //## begin FieldExpression::FieldExpression%420AC16002C1_const.initialization preserve=yes
185
  //## end FieldExpression::FieldExpression%420AC16002C1_const.initialization
186
{
187
  //## begin FieldExpression::FieldExpression%420AC16002C1_const.body preserve=yes
188
  //## end FieldExpression::FieldExpression%420AC16002C1_const.body
189
}
190
 
191
//## Operation: FieldExpression%42105AAC0084
192
FieldExpression::FieldExpression (const std::string &expression)
193
  //## begin FieldExpression::FieldExpression%42105AAC0084.hasinit preserve=no
194
  //## end FieldExpression::FieldExpression%42105AAC0084.hasinit
195
  //## begin FieldExpression::FieldExpression%42105AAC0084.initialization preserve=yes
196
 
197
:	m_expression( expression )
198
 
199
  //## end FieldExpression::FieldExpression%42105AAC0084.initialization
200
{
201
  //## begin FieldExpression::FieldExpression%42105AAC0084.body preserve=yes
202
  //## end FieldExpression::FieldExpression%42105AAC0084.body
203
}
204
 
205
 
206
FieldExpression::~FieldExpression()
207
{
208
  //## begin FieldExpression::~FieldExpression%420AC16002C1_dest.body preserve=yes
209
  //## end FieldExpression::~FieldExpression%420AC16002C1_dest.body
210
}
211
 
212
 
213
 
214
//## Other Operations (implementation)
215
//## Operation: evaluate%420456630303
216
const bool FieldExpression::evaluate (std::string &value, const bool &sideEffect, EvaluationContext& evaluationContext, std::vector< DefinedVariable * > &path, bool &postponed)
217
{
218
  //## begin FieldExpression::evaluate%420456630303.body preserve=yes
219
 
220
	if ( m_cachedValue.length() )
221
	{
222
		value = m_cachedValue;
223
		return ( true );
224
	}
225
 
226
	/**
227
	 *	TODO: Eventually replace the use of streams with a char buffer, but
228
	 *	right now I just need to get it working.
229
	 */
230
	if ( ( m_expression[ 0 ] == '\"' ) &&
231
		 ( m_expression[ m_expression.length() - 1 ] == '\"' ) )
232
	{
233
		value = m_cachedValue = m_expression.substr( 1, m_expression.length() - 2 );
234
		return ( true );
235
	}
236
 
237
	std::istringstream is( m_expression );
238
	skipCharacter( is, '=' );	// Skip the '=' if its there.
239
 
240
	/**
241
	 *	TODO: evaluate this field using the defined collection of variables
242
	 *	and sequence generators, making sure we respect the sideEffect flag.
243
	 */
244
	/**
245
		For now, we assume a very simple syntax:
246
 
247
			expression		::= function | variable | constant
248
			function		::= =functor ( [ argument list ] )
249
			variable		::= =variable
250
			constant		::= alphanumeric
251
			argument list	::= argument[, argument list ]
252
			argument		::= expression
253
	 */
254
	std::string	symbol;
255
	TokenId		token = TOKENID_INVALID;
256
	while ( readExpression( is, symbol, token, evaluationContext ) )
257
	{
258
		switch ( token )
259
		{
260
		case TOKENID_FUNCTION:
261
			return ( evaluateFunction( is, value, symbol, sideEffect, evaluationContext, path, postponed ) );
262
		case TOKENID_VARIABLE:
263
			return ( evaluateVariable( is, value, symbol, sideEffect, evaluationContext, path, postponed ) );
264
		case TOKENID_CONSTANT:
265
			// Its not a defined variable or function, so just evaluate to
266
			// it.
267
			m_cachedValue = value = m_expression;
268
			return ( true );
269
		}
270
	}
271
 
272
	return ( true );
273
 
274
  //## end FieldExpression::evaluate%420456630303.body
275
}
276
 
277
//## Operation: evaluateFunction%4208AE9D0216
278
const bool FieldExpression::evaluateFunction (std::istream &is, std::string &value, std::string &symbol, const bool &sideEffect, EvaluationContext& evaluationContext, std::vector< DefinedVariable * > &path, bool &postponed)
279
{
280
  //## begin FieldExpression::evaluateFunction%4208AE9D0216.body preserve=yes
281
 
282
	/**
283
	 *	Check parameter lists on all functions calls, and report an error
284
	 *	when a function is called with superfluous arguments.
285
	 */
286
 
287
	postponed = false;
288
	switch ( getFunctionId( symbol ) )
289
	{
290
	case EXPRESSIONID_UDTYPE:
291
		{
292
			AnsiString os;
293
			os.sprintf( "%hu", evaluationContext.getTransaction().getUdType() );
294
			m_cachedValue = value = os.c_str();
295
		}
296
		return ( true );
297
	case EXPRESSIONID_UDSUBTYPE:
298
		{
299
			AnsiString os;
300
			os.sprintf( "%hu", evaluationContext.getTransaction().getUdSubtype() );
301
			m_cachedValue = value = os.c_str();
302
		}
303
		return ( true );
304
	case EXPRESSIONID_TODAY:
305
		m_cachedValue = value = TDateTime::CurrentDateTime().FormatString( "dd-mm-yyyy" ).c_str();
306
		return ( true );
307
	case EXPRESSIONID_FORMATVERSION:
308
		{
309
			AnsiString os;
310
			os.sprintf( "%d", evaluationContext.getTransaction().getFormatVersion() );
311
			m_cachedValue = value = os.c_str();
312
		}
313
		return ( true );
314
	case EXPRESSIONID_NOW:
315
		m_cachedValue = value = TDateTime::CurrentDateTime().FormatString( "dd-mm-yyyy hh:nn:ss" ).c_str();
316
		return ( true );
317
	case EXPRESSIONID_UTCNOW:
318
		{
319
			const TDateTime time = TDateTime::CurrentDateTime() + ( ( _timezone / 3600.0 ) / 24.0 );
320
 
321
			m_cachedValue = value = time.FormatString( "dd-mm-yyyy hh:nn:ss" ).c_str();
322
		}
323
		return ( true );
324
	case EXPRESSIONID_YESTERDAY:
325
		{
326
			const TDateTime time = TDateTime::CurrentDateTime() - 1;
327
 
328
			m_cachedValue = value = time.FormatString( "dd-mm-yyyy" ).c_str();
329
		}
330
		return ( true );
331
	case EXPRESSIONID_TOMORROW:
2267 kivins 332
		{      
333
        	std::string days;
334
            int advanceDays;
335
			if ( skipCharacter( is, '(' ) &&
336
				 readTerm( is, days ) &&
337
				 skipCharacter( is, ')' ) )
338
			{
339
				advanceDays	= 	atoi( days.c_str() );
340
                if (advanceDays == 0) advanceDays = 1; //for invalid format default to tomorrow
341
            }
342
            else
343
            {
344
                advanceDays = 1;
345
            }							
346
 
347
			const TDateTime time = TDateTime::CurrentDateTime() + advanceDays;
2263 kivins 348
 
349
			m_cachedValue = value = time.FormatString( "dd-mm-yyyy" ).c_str();
350
		}
2267 kivins 351
		return ( true );        
352
    case EXPRESSIONID_SETSHIFTSTART:
353
		{                                         
354
            const TDateTime time = TDateTime::CurrentDateTime() + ( ( _timezone / 3600.0 ) / 24.0 );
355
 
356
			value = ( time.FormatString( "dd-mm-yyyy hh:nn:ss" ).c_str());
357
 
358
            evaluationContext.setStartTime (value);
359
		}
360
		return ( true );    
361
    case EXPRESSIONID_USESHIFTSTART:
362
		{                  
363
            value = evaluationContext.getStartTime();
364
		}
2263 kivins 365
		return ( true );
366
	case EXPRESSIONID_ACCOUNTTYPE:
367
		switch( evaluationContext.getTransaction().getUdType() )
368
		{
369
		case 1:	// Card
370
			value = "2";
371
			break;
372
		case 2:	// Application
373
			value = "1";
374
			break;
375
		case 3:	// Product
376
			value = "3";
377
			break;
378
		case 4:	// Other
379
			value = "4";
380
			break;
381
		case 5:	// Audit
382
			value = "4";
383
			break;
384
		case 6:	// Event
385
			value = "4";
386
			break;
387
		case 7:	// Project
388
			value = "4";
389
			break;
390
		default:
391
			value.erase();
392
			break;
393
		}
394
		m_cachedValue = value;
395
		return ( true );
396
	case EXPRESSIONID_RAND:
397
		{
398
			std::string lowerBound;
399
			std::string upperBound;
400
			if ( skipCharacter( is, '(' ) &&
401
				 readTerm( is, lowerBound ) &&
402
				 skipCharacter( is, ',' ) &&
403
				 readTerm( is, upperBound ) &&
404
				 skipCharacter( is, ')' ) )
405
			{
406
				const int first	= std::min< int >(
407
									atoi( lowerBound.c_str() ),
408
									atoi( upperBound.c_str() ) );
409
				const int last	= std::max< int >(
410
									atoi( lowerBound.c_str() ),
411
									atoi( upperBound.c_str() ) );
412
 
413
				AnsiString os;
414
				os.sprintf( "%d",
415
					int( ( rand() / double( RAND_MAX ) ) *
416
						 ( last - first + 1 ) + first ) );
417
				value = os.c_str();
418
				return ( true );
419
			}
420
			else
421
			{
422
				MERROR( "Cannot parse argument list." );
423
			}
424
		}
425
		break;
426
	case EXPRESSIONID_SEQ:
427
		{
428
			bool persisted = false;
429
			std::string name;
430
			std::string first;
431
			std::string increment;
432
			std::string last;
433
			std::string discriminant;
434
			std::string	fullName;
435
 
436
			/**
437
			 *	SEQ( name, first, increment, last[, discriminant] )
438
			 *	name ::= transient name | # persisted name
439
			 */
440
			if ( skipCharacter( is, '(' ) )
441
			{
442
				persisted = skipCharacter( is, '#' );
443
 
444
				if ( readIdentifier( is, name ) &&
445
					 skipCharacter( is, ',' ) &&
446
					 readTerm( is, first ) &&
447
					 skipCharacter( is, ',' ) &&
448
					 readTerm( is, last ) &&
449
					 skipCharacter( is, ',' ) &&
450
					 readTerm( is, increment ) &&
451
					 ( ( skipCharacter( is, ',' ) &&
452
						 readIdentifier( is, discriminant ) ) ||
453
					   skipCharacter( is, ')' ) ) )
454
				{
455
					if ( discriminant.length() )
456
					{
457
						/**
458
						 *	We have a discriminant, so we evaluate it to form
459
						 *	our name,
460
						 */
461
						FieldExpression subexpression( discriminant );
462
 
463
						std::string discriminantValue;
464
						if ( subexpression.evaluate( discriminantValue, true, evaluationContext, path, postponed ) )
465
						{
466
							AnsiString full;
467
							full.sprintf( "%s[%s]", name.c_str(), discriminantValue.c_str() );
468
							fullName = full.c_str();
469
						}
470
					}
471
					else
472
					{
473
						fullName = name;
474
					}
475
 
476
					Sequence & sequence = evaluationContext.
477
						getSequenceCollection().getSequence(
478
							fullName,
479
							persisted,
480
							atoi( first.c_str() ) );
2267 kivins 481
 
482
                    // don't increment on very first use of a new sequence  
483
                    if(!sequence.isDirty() || sequence.isUpdate())
484
                    {                    
485
    					sequence.incrementValue(
486
    						atoi( first.c_str() ),
487
    						atoi( last.c_str() ),
488
    						atoi( increment.c_str() ) );
489
                    }    
2263 kivins 490
					AnsiString os;
491
					os.sprintf( "%d", sequence.getValue() );
492
					value = os.c_str();
2267 kivins 493
 
494
                    sequence.setDirty (true); //used to force an increment next time round as well as db refresh    
2263 kivins 495
 
2267 kivins 496
					return ( true );
497
				}
498
			}
2263 kivins 499
 
2267 kivins 500
			MERROR( "Cannot parse argument list." );
501
		}
502
		break;
503
	case EXPRESSIONID_USESEQ:
504
		{
505
			bool persisted = false;
506
			std::string name;
507
			std::string discriminant;
508
			std::string	fullName;
509
 
510
			/**
511
			 *	SEQ( name, first, increment, last[, discriminant] )
512
			 *	name ::= transient name | # persisted name
513
			 */
514
			if ( skipCharacter( is, '(' ) )
515
			{
516
				persisted = skipCharacter( is, '#' );
517
				if ( readIdentifier( is, name ) &&
518
					 ( ( skipCharacter( is, ',' ) &&
519
						 readIdentifier( is, discriminant ) ) ||
520
					   skipCharacter( is, ')' ) ) )
521
				{
522
					if ( discriminant.length() )
523
					{
524
						/**
525
						 *	We have a discriminant, so we evaluate it to form
526
						 *	our name,
527
						 */
528
						FieldExpression subexpression( discriminant );
529
 
530
						std::string discriminantValue;
531
						if ( subexpression.evaluate( discriminantValue, true, evaluationContext, path, postponed ) )
532
						{
533
							AnsiString full;
534
							full.sprintf( "%s[%s]", name.c_str(), discriminantValue.c_str() );
535
							fullName = full.c_str();
536
						}
537
					}
538
					else
539
					{
540
						fullName = name;
541
					}
542
 
543
					Sequence & sequence = evaluationContext.
544
						getSequenceCollection().getSequence(
545
							fullName,
546
							true,      // really don't care
547
							1 );       // default if seq not already created
548
					AnsiString os;
549
					os.sprintf( "%d", sequence.getValue() );
550
					value = os.c_str();
551
 
552
                    // note: there is intentionally no increment
553
 
2263 kivins 554
					return ( true );
555
				}
556
			}
557
 
558
			MERROR( "Cannot parse argument list." );
559
		}
2267 kivins 560
		break;        
2263 kivins 561
	case EXPRESSIONID_KEYVERSION:
562
		if ( evaluationContext.haveMessageDigest() )
563
		{
564
			AnsiString os;
565
			os.sprintf( "%hu", evaluationContext.getMessageDigest().getKeyVersion() );
566
			value = os.c_str();
567
 
568
			return ( true );
569
		}
570
		break;
571
	case EXPRESSIONID_KEYNUMBER:
572
		if ( evaluationContext.haveMessageDigest() )
573
		{
574
			AnsiString os;
575
			os.sprintf( "%hu", evaluationContext.getMessageDigest().getKeyNumber() );
576
			value = os.c_str();
577
 
578
			return ( true );
579
		}
580
		break;
581
	case EXPRESSIONID_MAC:
582
		/**
583
		 *	We add the schema element to the collection of schema elements to
584
		 *	which we must assign the MAC.  Because we can compute the MAC only
585
		 *	when all fields have been evaluated, this must be postponed, and
586
		 *	until then we must report success.
587
		 */
588
		if ( evaluationContext.haveSchemaElement() )
589
		{
590
			evaluationContext.getTransaction().addMacField(
591
				evaluationContext.getSchemaElement().clone() );
592
			postponed = true;
593
 
594
			return ( true );
595
		}
596
		break;
597
	case EXPRESSIONID_SAMID:
598
		if ( evaluationContext.haveCryptographicServer() )
599
		{
600
			/**
601
			 *	We don't know which module will be used to compute the
602
			 *	MAC (security doesn't tell us), so until they do we
603
			 *	assume its the first module.
604
			 */
605
			/*
606
      if ( evaluationContext.getCryptographicServer().getModuleCount() )
607
			{
608
				AnsiString os;
609
				os.sprintf( "%hu", evaluationContext.getCryptographicServer().getSamId( 0 ) );
610
				value = os.c_str();
611
				return ( true );
612
			}
613
			*/
614
			value = 1;
615
			return ( true );
616
		}
617
		break;
618
	case EXPRESSIONID_SCENARIO_INDEX:
619
		{
620
			AnsiString os;
621
			os.sprintf( "%u", evaluationContext.getScenarioIndex() );
622
			value = os.c_str();
623
		}
624
		return ( true );
625
	case EXPRESSIONID_HOSTNAME:
626
		{
627
			char name[ 1024 ];
628
			unsigned long size = sizeof( name );
629
			if ( GetComputerName( name, &size ) )
630
			{
631
				value = name;
632
				return ( true );
633
			}
634
		}
635
	case EXPRESSIONID_USERNAME:
636
		{
637
			char name[ 1024 ];
638
			unsigned long size = sizeof( name );
639
			if ( GetUserName( name, &size ) )
640
			{
641
				value = name;
642
				return ( true );
643
			}
644
		}
645
	default:
646
		MERROR( "Function \"" << symbol << "\" is not implemented." );
647
		break;
648
	}
649
 
650
	return ( false );
651
 
652
  //## end FieldExpression::evaluateFunction%4208AE9D0216.body
653
}
654
 
655
//## Operation: evaluateVariable%420AE22101D7
656
const bool FieldExpression::evaluateVariable (std::istream &is, std::string &value, std::string &symbol, const bool &sideEffect, EvaluationContext& evaluationContext, std::vector< DefinedVariable * > &path, bool &postponed)
657
{
658
  //## begin FieldExpression::evaluateVariable%420AE22101D7.body preserve=yes
659
 
660
	return ( evaluationContext.getSymbolTable().getVariable( symbol, evaluationContext ).
661
				evaluate( value, sideEffect, evaluationContext, path, postponed ) );
662
 
663
  //## end FieldExpression::evaluateVariable%420AE22101D7.body
664
}
665
 
666
//## Operation: getExpression%420AC68F02E4
667
const std::string & FieldExpression::getExpression () const
668
{
669
  //## begin FieldExpression::getExpression%420AC68F02E4.body preserve=yes
670
 
671
	return ( m_expression );
672
 
673
  //## end FieldExpression::getExpression%420AC68F02E4.body
674
}
675
 
676
//## Operation: isFunctor%4209B773036F
677
const bool FieldExpression::isFunctor (const std::string &string)
678
{
679
  //## begin FieldExpression::isFunctor%4209B773036F.body preserve=yes
680
 
681
	PredefinedFunction const * where = 0;
682
 
683
	for ( where = functions; where->functor; ++where )
684
	{
685
		if ( string == where->functor )
686
		{
687
			return ( true );
688
		}
689
	}
690
 
691
	return ( false );
692
 
693
  //## end FieldExpression::isFunctor%4209B773036F.body
694
}
695
 
696
//## Operation: readIdentifier%42102FB70219
697
const bool FieldExpression::readIdentifier (std::istream &is, std::string &identifier)
698
{
699
  //## begin FieldExpression::readIdentifier%42102FB70219.body preserve=yes
700
 
701
	char character = 0;
702
 
703
	identifier.clear();
704
 
705
	is >> std::ws;
706
	if ( is.get( character ).good() )
707
	{
708
		if ( std::isalpha( character ) )
709
		{
710
			do
711
			{
712
				identifier += character;
713
			}
714
			while ( is.get( character ).good() &&
715
					( std::isalnum( character ) || ( character == '_' ) ) );
716
		}
717
 
718
		if ( is.good() )
719
		{
720
			is.putback( character );
721
		}
722
	}
723
 
724
	return ( identifier.length() > 0 );
725
 
726
  //## end FieldExpression::readIdentifier%42102FB70219.body
727
}
728
 
729
//## Operation: readTerm%420B0EB603D2
730
const bool FieldExpression::readTerm (std::istream &is, std::string &term)
731
{
732
  //## begin FieldExpression::readTerm%420B0EB603D2.body preserve=yes
733
 
734
	char character = 0;
735
 
736
	term.clear();
737
 
738
	is >> std::ws;
739
	if ( is.get( character ).good() )
740
	{
741
		const bool quoted = ( character == '\"' );
742
		if ( std::isalnum( character ) || ( character == '-' ) || quoted )
743
		{
744
			do
745
			{
746
				term += character;
747
			}
748
			while ( is.get( character ).good() && std::isalnum( character ) );
749
		}
750
 
751
		if ( is.good() && ( !quoted || character != '\"' ) )
752
		{
753
			is.putback( character );
754
		}
755
	}
756
 
757
	return ( term.length() > 0 );
758
 
759
  //## end FieldExpression::readTerm%420B0EB603D2.body
760
}
761
 
762
//## Operation: setExpression%420AC68F02F3
763
const std::string & FieldExpression::setExpression (const std::string &value)
764
{
765
  //## begin FieldExpression::setExpression%420AC68F02F3.body preserve=yes
766
 
767
	return ( m_expression = value );
768
 
769
  //## end FieldExpression::setExpression%420AC68F02F3.body
770
}
771
 
772
//## Operation: skipCharacter%420B100701E7
773
const bool FieldExpression::skipCharacter (std::istream &is, const char &character)
774
{
775
  //## begin FieldExpression::skipCharacter%420B100701E7.body preserve=yes
776
 
777
	char c = 0;
778
	is >> std::ws >> c;
779
 
780
	if ( is.good() )
781
	{
782
		if ( c == character )
783
		{
784
			return ( true );
785
		}
786
 
787
		is.putback( c );
788
	}
789
 
790
	return ( false );
791
 
792
  //## end FieldExpression::skipCharacter%420B100701E7.body
793
}
794
 
795
// Additional Declarations
796
  //## begin FieldExpression%420AC16002C1.declarations preserve=yes
797
  //## end FieldExpression%420AC16002C1.declarations
798
 
799
//## begin module%420AC16002C1.epilog preserve=yes
800
//## end module%420AC16002C1.epilog