Sat, 22 Nov 2025 12:49:20 +0100
add util/strreplace.h
/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2025 Olaf Wintermann. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef STRINGREPLACE_H #define STRINGREPLACE_H #include <cx/string.h> #include <cx/buffer.h> #ifdef __cplusplus extern "C" { #endif typedef enum StringSegmentType { /* * Static string segment */ STRING_SEGMENT_STR = 0, /* * Placeholder referenced by number, e.g., $1, $2, ... */ STRING_SEGMENT_NUM_PLACEHOLDER, /* * Placeholder referenced by name, e.g., ${varname} or $varname */ STRING_SEGMENT_VAR_PLACEHOLDER } StringSegmentType; typedef struct StringTemplateSegment StringTemplateSegment; typedef struct StringTemplate StringTemplate; struct StringTemplate { const CxAllocator *a; StringTemplateSegment *segments; }; struct StringTemplateSegment { /* * STRING_SEGMENT_STR: static string segment * STRING_SEGMENT_NUM_PLACEHOLDER: null * STRING_SEGMENT_VAR_PLACEHOLDER: variable name */ cxstring str; /* * Segment type */ StringSegmentType type; /* * reference number if type is STRING_SEGMENT_NUM_PLACEHOLDER */ int num; /* * Next segment */ StringTemplateSegment *next; }; /* * Callback for converting a var segment into a string * * a: The allocator passed to string_template_write_to * seg: Placeholder segment * userdata: The userdata pointer passed to string_template_write_to * free_str: If set to true, the returned string pointer will be freed * using the allocator's free function. */ typedef cxmutstr (*strtpl_var_func)(const CxAllocator *a, StringTemplateSegment *seg, void *userdata, WSBool *free_str); /* * Compiles a string template * * a: The allocator to use for building the compiled template * tpl: Semplate string * delim: Delimiter chars for variable names */ StringTemplate string_template_compile(const CxAllocator *a, cxstring tpl, char *delim); /* * Builds a string using the provided template and writes it to the stream. * * tpl: Template * a: aThe allocator passed to the strtpl_var_func callback * varfunc: The callback used for converting * STRING_SEGMENT_NUM_PLACEHOLDER and STRING_SEGMENT_VAR_PLACEHOLDER segments * userdata: The userdata pointer passed to the strtpl_var_func callback * stream: The stream object to which the resulting string should be written * writef: Stream write function */ int string_template_write_to(StringTemplate *tpl, const CxAllocator *a, strtpl_var_func varfunc, void *userdata, void *stream, cx_write_func writef); /* * Builds a string, using the provided template and allocator */ cxmutstr string_template_build_string(StringTemplate *tpl, const CxAllocator *a, strtpl_var_func varfunc, void *userdata); #ifdef __cplusplus } #endif #endif /* STRINGREPLACE_H */