summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2019-04-29 09:01:45 +0200
committerGitHub <noreply@github.com>2019-04-29 09:01:45 +0200
commitbc5b19e60406b2b0b7173d866a808313fca2b4ce (patch)
tree78b7ca86d7ec4d10e7ab66558888c3ea2337b27d /src
parentaf95615faa87d3181fb5e8bc140c1aa6a8eda085 (diff)
parent431601f2922c47d5a9e4394589d076da78d6d146 (diff)
downloadlibgit2-bc5b19e60406b2b0b7173d866a808313fca2b4ce.tar.gz
Merge pull request #4561 from pks-t/pks/downcasting
[RFC] util: introduce GIT_DOWNCAST macro
Diffstat (limited to 'src')
-rw-r--r--src/config_file.c4
-rw-r--r--src/iterator.c32
-rw-r--r--src/refdb_fs.c44
-rw-r--r--src/transports/http.c12
-rw-r--r--src/transports/smart.c26
-rw-r--r--src/transports/ssh.c14
-rw-r--r--src/util.h11
7 files changed, 79 insertions, 64 deletions
diff --git a/src/config_file.c b/src/config_file.c
index 7f8dd650e..a36c0aa02 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -227,9 +227,9 @@ static void backend_free(git_config_backend *_backend)
static int config_iterator_new(
git_config_iterator **iter,
- struct git_config_backend* backend)
+ struct git_config_backend *backend)
{
- diskfile_header *bh = (diskfile_header *) backend;
+ diskfile_header *bh = GIT_CONTAINER_OF(backend, diskfile_header, parent);
git_config_entries *entries;
int error;
diff --git a/src/iterator.c b/src/iterator.c
index 0db929211..d00b8aa62 100644
--- a/src/iterator.c
+++ b/src/iterator.c
@@ -1521,7 +1521,7 @@ static void filesystem_iterator_set_current(
static int filesystem_iterator_current(
const git_index_entry **out, git_iterator *i)
{
- filesystem_iterator *iter = (filesystem_iterator *)i;
+ filesystem_iterator *iter = GIT_CONTAINER_OF(i, filesystem_iterator, base);
if (!iterator__has_been_accessed(i))
return iter->base.cb->advance(out, i);
@@ -1568,7 +1568,7 @@ done:
static int filesystem_iterator_advance(
const git_index_entry **out, git_iterator *i)
{
- filesystem_iterator *iter = (filesystem_iterator *)i;
+ filesystem_iterator *iter = GIT_CONTAINER_OF(i, filesystem_iterator, base);
bool is_dir;
int error = 0;
@@ -1627,7 +1627,7 @@ static int filesystem_iterator_advance(
static int filesystem_iterator_advance_into(
const git_index_entry **out, git_iterator *i)
{
- filesystem_iterator *iter = (filesystem_iterator *)i;
+ filesystem_iterator *iter = GIT_CONTAINER_OF(i, filesystem_iterator, base);
filesystem_iterator_frame *frame;
filesystem_iterator_entry *prev_entry;
int error;
@@ -1664,7 +1664,7 @@ static int filesystem_iterator_advance_into(
int git_iterator_current_workdir_path(git_buf **out, git_iterator *i)
{
- filesystem_iterator *iter = (filesystem_iterator *)i;
+ filesystem_iterator *iter = GIT_CONTAINER_OF(i, filesystem_iterator, base);
const git_index_entry *entry;
if (i->type != GIT_ITERATOR_TYPE_FS &&
@@ -1724,15 +1724,19 @@ GIT_INLINE(bool) filesystem_iterator_current_is_ignored(
bool git_iterator_current_is_ignored(git_iterator *i)
{
+ filesystem_iterator *iter = NULL;
+
if (i->type != GIT_ITERATOR_TYPE_WORKDIR)
return false;
- return filesystem_iterator_current_is_ignored((filesystem_iterator *)i);
+ iter = GIT_CONTAINER_OF(i, filesystem_iterator, base);
+
+ return filesystem_iterator_current_is_ignored(iter);
}
bool git_iterator_current_tree_is_ignored(git_iterator *i)
{
- filesystem_iterator *iter = (filesystem_iterator *)i;
+ filesystem_iterator *iter = GIT_CONTAINER_OF(i, filesystem_iterator, base);
filesystem_iterator_frame *frame;
if (i->type != GIT_ITERATOR_TYPE_WORKDIR)
@@ -1747,7 +1751,7 @@ static int filesystem_iterator_advance_over(
git_iterator_status_t *status,
git_iterator *i)
{
- filesystem_iterator *iter = (filesystem_iterator *)i;
+ filesystem_iterator *iter = GIT_CONTAINER_OF(i, filesystem_iterator, base);
filesystem_iterator_frame *current_frame;
filesystem_iterator_entry *current_entry;
const git_index_entry *entry = NULL;
@@ -1866,7 +1870,7 @@ static int filesystem_iterator_init(filesystem_iterator *iter)
static int filesystem_iterator_reset(git_iterator *i)
{
- filesystem_iterator *iter = (filesystem_iterator *)i;
+ filesystem_iterator *iter = GIT_CONTAINER_OF(i, filesystem_iterator, base);
filesystem_iterator_clear(iter);
return filesystem_iterator_init(iter);
@@ -1874,7 +1878,7 @@ static int filesystem_iterator_reset(git_iterator *i)
static void filesystem_iterator_free(git_iterator *i)
{
- filesystem_iterator *iter = (filesystem_iterator *)i;
+ filesystem_iterator *iter = GIT_CONTAINER_OF(i, filesystem_iterator, base);
git__free(iter->root);
git_buf_dispose(&iter->current_path);
git_tree_free(iter->tree);
@@ -2083,7 +2087,7 @@ static int index_iterator_skip_pseudotree(index_iterator *iter)
static int index_iterator_advance(
const git_index_entry **out, git_iterator *i)
{
- index_iterator *iter = (index_iterator *)i;
+ index_iterator *iter = GIT_CONTAINER_OF(i, index_iterator, base);
const git_index_entry *entry = NULL;
bool is_submodule;
int error = 0;
@@ -2156,7 +2160,7 @@ static int index_iterator_advance(
static int index_iterator_advance_into(
const git_index_entry **out, git_iterator *i)
{
- index_iterator *iter = (index_iterator *)i;
+ index_iterator *iter = GIT_CONTAINER_OF(i, index_iterator, base);
if (! S_ISDIR(iter->tree_entry.mode)) {
if (out)
@@ -2174,7 +2178,7 @@ static int index_iterator_advance_over(
git_iterator_status_t *status,
git_iterator *i)
{
- index_iterator *iter = (index_iterator *)i;
+ index_iterator *iter = GIT_CONTAINER_OF(i, index_iterator, base);
const git_index_entry *entry;
int error;
@@ -2203,7 +2207,7 @@ static int index_iterator_init(index_iterator *iter)
static int index_iterator_reset(git_iterator *i)
{
- index_iterator *iter = (index_iterator *)i;
+ index_iterator *iter = GIT_CONTAINER_OF(i, index_iterator, base);
index_iterator_clear(iter);
return index_iterator_init(iter);
@@ -2211,7 +2215,7 @@ static int index_iterator_reset(git_iterator *i)
static void index_iterator_free(git_iterator *i)
{
- index_iterator *iter = (index_iterator *)i;
+ index_iterator *iter = GIT_CONTAINER_OF(i, index_iterator, base);
git_index_snapshot_release(&iter->entries, iter->base.index);
git_buf_dispose(&iter->tree_buf);
diff --git a/src/refdb_fs.c b/src/refdb_fs.c
index 30aa1a895..c8533e69f 100644
--- a/src/refdb_fs.c
+++ b/src/refdb_fs.c
@@ -327,7 +327,7 @@ static int refdb_fs_backend__exists(
git_refdb_backend *_backend,
const char *ref_name)
{
- refdb_fs_backend *backend = (refdb_fs_backend *)_backend;
+ refdb_fs_backend *backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent);
git_buf ref_path = GIT_BUF_INIT;
int error;
@@ -469,7 +469,7 @@ static int refdb_fs_backend__lookup(
git_refdb_backend *_backend,
const char *ref_name)
{
- refdb_fs_backend *backend = (refdb_fs_backend *)_backend;
+ refdb_fs_backend *backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent);
int error;
assert(backend);
@@ -502,7 +502,7 @@ typedef struct {
static void refdb_fs_backend__iterator_free(git_reference_iterator *_iter)
{
- refdb_fs_iter *iter = (refdb_fs_iter *) _iter;
+ refdb_fs_iter *iter = GIT_CONTAINER_OF(_iter, refdb_fs_iter, parent);
git_vector_free(&iter->loose);
git_pool_clear(&iter->pool);
@@ -591,8 +591,8 @@ static int refdb_fs_backend__iterator_next(
git_reference **out, git_reference_iterator *_iter)
{
int error = GIT_ITEROVER;
- refdb_fs_iter *iter = (refdb_fs_iter *)_iter;
- refdb_fs_backend *backend = (refdb_fs_backend *)iter->parent.db->backend;
+ refdb_fs_iter *iter = GIT_CONTAINER_OF(_iter, refdb_fs_iter, parent);
+ refdb_fs_backend *backend = GIT_CONTAINER_OF(iter->parent.db->backend, refdb_fs_backend, parent);
struct packref *ref;
while (iter->loose_pos < iter->loose.length) {
@@ -632,8 +632,8 @@ static int refdb_fs_backend__iterator_next_name(
const char **out, git_reference_iterator *_iter)
{
int error = GIT_ITEROVER;
- refdb_fs_iter *iter = (refdb_fs_iter *)_iter;
- refdb_fs_backend *backend = (refdb_fs_backend *)iter->parent.db->backend;
+ refdb_fs_iter *iter = GIT_CONTAINER_OF(_iter, refdb_fs_iter, parent);
+ refdb_fs_backend *backend = GIT_CONTAINER_OF(iter->parent.db->backend, refdb_fs_backend, parent);
struct packref *ref;
while (iter->loose_pos < iter->loose.length) {
@@ -674,7 +674,7 @@ static int refdb_fs_backend__iterator_next_name(
static int refdb_fs_backend__iterator(
git_reference_iterator **out, git_refdb_backend *_backend, const char *glob)
{
- refdb_fs_backend *backend = (refdb_fs_backend *)_backend;
+ refdb_fs_backend *backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent);
refdb_fs_iter *iter = NULL;
int error;
@@ -838,7 +838,7 @@ static int refdb_fs_backend__lock(void **out, git_refdb_backend *_backend, const
{
int error;
git_filebuf *lock;
- refdb_fs_backend *backend = (refdb_fs_backend *) _backend;
+ refdb_fs_backend *backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent);
lock = git__calloc(1, sizeof(git_filebuf));
GIT_ERROR_CHECK_ALLOC(lock);
@@ -1248,7 +1248,7 @@ static int refdb_fs_backend__write(
const git_oid *old_id,
const char *old_target)
{
- refdb_fs_backend *backend = (refdb_fs_backend *)_backend;
+ refdb_fs_backend *backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent);
git_filebuf file = GIT_FILEBUF_INIT;
int error = 0;
@@ -1274,7 +1274,7 @@ static int refdb_fs_backend__write_tail(
const git_oid *old_id,
const char *old_target)
{
- refdb_fs_backend *backend = (refdb_fs_backend *)_backend;
+ refdb_fs_backend *backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent);
int error = 0, cmp = 0, should_write;
const char *new_target = NULL;
const git_oid *new_id = NULL;
@@ -1364,7 +1364,7 @@ static int refdb_fs_backend__delete(
const char *ref_name,
const git_oid *old_id, const char *old_target)
{
- refdb_fs_backend *backend = (refdb_fs_backend *)_backend;
+ refdb_fs_backend *backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent);
git_filebuf file = GIT_FILEBUF_INIT;
int error = 0;
@@ -1387,7 +1387,7 @@ static int refdb_fs_backend__delete_tail(
const char *ref_name,
const git_oid *old_id, const char *old_target)
{
- refdb_fs_backend *backend = (refdb_fs_backend *)_backend;
+ refdb_fs_backend *backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent);
git_buf loose_path = GIT_BUF_INIT;
size_t pack_pos;
int error = 0, cmp = 0;
@@ -1455,7 +1455,7 @@ static int refdb_fs_backend__rename(
const git_signature *who,
const char *message)
{
- refdb_fs_backend *backend = (refdb_fs_backend *)_backend;
+ refdb_fs_backend *backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent);
git_reference *old, *new;
git_filebuf file = GIT_FILEBUF_INIT;
int error;
@@ -1511,7 +1511,7 @@ static int refdb_fs_backend__rename(
static int refdb_fs_backend__compress(git_refdb_backend *_backend)
{
int error;
- refdb_fs_backend *backend = (refdb_fs_backend *)_backend;
+ refdb_fs_backend *backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent);
assert(backend);
@@ -1525,7 +1525,7 @@ static int refdb_fs_backend__compress(git_refdb_backend *_backend)
static void refdb_fs_backend__free(git_refdb_backend *_backend)
{
- refdb_fs_backend *backend = (refdb_fs_backend *)_backend;
+ refdb_fs_backend *backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent);
assert(backend);
@@ -1703,7 +1703,7 @@ static int refdb_reflog_fs__ensure_log(git_refdb_backend *_backend, const char *
assert(_backend && name);
- backend = (refdb_fs_backend *) _backend;
+ backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent);
repo = backend->repo;
if ((error = retrieve_reflog_path(&path, repo, name)) < 0)
@@ -1736,7 +1736,7 @@ static int refdb_reflog_fs__has_log(git_refdb_backend *_backend, const char *nam
assert(_backend && name);
- backend = (refdb_fs_backend *) _backend;
+ backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent);
return has_reflog(backend->repo, name);
}
@@ -1752,7 +1752,7 @@ static int refdb_reflog_fs__read(git_reflog **out, git_refdb_backend *_backend,
assert(out && _backend && name);
- backend = (refdb_fs_backend *) _backend;
+ backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent);
repo = backend->repo;
if (reflog_alloc(&log, name) < 0)
@@ -1862,7 +1862,7 @@ static int refdb_reflog_fs__write(git_refdb_backend *_backend, git_reflog *reflo
assert(_backend && reflog);
- backend = (refdb_fs_backend *) _backend;
+ backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent);
if ((error = lock_reflog(&fbuf, backend, reflog->ref_name)) < 0)
return -1;
@@ -1984,7 +1984,7 @@ static int refdb_reflog_fs__rename(git_refdb_backend *_backend, const char *old_
assert(_backend && old_name && new_name);
- backend = (refdb_fs_backend *) _backend;
+ backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent);
repo = backend->repo;
if ((error = git_reference__normalize_name(
@@ -2055,7 +2055,7 @@ cleanup:
static int refdb_reflog_fs__delete(git_refdb_backend *_backend, const char *name)
{
- refdb_fs_backend *backend = (refdb_fs_backend *) _backend;
+ refdb_fs_backend *backend = GIT_CONTAINER_OF(_backend, refdb_fs_backend, parent);
git_buf path = GIT_BUF_INIT;
int error;
diff --git a/src/transports/http.c b/src/transports/http.c
index 80ba5ba73..9d77e627f 100644
--- a/src/transports/http.c
+++ b/src/transports/http.c
@@ -1144,7 +1144,7 @@ static int http_stream_write_chunked(
const char *buffer,
size_t len)
{
- http_stream *s = (http_stream *)stream;
+ http_stream *s = GIT_CONTAINER_OF(stream, http_stream, parent);
http_subtransport *t = OWNING_SUBTRANSPORT(s);
assert(t->connected);
@@ -1218,7 +1218,7 @@ static int http_stream_write_single(
const char *buffer,
size_t len)
{
- http_stream *s = (http_stream *)stream;
+ http_stream *s = GIT_CONTAINER_OF(stream, http_stream, parent);
http_subtransport *t = OWNING_SUBTRANSPORT(s);
git_buf request = GIT_BUF_INIT;
@@ -1252,7 +1252,7 @@ on_error:
static void http_stream_free(git_smart_subtransport_stream *stream)
{
- http_stream *s = (http_stream *)stream;
+ http_stream *s = GIT_CONTAINER_OF(stream, http_stream, parent);
if (s->chunk_buffer)
git__free(s->chunk_buffer);
@@ -1365,7 +1365,7 @@ static int http_action(
const char *url,
git_smart_service_t action)
{
- http_subtransport *t = (http_subtransport *)subtransport;
+ http_subtransport *t = GIT_CONTAINER_OF(subtransport, http_subtransport, parent);
int ret;
assert(stream);
@@ -1419,7 +1419,7 @@ static void free_auth_contexts(git_vector *contexts)
static int http_close(git_smart_subtransport *subtransport)
{
- http_subtransport *t = (http_subtransport *) subtransport;
+ http_subtransport *t = GIT_CONTAINER_OF(subtransport, http_subtransport, parent);
clear_parser_state(t);
@@ -1459,7 +1459,7 @@ static int http_close(git_smart_subtransport *subtransport)
static void http_free(git_smart_subtransport *subtransport)
{
- http_subtransport *t = (http_subtransport *) subtransport;
+ http_subtransport *t = GIT_CONTAINER_OF(subtransport, http_subtransport, parent);
http_close(subtransport);
diff --git a/src/transports/smart.c b/src/transports/smart.c
index fd7113c7e..7f66ae0dc 100644
--- a/src/transports/smart.c
+++ b/src/transports/smart.c
@@ -63,7 +63,7 @@ static int git_smart__set_callbacks(
git_transport_certificate_check_cb certificate_check_cb,
void *message_cb_payload)
{
- transport_smart *t = (transport_smart *)transport;
+ transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent);
t->progress_cb = progress_cb;
t->error_cb = error_cb;
@@ -128,7 +128,7 @@ static int git_smart__set_custom_headers(
git_transport *transport,
const git_strarray *custom_headers)
{
- transport_smart *t = (transport_smart *)transport;
+ transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent);
size_t i;
if (t->custom_headers.count)
@@ -212,7 +212,7 @@ static int git_smart__connect(
int direction,
int flags)
{
- transport_smart *t = (transport_smart *)transport;
+ transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent);
git_smart_subtransport_stream *stream;
int error;
git_pkt *pkt;
@@ -315,7 +315,7 @@ cleanup:
static int git_smart__ls(const git_remote_head ***out, size_t *size, git_transport *transport)
{
- transport_smart *t = (transport_smart *)transport;
+ transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent);
if (!t->have_refs) {
git_error_set(GIT_ERROR_NET, "the transport has not yet loaded the refs");
@@ -330,7 +330,7 @@ static int git_smart__ls(const git_remote_head ***out, size_t *size, git_transpo
int git_smart__negotiation_step(git_transport *transport, void *data, size_t len)
{
- transport_smart *t = (transport_smart *)transport;
+ transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent);
git_smart_subtransport_stream *stream;
int error;
@@ -387,21 +387,21 @@ int git_smart__get_push_stream(transport_smart *t, git_smart_subtransport_stream
static void git_smart__cancel(git_transport *transport)
{
- transport_smart *t = (transport_smart *)transport;
+ transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent);
git_atomic_set(&t->cancelled, 1);
}
static int git_smart__is_connected(git_transport *transport)
{
- transport_smart *t = (transport_smart *)transport;
+ transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent);
return t->connected;
}
static int git_smart__read_flags(git_transport *transport, int *flags)
{
- transport_smart *t = (transport_smart *)transport;
+ transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent);
*flags = t->flags;
@@ -410,7 +410,7 @@ static int git_smart__read_flags(git_transport *transport, int *flags)
static int git_smart__close(git_transport *transport)
{
- transport_smart *t = (transport_smart *)transport;
+ transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent);
git_vector *common = &t->common;
unsigned int i;
git_pkt *p;
@@ -447,7 +447,7 @@ static int git_smart__close(git_transport *transport)
static void git_smart__free(git_transport *transport)
{
- transport_smart *t = (transport_smart *)transport;
+ transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent);
git_vector *refs = &t->refs;
unsigned int i;
git_pkt *p;
@@ -479,7 +479,7 @@ static int ref_name_cmp(const void *a, const void *b)
int git_transport_smart_certificate_check(git_transport *transport, git_cert *cert, int valid, const char *hostname)
{
- transport_smart *t = (transport_smart *)transport;
+ transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent);
assert(transport && cert && hostname);
@@ -491,7 +491,7 @@ int git_transport_smart_certificate_check(git_transport *transport, git_cert *ce
int git_transport_smart_credentials(git_cred **out, git_transport *transport, const char *user, int methods)
{
- transport_smart *t = (transport_smart *)transport;
+ transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent);
assert(out && transport);
@@ -503,7 +503,7 @@ int git_transport_smart_credentials(git_cred **out, git_transport *transport, co
int git_transport_smart_proxy_options(git_proxy_options *out, git_transport *transport)
{
- transport_smart *t = (transport_smart *) transport;
+ transport_smart *t = GIT_CONTAINER_OF(transport, transport_smart, parent);
return git_proxy_options_dup(out, &t->proxy);
}
diff --git a/src/transports/ssh.c b/src/transports/ssh.c
index 5a6058fb7..9b5d8a528 100644
--- a/src/transports/ssh.c
+++ b/src/transports/ssh.c
@@ -132,7 +132,7 @@ static int ssh_stream_read(
size_t *bytes_read)
{
int rc;
- ssh_stream *s = (ssh_stream *)stream;
+ ssh_stream *s = GIT_CONTAINER_OF(stream, ssh_stream, parent);
*bytes_read = 0;
@@ -170,7 +170,7 @@ static int ssh_stream_write(
const char *buffer,
size_t len)
{
- ssh_stream *s = (ssh_stream *)stream;
+ ssh_stream *s = GIT_CONTAINER_OF(stream, ssh_stream, parent);
size_t off = 0;
ssize_t ret = 0;
@@ -196,7 +196,7 @@ static int ssh_stream_write(
static void ssh_stream_free(git_smart_subtransport_stream *stream)
{
- ssh_stream *s = (ssh_stream *)stream;
+ ssh_stream *s = GIT_CONTAINER_OF(stream, ssh_stream, parent);
ssh_subtransport *t;
if (!stream)
@@ -479,7 +479,7 @@ static int _git_ssh_session_create(
{
int rc = 0;
LIBSSH2_SESSION* s;
- git_socket_stream *socket = (git_socket_stream *) io;
+ git_socket_stream *socket = GIT_CONTAINER_OF(io, git_socket_stream, parent);
assert(session);
@@ -730,7 +730,7 @@ static int _ssh_action(
const char *url,
git_smart_service_t action)
{
- ssh_subtransport *t = (ssh_subtransport *) subtransport;
+ ssh_subtransport *t = GIT_CONTAINER_OF(subtransport, ssh_subtransport, parent);
switch (action) {
case GIT_SERVICE_UPLOADPACK_LS:
@@ -752,7 +752,7 @@ static int _ssh_action(
static int _ssh_close(git_smart_subtransport *subtransport)
{
- ssh_subtransport *t = (ssh_subtransport *) subtransport;
+ ssh_subtransport *t = GIT_CONTAINER_OF(subtransport, ssh_subtransport, parent);
assert(!t->current_stream);
@@ -763,7 +763,7 @@ static int _ssh_close(git_smart_subtransport *subtransport)
static void _ssh_free(git_smart_subtransport *subtransport)
{
- ssh_subtransport *t = (ssh_subtransport *) subtransport;
+ ssh_subtransport *t = GIT_CONTAINER_OF(subtransport, ssh_subtransport, parent);
assert(!t->current_stream);
diff --git a/src/util.h b/src/util.h
index d4fe6eee7..b9ab65273 100644
--- a/src/util.h
+++ b/src/util.h
@@ -30,6 +30,17 @@
# define max(a,b) ((a) > (b) ? (a) : (b))
#endif
+#if defined(__GNUC__)
+# define GIT_CONTAINER_OF(ptr, type, member) \
+ __builtin_choose_expr( \
+ __builtin_offsetof(type, member) == 0 && \
+ __builtin_types_compatible_p(typeof(&((type *) 0)->member), typeof(ptr)), \
+ ((type *) (ptr)), \
+ (void)0)
+#else
+# define GIT_CONTAINER_OF(ptr, type, member) (type *)(ptr)
+#endif
+
#define GIT_DATE_RFC2822_SZ 32
/**