<commit_before>/*
 * author: <NAME> <<EMAIL>>
 */

#include "istream_stopwatch.hxx"
#include "istream_internal.hxx"
#include "istream_forward.hxx"
#include "stopwatch.h"
#include "util/Cast.hxx"

#include <assert.h>

struct StopwatchIstream {
    struct istream output;

    struct istream *input;

    struct stopwatch *stopwatch;
};


/*
 * istream handler
 *
 */

static void
stopwatch_input_eof(void *ctx)
{
    auto *stopwatch = (StopwatchIstream *)ctx;

    stopwatch_event(stopwatch->stopwatch, "end");
    stopwatch_dump(stopwatch->stopwatch);

    istream_deinit_eof(&stopwatch->output);
}

static void
stopwatch_input_abort(GError *error, void *ctx)
{
    auto *stopwatch = (StopwatchIstream *)ctx;

    stopwatch_event(stopwatch->stopwatch, "abort");
    stopwatch_dump(stopwatch->stopwatch);

    istream_deinit_abort(&stopwatch->output, error);
}

static constexpr struct istream_handler stopwatch_input_handler = {
    .data = istream_forward_data,
    .direct = istream_forward_direct,
    .eof = stopwatch_input_eof,
    .abort = stopwatch_input_abort,
};


/*
 * istream implementation
 *
 */

static inline StopwatchIstream *
istream_to_stopwatch(struct istream *istream)
{
    return &ContainerCast2(*istream, &StopwatchIstream::output);
}

static void
istream_stopwatch_read(struct istream *istream)
{
    StopwatchIstream *stopwatch = istream_to_stopwatch(istream);

    istream_handler_set_direct(stopwatch->input,
                               stopwatch->output.handler_direct);

    istream_read(stopwatch->input);
}

static int
istream_stopwatch_as_fd(struct istream *istream)
{
    StopwatchIstream *stopwatch = istream_to_stopwatch(istream);

    int fd = istream_as_fd(stopwatch->input);
    if (fd >= 0) {
        stopwatch_event(stopwatch->stopwatch, "as_fd");
        stopwatch_dump(stopwatch->stopwatch);
        istream_deinit(&stopwatch->output);
    }

    return fd;
}

static void
istream_stopwatch_close(struct istream *istream)
{
    StopwatchIstream *stopwatch = istream_to_stopwatch(istream);

    assert(stopwatch->input != nullptr);

    istream_close_handler(stopwatch->input);
    istream_deinit(&stopwatch->output);
}

static constexpr struct istream_class istream_stopwatch = {
    .read = istream_stopwatch_read,
    .as_fd = istream_stopwatch_as_fd,
    .close = istream_stopwatch_close,
};


/*
 * constructor
 *
 */

struct istream *
istream_stopwatch_new(struct pool *pool, struct istream *input,
                      struct stopwatch *_stopwatch)
{
    assert(input != nullptr);
    assert(!istream_has_handler(input));

    if (_stopwatch == nullptr)
        return input;

    auto stopwatch = NewFromPool<StopwatchIstream>(*pool);
    istream_init(&stopwatch->output, &istream_stopwatch, pool);

    istream_assign_handler(&stopwatch->input, input,
                           &stopwatch_input_handler, stopwatch,
                           0);

    stopwatch->stopwatch = _stopwatch;

    return &stopwatch->output;
}<commit_msg>istream_stopwatch: use the OO API<commit_after>/*
 * author: <NAME> <<EMAIL>>
 */

#include "istream_stopwatch.hxx"
#include "istream_forward.hxx"
#include "stopwatch.h"

class StopwatchIstream final : public ForwardIstream {
    struct stopwatch &stopwatch;

public:
    StopwatchIstream(struct pool &p, struct istream &_input,
                     struct stopwatch &_stopwatch)
        :ForwardIstream(p, _input,
                        MakeIstreamHandler<StopwatchIstream>::handler, this),
         stopwatch(_stopwatch) {}

    /* virtual methods from class Istream */

    int AsFd() override;

    /* handler */

    void OnEof();
    void OnError(GError *error);
};


/*
 * istream handler
 *
 */

void
StopwatchIstream::OnEof()
{
    stopwatch_event(&stopwatch, "end");
    stopwatch_dump(&stopwatch);

    ForwardIstream::OnEof();
}

void
StopwatchIstream::OnError(GError *error)
{
    stopwatch_event(&stopwatch, "abort");
    stopwatch_dump(&stopwatch);

    ForwardIstream::OnError(error);
}

/*
 * istream implementation
 *
 */

int
StopwatchIstream::AsFd()
{
    int fd = input.AsFd();
    if (fd >= 0) {
        stopwatch_event(&stopwatch, "as_fd");
        stopwatch_dump(&stopwatch);
        Destroy();
    }

    return fd;
}

/*
 * constructor
 *
 */

struct istream *
istream_stopwatch_new(struct pool *pool, struct istream *input,
                      struct stopwatch *_stopwatch)
{
    if (_stopwatch == nullptr)
        return input;

    return NewIstream<StopwatchIstream>(*pool, *input, *_stopwatch);
}
{'fraction_non_alphanumeric': 0.11578481292893514, 'fraction_numerical': 0.0008855435023245517, 'mean_word_length': 3.5728744939271255, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6406173', 'n_tokens_mistral': 1501, 'n_tokens_neox': 1461, 'n_words': 272}