SDK Multiplataforma en C logo

SDK Multiplataforma en C

Streams

❮ Anterior
Siguiente ❯

El agua puede fluir, arrastrarse, gotear o estrellarse, sé agua amigo mío. Bruce Lee


Funciones

Stream*stm_from_block (...)
Stream*stm_memory (...)
Stream*stm_from_file (...)
Stream*stm_to_file (...)
Stream*stm_append_file (...)
Stream*stm_socket (...)
voidstm_close (...)
endian_tstm_get_write_endian (...)
endian_tstm_get_read_endian (...)
voidstm_set_write_endian (...)
voidstm_set_read_endian (...)
unicode_tstm_get_write_utf (...)
unicode_tstm_get_read_utf (...)
voidstm_set_write_utf (...)
voidstm_set_read_utf (...)
uint64_tstm_bytes_written (...)
uint64_tstm_bytes_readed (...)
sstate_tstm_state (...)
ferror_tstm_file_err (...)
serror_tstm_sock_err (...)
voidstm_corrupt (...)
String*stm_str (...)
const byte_t*stm_buffer (...)
uint32_tstm_buffer_size (...)
voidstm_write (...)
voidstm_write_char (...)
uint32_tstm_printf (...)
uint32_tstm_writef (...)
voidstm_write_bool (...)
voidstm_write_i8 (...)
voidstm_write_i16 (...)
voidstm_write_i32 (...)
voidstm_write_i64 (...)
voidstm_write_u8 (...)
voidstm_write_u16 (...)
voidstm_write_u32 (...)
voidstm_write_u64 (...)
voidstm_write_r32 (...)
voidstm_write_r64 (...)
voidstm_write_enum (...)
uint32_tstm_read (...)
voidstm_skip (...)
uint32_tstm_read_char (...)
const char_t*stm_read_chars (...)
const char_t*stm_read_line (...)
const char_t*stm_read_delim (...)
const char_t*stm_read_trim (...)
bool_tstm_read_bool (...)
int8_tstm_read_i8 (...)
int16_tstm_read_i16 (...)
int32_tstm_read_i32 (...)
int64_tstm_read_i64 (...)
uint8_tstm_read_u8 (...)
uint16_tstm_read_u16 (...)
uint32_tstm_read_u32 (...)
uint64_tstm_read_u64 (...)
real32_tstm_read_r32 (...)
real64_tstm_read_r64 (...)
typestm_read_enum (...)
voidstm_flush (...)
voidstm_pipe (...)
voidstm_lines (...)
voidstm_next (...)

Tipos y Constantes

StreamkSTDIN
StreamkSTDOUT
StreamkSTDERR

Un stream es un flujo de datos que corre desde un origen a un destino. Piensa en una llamada telefónica. Tenemos un origen (la persona que habla), un destino (la persona que escucha) y un canal (la propia línea). En programación, el stream es el equivalente a la línea telefónica, es la tubería que une la aplicación con un origen o destino de datos (Figura 1) y por la que circula información binaria, secuencias de bits. Al igual que ocurre con cualquier otro canal de comunicación, la información es volátil, disponible por un tiempo muy limitado. Una vez que llega al receptor, desaparece.

Dibujo de un proceso conectando su E/S mediante streams.
Figura 1: Los streams conectan al proceso con la máquina y con el mundo.

En esencia, son tres las operaciones elementales a realizar cuando trabajamos con streams:

  • Crear el stream. Define el tipo de canal de acuerdo con sus extremos.
  • Escribir datos al canal.
  • Leer datos desde el canal.

1. Tipos de stream

En realidad, es más correcto hablar de tipos de interlocutores (origen y destino) que de tipos de stream. Desde la perspectiva del programador, un stream es un tipo abstracto que presenta la misma funcionalidad independientemente de los extremos que conecta. Por tanto, al hablar de tipo de stream nos estamos refiriendo al tipo de constructor.

1.1. File stream

En File streams (Figura 2), el origen es la memoria del proceso y el destino un archivo en disco. Lo contrario también puede ocurrir, el origen es el archivo y el destino la memoria. Dependerá de como abramos el canal. No será posible realizar operaciones de escritura en un archivo abierto para lectura o viceversa (Listado 1). Archivos y directorios.

Dibujo de un proceso accediendo a disco mediante streams.
Figura 2: Los File streams permiten la comunicación con el sistema de archivos.

1.2. Socket stream

