Streams
El agua puede fluir, arrastrarse, gotear o estrellarse, sé agua amigo mío. Bruce Lee
Funciones
Tipos y Constantes
Stream | kSTDIN |
Stream | kSTDOUT |
Stream | kSTDERR |
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.

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.

- Utiliza stm_from_file para abrir un archivo y leer de él.
- Utiliza stm_to_file para crear un archivo y escribir en él.
- Utiliza stm_append_file para añadir contenido a un archivo existente.
1 2 3 4 5 6 7 8 9 10 |
Stream *stm = stm_to_file("C:\Users\user\john\out.txt", NULL); if (stm != NULL) { stm_writef(stm, "One "); stm_writef(stm, "Two "); stm_writef(stm, "Three"); stm_writef(stm, "."); stm_close(&stm); // 'out.txt' is closed = "One Two Three." } |
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.

- Utiliza stm_socket para conectar con un proceso remoto.
1 2 3 4 5 6 7 8 9 10 11 12 |
uint32_t ip; Stream *stm; bsocket_host_ip("www.google.com", &ip, NULL); stm = stm_socket(ip, 80, NULL); stm_writef(stm, "GET / HTTP/1.1\r\n"); stm_writef(stm, "Host: www.google.com\r\n"); stm_writef(stm, "\r\n"); stm_lines(line, stm) bstd_printf(line); bstd_printf("\n"); stm_next(line, stm); stm_close(&stm); |
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.

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.

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.
- kSTDIN: Para leer de la entrada estándar.
- kSTDOUT: Para escribir en la salida estándar.
- kSTDERR: Para escribir en la salida de errores.

1 2 3 4 5 |
real64_t value; const char_t *line; value = stm_read_r64(kSTDIN); line = stm_read_line(kSTDIN); stm_printf(kSTDOUT, "Value = %.4f", value); |
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.
- Utiliza stm_printf o stm_writef para escribir texto en un stream.
- Utiliza stm_read_char, stm_read_line o stm_read_delim para leer texto desde un stream. Si precisas de un mayor nivel de detalle en la interpretación de los textos, puedes utilizar el stream con el analizador léxico Analizador léxico con el fin de fragmentar el texto en tokens lexscn_token.
- Utiliza stm_set_read_utf o stm_set_write_utf para cambiar las Codificaciones UTF de entrada o salida de textos.

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).
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); } |

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).
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.
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.

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.

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 |
Retorna
El objeto stream o NULL
si falla la apertura del archivo.
Observaciones
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 |
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 |
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 |
Retorna
El objeto stream o NULL
si falla la conexión.
Observaciones
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 |
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
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
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 |
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 |
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
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 |
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 |
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 |
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. |