2009-04-09 6 views
8

L'esperimento attualmente in uso utilizza una base software con una cronologia delle fonti complicata e una licenza non ben definita. Sarebbe una notevole quantità di lavoro per razionalizzare le cose e rilasciare sotto una licenza fissa.Esistono implementazioni alternative dell'interfaccia GNU getline?

È anche progettato per eseguire una piattaforma unixish casuale, e solo alcune delle libc che supportiamo hanno GNU getline, ma in questo momento il codice si aspetta.

Qualcuno sa di una reimplementazione della semantica GNU getline disponibile con una licenza meno restrittiva?

Edit :: Lo chiedo perché Google non ha aiutato, e mi piacerebbe evitare di scrivere uno se possibile (potrebbe essere un esercizio divertente, ma non può essere il miglior uso del mio tempo.)

per essere più precisi, l'interfaccia in questione è:

ssize_t getline (char **lineptr, size_t *n, FILE *stream); 
+0

Promosso da [questa domanda] (http://stackoverflow.com/q/17407585/827263), ho corretto la dichiarazione; 'getline' restituisce' ssize_t', non 'size_t'. –

+2

Un'implementazione di dominio pubblico di getline(): http://stackoverflow.com/a/12169132/12711 –

risposta

2

Date un'occhiata alla pagina di Paul Hsieh su User Input. Puoi mandare un'e-mail all'autore se vuoi conoscere i termini esatti.

+0

Se devo scrivere qualcosa, questo sarà senza dubbio un buon impalcatura. Grazie. – dmckee

+0

Hai dato un'occhiata all'esempio: 'size_t fgetstralloc (char ** p, FILE * fp)' nella pagina a cui mi sono collegato? – dirkgently

+0

:: sigh :: Ovviamente no. Ho solo guardato la pagina un paio di volte. E sono anche un osservatore esperto. – dmckee

-1

Nel caso in cui si sta parlando readline, check out: editline

+1

Bello, ma temo che intendo davvero getline. – dmckee

+0

Eh, scusate, è solo che di solito ho trovato richieste per la sostituzione di readline :) – mitchnull

+0

Succede. La cosa FGITW fa accadere molto, ma non fa male ... – dmckee

15

Sono perplesso.

Ho guardato il collegamento, ho letto la descrizione e questa è una buona utilità.

Ma, stai dicendo che semplicemente non puoi riscrivere questa funzione alle specifiche? Le specifiche sembra abbastanza chiaro,

Qui:

/* This code is public domain -- Will Hartung 4/9/09 */ 
#include <stdio.h> 
#include <stdlib.h> 

size_t getline(char **lineptr, size_t *n, FILE *stream) { 
    char *bufptr = NULL; 
    char *p = bufptr; 
    size_t size; 
    int c; 

    if (lineptr == NULL) { 
     return -1; 
    } 
    if (stream == NULL) { 
     return -1; 
    } 
    if (n == NULL) { 
     return -1; 
    } 
    bufptr = *lineptr; 
    size = *n; 

    c = fgetc(stream); 
    if (c == EOF) { 
     return -1; 
    } 
    if (bufptr == NULL) { 
     bufptr = malloc(128); 
     if (bufptr == NULL) { 
      return -1; 
     } 
     size = 128; 
    } 
    p = bufptr; 
    while(c != EOF) { 
     if ((p - bufptr) > (size - 1)) { 
      size = size + 128; 
      bufptr = realloc(bufptr, size); 
      if (bufptr == NULL) { 
       return -1; 
      } 
     } 
     *p++ = c; 
     if (c == '\n') { 
      break; 
     } 
     c = fgetc(stream); 
    } 

    *p++ = '\0'; 
    *lineptr = bufptr; 
    *n = size; 

    return p - bufptr - 1; 
} 

int main(int argc, char** args) { 
    char *buf = NULL; /*malloc(10);*/ 
    int bufSize = 0; /*10;*/ 

    printf("%d\n", bufSize); 
    int charsRead = getline(&buf, &bufSize, stdin); 

    printf("'%s'", buf); 
    printf("%d\n", bufSize); 
    return 0; 
} 