Un socket es un canal de comunicación entre dos procesos a través de Internet (Figura 3). A diferencia de los file streams, los sockets permiten la comunicación bidireccional (full-duplex), es decir, ambos extremos pueden enviar y recibir información. La secuencia de intercambio de mensajes entre interlocutores está determinada por el protocolo (Listado 2), siendo HTTP, FTP, SMTP o LDAP algunos de los más utilizados para las transmisiones por Internet. Sockets.

Dibujo de un proceso accediendo accediendo a Internet mediante streams.
Figura 3: Un socket stream abre un canal de comunicación por Internet.

1.3. Block stream

Los block streams se utilizan para leer datos con formato a partir de un bloque de memoria genérico. (Figura 4). Esta zona de memoria se considera de solo lectura y no será modificada, por lo que no se permitirán operaciones de escritura en este tipo de streams. Cuando todo el bloque haya sido leído, se activará el estado ekSTEND.

  • Utiliza stm_from_block para leer desde zonas de memoria.
  • Dibujo de un proceso leyendo desde un bloque de memoria mediante streams.
    Figura 4: Con block streams leeremos datos con formato desde áreas de memoria.

1.4. Memory stream

Los memory streams son canales de lectura/escritura que permiten implementar el modelo productor/consumidor (Figura 5). En primer lugar, la información es escrita en el stream que la almacena en un búfer interno de memoria. Posteriormente, dicha información puede ser leída por otra función, hebra o proceso. El concepto es similar al de las tuberías (IPC-Pipes), con la salvedad de que no existe un límite de tamaño para el búfer, sino que crecerá bajo demanda.

  • Utiliza stm_memory para crear un stream en memoria.
  • Dibujo de un proceso compartiendo datos entre hebras mediante streams.
    Figura 5: Modelo productor/consumidor implementado con memory streams.
A pesar que este tipo de stream soporta operaciones de lectura y escritura no se considera full-duplex. La lectura se hace sobre datos escritos previamente, pero no puede "contestar" al interlocutor. No es una "conversación".

1.5. Standard stream

La E/S Estándar puede ser gestionada mediante streams utilizando tres objetos predefinidos (Figura 6). Estos objetos se crean al iniciar el programa y se liberarán automáticamente al terminar.

1.6. Text stream

Por un stream siempre viajan datos binarios genéricos. Como estos datos sean interpretados depende de los interlocutores y de su protocolo de comunicación. Los streams de texto son un caso particular donde se asume que la información binaria representa códigos de caracteres (codepoints) (Figura 7). No hay que hacer nada especial al crear un stream para indicar que es de tipo texto, sino utilizar las funciones del API especializadas en este tipo de información.

Los streams no tienen porqué ser de texto o binarios "puros". Pueden combinar ambos tipos de representaciones.

2. Ventajas de los streams

A pesar que es posible leer o escribir directamente en los canales E/S (Memoria, Archivos y directorios, Sockets, E/S Estándar), hacerlo a través de objetos Stream tiene ciertas ventajas. Por esto recomendamos utilizarlos en lugar de las API de bajo nivel por los siguientes motivos:

2.1. Unificar la serialización

Los streams ofrecen una interfaz uniforme, independientemente del origen y destino de los datos (Figura 8). Para la serialización de objetos tan solo debemos escribir un lector y un escritor, sin preocuparnos si objeto será guardado en disco, transmitido por Internet o almacenado temporalmente en memoria (Listado 4).

Listado 4: (De)serialización de un objeto mediante streams.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
typedef struct _product_t
{
    type_t type;
    String *code;
    String *description;
    Image *image64;
    real32_t price;
} Product;

void product_write(Stream *stm, Product *product)
{
    stm_write_enum(stm, product->type, type_t);
    str_write(stm, product->code);
    str_write(stm, product->description);
    image_write(stm, product->image64);
    stm_write_r32(stm, product->price);
}

void product_read(Stream *stm, Product *product)
{
    product->type = stm_read_enum(stm, type_t);
    product->code = str_read(stm);
    product->description = str_read(stm);
    product->image64 = image_read(stm);
    product->price = stm_read_r32(stm);
}
Unificación de canales E/S gracias a los streams.
Figura 8: Por medio de streams manejamos todos los canales E/S con la misma interfaz.

2.2. Mayor elegancia

Los canales E/S solo trabajan con bloques de bytes. Los streams implementan funciones de alto nivel para textos y tipos binarios. Esto hará nuestro código mucho más legible (Listado 5).

