Subversion Repositories DevTools

Rev

Rev 2226 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2218 sbetterm 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
 
2222 sbetterm 36
// ICryptographicServerProxy
37
#include "ICryptographicServerProxy.h"
38
// IMessageDigest
39
#include "IMessageDigest.h"
40
// IXmlSchemaWrapperElement
41
#include "IXmlSchemaWrapperElement.h"
2218 sbetterm 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
2236 mhunt 57
#include <time>
2218 sbetterm 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,
2222 sbetterm 84
	EXPRESSIONID_MAC,
85
	EXPRESSIONID_SAMID,
2226 sbetterm 86
	EXPRESSIONID_SCENARIO_INDEX,
87
	EXPRESSIONID_HOSTNAME,
88
	EXPRESSIONID_USERNAME
2218 sbetterm 89
};
90
struct PredefinedFunction
91
{
92
	const char *	functor;
93
	FunctionId		functionId;
94
};
95
 
96
static const PredefinedFunction functions[] =
97
{
98
	{ "FORMATVERSION",	EXPRESSIONID_FORMATVERSION },
99
	{ "NOW",			EXPRESSIONID_NOW },
100
	{ "UTCNOW",			EXPRESSIONID_UTCNOW },
101
	{ "TODAY",			EXPRESSIONID_TODAY },
102
	{ "YESTERDAY",		EXPRESSIONID_YESTERDAY },
103
	{ "TOMORROW",		EXPRESSIONID_TOMORROW },
104
	{ "RAND",			EXPRESSIONID_RAND },
105
	{ "UDTYPE",			EXPRESSIONID_UDTYPE },
106
	{ "UDSUBTYPE",		EXPRESSIONID_UDSUBTYPE },
107
	{ "ACCOUNTTYPE",	EXPRESSIONID_ACCOUNTTYPE },
108
	{ "SEQ",			EXPRESSIONID_SEQ },
109
	{ "KEYVERSION",		EXPRESSIONID_KEYVERSION },
110
	{ "KEYNUMBER",		EXPRESSIONID_KEYNUMBER },
111
	{ "MAC",			EXPRESSIONID_MAC },
2222 sbetterm 112
	{ "SAMID",			EXPRESSIONID_SAMID },
113
	{ "SCENARIOINDEX",	EXPRESSIONID_SCENARIO_INDEX },
2226 sbetterm 114
	{ "HOSTNAME",		EXPRESSIONID_HOSTNAME },
115
	{ "USERNAME",		EXPRESSIONID_USERNAME },
2218 sbetterm 116
	{ 0,				EXPRESSIONID_INVALID }
117
};
118
 
119
static const std::locale myLocale;
120
 
121
const FunctionId & getFunctionId( const std::string & string )
122
{
123
	PredefinedFunction const * where = 0;
124
 
125
	for ( where = functions; where->functor; ++where )
126
	{
127
		if ( string == where->functor )
128
		{
129
			break;
130
		}
131
	}
132
 
133
	return ( where->functionId );
134
}
135
 
2224 sbetterm 136
const bool readExpression( std::istream & stream, std::string & symbol, TokenId & token, EvaluationContext& evaluationContext )
2218 sbetterm 137
{
138
	symbol.erase();
139
 
140
	char character = 0;
141
	while ( stream.get( character ).good() )
142
	{
143
		if ( std::isalnum( character ) || character == '_' )
144
		{
145
			symbol += character;
146
		}
147
		else
148
		{
149
			stream.putback( character );	// Always put this back.
150
 
151
			if ( character == '(' )
152
			{
153
				token = TOKENID_FUNCTION;
154
				return ( true );
155
			}
156
 
157
			break;	// We have read in a lexeme, now tokenise it.
158
		}
159
	}
160
 
161
	// Only do this when we didn't fail reading from the stream.
162
	if ( stream.good() || stream.eof() )
163
	{
2224 sbetterm 164
		token = ( evaluationContext.getSymbolTable().isVariable( symbol, evaluationContext )
2218 sbetterm 165
			? TOKENID_VARIABLE
166
			: TOKENID_CONSTANT );
167
		return ( true );
168
	}
169
 
170
	return ( false );
171
}
172
//## end module%420AC16002C1.additionalDeclarations
173
 