15 minuti, e non ho scritto C in 10 anni. Rompe in minima parte il contratto della linea in quanto controlla solo se il lineptr è NULL, piuttosto che NULL e n == 0. Puoi correggerlo se lo desideri. (L'altro caso non ha molto senso per me, suppongo che tu possa restituire -1 in questo caso.)

Sostituisci "\ n" con una variabile per implementare "getdelim".

Le persone scrivono ancora il codice?

+6

Questo funziona bene per le stringhe brevi, ma potrebbe fallire dopo la riallocazione. bufptr può ottenere un nuovo indirizzo e p deve essere mantenuto allo stesso offset relativo. Nei miei test (con MinGW), realloc può tornare più volte con lo stesso puntatore (se ci sono abbastanza memoria in quel punto) o può restituire un nuovo indirizzo nella prima riallocazione. Il nuovo indirizzo può essere vicino in memoria o in un altro modo, e può anche essere prima del primo indirizzo e dopo. IE può rendere un numero casuale. Per correggere, metti "offset = p - bufptr;" sotto la linea EOF while e "p = bufptr + offset;" dopo il blocco if NULL. – Todd

+0

'((p - bufptr)> (dimensione - 1))' è un problema se 'size == 0' (e' * lineptr' era insolitamente non NULL) come 'size - 1' è un numero _large_. Suggerisci '((p - bufptr + 1)> dimensione)'. – chux

+0

restituisce malloc e realloc sul mio codice stdio.h void * puntatori. Quindi ho dovuto aggiungere operatori cast, anche (char *) per le due righe. – jamk

2

Se si compila per l'uso BSD fgetln invece

1

Utilizzare queste versioni portatili di NetBSD: getdelim() e getline()

Questi provengono da libnbcompat in pkgsrc, e dispone di una licenza BSD al in cima a ciascun file. Avete bisogno di entrambi perché getline() chiama getdelim(). Scarica le ultime versioni di entrambi i file. Vedi la licenza BSD nella parte superiore di ogni file. Modifica i file per adattarli al tuo programma: potresti dover dichiarare getline() e getdelim() in uno dei tuoi file di intestazione e modificare entrambi i file per includere l'intestazione invece delle intestazioni nbcompat.

Questa versione di getdelim() è portatile perché chiama fgetc(). Per contrasto, un getdelim() da una libc (come BSD libc o musl libc) probabilmente userebbe le funzionalità private di quella libc, quindi non funzionerebbe su piattaforme diverse.

Negli anni successivi allo POSIX 2008 specified getline(), più piattaforme Unixish hanno aggiunto la funzione getline(). È raro che manca getline(), ma può ancora succedere su vecchie piattaforme. Alcune persone cercano di avviare NetBSD pkgsrc su vecchie piattaforme (come PowerPC Mac OS X), quindi vogliono libnbcompat per fornire funzioni POSIX mancanti come getline().

1

Il codice di Will Hartung soffre di un problema molto serio. realloc molto probabilmente libererà il vecchio blocco e ne assegnerà uno nuovo, ma il puntatore p all'interno del codice continuerà a puntare all'originale. Questo tenta di risolverlo usando invece l'indicizzazione dell'array. Cerca anche di replicare più strettamente la logica POSIX standard.

/* The original code is public domain -- Will Hartung 4/9/09 */ 
/* Modifications, public domain as well, by Antti Haapala, 11/10/17 */ 

#include <stdio.h> 
#include <stdlib.h> 
#include <errno.h> 

// if typedef doesn't exist (msvc, blah) 
typedef intptr_t ssize_t; 

ssize_t geetline(char **lineptr, size_t *n, FILE *stream) { 
    size_t pos; 
    int c; 

    if (lineptr == NULL || stream == NULL || n == NULL) { 
     errno = EINVAL; 
     return -1; 
    } 

    c = fgetc(stream); 
    if (c == EOF) { 
     return -1; 
    } 

    if (*lineptr == NULL) { 
     *lineptr = malloc(128); 
     if (*lineptr == NULL) { 
      return -1; 
     } 
     *n = 128; 
    } 

    pos = 0; 
    while(c != EOF) { 
     if (pos + 1 >= *n) { 
      size_t new_size = *n + (*n >> 2); 
      if (new_size < 128) { 
       new_size = 128; 
      } 
      char *new_ptr = realloc(*lineptr, new_size); 
      if (new_ptr == NULL) { 
       return -1; 
      } 
      *n = new_size; 
      *lineptr = new_ptr; 
     } 

     (*lineptr)[pos ++] = c; 
     if (c == '\n') { 
      break; 
     } 
     c = fgetc(stream); 
    } 

    (*lineptr)[pos] = '\0'; 
    return pos - 1; 
}