Listado 5: Escritura de un objeto en disco directamente o a través de un stream.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
void product_write(File *file, Product *product)
{
    uint32_t size = str_len(product->description);
    const char_t *data = tc(product->description);
    bfile_write(file, (byte_t*)&product->id, sizeof(uint32_t), NULL, NULL);
    bfile_write(file, (byte_t*)&product->price, sizeof(real64_t), NULL, NULL);
    bfile_write(file, (byte_t*)&size, sizeof(uint32_t), NULL, NULL);
    bfile_write(file, (byte_t*)data, size, NULL, NULL);
}

void product_write(Stream *stream, Product *product)
{
    stm_write_u32(stream, product->id);
    stm_write_r64(stream, product->price);
    str_write(stream, product->description);
}

2.3. Mayor productividad

Relacionada con la anterior, los streams pueden "parsear" cadenas de texto directamente. Se pueden obtener caracteres, palabras o líneas sin tener que escanear la entrada carácter a carácter (Listado 6). Para mayor nivel de detalle, podemos utilizar el analizador léxico Analizador léxico.

Listado 6: Leer una línea de texto directamente o a través de un stream.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
String *getline(File *file)
{
    /* Potentially unsafe. */
    /* Risk of buffer overflow. */
    char_t buffer[MAXBUFF];
    uint32_t i = 0;
    char_t c;

    bfile_read(file, (byte_t*)&c, 1, NULL, NULL);
    while (c != '\n')
    {
        buffer[i] = c;
        i += 1;
        bfile_read(file, (byte_t*)&c, 1, NULL, NULL);
    }

    buffer[i] = '\0';
    return str_c(buffer);
}

String *getline(Stream *stream)
{
    /* Totally safe. */
    /* line is in dynamic cache. */
    const char_t *line = stm_read_line(stream);
    return str_c(line);
}

2.4. Mayor rendimiento

File streams y socket streams implementan una caché interna. Esto permite acceder menos veces al canal con un mayor volumen de datos, lo que implica mayor velocidad de proceso (Figura 9).

  • Utiliza stm_flush para vaciar la caché y volcar los datos en el canal.
  • Dibujo de los streams utilizando caché de datos.
    Figura 9: Los streams implementan memoria caché, lo que incrementa el rendimiento.

2.5. Orden de bytes

Al leer o escribir datos binarios de un canal E/S hay que prestar especial atención al orden de los bytes en tipos de datos de 16, 32 o 64 bits lo que se conoce como endianness. En máquinas litte endian, como es el caso de la familia de procesadores Intel x86/x64, el byte de menor orden se ubicará en la dirección de memoria más baja. En el caso de los big endian (Motorola 68000, PowerPC) ocurre al contrario, irá en en la más alta. Por ejemplo, si escribimos un entero de 32-bits en un archivo o socket desde una máquina little endian y lo leemos desde una big endian los datos estarán corrompidos al alterar el orden interno de bits (Figura 10). Los objetos Stream ajustan automáticamente el endianness en cada operación de lectura/escritura. Por defecto se establece ekLITEND, salvo en sockets que será ekBIGEND por ser el convenio aceptado para las comunicaciones en red. No obstante, puede cambiarse si es necesario.

  • Utiliza stm_set_write_endian para establecer el endianness del canal de salida. Los datos pasarán de CPU endian a Stream endian antes de ser escritos.
  • Utiliza stm_set_read_endian para establecer el endianness del canal de entrada. Los datos pasarán de Stream endian a CPU endian en el momento de ser leídos.
  • Dibujo de streams teniendo en cuenta el orden de bytes.
    Figura 10: Debemos tener en cuenta el endianness a la hora de compartir datos entre máquinas de diferente arquitectura.
El endianness no influye en las cadenas de texto UTF-8, pero sí en las UTF-16 y UTF-32.

3. Estado del stream

Un stream puede verse afectado por dos tipos de problemas. Por un lado la corrupción de datos que queda patente cuando leemos datos binarios desde el stream. Un claro ejemplo sería leer un booleano mediante stm_read_bool y obtener un valor de 129 cuando, evidentemente, este valor debería ser 0 (TRUE) ó 1 (FALSE). Normalmente, un stream se corrompe debido a la falta de coordinación entre el escritor y el lector y, por lo general, esta situación debe resolverse depurando y corrigiendo la serialización de objetos o el protocolo de datos. Por otro lado, pueden existir errores físicos en el canal (archivo eliminado, perdida de conexión a Internet, permisos, etc). En ambos casos el stream quedará "bloqueado" y serán ignoradas las operaciones de lectura o escritura que efectuemos sobre el mismo.

  • Utiliza stm_state para conocer el estado actual del canal.
  • Utiliza stm_file_err para obtener información extendida del error en streams de disco.
  • Utiliza stm_sock_err para obtener información extendida del error en sockets.
  • Utiliza stm_corrupt para marcar un stream como ekSTCORRUPT. En ocasiones es el propia aplicación la que detecta que el dato no es correcto (pe. fuera de rango).

kSTDIN

Stream kSTDIN;

Stream conectado a la entrada estándar stdin.


kSTDOUT

Stream kSTDOUT;

Stream conectado a la salida estándar stdout.


kSTDERR

Stream kSTDERR;

Stream conectado a la salida de errores stderr.


stm_from_block ()

Crea un stream de lectura a partir de un bloque de memoria ya existente.

Stream*
stm_from_block(const byte_t *data,
               const uint32_t size);
data

Puntero al bloque de memoria.

size

Tamaño en bytes del bloque de memoria.

Retorna

El objeto stream.

Observaciones

El bloque original no será modificado (solo lectura). Cuando se alcance el final del bloque stm_state devolverá ekSTEND. Block stream.


stm_memory ()

Crea un stream de lectura/escritura en memoria.

Stream*
stm_memory(const uint32_t size);
size

Tamaño inicial del búfer (en bytes). Crecerá si es necesario.

Retorna

El objeto stream.

Observaciones

Puede utilizarse como tubería interna para el intercambio de información entre funciones o hilos. Se comporta como un búfer FIFO (First In Fist Out). Para acceso multi-hilo debe estar protegido con un Mutex. Memory stream.


stm_from_file ()

Crea un stream para leer desde un archivo en disco.

Stream*
stm_from_file(const char_t *pathname,
              ferror_t *error);
pathname

Pathname del archivo. Filename y pathname.

error

Código de error si la función falla. Puede ser NULL.

Retorna

El objeto stream o NULL si falla la apertura del archivo.

Observaciones

File stream.


stm_to_file ()

Crea un stream para escribir datos a un archivo en disco.

Stream*
stm_to_file(const char_t *pathname,
            ferror_t *error);
pathname

Pathname del archivo. Filename y pathname.

error

Código de error si la función falla. Puede ser NULL.

Retorna

El objeto stream o NULL si falla la creación del archivo.

Observaciones

Si el archivo ya existe será sobrescrito. File stream.


stm_append_file ()

Crea un stream para escribir datos al final de un archivo existente.

Stream*
stm_append_file(const char_t *pathname,
                ferror_t *error);
pathname

Pathname del archivo. Filename y pathname.

error

Código de error si la función falla. Puede ser NULL.

Retorna

El objeto stream o NULL si falla la apertura del archivo.

Observaciones

Fallará si el archivo no existe (no lo crea). File stream.


stm_socket ()

Crea un stream y conecta con un host remoto.

Stream*
stm_socket(const uint32_t ip,
           const uint16_t port,
           const SockOpt *opts,
           serror_t *error);
ip

La dirección IPv4 de 32-bit. bsocket_host_ip.

port

El puerto de conexión.

opts

Opciones de conexión.

error

Código de error si la función falla. Puede ser NULL.

Retorna

El objeto stream o NULL si falla la conexión.

Observaciones

Socket stream.


stm_close ()

Cierra el stream. Todos los recursos como descriptores de archivos o sockets serán liberados. Previamente al cierre, se escribirán en el canal los datos en caché stm_flush.

void
stm_close(Stream **stm);
stm

El objeto stream. Será puesto a NULL tras la destrucción.


stm_get_write_endian ()

Obtiene el orden de bytes actual al escribir en el stream.

endian_t
stm_get_write_endian(const Stream *stm);
stm

El objeto stream.

Retorna

El Orden de bytes.


stm_get_read_endian ()

Obtiene el orden de bytes actual al leer del stream.

endian_t
stm_get_read_endian(const Stream *stm);
stm

El objeto stream.

Retorna

El Orden de bytes.


stm_set_write_endian ()

Establece el orden de bytes al escribir en el stream, a partir de ahora.

void
stm_set_write_endian(Stream *stm,
                     const endian_t endian);
stm

El objeto stream.

endian

El Orden de bytes.

Observaciones

Por defecto es ekLITEND, salvo en sockets que será ekBIGEND.


stm_set_read_endian ()

Establece el orden de bytes al leer del stream, a partir de ahora.

void
stm_set_read_endian(Stream *stm,
                    const endian_t endian);
stm

El objeto stream.

endian

El Orden de bytes.

Observaciones

Por defecto es ekLITEND, salvo en sockets que será ekBIGEND.


stm_get_write_utf ()

Obtiene la codificación UTF con la que se están escribiendo los textos en el stream.

unicode_t
stm_get_write_utf(const Stream *stm);
stm

El objeto stream.

Retorna

Codificaciones UTF.


stm_get_read_utf ()

Obtiene la codificación UTF con la que se están leyendo los textos en el stream.

unicode_t
stm_get_read_utf(const Stream *stm);
stm

El objeto stream.

Retorna

Codificaciones UTF.


stm_set_write_utf ()

Establece la codificación UTF al escribir textos en el stream, a partir de ahora.

void
stm_set_write_utf(Stream *stm,
                  const unicode_t format);
stm

El objeto stream.

format

Codificaciones UTF.


stm_set_read_utf ()

Establece la codificación UTF al leer textos en el stream, a partir de ahora.

void
stm_set_read_utf(Stream *stm,
                 const unicode_t format);
stm

El objeto stream.

format

Codificaciones UTF.


stm_bytes_written ()

Obtiene el total de bytes escritos en el stream desde su creación.

uint64_t
stm_bytes_written(const Stream *stm);
stm

El objeto stream.

Retorna

El número total de bytes escritos.


stm_bytes_readed ()

Obtiene el total de bytes leídos desde el stream desde su creación.

uint64_t
stm_bytes_readed(const Stream *stm);
stm

El objeto stream.

Retorna

El número total de bytes leídos.


stm_state ()

Obtiene el estado actual del stream.

sstate_t
stm_state(const Stream *stm);
stm

El objeto stream.

Retorna

El Estado del stream.


stm_file_err ()

Obtiene información adicional sobre el error, en streams de disco.

ferror_t
stm_file_err(const Stream *stm);
stm

El objeto stream.

Retorna

Error de archivo.

Observaciones

Solo es relevante en File stream con el estado ekSTBROKEN.


stm_sock_err ()

Obtiene información adicional sobre el error, en streams de red.

serror_t
stm_sock_err(const Stream *stm);
stm

El objeto stream.

Retorna

Error de socket.

Observaciones

Solo es relevante en Socket stream con el estado ekSTBROKEN.


stm_corrupt ()

Establece el estado del stream a ekSTCORRUPT.

void
stm_corrupt(Stream *stm);
stm

El objeto stream.

Observaciones

En ocasiones, es la aplicación la que detecta que los datos están corruptos ya que la semántica de los mismos no coincide con lo esperado.


stm_str ()

Crea un string con el contenido actual del búfer interno. Solo es válido para stream en memoria. stm_memory.

String*
stm_str(const Stream *stm);
stm

El objeto stream.

Retorna

El string con el contenido del búfer.


stm_buffer ()

Obtiene un puntero al contenido actual del búfer interno. Solo es válido para stream en memoria. stm_memory.

const byte_t*
stm_buffer(const Stream *stm);
stm

El objeto stream.

Retorna

Puntero al búfer interno.

Observaciones

Este puntero es de solo lectura. Escribir aquí tendrá consecuencias indeseadas.


stm_buffer_size ()

Obtiene el tamaño actual del búfer interno. Solo es válido para stream en memoria. stm_memory.

uint32_t
stm_buffer_size(const Stream *stm);
stm

El objeto stream.

Retorna

El tamaño del búfer interno (en bytes).


stm_write ()

Escribe bytes en el stream.

void
stm_write(Stream *stm,
          const byte_t *data,
          const uint32_t size);
stm

El objeto stream.

data

Puntero al bloque de datos a escribir.

size

Número de bytes a escribir.

Observaciones

El bloque se escribe tal cual llega, sin tener en cuenta el Orden de bytes ni las Codificaciones UTF.


stm_write_char ()

Escribe un carácter Unicode en el stream.

void
stm_write_char(Stream *stm,
               const uint32_t codepoint);
stm

El objeto stream.

codepoint

El código Unicode del carácter.

Observaciones

La codificación se puede cambiar con stm_set_write_utf.


stm_printf ()

Escribe texto en el stream, utilizando el formato del printf.

uint32_t
stm_printf(Stream *stm,
           const char_t *format,
           ...);
1
stm_printf(stream, Code: %-10s Price %5.2f\n
stm

El objeto stream.

format

Cadena con el formato tipo-printf con un número variable de parámetros.

...

Argumentos o variables del printf.

Retorna

El número de bytes escritos.

Observaciones

El carácter nulo final ('\0') no será escrito. La codificación se puede cambiar con stm_set_write_utf.


stm_writef ()

Escribe una cadena C UTF8 en el stream.

uint32_t
stm_writef(Stream *stm,
           const char_t *str);
stm

El objeto stream.

str

Cadena C UTF8 terminada en carácter nulo '\0'.

Retorna

El número de bytes escritos.

Observaciones

El carácter nulo final ('\0') no será escrito. Está función es más rápida que stm_printf cuando la cadena es constante y no necesita formato. Para objetos String utiliza str_writef. La codificación se puede cambiar con stm_set_write_utf.


stm_write_bool ()

Escribe una variable bool_t en el stream.

void
stm_write_bool(Stream *stm,
               const bool_t value);
stm

El objeto stream.

value

Variable a escribir.

Observaciones

Es una escritura binaria. No utilizar en streams de texto "puros".


stm_write_i8 ()

Escribe una variable int8_t en el stream.

void
stm_write_i8(Stream *stm,
             const int8_t value);
stm

El objeto stream.

value

Variable a escribir.

Observaciones

Es una escritura binaria. No utilizar en streams de texto "puros".


stm_write_i16 ()

Escribe una variable int16_t en el stream.

void
stm_write_i16(Stream *stm,
              const int16_t value);
stm

El objeto stream.

value

Variable a escribir.

Observaciones

Es una escritura binaria. No utilizar en streams de texto "puros". Orden de bytes.


stm_write_i32 ()

Escribe una variable int32_t en el stream.

void
stm_write_i32(Stream *stm,
              const int32_t value);
stm

El objeto stream.

value

Variable a escribir.

Observaciones

Es una escritura binaria. No utilizar en streams de texto "puros". Orden de bytes.


stm_write_i64 ()

Escribe una variable int64_t en el stream.

void
stm_write_i64(Stream *stm,
              const int64_t value);
stm

El objeto stream.

value

Variable a escribir.

Observaciones

Es una escritura binaria. No utilizar en streams de texto "puros". Orden de bytes.


stm_write_u8 ()

Escribe una variable uint8_t en el stream.

void
stm_write_u8(Stream *stm,
             const uint8_t value);
stm

El objeto stream.

value

Variable a escribir.

Observaciones

Es una escritura binaria. No utilizar en streams de texto "puros".


stm_write_u16 ()

Escribe una variable uint16_t en el stream.

void
stm_write_u16(Stream *stm,
              const uint16_t value);
stm

El objeto stream.

value

Variable a escribir.

Observaciones

Es una escritura binaria. No utilizar en streams de texto "puros". Orden de bytes.


stm_write_u32 ()

Escribe una variable uint32_t en el stream.

void
stm_write_u32(Stream *stm,
              const uint32_t value);
stm

El objeto stream.

value

Variable a escribir.

Observaciones

Es una escritura binaria. No utilizar en streams de texto "puros". Orden de bytes.


stm_write_u64 ()

Escribe una variable uint64_t en el stream.

void
stm_write_u64(Stream *stm,
              const uint64_t value);
stm

El objeto stream.

value

Variable a escribir.

Observaciones

Es una escritura binaria. No utilizar en streams de texto "puros". Orden de bytes.


stm_write_r32 ()

Escribe una variable real32_t en el stream.

void
stm_write_r32(Stream *stm,
              const real32_t value);
stm

El objeto stream.

value

Variable a escribir.

Observaciones

Es una escritura binaria. No utilizar en streams de texto "puros". Orden de bytes.


stm_write_r64 ()

Escribe una variable real64_t en el stream.

void
stm_write_r64(Stream *stm,
              const real64_t value);
stm

El objeto stream.

value

Variable a escribir.

Observaciones

Es una escritura binaria. No utilizar en streams de texto "puros". Orden de bytes.


stm_write_enum ()

Escribe una variable enum en el stream.

void
stm_write_enum(Stream *stm,
               const type value,
               type);
stm

El objeto stream.

value

Variable a escribir.

type

El tipo del enum.

Observaciones

Es una escritura binaria. No utilizar en streams de texto "puros". Orden de bytes.


stm_read ()

Lee bytes desde el stream.

uint32_t
stm_read(Stream *stm,
         byte_t *data,
         const uint32_t size);
stm

El objeto stream.

data

Puntero al búfer donde se escribirán los datos leídos.

size

La cantidad de bytes a leer (tamaño del búfer).

Retorna

El número de bytes realmente leídos.


stm_skip ()

Salta e ignora los próximos bytes del stream.

void
stm_skip(Stream *stm,
         const uint32_t size);
stm

El objeto stream.

size

La cantidad de bytes a saltar.


stm_read_char ()

Lee un carácter de texto desde el stream.

uint32_t
stm_read_char(Stream *stm);
stm

El objeto stream.

Retorna

El código Unicode del carácter.

Observaciones

La codificación del texto de entrada puede ajustarse con stm_set_read_utf.


stm_read_chars ()

Lee varios caracteres desde el stream.

const char_t*
stm_read_chars(Stream *stm,
               const uint32_t n);
stm

El objeto stream.

n

La cantidad de caracteres a leer.

Retorna

Puntero a la cadena C UTF8 leída. Terminará con el carácter nulo '\0'.

Observaciones

El puntero devuelto es temporal y será sobrescrito en la próxima lectura. Si es necesario, haz una copia con str_c. La codificación del texto de entrada puede ajustarse con stm_set_read_utf.


stm_read_line ()

Lee caracteres del stream hasta alcanzar un final de línea '\n'.

const char_t*
stm_read_line(Stream *stm);
stm

El objeto stream.

Retorna

Puntero a la cadena C UTF8 leída. Terminará con el carácter nulo '\0'. Los caracteres '\n' o '\r\n' serán eliminados.

Observaciones

El puntero devuelto es temporal y será sobrescrito en la próxima lectura. Si es necesario, haz una copia con str_c. La codificación del texto de entrada puede ajustarse con stm_set_read_utf.


stm_read_delim ()

Lee caracteres del stream hasta alcanzar un carácter delimitador.

const char_t*
stm_read_delim(Stream *stm,
               const uint32_t codepoint);
stm

El objeto stream.

codepoint

El carácter delimitador.

Retorna

Puntero a la cadena C UTF8 leída. Terminará con el carácter nulo '\0'.

Observaciones

Útil para leer tokens sencillos desde streams de texto. Si necesitas mayor control sobre los tokens utiliza lexscn_token. El carácter delimitador será eliminado del stream y no incluido en el resultado. El puntero devuelto es temporal y será sobrescrito en la próxima lectura. Si es necesario, haz una copia con str_c. La codificación del texto de entrada puede ajustarse con stm_set_read_utf.


stm_read_trim ()

Lee la siguiente token delimitado por espacios en blanco.

const char_t*
stm_read_trim(Stream *stm);
stm

El objeto stream.

Retorna

Puntero a la cadena C UTF8 leída. Terminará con el carácter nulo '\0'.

Observaciones

Útil para leer tokens sencillos desde streams de texto. Ignorará todos los espacios en blanco iniciales y leerá caracteres hasta encontrar el primer blanco (' ', '\\t', '\\n', '\\v', '\\f', '\\r'). Si necesitas mayor control sobre los tokens utiliza lexscn_token. El puntero devuelto es temporal y será sobrescrito en la próxima lectura. Si es necesario, haz una copia con str_c. La codificación del texto de entrada puede ajustarse con stm_set_read_utf.


stm_read_bool ()

Lee una variable bool_t desde el stream.

bool_t
stm_read_bool(Stream *stm);
stm

El objeto stream.

Retorna

Variable leída.

Observaciones

Es una lectura binaria. No utilizar en streams de texto "puros".


stm_read_i8 ()

Lee una variable int8_t desde el stream.

int8_t
stm_read_i8(Stream *stm);
stm

El objeto stream.

Retorna

Variable leída.

Observaciones

Es una lectura binaria. No utilizar en streams de texto "puros".


stm_read_i16 ()

Lee una variable int16_t desde el stream.

int16_t
stm_read_i16(Stream *stm);
stm

El objeto stream.

Retorna

Variable leída.

Observaciones

Es una lectura binaria. No utilizar en streams de texto "puros". Orden de bytes.


stm_read_i32 ()

Lee una variable int32_t desde el stream.

int32_t
stm_read_i32(Stream *stm);
stm

El objeto stream.

Retorna

Variable leída.

Observaciones

Es una lectura binaria. No utilizar en streams de texto "puros". Orden de bytes.


stm_read_i64 ()

Lee una variable int64_t desde el stream.

int64_t
stm_read_i64(Stream *stm);
stm

El objeto stream.

Retorna

Variable leída.

Observaciones

Es una lectura binaria. No utilizar en streams de texto "puros". Orden de bytes.


stm_read_u8 ()

Lee una variable uint8_t desde el stream.

uint8_t
stm_read_u8(Stream *stm);
stm

El objeto stream.

Retorna

Variable leída.

Observaciones

Es una lectura binaria. No utilizar en streams de texto "puros".


stm_read_u16 ()

Lee una variable uint16_t desde el stream.

uint16_t
stm_read_u16(Stream *stm);
stm

El objeto stream.

Retorna

Variable leída.

Observaciones

Es una lectura binaria. No utilizar en streams de texto "puros". Orden de bytes.


stm_read_u32 ()

Lee una variable uint32_t desde el stream.

uint32_t
stm_read_u32(Stream *stm);
stm

El objeto stream.

Retorna

Variable leída.

Observaciones

Es una lectura binaria. No utilizar en streams de texto "puros". Orden de bytes.


stm_read_u64 ()

Lee una variable uint64_t desde el stream.

uint64_t
stm_read_u64(Stream *stm);
stm

El objeto stream.

Retorna

Variable leída.

Observaciones

Es una lectura binaria. No utilizar en streams de texto "puros". Orden de bytes.


stm_read_r32 ()

Lee una variable real32_t desde el stream.

real32_t
stm_read_r32(Stream *stm);
stm

El objeto stream.

Retorna

Variable leída.

Observaciones

Es una lectura binaria. No utilizar en streams de texto "puros". Orden de bytes.


stm_read_r64 ()

Lee una variable real64_t desde el stream.

real64_t
stm_read_r64(Stream *stm);
stm

El objeto stream.

Retorna

Variable leída.

Observaciones

Es una lectura binaria. No utilizar en streams de texto "puros". Orden de bytes.


stm_read_enum ()

Lee una variable enum desde el stream.

type
stm_read_enum(Stream *stm,
              type);
stm

El objeto stream.

type

El tipo del enum.

Retorna

Variable leída.

Observaciones

Es una lectura binaria. No utilizar en streams de texto "puros". Orden de bytes.


stm_flush ()

Escribe en el canal la información existente en la caché.

void
stm_flush(Stream *stm);
stm

El objeto stream.

Observaciones

Para mejorar el rendimiento, las operaciones de escritura en streams de disco o sockets se almacenan en una caché interna del stream. Esta función fuerza la escritura en el canal y limpia el búfer. Será útil con protocolos full-duplex donde el receptor espera contestación para continuar.


stm_pipe ()

Conecta dos streams, leyendo datos de uno y escribiéndolos en otro.

void
stm_pipe(Stream *from,
         Stream *to,
         const uint32_t n);
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// This example is based in a private protocol.
// Read from socket n-bytes and write them to file.
uint32_t ip;
uint32_t size;
Stream *sockstm;
Stream *filestm;
bsocket_host_ip("www.myserver.com", &ip, NULL);
sockstm = stm_socket(ip, 1647, NULL);
filestm = stm_to_file("C:\Users\peter\image.png", NULL);
stm_writef(sockstm, "Give me file 'peter.png'");
size = stm_read_u32(sockstm, NULL);
stm_pipe(sockstm, filestm, size);
stm_close(&sockstm);
stm_close(&filestm);
from

El objeto stream de entrada (para leer).

to

El objeto stream de salida (para escribir).

n

La cantidad de bytes a trasvasar.

Observaciones

El trasvase se realizará sobre datos "en bruto", sin tener en cuenta Orden de bytes o Codificaciones UTF. Si tienes claro que esto no afecta, es mucho más rápido que utilizar operaciones atómicas de lectura/escritura.


stm_lines ()

Itera sobre todas las líneas en un Text stream. Debes usar stm_next para cerrar el bucle.

void
stm_lines(const char_t *line,
          Stream *stm);
1
2
3
4
5
6
uint32_t i = 1;
Stream *stm = stm_from_file("/home/john/friends.txt", NULL);
stm_lines(line, stm)
    bstd_printf("Friend %d, name %s\n", i++, line);
stm_next(line, stm);
stm_close(&stm);
line

Nombre de la variable que albergará temporalmente la línea. Utiliza una caché interna del stream, por lo que deberás hacer una copia con str_c si necesitas conservarla.

stm

Stream.


stm_next ()

Cierra un bucle abierto por stm_lines.

void
stm_next(const char_t *line,
         Stream *stm);
line

Nombre de la variable línea.

stm

Stream.

❮ Anterior
Siguiente ❯