174
 
175
// Class FieldExpression 
176
 
177
FieldExpression::FieldExpression()
178
  //## begin FieldExpression::FieldExpression%420AC16002C1_const.initialization preserve=yes
179
  //## end FieldExpression::FieldExpression%420AC16002C1_const.initialization
180
{
181
  //## begin FieldExpression::FieldExpression%420AC16002C1_const.body preserve=yes
182
  //## end FieldExpression::FieldExpression%420AC16002C1_const.body
183
}
184
 
185
//## Operation: FieldExpression%42105AAC0084
186
FieldExpression::FieldExpression (const std::string &expression)
187
  //## begin FieldExpression::FieldExpression%42105AAC0084.hasinit preserve=no
188
  //## end FieldExpression::FieldExpression%42105AAC0084.hasinit
189
  //## begin FieldExpression::FieldExpression%42105AAC0084.initialization preserve=yes
190
 
191
:	m_expression( expression )
192
 
193
  //## end FieldExpression::FieldExpression%42105AAC0084.initialization
194
{
195
  //## begin FieldExpression::FieldExpression%42105AAC0084.body preserve=yes
196
  //## end FieldExpression::FieldExpression%42105AAC0084.body
197
}
198
 
199
 
200
FieldExpression::~FieldExpression()
201
{
202
  //## begin FieldExpression::~FieldExpression%420AC16002C1_dest.body preserve=yes
203
  //## end FieldExpression::~FieldExpression%420AC16002C1_dest.body
204
}
205
 
206
 
207
 
208
//## Other Operations (implementation)
209
//## Operation: evaluate%420456630303
210
const bool FieldExpression::evaluate (std::string &value, const bool &sideEffect, EvaluationContext& evaluationContext, std::vector< DefinedVariable * > &path, bool &postponed)
211
{
212
  //## begin FieldExpression::evaluate%420456630303.body preserve=yes
213
 
214
	if ( m_cachedValue.length() )
215
	{
216
		value = m_cachedValue;
217
		return ( true );
218
	}
219
 
220
	/**
221
	 *	TODO: Eventually replace the use of streams with a char buffer, but
222
	 *	right now I just need to get it working.
223
	 */
224
	if ( ( m_expression[ 0 ] == '\"' ) &&
225
		 ( m_expression[ m_expression.length() - 1 ] == '\"' ) )
226
	{
227
		value = m_cachedValue = m_expression.substr( 1, m_expression.length() - 2 );
228
		return ( true );
229
	}
230
 
231
	std::istringstream is( m_expression );
232
	skipCharacter( is, '=' );	// Skip the '=' if its there.
233
 
234
	/**
235
	 *	TODO: evaluate this field using the defined collection of variables
236
	 *	and sequence generators, making sure we respect the sideEffect flag.
237
	 */
238
	/**
239
		For now, we assume a very simple syntax:
240
 
241
			expression		::= function | variable | constant
242
			function		::= =functor ( [ argument list ] )
243
			variable		::= =variable
244
			constant		::= alphanumeric
245
			argument list	::= argument[, argument list ]
246
			argument		::= expression
247
	 */
248
	std::string	symbol;
249
	TokenId		token = TOKENID_INVALID;
2224 sbetterm 250
	while ( readExpression( is, symbol, token, evaluationContext ) )
2218 sbetterm 251
	{
252
		switch ( token )
253
		{
254
		case TOKENID_FUNCTION:
255
			return ( evaluateFunction( is, value, symbol, sideEffect, evaluationContext, path, postponed ) );
256
		case TOKENID_VARIABLE:
257
			return ( evaluateVariable( is, value, symbol, sideEffect, evaluationContext, path, postponed ) );
258
		case TOKENID_CONSTANT:
259
			// Its not a defined variable or function, so just evaluate to
260
			// it.
261
			m_cachedValue = value = m_expression;
262
			return ( true );
263
		}
264
	}
265
 
266
	return ( true );
267
 
268
  //## end FieldExpression::evaluate%420456630303.body
269
}
270
 
