summaryrefslogtreecommitdiff
path: root/src/TMCG_StackSecret.hh
blob: 740f8e8670bf9a9de556be296a4f7048630fdd3e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
/*******************************************************************************
  Data structure for the secrets of a stack. This file is part of LibTMCG.

 Copyright (C) 2004, 2005, 2006, 2007, 
               2016, 2017, 2018, 2019  Heiko Stamer <[email protected]>

   LibTMCG is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   LibTMCG is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with LibTMCG; if not, write to the Free Software
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*******************************************************************************/

#ifndef INCLUDED_TMCG_StackSecret_HH
	#define INCLUDED_TMCG_StackSecret_HH
	
// C++/STL header
#include <cstdlib>
#include <string>
#include <iostream>
#include <vector>
#include <utility>
#include <algorithm>
#include <functional>
	
#include "parse_helper.hh"

/** @brief Data structure for the secrets of a stack of cards.
    
    This struct is a simple container for the secrets involved in the
    masking operation of cards. Additionally, the permutation of the
    corresponding shuffle of the stack is stored.
    The elements are pairs where the first component is a permutation
    index and the second component is the card secret. These secrets
    can be either of type TMCG_CardSecret or VTMF_CardSecret depending
    on which kind of encoding scheme is used.
    
    @param CardSecretType is the type of the stored card secrets. */
template <typename CardSecretType> struct TMCG_StackSecret
{
	/** This member is the underlying container of the stack secret. */
	std::vector<std::pair<size_t, CardSecretType> > stack;
	
	/** This is a simple equality test for the first component of a pair. */
	struct eq_first_component : public std::binary_function<
		std::pair<size_t, CardSecretType>,
		std::pair<size_t, CardSecretType>, bool>
	{
		/** This is the comparator for equality. */
		bool operator() 
			(const std::pair<size_t, CardSecretType>& p1,
			 const std::pair<size_t, CardSecretType>& p2) const
		{
			return (p1.first == p2.first);
		}
	};
	
	/** This constructor initializes an empty stack secret. */
	TMCG_StackSecret
		()
	{
	}
	
	/** A simple assignment-operator.
	    @param that is the stack secret to be assigned. */
	TMCG_StackSecret& operator =
		(const TMCG_StackSecret<CardSecretType>& that)
	{
		stack.clear();
		stack = that.stack;
		return *this;
	}
	
	/** This operator provides random access to the pairs of the stack secret.
	    @returns The @a n th pair from the top of the stack secret. */
	const std::pair<size_t, CardSecretType>& operator []
		(const size_t n) const
	{
		return stack[n];
	}
	
	/** This operator provides random access to the pairs of the stack secret.
	    @returns The @a n th pair from the top of the stack secret. */
	std::pair<size_t, CardSecretType>& operator []
		(const size_t n)
	{
		return stack[n];
	}
	
	/** @returns The size of the stack secret. */
	size_t size
		() const
	{
		return stack.size();
	}
	
	/** This method pushes a pair to the back of the stack secret.
	    @param index is the permutation index (first component) to be pushed.
	    @param cs is the card secret (second component) to be pushed. */
	void push
		(const size_t index, const CardSecretType& cs)
	{
		if (stack.size() < TMCG_MAX_CARDS)
			stack.push_back(std::pair<size_t, CardSecretType>(index, cs));
	}
	
	/** Clears the stack secret. */
	void clear
		()
	{
		stack.clear();
	}
	
	/** This method searches for a permutation index in the stack secret.
	    @param index is the permutation index to be found.
	    @returns The position in the stack secret, if @a index was found.
	    Otherwise, it returns the size of the stack secret. */
	size_t find_position
		(const size_t index) const
	{
		return distance(stack.begin(), std::find_if(stack.begin(), stack.end(),
			std::bind2nd(eq_first_component(),
				std::pair<size_t, CardSecretType>(index, CardSecretType()))));
	}
	
	/** This method searches for a permutation index in the stack secret.
	    @param index is the permutation index to be found.
	    @returns True, if @a index was found. */
	bool find
		(const size_t index) const
	{
		return (find_position(index) == stack.size() ? false : true);
	}
	
	/** This function imports the stack secret.
	    @param s is correctly formated input string.
	    @returns True, if the import was successful. */
	bool import
		(std::string s)
	{

		try
		{
			// check magic
			if (!TMCG_ParseHelper::cm(s, "sts", '^'))
				throw false;
			
			// size of stack
			std::string size_str;
			if (!TMCG_ParseHelper::gs(s, '^', size_str))
				throw false;
			char *ec;
			size_t size = std::strtoul(size_str.c_str(), &ec, 10);
			if (*ec != '\0')
				throw false;
			if ((size <= 0) || (size > TMCG_MAX_CARDS))
				throw false;
			if (!TMCG_ParseHelper::nx(s, '^'))
				throw false;
			
			// cards on stack
			for (size_t i = 0; i < size; i++)
			{
				std::pair<size_t, CardSecretType> lej;
				std::string pi_str, cs_str;
				
				// permutation index
				if (!TMCG_ParseHelper::gs(s, '^', pi_str))
					throw false;
				lej.first = std::strtoul(pi_str.c_str(), &ec, 10);
				if (*ec != '\0')
					throw false;
				if (lej.first >= size)
					throw false;
				if (!TMCG_ParseHelper::nx(s, '^'))
					throw false;
				
				// card secret
				if (!TMCG_ParseHelper::gs(s, '^', cs_str))
					throw false;
				if (!lej.second.import(cs_str))
					throw false;
				if (!TMCG_ParseHelper::nx(s, '^'))
					throw false;
				
				// store pair
				stack.push_back(lej);
			}

			// check whether the index component is a correct permutation
			for (size_t i = 0; i < size; i++)
			{
				if (find_position(i) >= size)
					throw false;
			}
			
			// finish
			throw true;
		}
		catch (bool return_value)
		{
			return return_value;
		}
	}
	
	/** This destructor releases all occupied resources. */
	~TMCG_StackSecret
		()
	{
		stack.clear();
	}
};

/** @relates TMCG_StackSecret
    This operator prints a stack secret to an output stream.
    @param out is the output stream.
    @param stacksecret is the stack secret to be printed. */
template<typename CardSecretType> std::ostream& operator <<
	(std::ostream& out, const TMCG_StackSecret<CardSecretType>& stacksecret)
{
	out << "sts^" << stacksecret.size() << "^";
	for (size_t i = 0; i < stacksecret.size(); i++)
		out << stacksecret[i].first << "^" << stacksecret[i].second << "^";
	return out;
}

/** @relates TMCG_StackSecret
    This operator imports a stack secret from an input stream. It has
    to be delimited by a newline character.
    The failbit of the stream is set, if any parse error occurred.
    @param in is the input stream.
    @param stacksecret is the stack secret to be imported. */
template<typename CardSecretType> std::istream& operator >>
	(std::istream& in, TMCG_StackSecret<CardSecretType>& stacksecret)
{
	char *tmp = new char[TMCG_MAX_STACK_CHARS];
	in.getline(tmp, TMCG_MAX_STACK_CHARS);
	if (!stacksecret.import(std::string(tmp)))
		in.setstate(std::istream::iostate(std::istream::failbit));
	delete [] tmp;
	return in;
}

#endif