/* * 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" struct Stream_Chunk{ Application_Links *app; Buffer_Summary *buffer; char *base_data; int32_t start, end; int32_t min_start, max_end; bool32 add_null; int32_t data_size; char *data; }; static int32_t round_down(int32_t x, int32_t b){ int32_t r = 0; if (x >= 0){ r = x - (x % b); } return(r); } static int32_t round_up(int32_t x, int32_t b){ int32_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, int32_t pos, char *data, int32_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; int32_t start, end; int32_t count, token_count; }; static bool32 init_stream_tokens(Stream_Tokens *stream, Application_Links *app, Buffer_Summary *buffer, int32_t pos, Cpp_Token *data, int32_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 = count; stream->start = round_down(pos, count); stream->end = 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