You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

80 lines
2.1 KiB

  1. // This file is part of Jiffy released under the MIT license.
  2. // See the LICENSE file for more information.
  3. #include <set>
  4. #include <string>
  5. #include <assert.h>
  6. #include "erl_nif.h"
  7. #define MAP_TYPE_PRESENT \
  8. ((ERL_NIF_MAJOR_VERSION == 2 && ERL_NIF_MINOR_VERSION >= 6) \
  9. || (ERL_NIF_MAJOR_VERSION > 2))
  10. #define BEGIN_C extern "C" {
  11. #define END_C }
  12. BEGIN_C
  13. int
  14. make_object(ErlNifEnv* env, ERL_NIF_TERM pairs, ERL_NIF_TERM* out,
  15. int ret_map, int dedupe_keys)
  16. {
  17. ERL_NIF_TERM ret;
  18. ERL_NIF_TERM key;
  19. ERL_NIF_TERM val;
  20. std::set<std::string> seen;
  21. #if MAP_TYPE_PRESENT
  22. if(ret_map) {
  23. ret = enif_make_new_map(env);
  24. while(enif_get_list_cell(env, pairs, &val, &pairs)) {
  25. if(!enif_get_list_cell(env, pairs, &key, &pairs)) {
  26. assert(0 == 1 && "Unbalanced object pairs.");
  27. }
  28. ErlNifBinary bin;
  29. if(!enif_inspect_binary(env, key, &bin)) {
  30. return 0;
  31. }
  32. std::string skey((char*) bin.data, bin.size);
  33. if(seen.count(skey) == 0) {
  34. seen.insert(skey);
  35. if(!enif_make_map_put(env, ret, key, val, &ret)) {
  36. return 0;
  37. }
  38. }
  39. }
  40. *out = ret;
  41. return 1;
  42. }
  43. #endif
  44. ret = enif_make_list(env, 0);
  45. while(enif_get_list_cell(env, pairs, &val, &pairs)) {
  46. if(!enif_get_list_cell(env, pairs, &key, &pairs)) {
  47. assert(0 == 1 && "Unbalanced object pairs.");
  48. }
  49. if(dedupe_keys) {
  50. ErlNifBinary bin;
  51. if(!enif_inspect_binary(env, key, &bin)) {
  52. return 0;
  53. }
  54. std::string skey((char*) bin.data, bin.size);
  55. if(seen.count(skey) == 0) {
  56. seen.insert(skey);
  57. val = enif_make_tuple2(env, key, val);
  58. ret = enif_make_list_cell(env, val, ret);
  59. }
  60. } else {
  61. val = enif_make_tuple2(env, key, val);
  62. ret = enif_make_list_cell(env, val, ret);
  63. }
  64. }
  65. *out = enif_make_tuple1(env, ret);
  66. return 1;
  67. }
  68. END_C