Fix ::save_all/::load_all so that they check the correct criteria for opt-out. Now load/save_all work.

Fix prototype for AP_Var_group::serialize so that it's called correctly when saving a group.  Now group load/save works.

Add load/save_all and group load/save unit tests.

git-svn-id: https://arducopter.googlecode.com/svn/trunk@1533 f9c3cf11-9bcb-44bc-f272-b75c42450872
This commit is contained in:
DrZiplok@gmail.com 2011-01-23 09:27:58 +00:00
parent 3adec05593
commit 82fdeb11bb
3 changed files with 71 additions and 24 deletions

View File

@ -204,17 +204,17 @@ bool AP_Var::load(void)
bool AP_Var::save_all(void) bool AP_Var::save_all(void)
{ {
bool result = true; bool result = true;
AP_Var *p = _variables; AP_Var *vp = _variables;
while (p) { while (vp) {
if (!p->has_flags(k_flag_no_auto_load) && // not opted out if (!vp->has_flags(k_flag_no_auto_load) && // not opted out of autosave
!(p->_group)) { // not saved with a group (vp->_key != k_key_none)) { // has a key
if (!p->save()) { if (!vp->save()) {
result = false; result = false;
} }
} }
p = p->_link; vp = vp->_link;
} }
return result; return result;
} }
@ -223,18 +223,18 @@ bool AP_Var::save_all(void)
// //
bool AP_Var::load_all(void) bool AP_Var::load_all(void)
{ {
bool result; bool result = true;
AP_Var *p = _variables; AP_Var *vp = _variables;
while (p) { while (vp) {
if (!p->has_flags(k_flag_no_auto_load) && // not opted out if (!vp->has_flags(k_flag_no_auto_load) && // not opted out of autoload
!(p->_group)) { // not loaded with a group (vp->_key != k_key_none)) { // has a key
if (!p->load()) { if (!vp->load()) {
result = false; result = false;
} }
} }
p = p->_link; vp = vp->_link;
} }
return result; return result;
} }
@ -321,7 +321,9 @@ AP_Var::first_member(AP_Var_group *group)
vp = &_grouped_variables; vp = &_grouped_variables;
log("seeking %p", group);
while (*vp) { while (*vp) {
log("consider %p with %p", *vp, (*vp)->_group);
if ((*vp)->_group == group) { if ((*vp)->_group == group) {
return *vp; return *vp;
} }
@ -412,7 +414,7 @@ bool AP_Var::_EEPROM_scan(void)
vp = vp->_link; vp = vp->_link;
} }
if (!vp) { if (!vp) {
log("key %u not claimed", var_header.key); log("key %u not claimed (already scanned or unknown)", var_header.key);
} }
// move to the next variable header // move to the next variable header
@ -460,13 +462,13 @@ bool AP_Var::_EEPROM_locate(bool allocate)
if (!(_key & k_key_not_located)) { if (!(_key & k_key_not_located)) {
return true; // it has return true; // it has
} }
// If not located and not permitted to allocate, we have failed. // If not located and not permitted to allocate, we have failed.
// //
if (!allocate) { if (!allocate) {
log("not found, cannot allocate"); log("cannot allocate");
return false; return false;
} }
log("needs allocation");
// Ask the serializer for the size of the thing we are allocating, and fail // Ask the serializer for the size of the thing we are allocating, and fail
// if it is too large or if it has no size, as we will not be able to allocate // if it is too large or if it has no size, as we will not be able to allocate
@ -530,9 +532,12 @@ bool AP_Var::_EEPROM_locate(bool allocate)
} }
size_t size_t
AP_Var_group::serialize(void *buf, size_t buf_size) AP_Var_group::serialize(void *buf, size_t buf_size) const
{ {
return _serialize_unserialize(buf, buf_size, true); // We have to cast away the const in order to call _serialize_unserialize,
// as it cannot be const due to changing this when called to unserialize.
//
return const_cast<AP_Var_group *>(this)->_serialize_unserialize(buf, buf_size, true);
} }
size_t size_t
@ -551,6 +556,7 @@ AP_Var_group::_serialize_unserialize(void *buf, size_t buf_size, bool do_seriali
// Traverse the list of group members, serializing each in order // Traverse the list of group members, serializing each in order
// //
vp = first_member(this); vp = first_member(this);
log("starting with %p", vp);
bp = (uint8_t *)buf; bp = (uint8_t *)buf;
resid = buf_size; resid = buf_size;
total_size = 0; total_size = 0;
@ -559,8 +565,10 @@ AP_Var_group::_serialize_unserialize(void *buf, size_t buf_size, bool do_seriali
// (un)serialise the group member // (un)serialise the group member
if (do_serialize) { if (do_serialize) {
size = vp->serialize(bp, buf_size); size = vp->serialize(bp, buf_size);
log("serialize %p -> %u", vp, size);
} else { } else {
size = vp->unserialize(bp, buf_size); size = vp->unserialize(bp, buf_size);
log("unserialize %p -> %u", vp, size);
} }
// Account for the space that this variable consumes in the buffer // Account for the space that this variable consumes in the buffer
@ -574,6 +582,7 @@ AP_Var_group::_serialize_unserialize(void *buf, size_t buf_size, bool do_seriali
// and the calling function will have to treat it as an error. // and the calling function will have to treat it as an error.
// //
total_size += size; total_size += size;
log("used %u", total_size);
if (size <= resid) { if (size <= resid) {
// there was space for this one, account for it // there was space for this one, account for it
resid -= size; resid -= size;
@ -584,4 +593,3 @@ AP_Var_group::_serialize_unserialize(void *buf, size_t buf_size, bool do_seriali
} }
return total_size; return total_size;
} }

View File

@ -301,7 +301,7 @@ public:
/// Returns the next variable that is a member of the same group. /// Returns the next variable that is a member of the same group.
/// ///
/// This does not behave correctly if called on a variable that is not a group member. /// This will not behave correctly if called on a variable that is not a group member.
/// ///
/// @param group The group whose member(s) are sought. /// @param group The group whose member(s) are sought.
/// @return The next variable in the group, or NULL if there are none. /// @return The next variable in the group, or NULL if there are none.
@ -310,7 +310,8 @@ public:
/// Returns the storage key for a variable. /// Returns the storage key for a variable.
/// ///
/// Note that group members do not have storage keys - the key is held by the group. /// Note that group members do not have storage keys - the key is held by the group
/// and instead the key indicates the variable's ordering within the group.
/// ///
/// @return The variable's key, or k_key_none if it does not have a key. /// @return The variable's key, or k_key_none if it does not have a key.
/// ///
@ -390,7 +391,7 @@ public:
/// have overflowed the buffer. If the value is less than or /// have overflowed the buffer. If the value is less than or
/// equal to buf_size, serialization was successful. /// equal to buf_size, serialization was successful.
/// ///
virtual size_t serialize(void *buf, size_t buf_size); virtual size_t serialize(void *buf, size_t buf_size) const;
/// Unserialize the group. /// Unserialize the group.
/// ///
@ -416,7 +417,6 @@ private:
/// operating on the data. If the value is less than or equal /// operating on the data. If the value is less than or equal
/// to buf_size, the operation was successful. /// to buf_size, the operation was successful.
/// ///
size_t _serialize_unserialize(void *buf, size_t buf_size, bool do_serialize); size_t _serialize_unserialize(void *buf, size_t buf_size, bool do_serialize);
}; };

