FreeBSD/contrib/subversion/subversion/libsvn_fs_x/revprops.c
/* Given FS and the full packed file content in REVPROPS->PACKED_REVPROPS,
 * fill the START_REVISION member, and make PACKED_REVPROPS point to the
 * first serialized revprop.  If READ_ALL is set, initialize the SIZES
 * and OFFSETS members as well.
 *
 * Parse the revprops for REVPROPS->REVISION and set the PROPERTIES as
 * well as the SERIALIZED_SIZE member.  If revprop caching has been
 * enabled, parse all revprops in the pack and cache them.
 */
Given FS and the full packed file content in REVPROPS->PACKED_REVPROPS,
fill the START_REVISION member, and make PACKED_REVPROPS point to the
first serialized revprop.  If READ_ALL is set, initialize the SIZES
and OFFSETS members as well.

Parse the revprops for REVPROPS->REVISION and set the PROPERTIES as
well as the SERIALIZED_SIZE member.  If revprop caching has been
enabled, parse all revprops in the pack and cache them.
Given FS and the full packed file content in REVPROPS - > PACKED_REVPROPS fill the START_REVISION member and make PACKED_REVPROPS point to the first serialized revprop . If READ_ALL is set initialize the SIZES and OFFSETS members as well . Parse the revprops for REVPROPS - > REVISION and set the PROPERTIES as well as the SERIALIZED_SIZE member . If revprop caching has been enabled parse all revprops in the pack and cache them .
static svn_error_t *
parse_packed_revprops(svn_fs_t *fs,
                      packed_revprops_t *revprops,
                      svn_boolean_t read_all,
                      apr_pool_t *result_pool,
                      apr_pool_t *scratch_pool)
{
  svn_stream_t *stream;
  apr_int64_t first_rev, count, i;
  apr_off_t offset;
  const char *header_end;
  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
  svn_boolean_t cache_all = has_revprop_cache(fs, scratch_pool);
  svn_stringbuf_t *compressed = revprops->packed_revprops;
  svn_stringbuf_t *uncompressed = svn_stringbuf_create_empty(result_pool);
  SVN_ERR(svn__decompress(compressed, uncompressed, APR_SIZE_MAX));
  stream = svn_stream_from_stringbuf(uncompressed, scratch_pool);
  SVN_ERR(svn_fs_x__read_number_from_stream(&first_rev, NULL, stream,
                                            iterpool));
  SVN_ERR(svn_fs_x__read_number_from_stream(&count, NULL, stream, iterpool));
  if (   !same_shard(fs, revprops->revision, first_rev)
      || !same_shard(fs, revprops->revision, first_rev + count - 1)
      || count < 1)
    return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
                             _("Revprop pack for revision r%ld"
                               " contains revprops for r%ld .. r%ld"),
                             revprops->revision,
                             (svn_revnum_t)first_rev,
                             (svn_revnum_t)(first_rev + count -1));
  if (!svn_fs_x__is_packed_revprop(fs, first_rev))
    return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
                             _("Revprop pack for revision r%ld"
                               " starts at non-packed revisions r%ld"),
                             revprops->revision, (svn_revnum_t)first_rev);
  header_end = strstr(uncompressed->data, "\n\n");
  if (header_end == NULL)
    return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
                            _("Header end not found"));
  offset = header_end - uncompressed->data + 2;
  revprops->packed_revprops = svn_stringbuf_create_empty(result_pool);
  revprops->packed_revprops->data = uncompressed->data + offset;
  revprops->packed_revprops->len = (apr_size_t)(uncompressed->len - offset);
  revprops->packed_revprops->blocksize = (apr_size_t)(uncompressed->blocksize - offset);
  revprops->start_revision = (svn_revnum_t)first_rev;
  if (read_all)
    {
      revprops->sizes = apr_array_make(result_pool, (int)count,
                                       sizeof(offset));
      revprops->offsets = apr_array_make(result_pool, (int)count,
                                         sizeof(offset));
    }
  for (i = 0, offset = 0, revprops->total_size = 0; i < count; ++i)
    {
      apr_int64_t size;
      svn_string_t serialized;
      svn_revnum_t revision = (svn_revnum_t)(first_rev + i);
      svn_pool_clear(iterpool);
      SVN_ERR(svn_fs_x__read_number_from_stream(&size, NULL, stream,
                                                iterpool));
      if (size + offset > (apr_int64_t)revprops->packed_revprops->len)
        return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
                        _("Packed revprop size exceeds pack file size"));
      serialized.data = revprops->packed_revprops->data + offset;
      serialized.len = (apr_size_t)size;
      if (revision == revprops->revision)
        {
          SVN_ERR(parse_revprop(&revprops->properties, fs, revision,
                                revprops->generation, &serialized,
                                result_pool, iterpool));
          revprops->serialized_size = serialized.len;
          if (!read_all && !cache_all)
            break;
        }
      else if (cache_all)
        {
          apr_hash_t *properties;
          SVN_ERR(parse_revprop(&properties, fs, revision,
                                revprops->generation, &serialized,
                                iterpool, iterpool));
        }
      if (read_all)
        {
          APR_ARRAY_PUSH(revprops->sizes, apr_off_t) = serialized.len;
          APR_ARRAY_PUSH(revprops->offsets, apr_off_t) = offset;
        }
      revprops->total_size += serialized.len;
      offset += serialized.len;
    }
  return SVN_NO_ERROR;
}
static svn_error_t * parse_packed_revprops ( svn_fs_t * fs , packed_revprops_t * revprops , svn_boolean_t read_all , apr_pool_t * result_pool , apr_pool_t * scratch_pool ) { svn_stream_t * stream ; apr_int64_t first_rev , count , i ; apr_off_t offset ; const char * header_end ; apr_pool_t * iterpool = svn_pool_create ( scratch_pool ) ; svn_boolean_t cache_all = has_revprop_cache ( fs , scratch_pool ) ; svn_stringbuf_t * compressed = revprops -> packed_revprops ; svn_stringbuf_t * uncompressed = svn_stringbuf_create_empty ( result_pool ) ; SVN_ERR ( svn__decompress ( compressed , uncompressed , APR_SIZE_MAX ) ) ; stream = svn_stream_from_stringbuf ( uncompressed , scratch_pool ) ; SVN_ERR ( svn_fs_x__read_number_from_stream ( & first_rev , NULL , stream , iterpool ) ) ; SVN_ERR ( svn_fs_x__read_number_from_stream ( & count , NULL , stream , iterpool ) ) ; if ( ! same_shard ( fs , revprops -> revision , first_rev ) || ! same_shard ( fs , revprops -> revision , first_rev + count - 1 ) || count < 1 ) return svn_error_createf ( SVN_ERR_FS_CORRUPT , NULL , _ ( " " " " ) , revprops -> revision , ( svn_revnum_t ) first_rev , ( svn_revnum_t ) ( first_rev + count - 1 ) ) ; if ( ! svn_fs_x__is_packed_revprop ( fs , first_rev ) ) return svn_error_createf ( SVN_ERR_FS_CORRUPT , NULL , _ ( " " " " ) , revprops -> revision , ( svn_revnum_t ) first_rev ) ; header_end = strstr ( uncompressed -> data , " \n \n " ) ; if ( header_end == NULL ) return svn_error_create ( SVN_ERR_FS_CORRUPT , NULL , _ ( " " ) ) ; offset = header_end - uncompressed -> data + 2 ; revprops -> packed_revprops = svn_stringbuf_create_empty ( result_pool ) ; revprops -> packed_revprops -> data = uncompressed -> data + offset ; revprops -> packed_revprops -> len = ( apr_size_t ) ( uncompressed -> len - offset ) ; revprops -> packed_revprops -> blocksize = ( apr_size_t ) ( uncompressed -> blocksize - offset ) ; revprops -> start_revision = ( svn_revnum_t ) first_rev ; if ( read_all ) { revprops -> sizes = apr_array_make ( result_pool , ( int ) count , sizeof ( offset ) ) ; revprops -> offsets = apr_array_make ( result_pool , ( int ) count , sizeof ( offset ) ) ; } for ( i = 0 , offset = 0 , revprops -> total_size = 0 ; i < count ; ++ i ) { apr_int64_t size ; svn_string_t serialized ; svn_revnum_t revision = ( svn_revnum_t ) ( first_rev + i ) ; svn_pool_clear ( iterpool ) ; SVN_ERR ( svn_fs_x__read_number_from_stream ( & size , NULL , stream , iterpool ) ) ; if ( size + offset > ( apr_int64_t ) revprops -> packed_revprops -> len ) return svn_error_create ( SVN_ERR_FS_CORRUPT , NULL , _ ( " " ) ) ; serialized . data = revprops -> packed_revprops -> data + offset ; serialized . len = ( apr_size_t ) size ; if ( revision == revprops -> revision ) { SVN_ERR ( parse_revprop ( & revprops -> properties , fs , revision , revprops -> generation , & serialized , result_pool , iterpool ) ) ; revprops -> serialized_size = serialized . len ; if ( ! read_all && ! cache_all ) break ; } else if ( cache_all ) { apr_hash_t * properties ; SVN_ERR ( parse_revprop ( & properties , fs , revision , revprops -> generation , & serialized , iterpool , iterpool ) ) ; } if ( read_all ) { APR_ARRAY_PUSH ( revprops -> sizes , apr_off_t ) = serialized . len ; APR_ARRAY_PUSH ( revprops -> offsets , apr_off_t ) = offset ; } revprops -> total_size += serialized . len ; offset += serialized . len ; } return SVN_NO_ERROR ; }
Given FS and the full packed file content in REVPROPS->PACKED_REVPROPS,
 fill the START_REVISION member, and make PACKED_REVPROPS point to the
 first serialized revprop.
Given FS and the full packed file content in REVPROPS - > PACKED_REVPROPS fill the START_REVISION member and make PACKED_REVPROPS point to the first serialized revprop .
/* decompress (even if the data is only "stored", there is still a
   * length header to remove) */ /* read first revision number and number of revisions in the pack */ /* Check revision range for validity. */ /* Since start & end are in the same shard, it is enough to just test
   * the FIRST_REV for being actually packed.  That will also cover the
   * special case of rev 0 never being packed. */ /* make PACKED_REVPROPS point to the first char after the header.
   * This is where the serialized revprops are. */ /* STREAM still points to the first entry in the sizes list. */ /* Init / construct REVPROPS members. */ /* Now parse, revision by revision, the size and content of each
   * revisions' revprops. */ /* read & check the serialized size */ /* Parse this revprops list, if necessary */ /* Parse (and possibly cache) the one revprop list we care about. */ /* If we only wanted the revprops for REVISION then we are done. */ /* Parse and cache all other revprop lists. */ /* fill REVPROPS data structures */