diff --git a/apps/gitrekt/c_src/geef.c b/apps/gitrekt/c_src/geef.c index e7dd2076..0273cd8f 100644 --- a/apps/gitrekt/c_src/geef.c +++ b/apps/gitrekt/c_src/geef.c @@ -190,6 +190,7 @@ static ErlNifFunc geef_funcs[] = {"object_repository", 1, geef_object_repository}, {"object_lookup", 2, geef_object_lookup}, {"object_id", 1, geef_object_id}, + {"object_zlib_inflate", 1, geef_object_zlib_inflate}, {"commit_tree", 1, geef_commit_tree}, {"commit_tree_id", 1, geef_commit_tree_id}, {"commit_create", 8, geef_commit_create}, diff --git a/apps/gitrekt/c_src/object.c b/apps/gitrekt/c_src/object.c index 96ddeb5e..451603a8 100644 --- a/apps/gitrekt/c_src/object.c +++ b/apps/gitrekt/c_src/object.c @@ -2,6 +2,7 @@ #include "repository.h" #include "object.h" #include "oid.h" +#include #include #include @@ -113,3 +114,39 @@ geef_object_id(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) return enif_make_tuple2(env, atoms.ok, enif_make_binary(env, &bin)); } + +ERL_NIF_TERM +geef_object_zlib_inflate(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{ + ErlNifBinary bin; + z_stream z; + z.zalloc = Z_NULL; + z.zfree = Z_NULL; + z.opaque = Z_NULL; + + if (!enif_inspect_binary(env, argv[0], &bin)) + return enif_make_badarg(env); + + if (!geef_terminate_binary(&bin)) { + enif_release_binary(&bin); + return geef_oom(env); + } + + char output[bin.size*2]; + + z.avail_in = bin.size; + z.next_in = bin.data; + z.avail_out = bin.size*2; + z.next_out = output; + + inflateInit(&z); + inflate(&z, Z_NO_FLUSH); + inflateEnd(&z); + + if (enif_alloc_binary(z.total_out, &bin) < 0) + return -1; + + memcpy(bin.data, output, z.total_out); + + return enif_make_tuple3(env, atoms.ok, enif_make_binary(env, &bin), enif_make_ulong(env, z.total_in)); +} diff --git a/apps/gitrekt/c_src/object.h b/apps/gitrekt/c_src/object.h index 1c849510..b489be66 100644 --- a/apps/gitrekt/c_src/object.h +++ b/apps/gitrekt/c_src/object.h @@ -15,10 +15,11 @@ typedef struct { ERL_NIF_TERM geef_object_repository(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); ERL_NIF_TERM geef_object_lookup(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); ERL_NIF_TERM geef_object_id(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); +ERL_NIF_TERM geef_object_zlib_inflate(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); ERL_NIF_TERM geef_object_type2atom(const git_otype type); -git_otype geef_object_atom2type(ERL_NIF_TERM term); +git_otype geef_object_atom2type(ERL_NIF_TERM term); void geef_object_free(ErlNifEnv *env, void *cd); #endif diff --git a/apps/gitrekt/lib/gitrekt/git.ex b/apps/gitrekt/lib/gitrekt/git.ex index 015e237e..5f36d063 100644 --- a/apps/gitrekt/lib/gitrekt/git.ex +++ b/apps/gitrekt/lib/gitrekt/git.ex @@ -296,6 +296,14 @@ defmodule GitRekt.Git do raise Code.LoadError, file: @nif_path_lib end + @doc """ + Inflates the given `data` with *zlib*. + """ + @spec object_zlib_inflate(binary) :: {:ok, binary, non_neg_integer} | {:error, term} + def object_zlib_inflate(_data) do + raise Code.LoadError, file: @nif_path_lib + end + @doc """ Returns the tree id for the given `commit`. """