Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
Alchemy Viewer
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Locked files
Deploy
Releases
Package Registry
Operate
Terraform modules
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Silent mode is enabled
All outbound communications are blocked.
Learn more
.
Show more breadcrumbs
Alchemy Viewer
Alchemy Viewer
Commits
a81c084d
Commit
a81c084d
authored
15 years ago
by
Nat Goodspeed
Browse files
Options
Downloads
Patches
Plain Diff
Add llsd_equals(), a function whose absence sorely puzzles me
parent
01d39082
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
indra/llcommon/llsdutil.cpp
+92
-0
92 additions, 0 deletions
indra/llcommon/llsdutil.cpp
indra/llcommon/llsdutil.h
+3
-0
3 additions, 0 deletions
indra/llcommon/llsdutil.h
indra/test/llsdutil_tut.cpp
+56
-2
56 additions, 2 deletions
indra/test/llsdutil_tut.cpp
with
151 additions
and
2 deletions
indra/llcommon/llsdutil.cpp
+
92
−
0
View file @
a81c084d
...
@@ -576,3 +576,95 @@ std::string llsd_matches(const LLSD& prototype, const LLSD& data, const std::str
...
@@ -576,3 +576,95 @@ std::string llsd_matches(const LLSD& prototype, const LLSD& data, const std::str
// bad LLSD doesn't define isConvertible(Type to, Type from).
// bad LLSD doesn't define isConvertible(Type to, Type from).
return
match_types
(
prototype
.
type
(),
TypeVector
(),
data
.
type
(),
pfx
);
return
match_types
(
prototype
.
type
(),
TypeVector
(),
data
.
type
(),
pfx
);
}
}
bool
llsd_equals
(
const
LLSD
&
lhs
,
const
LLSD
&
rhs
)
{
// We're comparing strict equality of LLSD representation rather than
// performing any conversions. So if the types aren't equal, the LLSD
// values aren't equal.
if
(
lhs
.
type
()
!=
rhs
.
type
())
{
return
false
;
}
// Here we know both types are equal. Now compare values.
switch
(
lhs
.
type
())
{
case
LLSD
::
TypeUndefined
:
// Both are TypeUndefined. There's nothing more to know.
return
true
;
#define COMPARE_SCALAR(type) \
case LLSD::Type##type: \
/* LLSD::URI has operator!=() but not operator==() */
\
/* rely on the optimizer for all others */
\
return (! (lhs.as##type() != rhs.as##type()))
COMPARE_SCALAR
(
Boolean
);
COMPARE_SCALAR
(
Integer
);
// The usual caveats about comparing floating-point numbers apply. This is
// only useful when we expect identical bit representation for a given
// Real value, e.g. for integer-valued Reals.
COMPARE_SCALAR
(
Real
);
COMPARE_SCALAR
(
String
);
COMPARE_SCALAR
(
UUID
);
COMPARE_SCALAR
(
Date
);
COMPARE_SCALAR
(
URI
);
COMPARE_SCALAR
(
Binary
);
#undef COMPARE_SCALAR
case
LLSD
::
TypeArray
:
{
LLSD
::
array_const_iterator
lai
(
lhs
.
beginArray
()),
laend
(
lhs
.
endArray
()),
rai
(
rhs
.
beginArray
()),
raend
(
rhs
.
endArray
());
// Compare array elements, walking the two arrays in parallel.
for
(
;
lai
!=
laend
&&
rai
!=
raend
;
++
lai
,
++
rai
)
{
// If any one array element is unequal, the arrays are unequal.
if
(
!
llsd_equals
(
*
lai
,
*
rai
))
return
false
;
}
// Here we've reached the end of one or the other array. They're equal
// only if they're BOTH at end: that is, if they have equal length too.
return
(
lai
==
laend
&&
rai
==
raend
);
}
case
LLSD
::
TypeMap
:
{
// Build a set of all rhs keys.
std
::
set
<
LLSD
::
String
>
rhskeys
;
for
(
LLSD
::
map_const_iterator
rmi
(
rhs
.
beginMap
()),
rmend
(
rhs
.
endMap
());
rmi
!=
rmend
;
++
rmi
)
{
rhskeys
.
insert
(
rmi
->
first
);
}
// Now walk all the lhs keys.
for
(
LLSD
::
map_const_iterator
lmi
(
lhs
.
beginMap
()),
lmend
(
lhs
.
endMap
());
lmi
!=
lmend
;
++
lmi
)
{
// Try to erase this lhs key from the set of rhs keys. If rhs has
// no such key, the maps are unequal. erase(key) returns count of
// items erased.
if
(
rhskeys
.
erase
(
lmi
->
first
)
!=
1
)
return
false
;
// Both maps have the current key. Compare values.
if
(
!
llsd_equals
(
lmi
->
second
,
rhs
[
lmi
->
first
]))
return
false
;
}
// We've now established that all the lhs keys have equal values in
// both maps. The maps are equal unless rhs contains a superset of
// those keys.
return
rhskeys
.
empty
();
}
default
:
// We expect that every possible type() value is specifically handled
// above. Failing to extend this switch to support a new LLSD type is
// an error that must be brought to the coder's attention.
LL_ERRS
(
"llsd_equals"
)
<<
"llsd_equals("
<<
lhs
<<
", "
<<
rhs
<<
"): "
"unknown type "
<<
lhs
.
type
()
<<
LL_ENDL
;
return
false
;
// pacify the compiler
}
}
This diff is collapsed.
Click to expand it.
indra/llcommon/llsdutil.h
+
3
−
0
View file @
a81c084d
...
@@ -129,6 +129,9 @@ LL_COMMON_API BOOL compare_llsd_with_template(
...
@@ -129,6 +129,9 @@ LL_COMMON_API BOOL compare_llsd_with_template(
*/
*/
LL_COMMON_API
std
::
string
llsd_matches
(
const
LLSD
&
prototype
,
const
LLSD
&
data
,
const
std
::
string
&
pfx
=
""
);
LL_COMMON_API
std
::
string
llsd_matches
(
const
LLSD
&
prototype
,
const
LLSD
&
data
,
const
std
::
string
&
pfx
=
""
);
/// Deep equality
bool
llsd_equals
(
const
LLSD
&
lhs
,
const
LLSD
&
rhs
);
// Simple function to copy data out of input & output iterators if
// Simple function to copy data out of input & output iterators if
// there is no need for casting.
// there is no need for casting.
template
<
typename
Input
>
LLSD
llsd_copy_array
(
Input
iter
,
Input
end
)
template
<
typename
Input
>
LLSD
llsd_copy_array
(
Input
iter
,
Input
end
)
...
...
This diff is collapsed.
Click to expand it.
indra/test/llsdutil_tut.cpp
+
56
−
2
View file @
a81c084d
...
@@ -45,6 +45,7 @@
...
@@ -45,6 +45,7 @@
#include
"llquaternion.h"
#include
"llquaternion.h"
#include
"llsdutil.h"
#include
"llsdutil.h"
#include
"llsdutil_math.h"
#include
"llsdutil_math.h"
#include
"stringize.h"
#include
<set>
#include
<set>
#include
<boost/range.hpp>
#include
<boost/range.hpp>
...
@@ -207,14 +208,16 @@ namespace tut
...
@@ -207,14 +208,16 @@ namespace tut
map
.
insert
(
"URI"
,
LLSD
::
URI
());
map
.
insert
(
"URI"
,
LLSD
::
URI
());
map
.
insert
(
"Binary"
,
LLSD
::
Binary
());
map
.
insert
(
"Binary"
,
LLSD
::
Binary
());
map
.
insert
(
"Map"
,
LLSD
().
insert
(
"foo"
,
LLSD
()));
map
.
insert
(
"Map"
,
LLSD
().
insert
(
"foo"
,
LLSD
()));
// array can
't
be constructed on the fly
//
Only an empty
array can be constructed on the fly
LLSD
array
;
LLSD
array
;
array
.
append
(
LLSD
());
array
.
append
(
LLSD
());
map
.
insert
(
"Array"
,
array
);
map
.
insert
(
"Array"
,
array
);
// These iterators are declared outside our various for loops to avoid
// These iterators are declared outside our various for loops to avoid
// fatal MSVC warning: "I used to be broken, but I'm all better now!"
// fatal MSVC warning: "I used to be broken, but I'm all better now!"
LLSD
::
map_const_iterator
mi
(
map
.
beginMap
()),
mend
(
map
.
endMap
());
LLSD
::
map_const_iterator
mi
,
mend
(
map
.
endMap
());
/*-------------------------- llsd_matches --------------------------*/
// empty prototype matches anything
// empty prototype matches anything
for
(
mi
=
map
.
beginMap
();
mi
!=
mend
;
++
mi
)
for
(
mi
=
map
.
beginMap
();
mi
!=
mend
;
++
mi
)
...
@@ -337,5 +340,56 @@ namespace tut
...
@@ -337,5 +340,56 @@ namespace tut
static
const
char
*
matches
[]
=
{
"Binary"
};
static
const
char
*
matches
[]
=
{
"Binary"
};
test_matches
(
"Binary"
,
map
,
boost
::
begin
(
matches
),
boost
::
end
(
matches
));
test_matches
(
"Binary"
,
map
,
boost
::
begin
(
matches
),
boost
::
end
(
matches
));
}
}
/*-------------------------- llsd_equals ---------------------------*/
// Cross-product of each LLSD type with every other
for
(
LLSD
::
map_const_iterator
lmi
(
map
.
beginMap
()),
lmend
(
map
.
endMap
());
lmi
!=
lmend
;
++
lmi
)
{
for
(
LLSD
::
map_const_iterator
rmi
(
map
.
beginMap
()),
rmend
(
map
.
endMap
());
rmi
!=
rmend
;
++
rmi
)
{
// Name this test based on the map keys naming the types of
// interest, e.g "String::Integer".
// We expect the values (xmi->second) to be equal if and only
// if the type names (xmi->first) are equal.
ensure
(
STRINGIZE
(
lmi
->
first
<<
"::"
<<
rmi
->
first
),
bool
(
lmi
->
first
==
rmi
->
first
)
==
bool
(
llsd_equals
(
lmi
->
second
,
rmi
->
second
)));
}
}
// Array cases
LLSD
rarray
;
rarray
.
append
(
1.0
);
rarray
.
append
(
2
);
rarray
.
append
(
"3"
);
LLSD
larray
(
rarray
);
ensure
(
"llsd_equals(equal arrays)"
,
llsd_equals
(
larray
,
rarray
));
rarray
[
2
]
=
"4"
;
ensure
(
"llsd_equals(different [2])"
,
!
llsd_equals
(
larray
,
rarray
));
rarray
=
larray
;
rarray
.
append
(
LLSD
::
Date
());
ensure
(
"llsd_equals(longer right array)"
,
!
llsd_equals
(
larray
,
rarray
));
rarray
=
larray
;
rarray
.
erase
(
2
);
ensure
(
"llsd_equals(shorter right array)"
,
!
llsd_equals
(
larray
,
rarray
));
// Map cases
LLSD
rmap
;
rmap
[
"San Francisco"
]
=
65
;
rmap
[
"Phoenix"
]
=
92
;
rmap
[
"Boston"
]
=
77
;
LLSD
lmap
(
rmap
);
ensure
(
"llsd_equals(equal maps)"
,
llsd_equals
(
lmap
,
rmap
));
rmap
[
"Boston"
]
=
80
;
ensure
(
"llsd_equals(different [
\"
Boston
\"
])"
,
!
llsd_equals
(
lmap
,
rmap
));
rmap
=
lmap
;
rmap
[
"Atlanta"
]
=
95
;
ensure
(
"llsd_equals(superset right map)"
,
!
llsd_equals
(
lmap
,
rmap
));
rmap
=
lmap
;
lmap
[
"Seattle"
]
=
72
;
ensure
(
"llsd_equals(superset left map)"
,
!
llsd_equals
(
lmap
,
rmap
));
}
}
}
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment