2009-04-09 2 views
8

В эксперименте, в котором я сейчас работаю, используется база программного обеспечения со сложной историей источника и без определенной лицензии. Было бы большой объем работы по рационализации вещей и выпуску по фиксированной лицензии.Существуют ли альтернативные реализации интерфейса GNU getline?

Он также предназначен для запуска случайной платформы unixish, и только некоторые из поддерживаемых нами libc имеют GNU getline, но сейчас код ожидает этого.

Кто-нибудь знает о повторной реализации семантики GNU getline, доступной по менее ограничительной лицензии?

Редактировать: Я прошу, потому что Google не помог, и я хотел бы избежать написания одного, если это возможно (это может быть забавное упражнение, но это не может быть лучшим использованием моего времени.)

Чтобы быть более конкретным, интерфейс в вопросе:

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

Подсказка [этот вопрос] (http://stackoverflow.com/q/17407585/827263), я исправил декларацию; 'getline' возвращает' ssize_t', а не 'size_t'. –

+2

Реализация общего доступа getline(): http://stackoverflow.com/a/12169132/12711 –

ответ

2

Посмотрите на странице Пола Шей на User Input. Вы можете отправить письмо автору, если хотите узнать точные условия.

+0

Если я должен что-то написать, это, несомненно, будет хорошим эшафотом. Благодарю. – dmckee

+0

Вы посмотрели пример: 'size_t fgetstralloc (char ** p, FILE * fp)' на странице, с которой я связан? – dirkgently

+0

:: вздох :: Конечно нет. Я только пару раз смотрел на страницу. И я тоже обученный наблюдатель. – dmckee

-1

В случае, если речь идет о Readline, проверьте: editline

+1

Приятно, но, боюсь, я действительно имею в виду getline. – dmckee

+0

Эх, извините, я просто нашел запросы на замену readline :) – mitchnull

+0

Бывает. Вещь FGITW делает это много, но это не наносит вреда ... – dmckee

15

Я озадачен.

Я посмотрел ссылку, прочитал описание, и это прекрасная утилита.

Но, вы говорите, что вы просто не можете переписать эту функцию в спецификацию? Спецификация кажется вполне ясным,

Здесь:

/* 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 минут, и я не написал C в течение 10 лет. Он незначительно нарушает контракт getline в том, что он проверяет, является ли lineptr NULL, а не NULL и n == 0. Вы можете это исправить, если хотите. (Другой случай не имел для меня большого смысла, я думаю, вы могли бы вернуть -1 в этом случае.)

Замените '\ n' на переменную для реализации «getdelim».

Неужели люди все еще пишут код?

+6

Это отлично работает для коротких строк, но может потерпеть неудачу после перераспределения. bufptr может получить новый адрес, а p должен поддерживаться с одинаковым относительным смещением. В моих тестах (с MinGW) realloc может возвращаться несколько раз с одним и тем же указателем (если в этом месте будет достаточно памяти) или может вернуть новый адрес при первом перераспределении. Новый адрес может находиться рядом с памятью или удалён, а также может быть до первого адреса, а также после. IE он может сделать p случайным числом. Чтобы исправить, поставьте «offset = p - bufptr;» под линией EOF и «p = bufptr + offset»; после блока if NULL. – Todd

+0

'((p - bufptr)> (size - 1))' является проблемой, если 'size == 0' (и' * lineptr' был нехарактерным, но не NULL), поскольку 'size - 1' является номером _large_. Предложите '((p - bufptr + 1)> размер)'. – chux

+0

malloc и realloc возвращаются на мой stdio.h код void * указатели. Поэтому мне пришлось добавить операторы-литеры, а также (char *) для двух строк. – jamk

2

При компиляции для использования BSD fgetln вместо

1

Используйте эти портативные версии от NetBSD: getdelim() и getline()

Они приходят из libnbcompat в Pkgsrc, и иметь лицензию BSD в то вверху каждого файла. Вам нужны оба, потому что getline() вызывает getdelim(). Выполните последние версии обоих файлов. См. Лицензию BSD в верхней части каждого файла. Измените файлы, которые будут вписываться в вашу программу: вам может потребоваться объявить getline() и getdelim() в одном из ваших файлов заголовков и изменить оба файла, чтобы включить ваш заголовок вместо заголовков nbcompat.

Эта версия getdelim() переносима, поскольку она вызывает функцию fgetc(). Для сравнения, getdelim() из libc (например, BSD libc или musl libc), вероятно, будет использовать частные функции этого libc, поэтому он не будет работать на разных платформах.

С тех пор, как POSIX 2008 specified getline(), больше платформ Unixix добавили функцию getline(). Редко бывает, что getline() отсутствует, но это все равно может случиться на старых платформах. Несколько человек пытаются загружать NetBSD pkgsrc на старых платформах (например, PowerPC Mac OS X), поэтому они хотят, чтобы libnbcompat предоставлял отсутствующие функции POSIX, такие как getline().

1

Код Will Hartung имеет очень серьезную проблему. realloc, скорее всего, освободит старый блок и выделит новый, но указатель p в коде будет продолжать указывать на оригинал. Этот пытается исправить это, используя вместо этого индексацию массива. Он также пытается более точно воспроизвести стандартную логику POSIX.

/* 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; 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^