/* annotation-builder.c:
*
* vim:smartindent ts=8:sts=2:sta:et:ai:shiftwidth=2
****************************************************************
* Copyright (C) 2005 Canonical Limited
* Authors: Robert Collins <robert.collins@canonical.com>
*
* See the file "COPYING" for further information about
* the copyright and warranty status of this work.
*/
#include "hackerlab/bugs/exception.h"
#include "hackerlab/bugs/panic.h"
#include "hackerlab/os/errno.h"
#include "hackerlab/char/str.h"
#include "libarch/annotation-builder.h"
/* local static functions */
static int arch_annotation_builder_destructor (void * data);
static int
arch_annotation_builder_find_file (arch_annotation_builder_t *builder, t_uchar const *file_id)
{
int position;
for (position = 0; position < ar_size_arch_annotated_file (builder->files); ++position)
if (!str_cmp (file_id, builder->files[position]->file_id))
return position;
return -1;
}
void
arch_annotation_builder_init (arch_annotation_builder_t *builder)
{
builder->files = NULL;
builder->current_file = NULL;
builder->current_patch = NULL;
}
int
arch_annotation_builder_destructor (void * data)
{
arch_annotation_builder_t * builder = talloc_get_type (data, arch_annotation_builder_t);
invariant (!!builder);
arch_annotation_builder_finalise (builder);
return 0;
}
arch_annotation_builder_t *
arch_annotation_builder_new (void * context)
{
arch_annotation_builder_t * builder = talloc (context, arch_annotation_builder_t);
arch_annotation_builder_init (builder);
talloc_set_destructor (builder, arch_annotation_builder_destructor);
return builder;
}
void
arch_annotation_builder_finalise (arch_annotation_builder_t *builder)
{
arch_patch_delete (&builder->current_patch);
}
/**
* \@brief note a file by its observed id, and the number of lines we need to annotate.
*/
void
arch_annotation_builder_add_file (arch_annotation_builder_t *builder, t_uchar const *file_id, int size_if_start)
{
int position = arch_annotation_builder_find_file (builder, file_id);
if (position != -1)
{
builder->current_file = builder->files[position];
return;
}
invariant (size_if_start != -1);
ar_push_arch_annotated_file (&builder->files, arch_annotated_file_new (talloc_context, file_id, size_if_start));
builder->current_file = builder->files[ar_size_arch_annotated_file (builder->files) - 1];
talloc_steal (ar_base (builder->files), builder->current_file);
talloc_steal (builder, ar_base (builder->files));
}
int
arch_annotation_builder_has_file (arch_annotation_builder_t *builder, t_uchar const *file_id)
{
return arch_annotation_builder_find_file(builder, file_id) != -1;
}
/**
* \brief retrieve and remove the annotated file for file_id
* \throw ENOENT if file_id is not in the annotated files list
* \param builder the builder
* \param context the talloc context for the returned file object
* \param file_id the file to retrieve
* \return an arch_annotated_file_t *
*/
arch_annotated_file_t *
arch_annotation_builder_get_file (arch_annotation_builder_t *builder, void * context, t_uchar const *file_id)
{
arch_annotated_file_t *result;
int position = arch_annotation_builder_find_file (builder, file_id);
if (position == -1)
Throw (exception (ENOENT, "arch_annotation_builder_get_file: No such file."));
result = *ar_ref_arch_annotated_file (&builder->files, position);
for (; position < ar_size_arch_annotated_file (builder->files) - 1; ++position )
{
*ar_ref_arch_annotated_file (&builder->files, position) = *ar_ref_arch_annotated_file (&builder->files, position + 1);
}
ar_pop_arch_annotated_file (&builder->files);
builder->current_file = NULL;
return talloc_steal (context, result);
}
/**
* \@brief add a patch
*/
void
arch_annotation_builder_add_patch (arch_annotation_builder_t *builder, arch_patch_id *patch, t_uchar const * creator)
{
arch_patch_delete (&builder->current_patch);
builder->current_patch = arch_patch_new (patch->patch_id);
arch_patch_creator_set (builder->current_patch, creator);
}
void
arch_annotation_builder_subtract_line (arch_annotation_builder_t *builder, int old_offset)
{
invariant (builder->current_file != NULL);
invariant (builder->current_patch != NULL);
arch_annotated_file_note_subtract (builder->current_file, old_offset);
}
void
arch_annotation_builder_add_line (arch_annotation_builder_t *builder, int line)
{
invariant (builder->current_file != NULL);
invariant (builder->current_patch != NULL);
arch_annotated_file_note_line (builder->current_file, line, builder->current_patch, 0);
}
void
arch_annotation_builder_process_changes(arch_annotation_builder_t *builder, patch_line_changes_list changes)
{
int position;
for (position = 0; position < ar_size_patch_line_change (changes); ++ position)
{
if (changes[position].operation == PATCH_ADD_LINE)
{
arch_annotation_builder_add_line(builder, changes[position].offset);
}
else
{
arch_annotation_builder_subtract_line(builder, changes[position].offset);
}
}
}
syntax highlighted by Code2HTML, v. 0.9.1