271
//## Operation: evaluateFunction%4208AE9D0216
272
const bool FieldExpression::evaluateFunction (std::istream &is, std::string &value, std::string &symbol, const bool &sideEffect, EvaluationContext& evaluationContext, std::vector< DefinedVariable * > &path, bool &postponed)
273
{
274
  //## begin FieldExpression::evaluateFunction%4208AE9D0216.body preserve=yes
275
 
276
	/**
277
	 *	Check parameter lists on all functions calls, and report an error
278
	 *	when a function is called with superfluous arguments.
279
	 */
280
 
281
	postponed = false;
282
	switch ( getFunctionId( symbol ) )
283
	{
284
	case EXPRESSIONID_UDTYPE:
285
		{
286
			AnsiString os;
287
			os.sprintf( "%hu", evaluationContext.getTransaction().getUdType() );
288
			m_cachedValue = value = os.c_str();
289
		}
290
		return ( true );
291
	case EXPRESSIONID_UDSUBTYPE:
292
		{
293
			AnsiString os;
294
			os.sprintf( "%hu", evaluationContext.getTransaction().getUdSubtype() );
295
			m_cachedValue = value = os.c_str();
296
		}
297
		return ( true );
298
	case EXPRESSIONID_TODAY:
299
		m_cachedValue = value = TDateTime::CurrentDateTime().FormatString( "dd-mm-yyyy" ).c_str();
300
		return ( true );
301
	case EXPRESSIONID_FORMATVERSION:
302
		{
303
			AnsiString os;
304
			os.sprintf( "%d", evaluationContext.getTransaction().getFormatVersion() );
305
			m_cachedValue = value = os.c_str();
306
		}
307
		return ( true );
308
	case EXPRESSIONID_NOW:
309
		m_cachedValue = value = TDateTime::CurrentDateTime().FormatString( "dd-mm-yyyy hh:nn:ss" ).c_str();
310
		return ( true );
311
	case EXPRESSIONID_UTCNOW:
312
		{
313
			const TDateTime time = TDateTime::CurrentDateTime() + ( ( _timezone / 3600.0 ) / 24.0 );
314
 
315
			m_cachedValue = value = time.FormatString( "dd-mm-yyyy hh:nn:ss" ).c_str();
316
		}
317
		return ( true );
318
	case EXPRESSIONID_YESTERDAY:
319
		{
320
			const TDateTime time = TDateTime::CurrentDateTime() - 1;
321
 
322
			m_cachedValue = value = time.FormatString( "dd-mm-yyyy" ).c_str();
323
		}
324
		return ( true );
325
	case EXPRESSIONID_TOMORROW:
326
		{
327
			const TDateTime time = TDateTime::CurrentDateTime() + 1;
328
 
329
			m_cachedValue = value = time.FormatString( "dd-mm-yyyy" ).c_str();
330
		}
331
		return ( true );
332
	case EXPRESSIONID_ACCOUNTTYPE:
333
		switch( evaluationContext.getTransaction().getUdType() )
334
		{
335
		case 1:	// Card
336
			value = "2";
337
			break;
338
		case 2:	// Application
339
			value = "1";
340
			break;
341
		case 3:	// Product
342
			value = "3";
343
			break;
344
		case 4:	// Other
345
			value = "4";
346
			break;
347
		case 5:	// Audit
348
			value = "4";
349
			break;
350
		case 6:	// Event
351
			value = "4";
352
			break;
353
		case 7:	// Project
354
			value = "4";
355
			break;
356
		default:
357
			value.erase();
358
			break;
359
		}
360
		m_cachedValue = value;
361
		return ( true );
362
	case EXPRESSIONID_RAND:
363
		{
364
			std::string lowerBound;
365
			std::string upperBound;
366
			if ( skipCharacter( is, '(' ) &&
367
				 readTerm( is, lowerBound ) &&
368
				 skipCharacter( is, ',' ) &&
369
				 readTerm( is, upperBound ) &&
370
				 skipCharacter( is, ')' ) )
371
			{
372
				const int first	= std::min< int >(
373
									atoi( lowerBound.c_str() ),
374
									atoi( upperBound.c_str() ) );
375
				const int last	= std::max< int >(
376
									atoi( lowerBound.c_str() ),
377
									atoi( upperBound.c_str() ) );
378
 
379
				AnsiString os;
380
				os.sprintf( "%d",
381
					int( ( rand() / double( RAND_MAX ) ) *
382
						 ( last - first + 1 ) + first ) );
383
				value = os.c_str();
384
				return ( true );
385
			}
386
			else
387
			{
388
				MERROR( "Cannot parse argument list." );
389
			}
390
		}
391
		break;
392
	case EXPRESSIONID_SEQ:
393
		{
394
			bool persisted = false;
395
			std::string name;
396
			std::string first;
397
			std::string increment;
398
			std::string last;
399
			std::string discriminant;
400
			std::string	fullName;
401
 
402
			/**
403
			 *	SEQ( name, first, increment, last[, discriminant] )
404
			 *	name ::= transient name | # persisted name
405
			 */
406
			if ( skipCharacter( is, '(' ) )
407
			{
408
				persisted = skipCharacter( is, '#' );
409
 
410
				if ( readIdentifier( is, name ) &&
411
					 skipCharacter( is, ',' ) &&
412
					 readTerm( is, first ) &&
413
					 skipCharacter( is, ',' ) &&
414
					 readTerm( is, last ) &&
415
					 skipCharacter( is, ',' ) &&
416
					 readTerm( is, increment ) &&
417
					 ( ( skipCharacter( is, ',' ) &&
418
						 readIdentifier( is, discriminant ) ) ||
419
					   skipCharacter( is, ')' ) ) )
420
				{
421
					if ( discriminant.length() )
422
					{
423
						/**
424
						 *	We have a discriminant, so we evaluate it to form
425
						 *	our name,
426
						 */
427
						FieldExpression subexpression( discriminant );
428
 
429
						std::string discriminantValue;
430
						if ( subexpression.evaluate( discriminantValue, true, evaluationContext, path, postponed ) )
431
						{
432
							AnsiString full;
433
							full.sprintf( "%s[%s]", name.c_str(), discriminantValue.c_str() );
434
							fullName = full.c_str();
435
						}
436
					}
437
					else
438
					{
439
						fullName = name;
440
					}
441
 
442
					Sequence & sequence = evaluationContext.
443
						getSequenceCollection().getSequence(
444
							fullName,
445
							persisted,
446
							atoi( first.c_str() ) );
447
					AnsiString os;
448
					os.sprintf( "%d", sequence.getValue() );
449
					value = os.c_str();
450
 
451
					sequence.incrementValue(
452
						atoi( first.c_str() ),
453
						atoi( last.c_str() ),
454
						atoi( increment.c_str() ) );
455
 
456
					return ( true );
457
				}
458
			}
459
 
460
			MERROR( "Cannot parse argument list." );
461
		}
462
		break;
463
	case EXPRESSIONID_KEYVERSION:
464
		if ( evaluationContext.haveMessageDigest() )
465
		{
466
			AnsiString os;
467
			os.sprintf( "%hu", evaluationContext.getMessageDigest().getKeyVersion() );
468
			value = os.c_str();
469
 
470
			return ( true );
471
		}
472
		break;
473
	case EXPRESSIONID_KEYNUMBER:
474
		if ( evaluationContext.haveMessageDigest() )
475
		{
476
			AnsiString os;
477
			os.sprintf( "%hu", evaluationContext.getMessageDigest().getKeyNumber() );
478
			value = os.c_str();
479
 
480
			return ( true );
481
		}
482
		break;
483
	case EXPRESSIONID_MAC:
484
		/**
485
		 *	We add the schema element to the collection of schema elements to
486
		 *	which we must assign the MAC.  Because we can compute the MAC only
487
		 *	when all fields have been evaluated, this must be postponed, and
488
		 *	until then we must report success.
489
		 */
490
		if ( evaluationContext.haveSchemaElement() )
491
		{
492
			evaluationContext.getTransaction().addMacField(
493
				evaluationContext.getSchemaElement().clone() );
494
			postponed = true;
495
 
496
			return ( true );
497
		}
498
		break;
2222 sbetterm 499
	case EXPRESSIONID_SAMID:
500
		if ( evaluationContext.haveCryptographicServer() )
501
		{
502
			/**
503
			 *	We don't know which module will be used to compute the
504
			 *	MAC (security doesn't tell us), so until they do we
505
			 *	assume its the first module.
506
			 */
507
			if ( evaluationContext.getCryptographicServer().getModuleCount() )
508
			{
509
				AnsiString os;
510
				os.sprintf( "%hu", evaluationContext.getCryptographicServer().getSamId( 0 ) );
511
				value = os.c_str();
512
				return ( true );
513
			}
514
		}
515
		break;
516
	case EXPRESSIONID_SCENARIO_INDEX:
517
		{
518
			AnsiString os;
519
			os.sprintf( "%u", evaluationContext.getScenarioIndex() );
520
			value = os.c_str();
521
		}
522
		return ( true );
2226 sbetterm 523
	case EXPRESSIONID_HOSTNAME:
524
		{
525
			char name[ 1024 ];
526
			unsigned long size = sizeof( name );
527
			if ( GetComputerName( name, &size ) )
528
			{
529
				value = name;
530
				return ( true );
531
			}
532
		}
533
	case EXPRESSIONID_USERNAME:
534
		{
535
			char name[ 1024 ];
536
			unsigned long size = sizeof( name );
537
			if ( GetUserName( name, &size ) )
538
			{
539
				value = name;
540
				return ( true );
541
			}
542
		}
2218 sbetterm 543
	default:
2222 sbetterm 544
		MERROR( "Function \"" << symbol << "\" is not implemented." );
2218 sbetterm 545
		break;
546
	}
547
 
548
	return ( false );
549
 
550
  //## end FieldExpression::evaluateFunction%4208AE9D0216.body
551
}
552
 
