diff --git a/c_src/blob.c b/c_src/blob.c new file mode 100644 index 0000000..2d6551b --- /dev/null +++ b/c_src/blob.c @@ -0,0 +1,47 @@ +#include +#include + +#include "geef.h" +#include "object.h" +#include "blob.h" + +ERL_NIF_TERM +geef_blob_size(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{ + geef_object *obj; + const git_blob *blob; + + if (!enif_get_resource(env, argv[0], geef_object_type, (void **) &obj)) + return enif_make_badarg(env); + + blob = (git_blob *)obj->obj; + + return enif_make_uint64(env, git_blob_rawsize(blob)); +} + +ERL_NIF_TERM +geef_blob_content(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{ + geef_object *obj; + const git_blob *blob; + ErlNifBinary bin; + size_t len; + const void *content; + + if (!enif_get_resource(env, argv[0], geef_object_type, (void **) &obj)) + return enif_make_badarg(env); + + blob = (git_blob *)obj->obj; + + len = git_blob_rawsize(blob); + content = git_blob_rawcontent(blob); + if (!content) + return atoms.error; + + if (!enif_alloc_binary(len, &bin)) + return atoms.error; + + memcpy(bin.data, content, len); + + return enif_make_tuple2(env, atoms.ok, enif_make_binary(env, &bin)); +} diff --git a/c_src/blob.h b/c_src/blob.h new file mode 100644 index 0000000..02886fe --- /dev/null +++ b/c_src/blob.h @@ -0,0 +1,9 @@ +#ifndef GEEF_BLOB_H +#define GEEF_BLOB_H + +#include "object.h" + +ERL_NIF_TERM geef_blob_size(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); +ERL_NIF_TERM geef_blob_content(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); + +#endif diff --git a/c_src/geef.c b/c_src/geef.c index f989f32..898ae54 100644 --- a/c_src/geef.c +++ b/c_src/geef.c @@ -5,6 +5,7 @@ #include "object.h" #include "commit.h" #include "tree.h" +#include "blob.h" #include "geef.h" #include #include @@ -102,6 +103,8 @@ static ErlNifFunc geef_funcs[] = {"commit_tree", 1, geef_commit_tree}, {"commit_tree_id", 1, geef_commit_tree_id}, {"tree_bypath", 2, geef_tree_bypath}, + {"blob_size", 1, geef_blob_size}, + {"blob_content", 1, geef_blob_content}, }; ERL_NIF_INIT(geef, geef_funcs, load, NULL, NULL, unload) diff --git a/src/geef.erl b/src/geef.erl index 0d6b1d2..87a15b5 100644 --- a/src/geef.erl +++ b/src/geef.erl @@ -11,7 +11,7 @@ -export([oid_fmt/1, oid_parse/1]). % objects --export([object_lookup/2, object_id/1, commit_tree_id/1, commit_tree/1, tree_bypath/2]). +-export([object_lookup/2, object_id/1, commit_tree_id/1, commit_tree/1, tree_bypath/2, blob_size/1, blob_content/1]). -on_load(load_enif/0). @@ -89,6 +89,14 @@ commit_tree(_Handle) -> tree_bypath(_TreeHandle, _Path) -> nif_error(?LINE). +-spec blob_size(term) -> {ok, integer()} | error. +blob_size(_ObjHandle) -> + nif_error(?LINE). + +-spec blob_content(term) -> {ok, binary()} | error. +blob_content(_ObjHandle) -> + nif_error(?LINE). + nif_error(Line) -> erlang:nif_error({nif_not_loaded,module,?MODULE,line,Line}). diff --git a/src/geef_blob.erl b/src/geef_blob.erl index 3a88e8d..fd8cad3 100644 --- a/src/geef_blob.erl +++ b/src/geef_blob.erl @@ -1,9 +1,12 @@ -module(geef_blob). +-ifdef(TEST). +-include_lib("eunit/include/eunit.hrl"). +-endif. -include("geef_records.hrl"). --export([lookup/2, id/1]). +-export([lookup/2, id/1, size/1, content/1]). -spec lookup(repo(), oid() | iolist()) -> object(). lookup(Repo, Id) -> @@ -13,3 +16,21 @@ lookup(Repo, Id) -> -spec id(object()) -> oid(). id(Obj = #object{type=blob}) -> geef_object:id(Obj). + +size(#object{type=blob, handle=Handle}) -> + geef:blob_size(Handle). + +content(#object{type=blob, handle=Handle}) -> + {ok, Content} = geef:blob_content(Handle), + Content. + + +-ifdef(TEST). + +blob_size_test() -> + {ok, Repo} = geef_repo:open(".."), + Blob = lookup(Repo, "80d5c15a040c93a4f98f4496a05ebf30cdd58650"), + ?assertMatch(889, ?MODULE:size(Blob)), + ?assertMatch(889, erlang:size(content(Blob))). + +-endif.