1 /*****************************************************************************
2 * Author: Valient Gough <vgough@pobox.com>
3 *
4 *****************************************************************************
5 * Copyright (c) 2004, Valient Gough
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
15 * for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "Interface.h"
22
23 #include <utility>
24
25 #include "ConfigVar.h"
26 #include "Error.h"
27
28 namespace encfs {
29
Interface(const char * name_,int Current,int Revision,int Age)30 Interface::Interface(const char *name_, int Current, int Revision, int Age)
31 : _name(name_), _current(Current), _revision(Revision), _age(Age) {}
32
Interface(std::string name_,int Current,int Revision,int Age)33 Interface::Interface(std::string name_, int Current, int Revision, int Age)
34 : _name(std::move(name_)),
35 _current(Current),
36 _revision(Revision),
37 _age(Age) {}
38
Interface()39 Interface::Interface() : _current(0), _revision(0), _age(0) {}
40
41 Interface &Interface::operator=(const Interface &src) = default;
42
name() const43 const std::string &Interface::name() const { return _name; }
44
name()45 std::string &Interface::name() { return _name; }
46
current() const47 int Interface::current() const { return _current; }
48
current()49 int &Interface::current() { return _current; }
50
revision() const51 int Interface::revision() const { return _revision; }
52
revision()53 int &Interface::revision() { return _revision; }
54
age() const55 int Interface::age() const { return _age; }
56
age()57 int &Interface::age() { return _age; }
58
operator ==(const Interface & A,const Interface & B)59 bool operator==(const Interface &A, const Interface &B) {
60 return (A.name() == B.name() && A.current() == B.current() &&
61 A.revision() == B.revision() && A.age() == B.age());
62 }
63
operator !=(const Interface & A,const Interface & B)64 bool operator!=(const Interface &A, const Interface &B) {
65 return (A.name() != B.name() || A.current() != B.current() ||
66 A.revision() != B.revision() || A.age() != B.age());
67 }
68
69 // zero branch method of getting comparison sign..
70 // tricky.. makes assumptions
71 #if 0
72 static int sign( int a, int b )
73 {
74 unsigned int ab = ((unsigned int)(a - b)) >> 31;
75 unsigned int ba = ((unsigned int)(b - a)) >> 31;
76
77 return 1 + ba - ab;
78 }
79 #else
80 // simple, easy to check, unlikely to break due to unforseen events..
sign(int a,int b)81 static int sign(int a, int b) {
82 if (a < b) {
83 return 0;
84 }
85 if (a == b) {
86 return 1;
87 }
88 return 2;
89 }
90 #endif
91
diffSum(const Interface & A,const Interface & B)92 static int diffSum(const Interface &A, const Interface &B) {
93 int cS = sign(A.current(), B.current());
94 int aS = sign(A.age(), B.age());
95 int rS = sign(A.revision(), B.revision());
96
97 return (cS * 3 + aS) * 3 + rS;
98 }
99
100 const int EqualVersion = (1 * 3 + 1) * 3 + 1;
101
implements(const Interface & B) const102 bool Interface::implements(const Interface &B) const {
103 VLOG(1) << "checking if " << name() << "(" << current() << ":" << revision()
104 << ":" << age() << ") implements " << B.name() << "(" << B.current()
105 << ":" << B.revision() << ")";
106
107 if (name() != B.name()) {
108 return false;
109 }
110
111 int currentDiff = current() - B.current();
112 return (currentDiff >= 0 && currentDiff <= age());
113 }
114
operator <(const Interface & A,const Interface & B)115 bool operator<(const Interface &A, const Interface &B) {
116 if (A.name() == B.name()) {
117 return (diffSum(A, B) < EqualVersion);
118 }
119 return A.name() < B.name();
120 }
121
operator >(const Interface & A,const Interface & B)122 bool operator>(const Interface &A, const Interface &B) {
123 if (A.name() == B.name()) {
124 return (diffSum(A, B) > EqualVersion);
125 }
126 return A.name() < B.name();
127 }
128
operator <=(const Interface & A,const Interface & B)129 bool operator<=(const Interface &A, const Interface &B) {
130 if (A.name() == B.name()) {
131 return (diffSum(A, B) <= EqualVersion);
132 }
133 return A.name() < B.name();
134 }
135
operator >=(const Interface & A,const Interface & B)136 bool operator>=(const Interface &A, const Interface &B) {
137 if (A.name() == B.name()) {
138 return (diffSum(A, B) >= EqualVersion);
139 }
140 return A.name() < B.name();
141 }
142
operator <<(ConfigVar & dst,const Interface & iface)143 ConfigVar &operator<<(ConfigVar &dst, const Interface &iface) {
144 dst << iface.name() << iface.current() << iface.revision() << iface.age();
145 return dst;
146 }
147
operator >>(const ConfigVar & src,Interface & iface)148 const ConfigVar &operator>>(const ConfigVar &src, Interface &iface) {
149 src >> iface.name();
150 src >> iface.current();
151 src >> iface.revision();
152 src >> iface.age();
153 return src;
154 }
155
156 } // namespace encfs
157