/* annotated-file.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/char/str.h"
#include "hackerlab/os/errno.h"
#include "libarch/annotated-file.h"

static int arch_annotated_file_destroy (void *data);

void
arch_annotated_file_init (arch_annotated_file_t *file, t_uchar const * file_id, int lines)
{
    file->lines = lim_zalloc (0, sizeof (file->lines[0]) * lines );
    file->file_id = talloc_strdup (file, file_id);
    file->unknown_lines = lines;
    file->max_lines = lines;
    file_offset_mapper_init (&file->mapper, lines);
}

void 
arch_annotated_file_finalise (arch_annotated_file_t *file)
{
    int position;
    for (position = 0; position < file->max_lines; ++ position)
        arch_patch_delete (&(file->lines[position]));
    lim_free (0, file->lines);
    file->lines = NULL;
    file_offset_mapper_finalise (&file->mapper);
}

arch_annotated_file_t * 
arch_annotated_file_new (void * context, t_uchar const *file_id, int lines)
{
    arch_annotated_file_t *result = talloc (context, arch_annotated_file_t);
    talloc_set_destructor (result, arch_annotated_file_destroy);
    arch_annotated_file_init (result, file_id, lines);
    return result;
}

int
arch_annotated_file_destroy (void *data)
{
    arch_annotated_file_t *patch = talloc_get_type (data, arch_annotated_file_t);
    if (!patch)
        return 0;
    arch_annotated_file_finalise (patch);
    return 0;
}

#include "hackerlab/vu/safe.h"
/**
 * \brief annotate a specific line in the file
 * if final is true, then this is not the result of a merge.
 * \throw EINVAL if patch is NULL
 */
void
arch_annotated_file_note_line (arch_annotated_file_t *file,
                               int line, arch_patch_t *patch, int final)
{
    int mapped_line;
    if (!patch)
        Throw (exception (EINVAL, "No patch supplied to arch_annotated_file_note_line"));
    mapped_line = file_offset_mapper_map (&file->mapper, line);
    if (mapped_line >= file->max_lines)
        Throw (exception (EDOM, "arch_annotated_file_note_line: line is invalid"));
    file_offset_mapper_add (&file->mapper, line);
    if (mapped_line < 0)
        return;
    if (file->lines[mapped_line])
      {
        safe_printfmt (2, "Error : line %d mapped to %d which already has an annotation of %s\n", line, mapped_line, arch_patch_id_patch_id(arch_patch_patch_id(file->lines[mapped_line])));
        file_offset_mapper_print (2, &file->mapper);
      }
    if (file->lines[mapped_line] != NULL)
        Throw (exception (EEXIST, "arch_annotated_file_note_line: already mapped to"));
    file->lines[mapped_line] = arch_patch_copy (patch);
    if (final)
        --file->unknown_lines;
}

/**
 * \@brief note a - line from a patch.
 */
void
arch_annotated_file_note_subtract (arch_annotated_file_t *file, int line)
{
    file_offset_mapper_subtract (&file->mapper, line);
}


syntax highlighted by Code2HTML, v. 0.9.1