4coder/4coder_helper/4coder_streaming.h

260 lines
7.0 KiB
C
Raw Normal View History

/*
* Helpers for streaming over buffer data to avoid having to read it all at once.
*/
// TOP
#if !defined(FCODER_STREAMING_H)
#define FCODER_STREAMING_H
#include "4coder_helper/4coder_helper.h"
// TODO(allen): Rewrite the backward seek to get this on size_t instead of int64_t.
struct Stream_Chunk{
Application_Links *app;
Buffer_Summary *buffer;
char *base_data;
int64_t start, end;
int64_t min_start, max_end;
int64_t data_size;
bool32 add_null;
char *data;
};
static uint64_t
round_down(uint64_t x, uint64_t b){
uint64_t r = 0;
if (x >= 0){
r = x - (x % b);
}
return(r);
}
static uint64_t
round_up(uint64_t x, uint64_t b){
uint64_t r = 0;
if (x >= 0){
r = x - (x % b) + b;
}
return(r);
}
static bool32
init_stream_chunk(Stream_Chunk *chunk, Application_Links *app, Buffer_Summary *buffer, size_t pos, char *data, size_t size){
bool32 result = 0;
refresh_buffer(app, buffer);
if (pos >= 0 && pos < buffer->size && size > 0){
chunk->app = app;
chunk->buffer = buffer;
chunk->base_data = data;
chunk->data_size = size;
chunk->start = round_down(pos, size);
chunk->end = round_up(pos, size);
if (chunk->max_end > buffer->size || chunk->max_end == 0){
chunk->max_end = buffer->size;
}
if (chunk->max_end && chunk->max_end < chunk->end){
chunk->end = chunk->max_end;
}
if (chunk->min_start && chunk->min_start > chunk->start){
chunk->start = chunk->min_start;
}
if (chunk->start < chunk->end){
buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data);
chunk->data = chunk->base_data - chunk->start;
result = 1;
}
}
return(result);
}
static bool32
forward_stream_chunk(Stream_Chunk *chunk){
Application_Links *app = chunk->app;
Buffer_Summary *buffer = chunk->buffer;
bool32 result = 0;
refresh_buffer(app, buffer);
if (chunk->end < buffer->size){
chunk->start = chunk->end;
chunk->end += chunk->data_size;
if (chunk->max_end && chunk->max_end < chunk->end){
chunk->end = chunk->max_end;
}
if (chunk->min_start && chunk->min_start > chunk->start){
chunk->start = chunk->min_start;
}
if (chunk->start < chunk->end){
buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data);
chunk->data = chunk->base_data - chunk->start;
result = 1;
}
}
else if (chunk->add_null && chunk->end + 1 < buffer->size){
chunk->start = buffer->size;
chunk->end = buffer->size + 1;
chunk->base_data[0] = 0;
chunk->data = chunk->base_data - chunk->start;
result = 1;
}
return(result);
}
static bool32
backward_stream_chunk(Stream_Chunk *chunk){
Application_Links *app = chunk->app;
Buffer_Summary *buffer = chunk->buffer;
bool32 result = 0;
refresh_buffer(app, buffer);
if (chunk->start > 0){
chunk->end = chunk->start;
chunk->start -= chunk->data_size;
if (chunk->max_end && chunk->max_end < chunk->end){
chunk->end = chunk->max_end;
}
if (chunk->min_start && chunk->min_start > chunk->start){
chunk->start = chunk->min_start;
}
if (chunk->start < chunk->end){
buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data);
chunk->data = chunk->base_data - chunk->start;
result = 1;
}
}
else if (chunk->add_null && chunk->start > -1){
chunk->start = -1;
chunk->end = 0;
chunk->base_data[0] = 0;
chunk->data = chunk->base_data - chunk->start;
result = 1;
}
return(result);
}
struct Stream_Tokens{
Application_Links *app;
Buffer_Summary *buffer;
Cpp_Token *base_tokens;
Cpp_Token *tokens;
int64_t start, end;
int64_t count, token_count;
};
static bool32
init_stream_tokens(Stream_Tokens *stream, Application_Links *app, Buffer_Summary *buffer, size_t pos, Cpp_Token *data, size_t count){
bool32 result = 0;
refresh_buffer(app, buffer);
int32_t token_count = buffer_token_count(app, buffer);
if (buffer->tokens_are_ready && pos >= 0 && pos < token_count && count > 0){
stream->app = app;
stream->buffer = buffer;
stream->base_tokens = data;
stream->count = (int64_t)count;
stream->start = (int64_t)round_down(pos, count);
stream->end = (int64_t)round_up(pos, count);
stream->token_count = token_count;
if (stream->start < 0){
stream->start = 0;
}
if (stream->end > stream->token_count){
stream->end = stream->token_count;
}
buffer_read_tokens(app, buffer, stream->start, stream->end, stream->base_tokens);
stream->tokens = stream->base_tokens - stream->start;
result = 1;
}
return(result);
}
static Stream_Tokens
begin_temp_stream_token(Stream_Tokens *stream){
return(*stream);
}
static void
end_temp_stream_token(Stream_Tokens *stream, Stream_Tokens temp){
if (stream->start != temp.start || stream->end != temp.end){
Application_Links *app = stream->app;
buffer_read_tokens(app, temp.buffer, temp.start, temp.end, temp.base_tokens);
stream->tokens = stream->base_tokens - temp.start;
stream->start = temp.start;
stream->end = temp.end;
}
}
static bool32
forward_stream_tokens(Stream_Tokens *stream){
Application_Links *app = stream->app;
Buffer_Summary *buffer = stream->buffer;
bool32 result = 0;
refresh_buffer(app, buffer);
if (stream->end < stream->token_count){
stream->start = stream->end;
stream->end += stream->count;
if (stream->end > stream->token_count){
stream->end = stream->token_count;
}
if (stream->start < stream->end){
buffer_read_tokens(app, buffer, stream->start, stream->end, stream->base_tokens);
stream->tokens = stream->base_tokens - stream->start;
result = 1;
}
}
return(result);
}
static bool32
backward_stream_tokens(Stream_Tokens *stream){
Application_Links *app = stream->app;
Buffer_Summary *buffer = stream->buffer;
bool32 result = 0;
refresh_buffer(app, buffer);
if (stream->start > 0){
stream->end = stream->start;
stream->start -= stream->count;
if (0 > stream->start){
stream->start = 0;
}
if (stream->start < stream->end){
buffer_read_tokens(app, buffer, stream->start, stream->end, stream->base_tokens);
stream->tokens = stream->base_tokens - stream->start;
result = 1;
}
}
return(result);
}
#endif
// BOTTOM