/* segtext.h Segmented text file handling Copyright (C) 2013 Bill Currie Author: Bill Currie Date: 2013/02/26 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to: Free Software Foundation, Inc. 59 Temple Place - Suite 330 Boston, MA 02111-1307, USA */ #ifndef __QF_segtext_h #define __QF_segtext_h /** \defgroup segtext Segmented text files \ingroup utils Access named sections of a text file. Based on The OpenGL Shader Wrangler: https://prideout.net/blog/old/blog/index.html@p=11.html However, nothing is assumed about any of the segments: they are all nothing more than chunks of mostly random (lines cannot start with --) text with identifying tags. Also, the identifying tag represents only the shader_key of OpenGL Shader Wrangler's Effect.shader_key identifier. */ ///@{ /** Represent a single text segment Segments are separated by lines beginning with "--" (without the quotes). The first word ([A-Za-z0-9_.]+) following the double-hyphen is used as an identifying tag for the segment. Whitespace and any additional characters are ignored. The segment itself starts on the following line. */ typedef struct segchunk_s { struct segchunk_s *next; const char *tag; ///< identifying tag or null if no tag const char *text; ///< nul-terminated string holding the segment int start_line; ///< line number for first line of the segment } segchunk_t; /** Container for all the segments extracted from the provided text The first segment has no tag and may or may not be empty. Segments are stored sequentially in \a chunk_list are indexed by identifying tag (if present) in \a tab. Segments that have no identifying tag are not in \a tab, but can be accessed by walking \a chunk_list 's \a next field. */ typedef struct segtext_s { struct segtext_s *next; segchunk_t *chunk_list; struct hashtab_s *tab; } segtext_t; /** Parse a nul-terminated string into (optionally) tagged segments The segments are separated by lines beginning with a double-hyphen ("--"), with an optional tag following the double-hyphen on the same line. Valid tag characters are ASCII alpha-numerics, "." and "_". Whitespace is ignored and invalid characters are treated as whitespace. Only the first tag on the line is significant. \param src nul-terminated string to be parsed into segments \return Pointer to container of parsed segments. Can be freed using Segtext_delete(). */ segtext_t *Segtext_new (const char *src); /** Free a segmented text container created by Segtext_new() \param st Pointer to segmented text container to be freed. Must have been created by Segtext_new(). */ void Segtext_delete (segtext_t *st); /** Find a text segment via its identifying tag Like OpenGL Shader Wrangler, the segment tag does not have to be a perfect match with the specified tag: the segment with the longest string of sub-tags matching the leading subtags of the specified tag is selected. Tags are logically broken into sub-tag by the "." character. Thus in a collection of segments with tags "foo" and "foo.b", "foo.bar" will find the segment tagged "foo". However, if a segment tagged "foo.bar" is present, it will be returned. A segment tagged "foo.bar.baz" will not. \param st Pointer to segmented text container \param tag String specifying the tag identifying the segment to be returned. Valid tag characters are alphanumerics, "_" and "." (ie, [A-Za-z0-9._]). "." is used as a sub-tag separator for partial matches. \return Pointer to segment data block with the best matching tag, providing access to the segment's tag and starting line number, as well as the segment contents. Null if no matching tag was found. */ const segchunk_t *Segtext_FindChunk (const segtext_t *st, const char *tag); /** Find a text segment via its identifying tag Like OpenGL Shader Wrangler, the segment tag does not have to be a perfect match with the specified tag: the segment with the longest string of sub-tags matching the leading subtags of the specified tag is selected. Tags are logically broken into sub-tag by the "." character. Thus in a collection of segments with tags "foo" and "foo.b", "foo.bar" will find the segment tagged "foo". However, if a segment tagged "foo.bar" is present, it will be returned. A segment tagged "foo.bar.baz" will not. \param st Pointer to segmented text container \param tag String specifying the tag identifying the segment to be returned. Valid tag characters are alphanumerics, "_" and "." (ie, [A-Za-z0-9._]). "." is used as a sub-tag separator for partial matches. \return Contents of the segment with the best matching tag, or null if no matching tag was found. */ const char *Segtext_Find (const segtext_t *st, const char *tag); ///@} #endif//__QF_segtext_h