What's wrong with this sparsehash serialization code?

166 views
Skip to first unread message

Yin Steve

unread,
May 25, 2015, 1:51:51 PM5/25/15
to google-s...@googlegroups.com
I copy some example code from sparse_hash_map page, and run the serialization test there, this one below works well :
#include <map>
#include <sstream>
#include <iostream>
#include <fstream>

#include <boost/serialization/serialization.hpp>
#include <boost/serialization/map.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>

#include <sparsehash/sparse_hash_map>
using google::sparse_hash_map;      // namespace where class lives by default

using namespace std;

struct StringToIntSerializer {
  bool operator()(FILE* fp, const std::pair<const int, std::string>& value) const {
    // Write the key.  We ignore endianness for this example.
    if (fwrite(&value.first, sizeof(value.first), 1, fp) != 1)

      return false;
    // Write the value.
    assert(value.second.length() <= 255);   // we only support writing small strings
    const unsigned char size = value.second.length();
    if (fwrite(&size, 1, 1, fp) != 1)
      return false;
    if (fwrite(value.second.data(), size, 1, fp) != 1)
      return false;
    return true;
  }
  bool operator()(FILE* fp, std::pair<const int, std::string>* value) const {
    // Read the key.  Note the need for const_cast to get around
    // the fact hash_map keys are always const.
    if (fread(const_cast<int*>(&value->first), sizeof(value->first), 1, fp) != 1)
      return false;
    // Read the value.
    unsigned char size;    // all strings are <= 255 chars long
    if (fread(&size, 1, 1, fp) != 1)
      return false;
    char* buf = new char[size];
    if (fread(buf, size, 1, fp) != 1) {
      delete[] buf;
      return false;
    }
    new(&value->second) string(buf, size);
    delete[] buf;
    return true;
  }
};


int main(){
  sparse_hash_map<int, string> mymap;
  mymap[1] = "foo";
  mymap[2] = "boo";
  FILE* fp = fopen("hashtable.data", "w");
  mymap.serialize(StringToIntSerializer(), fp);
  fclose(fp);

  sparse_hash_map<int, string> mymap2;
  FILE* fp_in = fopen("hashtable.data", "r");
  mymap2.unserialize(StringToIntSerializer(), fp_in);
  fclose(fp_in);
  assert(mymap == mymap2);
  cout << mymap2[1] << endl;
}



but when switch the types of key-value pair in sparse_hash_map to <string, int>, it fails(codes is shown below). Is there anything wrong with this code below? really need some help here :)
#include <map>
#include <sstream>
#include <iostream>
#include <fstream>

#include <boost/serialization/serialization.hpp>
#include <boost/serialization/map.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>

#include <sparsehash/sparse_hash_map>
using google::sparse_hash_map;      // namespace where class lives by default

using namespace std;

struct StringToIntSerializer {
  bool operator()(FILE* fp, const std::pair<std::string,const int>& value) const {
    // Write the key.
    assert(value.first.length() <= 255);   // we only support writing small strings
    const unsigned char size = value.first.length();
    if (fwrite(&size, 1, 1, fp) != 1)
      return false;
    if (fwrite(value.first.data(), size, 1, fp) != 1)
      return false;

    // Write the value.  We ignore endianness for this example.
    if (fwrite(&value.second, sizeof(value.second), 1, fp) != 1)
      return false;

    return true;
  }
  bool operator()(FILE* fp, std::pair<std::string, const int>* value) const {
    // Read the key.
    unsigned char size;    // all strings are <= 255 chars long
    if (fread(&size, 1, 1, fp) != 1)
      return false;
    char* buf = new char[size];
    if (fread(buf, size, 1, fp) != 1) {
      delete[] buf;
      return false;
    }
    new(&value->first) string(buf, size);
    delete[] buf;

    // Read the value.  Note the need for const_cast to get around
    // the fact hash_map keys are always const.
    if (fread(const_cast<int*>(&value->second), sizeof(value->second), 1, fp) != 1)
      return false;

    return true;
  }
};


int main(){
  sparse_hash_map<string,int> mymap, mymap2;
  mymap["foo"] = 1;
  mymap["boo"] = 2;
  FILE* fp = fopen("hashtable.data", "w");
  mymap.serialize(StringToIntSerializer(), fp);
  fclose(fp);

  FILE* fp_in = fopen("hashtable.data", "r");
  mymap2.unserialize(StringToIntSerializer(), fp_in);
  fclose(fp_in);
  assert(mymap == mymap2);
  cout << mymap2["foo"] << endl;
}



BTW,the method mymap.serialize works well, it's mymap2.unserialize doesn't work. And the error message is like this:
/usr/local/include/sparsehash/sparsetable:1763:13: error: no matching function for call to object
      of type 'StringToIntSerializer'
      if ( !serializer(fp, &*it) )  return false;

Thanks.

Geoff Pike

unread,
May 25, 2015, 2:14:56 PM5/25/15
to google-s...@googlegroups.com
On Mon, May 25, 2015 at 10:51 AM, Yin Steve <steve...@gmail.com> wrote:
> std::pair<std::string, const int>

I think you need const on the key rather than the value.

Geoff

Yin Steve

unread,
May 25, 2015, 10:30:14 PM5/25/15
to google-s...@googlegroups.com
MANY Thanks!! Geoff. It solves my problem perfectly :)

1971 powerChina

unread,
Jun 2, 2015, 11:06:37 PM6/2/15
to google-s...@googlegroups.com
you can see that example:
https://sourceforge.net/projects/pwwhashmap/files/?source=navbar

在 2015年5月26日星期二 UTC+8上午1:51:51,Yin Steve写道:
Reply all
Reply to author
Forward
0 new messages