1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ucx/properties.c Fri Jul 12 20:50:18 2013 +0200 1.3 @@ -0,0 +1,204 @@ 1.4 +/* 1.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 1.6 + * 1.7 + * Copyright 2013 Olaf Wintermann. All rights reserved. 1.8 + * 1.9 + * Redistribution and use in source and binary forms, with or without 1.10 + * modification, are permitted provided that the following conditions are met: 1.11 + * 1.12 + * 1. Redistributions of source code must retain the above copyright 1.13 + * notice, this list of conditions and the following disclaimer. 1.14 + * 1.15 + * 2. Redistributions in binary form must reproduce the above copyright 1.16 + * notice, this list of conditions and the following disclaimer in the 1.17 + * documentation and/or other materials provided with the distribution. 1.18 + * 1.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 1.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 1.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 1.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 1.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 1.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 1.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 1.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 1.29 + * POSSIBILITY OF SUCH DAMAGE. 1.30 + */ 1.31 + 1.32 +#include <stdio.h> 1.33 +#include <stdlib.h> 1.34 +#include <string.h> 1.35 + 1.36 +#include "properties.h" 1.37 + 1.38 +UcxPropParser *ucx_prop_new() { 1.39 + UcxPropParser *parser = (UcxPropParser*)malloc( 1.40 + sizeof(UcxPropParser)); 1.41 + if(!parser) { 1.42 + return NULL; 1.43 + } 1.44 + 1.45 + parser->buffer = NULL; 1.46 + parser->buflen = 0; 1.47 + parser->pos = 0; 1.48 + parser->tmp = NULL; 1.49 + parser->tmplen = 0; 1.50 + parser->tmpcap = 0; 1.51 + parser->delimiter = '='; 1.52 + parser->comment1 = '#'; 1.53 + parser->comment2 = 0; 1.54 + parser->comment3 = 0; 1.55 + 1.56 + return parser; 1.57 +} 1.58 + 1.59 +void ucx_prop_free(UcxPropParser *parser) { 1.60 + if(parser->tmp) { 1.61 + free(parser->tmp); 1.62 + } 1.63 + free(parser); 1.64 +} 1.65 + 1.66 +void ucx_prop_fill(UcxPropParser *parser, char *buf, size_t len) { 1.67 + parser->buffer = buf; 1.68 + parser->buflen = len; 1.69 + parser->pos = 0; 1.70 +} 1.71 + 1.72 +static void parser_tmp_append(UcxPropParser *parser, char *buf, size_t len) { 1.73 + if(parser->tmpcap - parser->tmplen < len) { 1.74 + size_t newcap = parser->tmpcap + len + 64; 1.75 + parser->tmp = (char*)realloc(parser->tmp, newcap); 1.76 + parser->tmpcap = newcap; 1.77 + } 1.78 + memcpy(parser->tmp + parser->tmplen, buf, len); 1.79 + parser->tmplen += len; 1.80 +} 1.81 + 1.82 +int ucx_prop_parse(UcxPropParser *parser, sstr_t *name, sstr_t *value) { 1.83 + if(parser->tmplen > 0) { 1.84 + char *buf = parser->buffer + parser->pos; 1.85 + size_t len = parser->buflen - parser->pos; 1.86 + sstr_t str = sstrn(buf, len); 1.87 + sstr_t nl = sstrchr(str, '\n'); 1.88 + if(nl.ptr) { 1.89 + size_t newlen = (size_t)(nl.ptr - buf) + 1; 1.90 + parser_tmp_append(parser, buf, newlen); 1.91 + // the tmp buffer contains exactly one line now 1.92 + 1.93 + char *orig_buf = parser->buffer; 1.94 + size_t orig_len = parser->buflen; 1.95 + 1.96 + parser->buffer = parser->tmp; 1.97 + parser->buflen = parser->tmplen; 1.98 + parser->pos = 0; 1.99 + parser->tmp = NULL; 1.100 + parser->tmpcap = 0; 1.101 + parser->tmplen = 0; 1.102 + // run parse with the tmp buffer as main buffer 1.103 + int ret = ucx_prop_parse(parser, name, value); 1.104 + 1.105 + // restore original buffer 1.106 + parser->tmp = parser->buffer; 1.107 + parser->buffer = orig_buf; 1.108 + parser->buflen = orig_len; 1.109 + parser->pos = newlen; 1.110 + 1.111 + /* 1.112 + * if ret == 0 the tmp buffer contained just space or comment 1.113 + * we parse again with the original buffer to get a name/value 1.114 + * or a new tmp buffer 1.115 + */ 1.116 + return ret ? ret : ucx_prop_parse(parser, name, value); 1.117 + } else { 1.118 + parser_tmp_append(parser, buf, len); 1.119 + return 0; 1.120 + } 1.121 + } else if(parser->tmp) { 1.122 + free(parser->tmp); 1.123 + parser->tmp = NULL; 1.124 + } 1.125 + 1.126 + char comment1 = parser->comment1; 1.127 + char comment2 = parser->comment2; 1.128 + char comment3 = parser->comment3; 1.129 + char delimiter = parser->delimiter; 1.130 + 1.131 + // get one line and parse it 1.132 + while(1) { 1.133 + if(parser->pos >= parser->buflen) { 1.134 + return 0; 1.135 + } 1.136 + char *buf = parser->buffer + parser->pos; 1.137 + size_t len = parser->buflen - parser->pos; 1.138 + 1.139 + /* 1.140 + * First we check if we have at least one line. We also get indices of 1.141 + * delimiter and comment chars 1.142 + */ 1.143 + size_t delimiter_index = 0; 1.144 + size_t comment_index = 0; 1.145 + int has_comment = 0; 1.146 + 1.147 + size_t i = 0; 1.148 + char c = 0; 1.149 + for(;i<len;i++) { 1.150 + c = buf[i]; 1.151 + if(c == comment1 || c == comment2 || c == comment3) { 1.152 + if(comment_index == 0) { 1.153 + comment_index = i; 1.154 + has_comment = 1; 1.155 + } 1.156 + } else if(c == delimiter) { 1.157 + if(delimiter_index == 0 && !has_comment) { 1.158 + delimiter_index = i; 1.159 + } 1.160 + } else if(c == '\n') { 1.161 + break; 1.162 + } 1.163 + } 1.164 + 1.165 + if(c != '\n') { 1.166 + // we have not enough data for a line 1.167 + // store remaining bytes in temporary buffer for next round 1.168 + parser->tmpcap = len + 128; 1.169 + parser->tmp = (char*)malloc(parser->tmpcap); 1.170 + parser->tmplen = len; 1.171 + memcpy(parser->tmp, buf, len); 1.172 + return 0; 1.173 + } 1.174 + 1.175 + sstr_t line = has_comment ? sstrn(buf, comment_index) : sstrn(buf, i); 1.176 + // check line 1.177 + if(delimiter_index == 0) { 1.178 + line = sstrtrim(line); 1.179 + if(line.length != 0) { 1.180 + // syntax error 1.181 + // TODO 1.182 + } 1.183 + parser->pos += i + 1; 1.184 + continue; 1.185 + } 1.186 + 1.187 + sstr_t n = sstrn(buf, delimiter_index); 1.188 + sstr_t v = sstrn(buf + delimiter_index + 1, i - delimiter_index - 1); 1.189 + n = sstrtrim(n); 1.190 + v = sstrtrim(v); 1.191 + if(n.length == 0 || v.length == 0) { 1.192 + // syntax error 1.193 + // TODO 1.194 + parser->pos += i + 1; 1.195 + continue; 1.196 + } 1.197 + 1.198 + *name = n; 1.199 + *value = v; 1.200 + 1.201 + parser->pos += i + 1; 1.202 + break; 1.203 + } 1.204 + 1.205 + return 1; 1.206 +} 1.207 +