[go: up one dir, main page]

Menu

[80c337]: / laddress.cpp  Maximize  Restore  History

Download this file

183 lines (160 with data), 5.8 kB

  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
#include "laddress.h"
#include <QDebug>
// LobAddress implementation here
LobAddress::LobAddress ()
{}
LobAddress::LobAddress ( const QString encoding )
{
//LobAddress result;
int i = 0;
while ( i < encoding.length() ) {
OmNode::OwnershipType stepType;
switch ( encoding[i++].toLatin1() ) {
case 'c': stepType = OmNode::AsChild; break;
case 'k': stepType = OmNode::AsKey; break;
case 'v': stepType = OmNode::AsValue; break;
case 's': continue; // self steps should be ignored
default : LobAddress(); return;// invalid step type, so return failure
}
int indexStart = i;
while ( ( i < encoding.length() ) && encoding[i].isDigit() )
i++;
if ( indexStart == i ) {
LobAddress(); // two letters in a row, or letter at end, so return failure
return;
}
unsigned int stepIndex = encoding.mid( indexStart, i-indexStart ).toUInt();
addStep( stepIndex, stepType );
}
//return result;
}
unsigned int LobAddress::stepIndex ( unsigned int i ) const
{
return stepIndices[i];
}
OmNode::OwnershipType LobAddress::stepType ( unsigned int i ) const
{
return stepTypes[i];
}
unsigned int LobAddress::numSteps () const
{
return stepIndices.count();
}
void LobAddress::addStep ( unsigned int index, OmNode::OwnershipType type )
{
if ( type == OmNode::None )
return;
stepIndices << index;
stepTypes << type;
}
LobAddress LobAddress::up () const
{
LobAddress result = *this;
result.stepIndices.removeLast();
result.stepTypes.removeLast();
return result;
}
LobAddress LobAddress::down () const
{
LobAddress result = *this;
result.stepIndices.removeFirst();
result.stepTypes.removeFirst();
return result;
}
LobAddress LobAddress::operator+ ( const LobAddress& other ) const
{
LobAddress result = *this;
result.stepIndices << other.stepIndices;
result.stepTypes << other.stepTypes;
return result;
}
bool LobAddress::operator< ( const LobAddress& other ) const
{
return strictOrderComparison( other, 0 );
}
bool LobAddress::strictOrderComparison ( const LobAddress& other, unsigned int i ) const
{
// they could be equal, which we will detect recursively by reaching a comparison
// of two empty lists, as this check notices:
if ( ( i >= numSteps() ) && ( i >= other.numSteps() ) )
return false;
// thus if i has fallen off the end of just one list, it is the lesser
if ( i >= numSteps() )
return true;
if ( i >= other.numSteps() )
return false;
// thus step i is in both lists, and we can compare it; we'll need this data:
unsigned int idx = stepIndex( i );
unsigned int oidx = other.stepIndex( i );
OmNode::OwnershipType type = stepType( i );
OmNode::OwnershipType otype = other.stepType( i );
// if both steps are to children, then judge by index, or recursively if indices equal:
if ( ( type == OmNode::AsChild ) && ( otype == OmNode::AsChild ) )
return ( idx == oidx ) ? strictOrderComparison( other, i + 1 ) : ( idx < oidx );
// if one is a child step and the other an attribute step, that determines order:
if ( type == OmNode::AsChild )
return false;
if ( otype == OmNode::AsChild )
return true;
// so both next steps are attributes; try to distinguish by index:
if ( idx != oidx )
return idx < oidx;
// so both next steps are to the same attribute; try to distinguish key from value:
if ( type != otype )
return type == OmNode::AsKey;
// so both are to the same key or value; recur
return strictOrderComparison( other, i + 1 );
}
bool LobAddress::operator== ( const LobAddress& other ) const
{
return ( stepIndices == other.stepIndices ) && ( stepTypes == other.stepTypes );
}
bool LobAddress::operator<= ( const LobAddress& other ) const
{
return ( *this < other ) || ( *this == other );
}
QString LobAddress::toString() const
{
QString result;
for ( int i = 0 ; i < stepIndices.count() ; i++ )
result += ( ( stepTypes[i] == OmNode::AsChild ) ? "c" :
( ( stepTypes[i] == OmNode::AsKey ) ? "k" : "v" ) )
+ QString::number( stepIndices[i] );
return result;
}
bool LobAddress::hasPrefix ( const LobAddress& other ) const{
if (numSteps() < other.numSteps()) return false;
for (unsigned int i = 0; i < other.numSteps(); i++)
if ((other.stepType(i) != stepType(i))
|| (other.stepIndex(i) != stepIndex(i)))
return false;
return true;
}
LobAddress LobAddress::addressInserted ( const LobAddress& loc ) const
{
LobAddress result = *this;
if ( !hasPrefix(loc.up())) return result;
if (numSteps() < loc.numSteps()) return result;
if ( (stepType(loc.numSteps()-1) != loc.stepType(loc.numSteps()-1))
&& (stepType(loc.numSteps()-1 ) != OmNode::AsKey || loc.stepType(loc.numSteps()-1)!= OmNode::AsValue)
&& (stepType(loc.numSteps()-1 ) != OmNode::AsValue || loc.stepType(loc.numSteps()-1)!= OmNode::AsKey))
return result;
if ( stepIndex(loc.numSteps()-1) >= loc.stepIndex(loc.numSteps()-1))
result.stepIndices[loc.numSteps()-1]++;
return result;
}
LobAddress LobAddress::addressRemoved ( const LobAddress& loc ) const
{
LobAddress result = *this;
if ( !hasPrefix(loc.up()) ) return result;
if (numSteps() < loc.numSteps()) return result;
if ( !stepType(loc.numSteps()-1) == loc.stepType(loc.numSteps()-1))
return result;
if ( stepIndex(loc.numSteps()-1) >= loc.stepIndex(loc.numSteps()-1))
result.stepIndices[loc.numSteps()-1]--;
return result;
}
uint qHash ( const LobAddress& key )
{
return qHash( key.toString() );
}