void buffer_stream_initialize( stream_buffer_t* stream, void* buffer, unsigned int mode, uint64_t size, uint64_t capacity, bool adopt, bool grow ) { memset( stream, 0, sizeof( stream_buffer_t ) ); stream_initialize( (stream_t*)stream, system_byteorder() ); if( !FOUNDATION_VALIDATE_MSG( adopt || !grow, "Cannot grow buffer streams that are not adopted" ) ) grow = false; if( !buffer ) { size = 0; capacity = 0; } if( size > capacity ) size = capacity; stream->type = STREAMTYPE_MEMORY; stream->path = string_format( "buffer://0x%" PRIfixPTR, stream ); stream->mode = mode & ( STREAM_OUT | STREAM_IN | STREAM_BINARY ); stream->buffer = buffer; stream->size = size; stream->capacity = capacity; stream->own = adopt; stream->grow = ( adopt && grow ); if( mode & STREAM_TRUNCATE ) stream->size = 0; if( mode & STREAM_ATEND ) stream->current = stream->size; stream->vtable = &_buffer_stream_vtable; }
void pipe_initialize( stream_pipe_t* pipestream ) { stream_t* stream = (stream_t*)pipestream; memset( stream, 0, sizeof( stream_pipe_t ) ); stream_initialize( stream, system_byteorder() ); pipestream->type = STREAMTYPE_PIPE; pipestream->path = string_format( "pipe://0x" PRIfixPTR, pipestream ); pipestream->mode = STREAM_OUT | STREAM_IN | STREAM_BINARY; pipestream->sequential = true; #if FOUNDATION_PLATFORM_WINDOWS { //Inheritable by default so process can use for stdstreams SECURITY_ATTRIBUTES security_attribs = {0}; security_attribs.nLength = sizeof( SECURITY_ATTRIBUTES ); security_attribs.bInheritHandle = TRUE; security_attribs.lpSecurityDescriptor = 0; if( !CreatePipe( &pipestream->handle_read, &pipestream->handle_write, &security_attribs, 0 ) ) log_warnf( 0, WARNING_SYSTEM_CALL_FAIL, "Unable to create unnamed pipe: %s", system_error_message( GetLastError() ) ); } #elif FOUNDATION_PLATFORM_POSIX || FOUNDATION_PLATFORM_PNACL int fds[2] = { 0, 0 }; if( pipe( fds ) < 0 ) log_warnf( 0, WARNING_SYSTEM_CALL_FAIL, "Unable to create unnamed pipe: %s", system_error_message( 0 ) ); pipestream->fd_read = fds[0]; pipestream->fd_write = fds[1]; #endif pipestream->vtable = &_pipe_stream_vtable; }
void buffer_stream_initialize(stream_buffer_t* stream, void* buffer, unsigned int mode, size_t size, size_t capacity, bool adopt, bool grow) { memset(stream, 0, sizeof(stream_buffer_t)); stream_initialize((stream_t*)stream, system_byteorder()); if (!adopt && grow) { log_warn(0, WARNING_INVALID_VALUE, STRING_CONST("Cannot grow buffer streams that are not adopted")); grow = false; } if (!buffer) { size = 0; capacity = 0; } if (size > capacity) size = capacity; stream->type = STREAMTYPE_MEMORY; stream->path = string_allocate_format(STRING_CONST("buffer://0x%" PRIfixPTR), (uintptr_t)stream); stream->mode = mode & (STREAM_OUT | STREAM_IN | STREAM_BINARY); stream->buffer = buffer; stream->size = size; stream->capacity = capacity; stream->own = adopt; stream->grow = (adopt && grow); stream->lastmod = time_current(); if ((mode & STREAM_OUT) && (mode & STREAM_TRUNCATE)) stream->size = 0; if (mode & STREAM_ATEND) stream->current = stream->size; stream->vtable = &_buffer_stream_vtable; }
void socket_stream_initialize(socket_stream_t* stream, socket_t* sock) { //Network streams are always little endian by default stream_initialize((stream_t*)stream, BYTEORDER_LITTLEENDIAN); stream->type = STREAMTYPE_SOCKET; stream->sequential = 1; stream->mode = STREAM_OUT | STREAM_IN | STREAM_BINARY; stream->vtable = &_socket_stream_vtable; stream->socket = sock; if (sock->stream_initialize_fn) sock->stream_initialize_fn(sock, (stream_t*)stream); }
void ringbuffer_stream_initialize( stream_ringbuffer_t* stream, unsigned int buffer_size, uint64_t total_size ) { memset( stream, 0, sizeof( stream_ringbuffer_t ) ); stream_initialize( (stream_t*)stream, system_byteorder() ); stream->type = STREAMTYPE_RINGBUFFER; stream->sequential = 1; stream->path = string_format( "ringbuffer://0x%" PRIfixPTR, stream ); stream->mode = STREAM_OUT | STREAM_IN | STREAM_BINARY; ringbuffer_initialize( RINGBUFFER_FROM_STREAM( stream ), buffer_size ); semaphore_initialize( &stream->signal_read, 0 ); semaphore_initialize( &stream->signal_write, 0 ); stream->total_size = total_size; stream->vtable = &_ringbuffer_stream_vtable; }
size_t utf8normalize(const char* input, size_t inputSize, char* target, size_t targetSize, size_t flags, int32_t* errors) { char* dst = target; size_t dst_size = targetSize; StreamState stream[4]; DecomposeState decompose_state; ComposeState compose_state; uint8_t compatibility = (flags & UTF8_NORMALIZE_COMPATIBILITY) != 0; StreamState* stream_output; uint8_t finished = 0; size_t bytes_written = 0; /* Decomposition uses the following process: input --> stream[0] --> (decompose) --> stream[1] --> (accumulate) --> stream[2] --> output The accumulation step is necessary in order to prevent buffer overflow attacks. Composition adds another stream buffer: input --> stream[0] --> (decompose) --> stream[1] --> (accumulate) --> stream[2] --> (compose) --> stream[3] --> output Although four streaming buffers may seem excessive, they are necessary for preventing allocations on the heap. */ /* Check for valid flags */ if ((flags & (UTF8_NORMALIZE_DECOMPOSE | UTF8_NORMALIZE_COMPOSE)) == 0) { UTF8_SET_ERROR(INVALID_FLAG); return bytes_written; } /* Validate parameters */ UTF8_VALIDATE_PARAMETERS_CHAR(char, bytes_written); /* Initialize decomposition */ memset(stream, 0, sizeof(stream)); if (!stream_initialize(&stream[0], input, inputSize) || !decompose_initialize(&decompose_state, &stream[0], &stream[1], compatibility)) { UTF8_SET_ERROR(INVALID_DATA); return bytes_written; } stream_output = &stream[2]; if ((flags & UTF8_NORMALIZE_COMPOSE) != 0) { /* Initialize composition */ if (!compose_initialize(&compose_state, &stream[2], &stream[3], compatibility)) { UTF8_SET_ERROR(INVALID_DATA); return bytes_written; } stream_output = &stream[3]; } do { uint8_t write = 0; /* Accumulate decomposed input in next stream */ if (stream[1].current > 0) { unicode_t* src_codepoint = stream[1].codepoint; unicode_t* dst_codepoint = stream[2].codepoint + stream[2].filled; uint8_t* src_qc = stream[1].quick_check; uint8_t* dst_qc = stream[2].quick_check + stream[2].filled; uint8_t* src_ccc = stream[1].canonical_combining_class; uint8_t* dst_ccc = stream[2].canonical_combining_class + stream[2].filled; if ((flags & UTF8_NORMALIZE_COMPOSE) != 0) { uint8_t i; /* Update stream properties to use composition values */ for (i = 0; i < stream[1].current; ++i) { *dst_qc++ = PROPERTY_GET(compose_state.qc_index, compose_state.qc_data, *src_codepoint); *dst_ccc++ = *src_ccc++; *dst_codepoint++ = *src_codepoint++; } } else { /* Copy directly */ memcpy(dst_codepoint, src_codepoint, stream[1].current * sizeof(unicode_t)); memcpy(dst_qc, src_qc, stream[1].current * sizeof(uint8_t)); memcpy(dst_ccc, src_ccc, stream[1].current * sizeof(uint8_t)); } stream[2].current += stream[1].current; stream[2].filled += stream[1].current; } /* Decompose input sequence into next stream */ finished = !decompose_execute(&decompose_state); if (!finished) { /* Output current stream it it could overflow accumulation buffer */ write = (stream[1].current + stream[2].filled) >= STREAM_SAFE_MAX; } /* Reorder potentially unordered decomposed stream */ if (!stream[1].stable) { stream_reorder(&stream[1]); } /* Write stream to output when overflowing or when accumulation buffer is empty*/ if (write || finished) { uint8_t i; /* Compose accumulation buffer */ if ((flags & UTF8_NORMALIZE_COMPOSE) != 0 && !compose_execute(&compose_state)) { break; } /* Write to output buffer */ for (i = 0; i < stream_output->current; ++i) { uint8_t encoded_size = codepoint_write(stream_output->codepoint[i], &dst, &dst_size); if (encoded_size == 0) { UTF8_SET_ERROR(NOT_ENOUGH_SPACE); return bytes_written; } bytes_written += encoded_size; } /* Reset accumulation buffer */ stream[2].current = 0; stream[2].filled = 0; } } while (!finished); UTF8_SET_ERROR(NONE); return bytes_written; }