553
//## Operation: evaluateVariable%420AE22101D7
554
const bool FieldExpression::evaluateVariable (std::istream &is, std::string &value, std::string &symbol, const bool &sideEffect, EvaluationContext& evaluationContext, std::vector< DefinedVariable * > &path, bool &postponed)
555
{
556
  //## begin FieldExpression::evaluateVariable%420AE22101D7.body preserve=yes
557
 
2224 sbetterm 558
	return ( evaluationContext.getSymbolTable().getVariable( symbol, evaluationContext ).
2218 sbetterm 559
				evaluate( value, sideEffect, evaluationContext, path, postponed ) );
560
 
561
  //## end FieldExpression::evaluateVariable%420AE22101D7.body
562
}
563
 
564
//## Operation: getExpression%420AC68F02E4
565
const std::string & FieldExpression::getExpression () const
566
{
567
  //## begin FieldExpression::getExpression%420AC68F02E4.body preserve=yes
568
 
569
	return ( m_expression );
570
 
571
  //## end FieldExpression::getExpression%420AC68F02E4.body
572
}
573
 
574
//## Operation: isFunctor%4209B773036F
575
const bool FieldExpression::isFunctor (const std::string &string)
576
{
577
  //## begin FieldExpression::isFunctor%4209B773036F.body preserve=yes
578
 
579
	PredefinedFunction const * where = 0;
580
 
581
	for ( where = functions; where->functor; ++where )
582
	{
583
		if ( string == where->functor )
584
		{
585
			return ( true );
586
		}
587
	}
588
 
589
	return ( false );
590
 
591
  //## end FieldExpression::isFunctor%4209B773036F.body
592
}
593
 
