diff options
Diffstat (limited to 'subversion/libsvn_fs_fs/id.c')
-rw-r--r-- | subversion/libsvn_fs_fs/id.c | 620 |
1 files changed, 428 insertions, 192 deletions
diff --git a/subversion/libsvn_fs_fs/id.c b/subversion/libsvn_fs_fs/id.c index 1317829..bd505e0 100644 --- a/subversion/libsvn_fs_fs/id.c +++ b/subversion/libsvn_fs_fs/id.c @@ -24,90 +24,311 @@ #include <stdlib.h> #include "id.h" +#include "index.h" + #include "../libsvn_fs/fs-loader.h" #include "private/svn_temp_serializer.h" #include "private/svn_string_private.h" -typedef struct id_private_t { - const char *node_id; - const char *copy_id; - const char *txn_id; - svn_revnum_t rev; - apr_off_t offset; -} id_private_t; +typedef struct fs_fs__id_t +{ + /* API visible part */ + svn_fs_id_t generic_id; + + /* private members */ + struct + { + svn_fs_fs__id_part_t node_id; + svn_fs_fs__id_part_t copy_id; + svn_fs_fs__id_part_t txn_id; + svn_fs_fs__id_part_t rev_item; + } private_id; +} fs_fs__id_t; -/* Accessing ID Pieces. */ -const char * -svn_fs_fs__id_node_id(const svn_fs_id_t *id) +/** Like strtol but with a fixed base of 10, locale independent and limited + * to non-negative values. Overflows are indicated by a FALSE return value + * in which case *RESULT_P will not be modified. + * + * This allows the compiler to generate massively faster code. + * (E.g. Avoiding locale specific processing). ID parsing is one of the + * most CPU consuming parts of FSFS data access. Better be quick. + */ +static svn_boolean_t +locale_independent_strtol(long *result_p, + const char* buffer, + const char** end) +{ + /* We allow positive values only. We use unsigned arithmetics to get + * well-defined overflow behavior. It also happens to allow for a wider + * range of compiler-side optimizations. */ + unsigned long result = 0; + while (1) + { + unsigned long c = (unsigned char)*buffer - (unsigned char)'0'; + unsigned long next; + + /* This implies the NUL check. */ + if (c > 9) + break; + + /* Overflow check. Passing this, NEXT can be no more than ULONG_MAX+9 + * before being truncated to ULONG but it still covers 0 .. ULONG_MAX. + */ + if (result > ULONG_MAX / 10) + return FALSE; + + next = result * 10 + c; + + /* Overflow check. In case of an overflow, NEXT is 0..9. + * In the non-overflow case, RESULT is either >= 10 or RESULT and NEXT + * are both 0. */ + if (next < result) + return FALSE; + + result = next; + ++buffer; + } + + *end = buffer; + if (result > LONG_MAX) + return FALSE; + + *result_p = (long)result; + + return TRUE; +} + +/* Parse the NUL-terminated ID part at DATA and write the result into *PART. + * Return TRUE if no errors were detected. */ +static svn_boolean_t +part_parse(svn_fs_fs__id_part_t *part, + const char *data) { - id_private_t *pvt = id->fsap_data; + const char *end; + + /* special case: ID inside some transaction */ + if (data[0] == '_') + { + part->revision = SVN_INVALID_REVNUM; + part->number = svn__base36toui64(&data, data + 1); + return *data == '\0'; + } + + /* special case: 0 / default ID */ + if (data[0] == '0' && data[1] == '\0') + { + part->revision = 0; + part->number = 0; + return TRUE; + } - return pvt->node_id; + /* read old style / new style ID */ + part->number = svn__base36toui64(&data, data); + if (data[0] != '-') + { + part->revision = 0; + return *data == '\0'; + } + + return locale_independent_strtol(&part->revision, data+1, &end); } +/* Parse the transaction id in DATA and store the result in *TXN_ID. + * Return FALSE if there was some problem. + */ +static svn_boolean_t +txn_id_parse(svn_fs_fs__id_part_t *txn_id, + const char *data) +{ + const char *end; + if (!locale_independent_strtol(&txn_id->revision, data, &end)) + return FALSE; + + data = end; + if (*data != '-') + return FALSE; -const char * -svn_fs_fs__id_copy_id(const svn_fs_id_t *id) + ++data; + txn_id->number = svn__base36toui64(&data, data); + return *data == '\0'; +} + +/* Write the textual representation of *PART into P and return a pointer + * to the first position behind that string. + */ +static char * +unparse_id_part(char *p, + const svn_fs_fs__id_part_t *part) +{ + if (SVN_IS_VALID_REVNUM(part->revision)) + { + /* ordinary old style / new style ID */ + p += svn__ui64tobase36(p, part->number); + if (part->revision > 0) + { + *(p++) = '-'; + p += svn__i64toa(p, part->revision); + } + } + else + { + /* in txn: mark with "_" prefix */ + *(p++) = '_'; + p += svn__ui64tobase36(p, part->number); + } + + *(p++) = '.'; + + return p; +} + + + +/* Operations on ID parts */ + +svn_boolean_t +svn_fs_fs__id_part_is_root(const svn_fs_fs__id_part_t* part) +{ + return part->revision == 0 && part->number == 0; +} + +svn_boolean_t +svn_fs_fs__id_part_eq(const svn_fs_fs__id_part_t *lhs, + const svn_fs_fs__id_part_t *rhs) +{ + return lhs->revision == rhs->revision && lhs->number == rhs->number; +} + +svn_boolean_t +svn_fs_fs__id_txn_used(const svn_fs_fs__id_part_t *txn_id) { - id_private_t *pvt = id->fsap_data; + return SVN_IS_VALID_REVNUM(txn_id->revision) || (txn_id->number != 0); +} - return pvt->copy_id; +void +svn_fs_fs__id_txn_reset(svn_fs_fs__id_part_t *txn_id) +{ + txn_id->revision = SVN_INVALID_REVNUM; + txn_id->number = 0; } +svn_error_t * +svn_fs_fs__id_txn_parse(svn_fs_fs__id_part_t *txn_id, + const char *data) +{ + if (! txn_id_parse(txn_id, data)) + return svn_error_createf(SVN_ERR_FS_MALFORMED_TXN_ID, NULL, + "malformed txn id '%s'", data); + + return SVN_NO_ERROR; +} const char * -svn_fs_fs__id_txn_id(const svn_fs_id_t *id) +svn_fs_fs__id_txn_unparse(const svn_fs_fs__id_part_t *txn_id, + apr_pool_t *pool) { - id_private_t *pvt = id->fsap_data; + char string[2 * SVN_INT64_BUFFER_SIZE + 1]; + char *p = string; - return pvt->txn_id; + p += svn__i64toa(p, txn_id->revision); + *(p++) = '-'; + p += svn__ui64tobase36(p, txn_id->number); + + return apr_pstrmemdup(pool, string, p - string); } + + +/* Accessing ID Pieces. */ -svn_revnum_t -svn_fs_fs__id_rev(const svn_fs_id_t *id) +const svn_fs_fs__id_part_t * +svn_fs_fs__id_node_id(const svn_fs_id_t *fs_id) { - id_private_t *pvt = id->fsap_data; + const fs_fs__id_t *id = (const fs_fs__id_t *)fs_id; - return pvt->rev; + return &id->private_id.node_id; } -apr_off_t -svn_fs_fs__id_offset(const svn_fs_id_t *id) +const svn_fs_fs__id_part_t * +svn_fs_fs__id_copy_id(const svn_fs_id_t *fs_id) { - id_private_t *pvt = id->fsap_data; + const fs_fs__id_t *id = (const fs_fs__id_t *)fs_id; - return pvt->offset; + return &id->private_id.copy_id; } +const svn_fs_fs__id_part_t * +svn_fs_fs__id_txn_id(const svn_fs_id_t *fs_id) +{ + const fs_fs__id_t *id = (const fs_fs__id_t *)fs_id; + + return &id->private_id.txn_id; +} + + +const svn_fs_fs__id_part_t * +svn_fs_fs__id_rev_item(const svn_fs_id_t *fs_id) +{ + const fs_fs__id_t *id = (const fs_fs__id_t *)fs_id; + + return &id->private_id.rev_item; +} + +svn_revnum_t +svn_fs_fs__id_rev(const svn_fs_id_t *fs_id) +{ + const fs_fs__id_t *id = (const fs_fs__id_t *)fs_id; + + return id->private_id.rev_item.revision; +} + +apr_uint64_t +svn_fs_fs__id_item(const svn_fs_id_t *fs_id) +{ + const fs_fs__id_t *id = (const fs_fs__id_t *)fs_id; + + return id->private_id.rev_item.number; +} + +svn_boolean_t +svn_fs_fs__id_is_txn(const svn_fs_id_t *fs_id) +{ + const fs_fs__id_t *id = (const fs_fs__id_t *)fs_id; + + return svn_fs_fs__id_txn_used(&id->private_id.txn_id); +} + svn_string_t * -svn_fs_fs__id_unparse(const svn_fs_id_t *id, +svn_fs_fs__id_unparse(const svn_fs_id_t *fs_id, apr_pool_t *pool) { - id_private_t *pvt = id->fsap_data; + char string[6 * SVN_INT64_BUFFER_SIZE + 10]; + const fs_fs__id_t *id = (const fs_fs__id_t *)fs_id; + + char *p = unparse_id_part(string, &id->private_id.node_id); + p = unparse_id_part(p, &id->private_id.copy_id); - if ((! pvt->txn_id)) + if (svn_fs_fs__id_txn_used(&id->private_id.txn_id)) { - char rev_string[SVN_INT64_BUFFER_SIZE]; - char offset_string[SVN_INT64_BUFFER_SIZE]; - - svn__i64toa(rev_string, pvt->rev); - svn__i64toa(offset_string, pvt->offset); - return svn_string_createf(pool, "%s.%s.r%s/%s", - pvt->node_id, pvt->copy_id, - rev_string, offset_string); + *(p++) = 't'; + p += svn__i64toa(p, id->private_id.txn_id.revision); + *(p++) = '-'; + p += svn__ui64tobase36(p, id->private_id.txn_id.number); } else { - return svn_string_createf(pool, "%s.%s.t%s", - pvt->node_id, pvt->copy_id, - pvt->txn_id); + *(p++) = 'r'; + p += svn__i64toa(p, id->private_id.rev_item.revision); + *(p++) = '/'; + p += svn__i64toa(p, id->private_id.rev_item.number); } + + return svn_string_ncreate(string, p - string, pool); } @@ -117,23 +338,20 @@ svn_boolean_t svn_fs_fs__id_eq(const svn_fs_id_t *a, const svn_fs_id_t *b) { - id_private_t *pvta = a->fsap_data, *pvtb = b->fsap_data; + const fs_fs__id_t *id_a = (const fs_fs__id_t *)a; + const fs_fs__id_t *id_b = (const fs_fs__id_t *)b; if (a == b) return TRUE; - if (strcmp(pvta->node_id, pvtb->node_id) != 0) - return FALSE; - if (strcmp(pvta->copy_id, pvtb->copy_id) != 0) - return FALSE; - if ((pvta->txn_id == NULL) != (pvtb->txn_id == NULL)) - return FALSE; - if (pvta->txn_id && pvtb->txn_id && strcmp(pvta->txn_id, pvtb->txn_id) != 0) - return FALSE; - if (pvta->rev != pvtb->rev) - return FALSE; - if (pvta->offset != pvtb->offset) - return FALSE; - return TRUE; + + return svn_fs_fs__id_part_eq(&id_a->private_id.node_id, + &id_b->private_id.node_id) + && svn_fs_fs__id_part_eq(&id_a->private_id.copy_id, + &id_b->private_id.copy_id) + && svn_fs_fs__id_part_eq(&id_a->private_id.txn_id, + &id_b->private_id.txn_id) + && svn_fs_fs__id_part_eq(&id_a->private_id.rev_item, + &id_b->private_id.rev_item); } @@ -141,30 +359,54 @@ svn_boolean_t svn_fs_fs__id_check_related(const svn_fs_id_t *a, const svn_fs_id_t *b) { - id_private_t *pvta = a->fsap_data, *pvtb = b->fsap_data; + const fs_fs__id_t *id_a = (const fs_fs__id_t *)a; + const fs_fs__id_t *id_b = (const fs_fs__id_t *)b; if (a == b) return TRUE; - /* If both node_ids start with _ and they have differing transaction - IDs, then it is impossible for them to be related. */ - if (pvta->node_id[0] == '_') + + /* If both node_ids have been created within _different_ transactions + (and are still uncommitted), then it is impossible for them to be + related. + + Due to our txn-local temporary IDs, however, they might have been + given the same temporary node ID. We need to detect that case. + */ + if ( id_a->private_id.node_id.revision == SVN_INVALID_REVNUM + && id_b->private_id.node_id.revision == SVN_INVALID_REVNUM) { - if (pvta->txn_id && pvtb->txn_id && - (strcmp(pvta->txn_id, pvtb->txn_id) != 0)) + if (!svn_fs_fs__id_part_eq(&id_a->private_id.txn_id, + &id_b->private_id.txn_id)) return FALSE; + + /* At this point, matching node_ids implies relatedness. */ } - return (strcmp(pvta->node_id, pvtb->node_id) == 0); + return svn_fs_fs__id_part_eq(&id_a->private_id.node_id, + &id_b->private_id.node_id); } -int +svn_fs_node_relation_t svn_fs_fs__id_compare(const svn_fs_id_t *a, const svn_fs_id_t *b) { if (svn_fs_fs__id_eq(a, b)) - return 0; - return (svn_fs_fs__id_check_related(a, b) ? 1 : -1); + return svn_fs_node_unchanged; + return (svn_fs_fs__id_check_related(a, b) ? svn_fs_node_common_ancestor + : svn_fs_node_unrelated); +} + +int +svn_fs_fs__id_part_compare(const svn_fs_fs__id_part_t *a, + const svn_fs_fs__id_part_t *b) +{ + if (a->revision < b->revision) + return -1; + if (a->revision > b->revision) + return 1; + + return a->number < b->number ? -1 : a->number == b->number ? 0 : 1; } @@ -176,87 +418,102 @@ static id_vtable_t id_vtable = { svn_fs_fs__id_compare }; - svn_fs_id_t * -svn_fs_fs__id_txn_create(const char *node_id, - const char *copy_id, - const char *txn_id, - apr_pool_t *pool) +svn_fs_fs__id_txn_create_root(const svn_fs_fs__id_part_t *txn_id, + apr_pool_t *pool) { - svn_fs_id_t *id = apr_palloc(pool, sizeof(*id)); - id_private_t *pvt = apr_palloc(pool, sizeof(*pvt)); + fs_fs__id_t *id = apr_pcalloc(pool, sizeof(*id)); + + /* node ID and copy ID are "0" */ + + id->private_id.txn_id = *txn_id; + id->private_id.rev_item.revision = SVN_INVALID_REVNUM; - pvt->node_id = apr_pstrdup(pool, node_id); - pvt->copy_id = apr_pstrdup(pool, copy_id); - pvt->txn_id = apr_pstrdup(pool, txn_id); - pvt->rev = SVN_INVALID_REVNUM; - pvt->offset = -1; + id->generic_id.vtable = &id_vtable; + id->generic_id.fsap_data = id; - id->vtable = &id_vtable; - id->fsap_data = pvt; - return id; + return (svn_fs_id_t *)id; } +svn_fs_id_t *svn_fs_fs__id_create_root(const svn_revnum_t revision, + apr_pool_t *pool) +{ + fs_fs__id_t *id = apr_pcalloc(pool, sizeof(*id)); + + id->private_id.txn_id.revision = SVN_INVALID_REVNUM; + id->private_id.rev_item.revision = revision; + id->private_id.rev_item.number = SVN_FS_FS__ITEM_INDEX_ROOT_NODE; + + id->generic_id.vtable = &id_vtable; + id->generic_id.fsap_data = id; + + return (svn_fs_id_t *)id; +} svn_fs_id_t * -svn_fs_fs__id_rev_create(const char *node_id, - const char *copy_id, - svn_revnum_t rev, - apr_off_t offset, +svn_fs_fs__id_txn_create(const svn_fs_fs__id_part_t *node_id, + const svn_fs_fs__id_part_t *copy_id, + const svn_fs_fs__id_part_t *txn_id, apr_pool_t *pool) { - svn_fs_id_t *id = apr_palloc(pool, sizeof(*id)); - id_private_t *pvt = apr_palloc(pool, sizeof(*pvt)); + fs_fs__id_t *id = apr_pcalloc(pool, sizeof(*id)); - pvt->node_id = apr_pstrdup(pool, node_id); - pvt->copy_id = apr_pstrdup(pool, copy_id); - pvt->txn_id = NULL; - pvt->rev = rev; - pvt->offset = offset; + id->private_id.node_id = *node_id; + id->private_id.copy_id = *copy_id; + id->private_id.txn_id = *txn_id; + id->private_id.rev_item.revision = SVN_INVALID_REVNUM; - id->vtable = &id_vtable; - id->fsap_data = pvt; - return id; + id->generic_id.vtable = &id_vtable; + id->generic_id.fsap_data = id; + + return (svn_fs_id_t *)id; } svn_fs_id_t * -svn_fs_fs__id_copy(const svn_fs_id_t *id, apr_pool_t *pool) +svn_fs_fs__id_rev_create(const svn_fs_fs__id_part_t *node_id, + const svn_fs_fs__id_part_t *copy_id, + const svn_fs_fs__id_part_t *rev_item, + apr_pool_t *pool) { - svn_fs_id_t *new_id = apr_palloc(pool, sizeof(*new_id)); - id_private_t *new_pvt = apr_palloc(pool, sizeof(*new_pvt)); - id_private_t *pvt = id->fsap_data; + fs_fs__id_t *id = apr_pcalloc(pool, sizeof(*id)); - new_pvt->node_id = apr_pstrdup(pool, pvt->node_id); - new_pvt->copy_id = apr_pstrdup(pool, pvt->copy_id); - new_pvt->txn_id = pvt->txn_id ? apr_pstrdup(pool, pvt->txn_id) : NULL; - new_pvt->rev = pvt->rev; - new_pvt->offset = pvt->offset; + id->private_id.node_id = *node_id; + id->private_id.copy_id = *copy_id; + id->private_id.txn_id.revision = SVN_INVALID_REVNUM; + id->private_id.rev_item = *rev_item; - new_id->vtable = &id_vtable; - new_id->fsap_data = new_pvt; - return new_id; + id->generic_id.vtable = &id_vtable; + id->generic_id.fsap_data = id; + + return (svn_fs_id_t *)id; } svn_fs_id_t * -svn_fs_fs__id_parse(const char *data, - apr_size_t len, - apr_pool_t *pool) +svn_fs_fs__id_copy(const svn_fs_id_t *source, apr_pool_t *pool) { - svn_fs_id_t *id; - id_private_t *pvt; - char *data_copy, *str; + const fs_fs__id_t *id = (const fs_fs__id_t *)source; + fs_fs__id_t *new_id = apr_pmemdup(pool, id, sizeof(*new_id)); + + new_id->generic_id.fsap_data = new_id; + + return (svn_fs_id_t *)new_id; +} - /* Dup the ID data into POOL. Our returned ID will have references - into this memory. */ - data_copy = apr_pstrmemdup(pool, data, len); +/* Return an ID resulting from parsing the string DATA, or NULL if DATA is + an invalid ID string. *DATA will be modified / invalidated by this call. */ +static svn_fs_id_t * +id_parse(char *data, + apr_pool_t *pool) +{ + fs_fs__id_t *id; + char *str; /* Alloc a new svn_fs_id_t structure. */ - id = apr_palloc(pool, sizeof(*id)); - pvt = apr_palloc(pool, sizeof(*pvt)); - id->vtable = &id_vtable; - id->fsap_data = pvt; + id = apr_pcalloc(pool, sizeof(*id)); + id->generic_id.vtable = &id_vtable; + id->generic_id.fsap_data = id; /* Now, we basically just need to "split" this data on `.' characters. We will use svn_cstring_tokenize, which will put @@ -265,141 +522,120 @@ svn_fs_fs__id_parse(const char *data, string.*/ /* Node Id */ - str = svn_cstring_tokenize(".", &data_copy); + str = svn_cstring_tokenize(".", &data); if (str == NULL) return NULL; - pvt->node_id = str; + if (! part_parse(&id->private_id.node_id, str)) + return NULL; /* Copy Id */ - str = svn_cstring_tokenize(".", &data_copy); + str = svn_cstring_tokenize(".", &data); if (str == NULL) return NULL; - pvt->copy_id = str; + if (! part_parse(&id->private_id.copy_id, str)) + return NULL; /* Txn/Rev Id */ - str = svn_cstring_tokenize(".", &data_copy); + str = svn_cstring_tokenize(".", &data); if (str == NULL) return NULL; if (str[0] == 'r') { apr_int64_t val; + const char *tmp; svn_error_t *err; /* This is a revision type ID */ - pvt->txn_id = NULL; + id->private_id.txn_id.revision = SVN_INVALID_REVNUM; + id->private_id.txn_id.number = 0; - data_copy = str + 1; - str = svn_cstring_tokenize("/", &data_copy); + data = str + 1; + str = svn_cstring_tokenize("/", &data); if (str == NULL) return NULL; - pvt->rev = SVN_STR_TO_REV(str); - - str = svn_cstring_tokenize("/", &data_copy); - if (str == NULL) + if (!locale_independent_strtol(&id->private_id.rev_item.revision, + str, &tmp)) return NULL; - err = svn_cstring_atoi64(&val, str); + + err = svn_cstring_atoi64(&val, data); if (err) { svn_error_clear(err); return NULL; } - pvt->offset = (apr_off_t)val; + id->private_id.rev_item.number = (apr_uint64_t)val; } else if (str[0] == 't') { /* This is a transaction type ID */ - pvt->txn_id = str + 1; - pvt->rev = SVN_INVALID_REVNUM; - pvt->offset = -1; + id->private_id.rev_item.revision = SVN_INVALID_REVNUM; + id->private_id.rev_item.number = 0; + + if (! txn_id_parse(&id->private_id.txn_id, str + 1)) + return NULL; } else return NULL; - return id; + return (svn_fs_id_t *)id; } -/* (de-)serialization support */ - -/* Serialization of the PVT sub-structure within the CONTEXT. - */ -static void -serialize_id_private(svn_temp_serializer__context_t *context, - const id_private_t * const *pvt) +svn_error_t * +svn_fs_fs__id_parse(const svn_fs_id_t **id_p, + char *data, + apr_pool_t *pool) { - const id_private_t *private = *pvt; - - /* serialize the pvt data struct itself */ - svn_temp_serializer__push(context, - (const void * const *)pvt, - sizeof(*private)); + svn_fs_id_t *id = id_parse(data, pool); + if (id == NULL) + return svn_error_createf(SVN_ERR_FS_MALFORMED_NODEREV_ID, NULL, + "Malformed node revision ID string"); - /* append the referenced strings */ - svn_temp_serializer__add_string(context, &private->node_id); - svn_temp_serializer__add_string(context, &private->copy_id); - svn_temp_serializer__add_string(context, &private->txn_id); + *id_p = id; - /* return to caller's nesting level */ - svn_temp_serializer__pop(context); + return SVN_NO_ERROR; } +/* (de-)serialization support */ + /* Serialize an ID within the serialization CONTEXT. */ void svn_fs_fs__id_serialize(svn_temp_serializer__context_t *context, - const struct svn_fs_id_t * const *id) + const svn_fs_id_t * const *in) { + const fs_fs__id_t *id = (const fs_fs__id_t *)*in; + /* nothing to do for NULL ids */ - if (*id == NULL) + if (id == NULL) return; /* serialize the id data struct itself */ - svn_temp_serializer__push(context, - (const void * const *)id, - sizeof(**id)); - - /* serialize the id_private_t data sub-struct */ - serialize_id_private(context, - (const id_private_t * const *)&(*id)->fsap_data); - - /* return to caller's nesting level */ - svn_temp_serializer__pop(context); -} - -/* Deserialization of the PVT sub-structure in BUFFER. - */ -static void -deserialize_id_private(void *buffer, id_private_t **pvt) -{ - /* fixup the reference to the only sub-structure */ - id_private_t *private; - svn_temp_deserializer__resolve(buffer, (void**)pvt); - - /* fixup the sub-structure itself */ - private = *pvt; - svn_temp_deserializer__resolve(private, (void**)&private->node_id); - svn_temp_deserializer__resolve(private, (void**)&private->copy_id); - svn_temp_deserializer__resolve(private, (void**)&private->txn_id); + svn_temp_serializer__add_leaf(context, + (const void * const *)in, + sizeof(fs_fs__id_t)); } /* Deserialize an ID inside the BUFFER. */ void -svn_fs_fs__id_deserialize(void *buffer, svn_fs_id_t **id) +svn_fs_fs__id_deserialize(void *buffer, svn_fs_id_t **in_out) { + fs_fs__id_t *id; + /* The id maybe all what is in the whole buffer. * Don't try to fixup the pointer in that case*/ - if (*id != buffer) - svn_temp_deserializer__resolve(buffer, (void**)id); + if (*in_out != buffer) + svn_temp_deserializer__resolve(buffer, (void**)in_out); + + id = (fs_fs__id_t *)*in_out; /* no id, no sub-structure fixup necessary */ - if (*id == NULL) + if (id == NULL) return; /* the stored vtable is bogus at best -> set the right one */ - (*id)->vtable = &id_vtable; - - /* handle sub-structures */ - deserialize_id_private(*id, (id_private_t **)&(*id)->fsap_data); + id->generic_id.vtable = &id_vtable; + id->generic_id.fsap_data = id; } |