View File

@ -291,14 +291,53 @@ setup(void)
// AP_Var: reload // AP_Var: reload
{ {
TEST(reload); TEST(var_reload);
AP_Float f1(0, 1); AP_Float f1(0, 1);
REQUIRE(true == f1.load()); REQUIRE(true == f1.load());
REQUIRE(f1 == 10.0); REQUIRE(f1 == 10.0);
AP_Var::erase_all();
} }
// AP_Var: save/load all
{
TEST(var_save_load_all);
AP_Float f1(10.0, 1);
AP_Float f2(123.0, 2);
REQUIRE(true == AP_Var::save_all());
f1 = 0;
f2 = 0;
REQUIRE(true == AP_Var::load_all());
REQUIRE(f1 == 10.0);
REQUIRE(f2 == 123.0);
AP_Var::erase_all();
}
// AP_Var: group load/save
{
TEST(var_group_save_load);
AP_Var_group group(10);
AP_Float f1(&group, 0, 10.0);
AP_Float f2(&group, 0, 123.0);
AP_Float f3(-1.0);
REQUIRE(true == group.save());
f1 = 0;
f2 = 0;
f3 = 0;
REQUIRE(true == group.load());
REQUIRE(f1 == 10.0);
REQUIRE(f2 == 123.0);
REQUIRE(f3 == 0);
AP_Var::erase_all();
}
#if SAVE #if SAVE
// AP_Var: load and save // AP_Var: load and save