1 
2 /* Web Polygraph       http://www.web-polygraph.org/
3  * Copyright 2003-2011 The Measurement Factory
4  * Licensed under the Apache License, Version 2.0 */
5 
6 #include "pgl/pgl.h"
7 
8 #include "xstd/Assert.h"
9 #include "pgl/PglArraySym.h"
10 #include "pgl/PglClonerSym.h"
11 
12 
13 
14 String ClonerSym::TheType = "Cloner";
15 
16 static String strContainer = "Container";
17 
18 
ClonerSym(const SynSym & aSource,int aCount)19 ClonerSym::ClonerSym(const SynSym &aSource, int aCount): ContainerSym(TheType),
20 	theSource(aSource.clone()), theCount(aCount) {
21 	Assert(theSource);
22 	Assert(theCount > 0);
23 }
24 
~ClonerSym()25 ClonerSym::~ClonerSym() {
26 	delete theSource;
27 }
28 
isA(const String & type) const29 bool ClonerSym::isA(const String &type) const {
30 	if (type == TheType || ContainerSym::isA(type))
31 		return true;
32 
33 	if (const char *p = type.str("[]"))
34 		return theSource->isA(type(0, p - type.cstr()));
35 
36 	return false;
37 }
38 
dupe(const String & type) const39 SynSym *ClonerSym::dupe(const String &type) const {
40 	if (isA(type)) {
41 		ClonerSym *clone = new ClonerSym(*theSource, theCount);
42 		return clone;
43 	}
44 
45 	if (const char *p = type.str("[]")) {
46 		const String itemType = type(0, p - type.cstr());
47 		if (theSource->canBe(itemType)) {
48 			ArraySym *arr = new ArraySym(itemType);
49 			arr->add(*this);
50 			return arr;
51 		}
52 	}
53 
54 	return 0;
55 }
56 
count() const57 int ClonerSym::count() const {
58 	if (theSource->isA(strContainer))
59 		return theCount*((const ContainerSym&)theSource->cast(strContainer)).count();
60 	else
61 		return theCount;
62 }
63 
probsSet() const64 bool ClonerSym::probsSet() const {
65 	if (theSource->isA(strContainer))
66 		return ((const ContainerSym&)theSource->cast(strContainer)).probsSet();
67 	else
68 		return false;
69 }
70 
itemProb(int idx,double & prob) const71 const SynSym *ClonerSym::itemProb(int idx, double &prob) const {
72 	const int cnt = count();
73 	Assert(cnt > 0);
74 	Assert(0 <= idx && idx < cnt);
75 	if (theSource->isA(strContainer)) {
76 		const ContainerSym &c = (const ContainerSym&)theSource->cast(strContainer);
77 		const int iOffset = idx / theCount;
78 		const SynSym *i = c.itemProb(iOffset, prob);
79 		prob /= theCount;
80 		return i;
81 	} else {
82 		prob = 1.0/theCount;
83 		return theSource;
84 	}
85 }
86 
forEach(Visitor & v,RndGen * const rng) const87 void ClonerSym::forEach(Visitor &v, RndGen *const rng) const {
88 	if (theSource->isA(strContainer)) {
89 		const ContainerSym &c = (const ContainerSym&)theSource->cast(strContainer);
90 		for (int i = 0; i < theCount; ++i)
91 			c.forEach(v, rng);
92 	} else {
93 		for (int i = 0; i < theCount; ++i)
94 			v.visit(*theSource);
95 	}
96 }
97 
print(ostream & os,const String & pfx) const98 ostream &ClonerSym::print(ostream &os, const String &pfx) const {
99 	return theSource->print(os, pfx) << " ** " << theCount;
100 }
101