1212
1313static ErlNifResourceType * connection_type = NULL ;
1414static ErlNifResourceType * statement_type = NULL ;
15+ static sqlite3_mem_methods default_alloc_methods = {0 };
1516
1617typedef struct connection
1718{
@@ -23,6 +24,83 @@ typedef struct statement
2324 sqlite3_stmt * statement ;
2425} statement_t ;
2526
27+ static void *
28+ exqlite_malloc (int bytes )
29+ {
30+ assert (bytes > 0 );
31+
32+ int * p = enif_alloc (bytes + sizeof (int ));
33+ if (p ) {
34+ p [0 ] = bytes ;
35+ p ++ ;
36+ }
37+
38+ return p ;
39+ }
40+
41+ static void
42+ exqlite_free (void * prior )
43+ {
44+ if (!prior ) {
45+ return ;
46+ }
47+
48+ int * p = prior ;
49+
50+ // Shift the pointer back to free the proper block of data
51+ p -- ;
52+
53+ return enif_free (p );
54+ }
55+
56+ static void *
57+ exqlite_realloc (void * prior , int bytes )
58+ {
59+ assert (prior );
60+ assert (bytes > 0 );
61+
62+ int * p = prior ;
63+ p -- ;
64+
65+ p = enif_realloc (p , bytes + sizeof (int ));
66+ if (p ) {
67+ p [0 ] = bytes ;
68+ p ++ ;
69+ }
70+
71+ return p ;
72+ }
73+
74+ static int
75+ exqlite_mem_size (void * prior )
76+ {
77+ if (!prior ) {
78+ return 0 ;
79+ }
80+
81+ int * p = prior ;
82+ p -- ;
83+
84+ return p [0 ];
85+ }
86+
87+ static int
88+ exqlite_mem_round_up (int bytes )
89+ {
90+ return (bytes + 7 ) & ~7 ;
91+ }
92+
93+ static int
94+ exqlite_mem_init (void * ptr )
95+ {
96+ return SQLITE_OK ;
97+ }
98+
99+ static void
100+ exqlite_mem_shutdown (void * ptr )
101+ {
102+ }
103+
26104static const char *
27105get_sqlite3_error_msg (int rc , sqlite3 * db )
28106{
@@ -496,7 +574,7 @@ exqlite_multi_step(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
496574 return enif_make_tuple2 (env , make_atom (env , "done" ), rows );
497575
498576 case SQLITE_ROW :
499- row = make_row (env , statement -> statement );
577+ row = make_row (env , statement -> statement );
500578 rows = enif_make_list_cell (env , row , rows );
501579 break ;
502580
@@ -533,10 +611,9 @@ exqlite_step(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
533611 switch (rc ) {
534612 case SQLITE_ROW :
535613 return enif_make_tuple2 (
536- env ,
537- make_atom (env , "row" ),
538- make_row (env , statement -> statement )
539- );
614+ env ,
615+ make_atom (env , "row" ),
616+ make_row (env , statement -> statement ));
540617 case SQLITE_BUSY :
541618 return make_atom (env , "busy" );
542619 case SQLITE_DONE :
@@ -651,8 +728,8 @@ exqlite_serialize(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
651728
652729 connection_t * conn = NULL ;
653730 ErlNifBinary database_name ;
654- ERL_NIF_TERM eos = enif_make_int (env , 0 );
655- unsigned char * buffer = NULL ;
731+ ERL_NIF_TERM eos = enif_make_int (env , 0 );
732+ unsigned char * buffer = NULL ;
656733 sqlite3_int64 buffer_size = 0 ;
657734 ERL_NIF_TERM serialized ;
658735
@@ -668,7 +745,7 @@ exqlite_serialize(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
668745 return make_error_tuple (env , "database_name_not_iolist" );
669746 }
670747
671- buffer = sqlite3_serialize (conn -> db , (char * ) database_name .data , & buffer_size , 0 );
748+ buffer = sqlite3_serialize (conn -> db , (char * )database_name .data , & buffer_size , 0 );
672749 if (!buffer ) {
673750 return make_error_tuple (env , "serialization_failed" );
674751 }
@@ -684,13 +761,13 @@ exqlite_deserialize(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
684761{
685762 assert (env );
686763
687- connection_t * conn = NULL ;
764+ connection_t * conn = NULL ;
688765 unsigned char * buffer = NULL ;
689766 ErlNifBinary database_name ;
690767 ERL_NIF_TERM eos = enif_make_int (env , 0 );
691768 ErlNifBinary serialized ;
692- int size = 0 ;
693- int rc = 0 ;
769+ int size = 0 ;
770+ int rc = 0 ;
694771 int flags = SQLITE_DESERIALIZE_FREEONCLOSE | SQLITE_DESERIALIZE_RESIZEABLE ;
695772
696773 if (argc != 3 ) {
@@ -709,7 +786,7 @@ exqlite_deserialize(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
709786 return enif_make_badarg (env );
710787 }
711788
712- size = serialized .size ;
789+ size = serialized .size ;
713790 buffer = sqlite3_malloc (size );
714791 if (!buffer ) {
715792 return make_error_tuple (env , "deserialization_failed" );
@@ -785,6 +862,19 @@ on_load(ErlNifEnv* env, void** priv, ERL_NIF_TERM info)
785862{
786863 assert (env );
787864
865+ static const sqlite3_mem_methods methods = {
866+ exqlite_malloc ,
867+ exqlite_free ,
868+ exqlite_realloc ,
869+ exqlite_mem_size ,
870+ exqlite_mem_round_up ,
871+ exqlite_mem_init ,
872+ exqlite_mem_shutdown ,
873+ 0 };
874+
875+ sqlite3_config (SQLITE_CONFIG_GETMALLOC , & default_alloc_methods );
876+ sqlite3_config (SQLITE_CONFIG_MALLOC , & methods );
877+
788878 connection_type = enif_open_resource_type (
789879 env ,
790880 "exqlite" ,
@@ -810,6 +900,13 @@ on_load(ErlNifEnv* env, void** priv, ERL_NIF_TERM info)
810900 return 0 ;
811901}
812902
903+ static void
904+ on_unload (ErlNifEnv * caller_env , void * priv_data )
905+ {
906+ assert (caller_env );
907+
908+ sqlite3_config (SQLITE_CONFIG_MALLOC , & default_alloc_methods );
909+ }
813910
814911//
815912// Enable extension loading
@@ -870,4 +967,4 @@ static ErlNifFunc nif_funcs[] = {
870967#define ERL_NIF_INIT_DECL (MODNAME ) ErlNifEntry* sqlite3_nif_nif_init(ERL_NIF_INIT_ARGS)
871968#endif
872969
873- ERL_NIF_INIT (Elixir .Exqlite .Sqlite3NIF , nif_funcs , on_load , NULL , NULL , NULL )
970+ ERL_NIF_INIT (Elixir .Exqlite .Sqlite3NIF , nif_funcs , on_load , NULL , NULL , on_unload )
0 commit comments