594
//## Operation: readIdentifier%42102FB70219
595
const bool FieldExpression::readIdentifier (std::istream &is, std::string &identifier)
596
{
597
  //## begin FieldExpression::readIdentifier%42102FB70219.body preserve=yes
598
 
599
	char character = 0;
600
 
601
	identifier.clear();
602
 
603
	is >> std::ws;
604
	if ( is.get( character ).good() )
605
	{
606
		if ( std::isalpha( character ) )
607
		{
608
			do
609
			{
610
				identifier += character;
611
			}
612
			while ( is.get( character ).good() &&
613
					( std::isalnum( character ) || ( character == '_' ) ) );
614
		}
615
 
616
		if ( is.good() )
617
		{
618
			is.putback( character );
619
		}
620
	}
621
 
622
	return ( identifier.length() > 0 );
623
 
624
  //## end FieldExpression::readIdentifier%42102FB70219.body
625
}
626
 
627
//## Operation: readTerm%420B0EB603D2
628
const bool FieldExpression::readTerm (std::istream &is, std::string &term)
629
{
630
  //## begin FieldExpression::readTerm%420B0EB603D2.body preserve=yes
631
 
632
	char character = 0;
633
 
634
	term.clear();
635
 
636
	is >> std::ws;
637
	if ( is.get( character ).good() )
638
	{
639
		const bool quoted = ( character == '\"' );
640
		if ( std::isalnum( character ) || ( character == '-' ) || quoted )
641
		{
642
			do
643
			{
644
				term += character;
645
			}
646
			while ( is.get( character ).good() && std::isalnum( character ) );
647
		}
648
 
649
		if ( is.good() && ( !quoted || character != '\"' ) )
650
		{
651
			is.putback( character );
652
		}
653
	}
654
 
655
	return ( term.length() > 0 );
656
 
657
  //## end FieldExpression::readTerm%420B0EB603D2.body
658
}
659
 
