<commit_before>/* bson_decoder.hh
   Decodes bson-fields in a template-friendly way.

   <NAME>
*/

#ifndef MONGOXX_BSON_DECODER_HH
#define MONGOXX_BSON_DECODER_HH

#include "mongo/client/dbclient.h"

namespace mongoxx {

  class bson_error : public std::runtime_error {
  public:
    explicit bson_error(std::string const &message) : runtime_error(message) { }
  };

  
  template <typename T>
  class BSONDecoder;

  template <>
  class BSONDecoder<std::string> {
  public:
    std::string decode(mongo::BSONObj const& obj, std::string const& field_name) {
      if (not obj.hasField(field_name.c_str())) {
	throw bson_error("Field '" + field_name + "' is not in the BSON object.");
      }
      mongo::BSONElement element = obj.getField(field_name);
      if (element.type() != mongo::String) {
	throw bson_error("Field '" + field_name + "' is not of string type.");
      }
      return element.str();
    }
  };

  template <>
  class BSONDecoder<int> {
  public:
    int decode(mongo::BSONObj const& obj, std::string const& field_name) {
      if (not obj.hasField(field_name.c_str())) {
	throw bson_error("Field '" + field_name + "' is not in the BSON object.");
      }
      mongo::BSONElement element = obj.getField(field_name);
      if (element.type() != mongo::NumberInt) {
	throw bson_error("Field '" + field_name + "' is not of int type.");
      }
      return element.Int();
    }
  };

  template <>
  class BSONDecoder<unsigned int> {
  public:
    unsigned int decode(mongo::BSONObj const& obj, std::string const& field_name) {
      if (not obj.hasField(field_name.c_str())) {
	throw bson_error("Field '" + field_name + "' is not in the BSON object.");
      }
      mongo::BSONElement element = obj.getField(field_name);
      if (element.type() != mongo::NumberInt) {
	throw bson_error("Field '" + field_name + "' is not of int type.");
      }
      return element.Int();
    }
  };

  template <>
  class BSONDecoder<long long> {
  public:
    long long decode(mongo::BSONObj const& obj, std::string const& field_name) {
      if (not obj.hasField(field_name.c_str())) {
	throw bson_error("Field '" + field_name + "' is not in the BSON object.");
      }
      mongo::BSONElement element = obj.getField(field_name);
      if (element.type() != mongo::NumberLong) {
	throw bson_error("Field '" + field_name + "' is not of long type.");
      }
      return element.Long();
    }
  };

  template <>
  class BSONDecoder<bool> {
  public:
    bool decode(mongo::BSONObj const& obj, std::string const& field_name) {
      if (not obj.hasField(field_name.c_str())) {
	throw bson_error("Field '" + field_name + "' is not in the BSON object.");
      }
      mongo::BSONElement element = obj.getField(field_name);
      if (element.type() != mongo::Bool) {
	throw bson_error("Field '" + field_name + "' is not of boolean type.");
      }
      return element.Bool();
    }
  };

  template <>
  class BSONDecoder<double> {
  public:
    double decode(mongo::BSONObj const& obj, std::string const& field_name) {
      if (not obj.hasField(field_name.c_str())) {
	throw bson_error("Field '" + field_name + "' is not in the BSON object.");
      }
      mongo::BSONElement element = obj.getField(field_name);
      if (element.type() != mongo::NumberDouble) {
	throw bson_error("Field '" + field_name + "' is not of double type.");
      }
      return element.Double();
    }
  };

};

#endif
<commit_msg>Factor the common code out of the decoder functions.<commit_after>/* bson_decoder.hh
   Decodes bson-fields in a template-friendly way.

   <NAME>
*/

#ifndef MONGOXX_BSON_DECODER_HH
#define MONGOXX_BSON_DECODER_HH

#include "mongo/client/dbclient.h"

namespace mongoxx {

  class bson_error : public std::runtime_error {
  public:
    explicit bson_error(std::string const &message) : runtime_error(message) { }
  };

  
  template <typename T>
  class BSONDecoder;

  template <typename T>
  T _super_decode(mongo::BSONObj const& obj, std::string const& field_name,
		  mongo::BSONType type, std::string const& type_name,
		  T (mongo::BSONElement::*result)() const) {
    if (not obj.hasField(field_name.c_str())) {
      throw bson_error("Field '" + field_name + "' is not in the BSON object.");
    }
    mongo::BSONElement element = obj.getField(field_name);
    if (element.type() != type) {
      throw bson_error("Field '" + field_name + "' is not of " + type_name + " type.");
    }
    return (element.*result)();
  }

  template <>
  class BSONDecoder<std::string> {
  public:
    std::string decode(mongo::BSONObj const& obj, std::string const& field_name) {
      return _super_decode(obj, field_name, mongo::String, "string",
			   &mongo::BSONElement::str);
    }
  };

  template <>
  class BSONDecoder<int> {
  public:
    int decode(mongo::BSONObj const& obj, std::string const& field_name) {
      return _super_decode(obj, field_name, mongo::NumberInt, "int",
			   &mongo::BSONElement::Int);
    }
  };

  template <>
  class BSONDecoder<unsigned int> {
  public:
    unsigned int decode(mongo::BSONObj const& obj, std::string const& field_name) {
      return _super_decode(obj, field_name, mongo::NumberInt, "int",
			   &mongo::BSONElement::Int);
    }
  };

  template <>
  class BSONDecoder<long long> {
  public:
    long long decode(mongo::BSONObj const& obj, std::string const& field_name) {
      return _super_decode(obj, field_name, mongo::NumberLong, "long",
			   &mongo::BSONElement::Long);
    }
  };

  template <>
  class BSONDecoder<bool> {
  public:
    bool decode(mongo::BSONObj const& obj, std::string const& field_name) {
      return _super_decode(obj, field_name, mongo::Bool, "boolean",
			   &mongo::BSONElement::Bool);
    }
  };

  template <>
  class BSONDecoder<double> {
  public:
    double decode(mongo::BSONObj const& obj, std::string const& field_name) {
      return _super_decode(obj, field_name, mongo::NumberDouble, "double",
			   &mongo::BSONElement::Double);
    }
  };

};

#endif

{'fraction_non_alphanumeric': 0.14240241246439939, 'fraction_numerical': 0.0, 'mean_word_length': 3.481981981981982, 'pattern_counts': {'":': 0, '<': 32, '<?xml version=': 0, '>': 32, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7355880', 'n_tokens_mistral': 2068, 'n_tokens_neox': 2009, 'n_words': 464}