<commit_before>/*
  editinteractor.cpp - Interface for edit interactors
  Copyright (C) 2007 Klarälvdalens Datakonsult AB

  This file is part of GPGME++.

  GPGME++ is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  GPGME++ is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU Library General Public License for more details.

  You should have received a copy of the GNU Library General Public License
  along with GPGME++; see the file COPYING.LIB.  If not, write to the
  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  Boston, MA 02110-1301, USA.
*/

#include "editinteractor.h"
#include "callbacks.h"
#include "error.h"

#include <gpg-error.h>

#ifdef _WIN32
# include <io.h>
#include <windows.h>
#else
# include <unistd.h>
#endif

#include <cerrno>
#include <cstring>

using namespace GpgME;

class EditInteractor::Private {
    friend class ::GpgME::EditInteractor;
    friend class ::GpgME::CallbackHelper;
    EditInteractor * const q;
public:
    explicit Private( EditInteractor * qq );
    ~Private();

private:
    unsigned int state;
    Error error;
    std::FILE * debug;
};

class GpgME::CallbackHelper {
private:
    static int writeAll( int fd, const void * buf, uint count ) {
        uint toWrite = count;
        while ( toWrite > 0 ) {
#ifdef Q_OS_WIN
            DWORD n;
            if ( !WriteFile( (HANDLE)fd, buf, toWrite, &n, NULL ) )
                return -1;
#else
            const int n = write( fd, buf, toWrite );
#endif
            if ( n < 0 )
                return n;
            toWrite -= n;
        }
        return count;
    }

public:
    static int edit_interactor_callback_impl( void * opaque, gpgme_status_code_t status, const char * args, int fd ) {
        EditInteractor::Private * ei = (EditInteractor::Private*)opaque;

        Error err;

            // advance to next state based on input:
            const unsigned int oldState = ei->state;
            ei->state = ei->q->nextState( status, args, err );
            if ( err ) {
                ei->state = oldState;
                goto error;
            }
            if ( ei->debug )
                std::fprintf( ei->debug, "EditInteractor: %u -> nextState( %u, %s ) -> %u\n",
                              oldState, (unsigned int)status, args ? args : "<null>", ei->state );

            if ( ei->state != oldState &&
                 // if there was an error from before, we stop here (### this looks weird, can this happen at all?)
                 gpg_err_code( ei->error.code() ) == GPG_ERR_NO_ERROR ) {

                // successful state change -> call action
                if ( const char * const result = ei->q->action( err ) ) {
                    if ( err )
                        goto error;
                    if ( ei->debug )
                        std::fprintf( ei->debug, "EditInteractor: action result \"%s\"\n", result );
                    // if there's a result, write it:
                    if ( *result ) {
                        errno = 0;
                        if ( writeAll( fd, result, std::strlen( result ) != std::strlen( result ) ) ) {
                            if ( ei->debug )
                                std::fprintf( ei->debug, "EditInteractor: Could not write to fd %d (%s)\n", fd, strerror( errno ) );
                            err = Error( GPG_ERR_GENERAL );
                            goto error;
                        }
                    }
                    errno = 0;
                    if ( writeAll( fd, "\n", 1 ) != 1 ) {
                        if ( ei->debug )
                            std::fprintf( ei->debug, "EditInteractor: Could not write to fd %d (%s)\n", fd, strerror( errno ) );
                        err = Error( GPG_ERR_GENERAL );<commit_msg>fix stupid error, use size_t<commit_after>/*
  editinteractor.cpp - Interface for edit interactors
  Copyright (C) 2007 Klarälvdalens Datakonsult AB

  This file is part of GPGME++.

  GPGME++ is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  GPGME++ is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU Library General Public License for more details.

  You should have received a copy of the GNU Library General Public License
  along with GPGME++; see the file COPYING.LIB.  If not, write to the
  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  Boston, MA 02110-1301, USA.
*/

#include "editinteractor.h"
#include "callbacks.h"
#include "error.h"

#include <gpg-error.h>

#ifdef _WIN32
# include <io.h>
#include <windows.h>
#else
# include <unistd.h>
#endif

#include <cerrno>
#include <cstring>

using namespace GpgME;

class EditInteractor::Private {
    friend class ::GpgME::EditInteractor;
    friend class ::GpgME::CallbackHelper;
    EditInteractor * const q;
public:
    explicit Private( EditInteractor * qq );
    ~Private();

private:
    unsigned int state;
    Error error;
    std::FILE * debug;
};

class GpgME::CallbackHelper {
private:
    static int writeAll( int fd, const void * buf, size_t count ) {
        size_t toWrite = count;
        while ( toWrite > 0 ) {
#ifdef Q_OS_WIN
            DWORD n;
            if ( !WriteFile( (HANDLE)fd, buf, toWrite, &n, NULL ) )
                return -1;
#else
            const int n = write( fd, buf, toWrite );
#endif
            if ( n < 0 )
                return n;
            toWrite -= n;
        }
        return count;
    }

public:
    static int edit_interactor_callback_impl( void * opaque, gpgme_status_code_t status, const char * args, int fd ) {
        EditInteractor::Private * ei = (EditInteractor::Private*)opaque;

        Error err;

            // advance to next state based on input:
            const unsigned int oldState = ei->state;
            ei->state = ei->q->nextState( status, args, err );
            if ( err ) {
                ei->state = oldState;
                goto error;
            }
            if ( ei->debug )
                std::fprintf( ei->debug, "EditInteractor: %u -> nextState( %u, %s ) -> %u\n",
                              oldState, (unsigned int)status, args ? args : "<null>", ei->state );

            if ( ei->state != oldState &&
                 // if there was an error from before, we stop here (### this looks weird, can this happen at all?)
                 gpg_err_code( ei->error.code() ) == GPG_ERR_NO_ERROR ) {

                // successful state change -> call action
                if ( const char * const result = ei->q->action( err ) ) {
                    if ( err )
                        goto error;
                    if ( ei->debug )
                        std::fprintf( ei->debug, "EditInteractor: action result \"%s\"\n", result );
                    // if there's a result, write it:
                    if ( *result ) {
                        errno = 0;
                        if ( writeAll( fd, result, std::strlen( result ) ) != std::strlen( result ) ) {
                            if ( ei->debug )
                                std::fprintf( ei->debug, "EditInteractor: Could not write to fd %d (%s)\n", fd, strerror( errno ) );
                            err = Error( GPG_ERR_GENERAL );
                            goto error;
                        }
                    }
                    errno = 0;
                    if ( writeAll( fd, "\n", 1 ) != 1 ) {
                        if ( ei->debug )
                            std::fprintf( ei->debug, "EditInteractor: Could not write to fd %d (%s)\n", fd, strerror( errno ) );
                        err = Error( GPG_ERR_GENERAL );
{'fraction_non_alphanumeric': 0.1035744784677321, 'fraction_numerical': 0.00609979260705136, 'mean_word_length': 1.7537789721195836, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 61, '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': '4694812', 'n_tokens_mistral': 2382, 'n_tokens_neox': 2249, 'n_words': 816}