660
//## Operation: setExpression%420AC68F02F3
661
const std::string & FieldExpression::setExpression (const std::string &value)
662
{
663
  //## begin FieldExpression::setExpression%420AC68F02F3.body preserve=yes
664
 
665
	return ( m_expression = value );
666
 
667
  //## end FieldExpression::setExpression%420AC68F02F3.body
668
}
669
 
670
//## Operation: skipCharacter%420B100701E7
671
const bool FieldExpression::skipCharacter (std::istream &is, const char &character)
672
{
673
  //## begin FieldExpression::skipCharacter%420B100701E7.body preserve=yes
674
 
675
	char c = 0;
676
	is >> std::ws >> c;
677
 
678
	if ( is.good() )
679
	{
680
		if ( c == character )
681
		{
682
			return ( true );
683
		}
684
 
685
		is.putback( c );
686
	}
687
 
688
	return ( false );
689
 
690
  //## end FieldExpression::skipCharacter%420B100701E7.body
691
}
692
 
693
// Additional Declarations
694
  //## begin FieldExpression%420AC16002C1.declarations preserve=yes
695
  //## end FieldExpression%420AC16002C1.declarations
696
 
697
//## begin module%420AC16002C1.epilog preserve=yes
698
//## end module%420AC16002C1.epilog