hirc

[archived] IRC client
git clone https://hhvn.uk/hirc
git clone git://hhvn.uk/hirc
Log | Files | Refs

str.c (4514B)


      1 /*
      2  * src/str.c from hirc
      3  *
      4  * Copyright (c) 2021-2022 hhvn <dev@hhvn.uk>
      5  *
      6  * Permission to use, copy, modify, and distribute this software for any
      7  * purpose with or without fee is hereby granted, provided that the above
      8  * copyright notice and this permission notice appear in all copies.
      9  *
     10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     17  *
     18  */
     19 
     20 #include <string.h>
     21 #include <stdlib.h>
     22 #include <limits.h>
     23 #include "hirc.h"
     24 
     25 /* Helper functions for widechar <-> utf-8 conversion */
     26 wchar_t *
     27 stowc(char *str) {
     28 	wchar_t *ret;
     29 	size_t len;
     30 
     31 	if (!str) return NULL;
     32 
     33 	len = mbstowcs(NULL, str, 0) + 1;
     34 	if (!len) return NULL;
     35 	ret = emalloc(len * sizeof(wchar_t));
     36 	mbstowcs(ret, str, len);
     37 	return ret;
     38 }
     39 
     40 char *
     41 wctos(wchar_t *str) {
     42 	char *ret;
     43 	size_t len;
     44 
     45 	if (!str) return NULL;
     46 
     47 	len = wcstombs(NULL, str, 0) + 1;
     48 	if (!len) return NULL;
     49 	ret = emalloc(len);
     50 	wcstombs(ret, str, len);
     51 	return ret;
     52 }
     53 
     54 char *
     55 homepath(char *path) {
     56 	static char ret[1024];
     57 
     58 	if (*path == '~') {
     59 		snprintf(ret, sizeof(ret), "%s/%s", getenv("HOME"), path + 1);
     60 		return ret;
     61 	}
     62 
     63 	return path;
     64 }
     65 
     66 int
     67 strcmp_n(const char *s1, const char *s2) {
     68 	if (!s1 && !s2)
     69 		return 0;
     70 	else if (!s1)
     71 		return INT_MIN;
     72 	else if (!s2)
     73 		return INT_MAX;
     74 	else
     75 		return strcmp(s1, s2);
     76 }
     77 
     78 char *
     79 struntil(char *str, char until) {
     80 	static char ret[1024];
     81 	int i;
     82 
     83 	for (i=0; str && *str && i < 1024 && *str != until; i++, str++)
     84 		ret[i] = *str;
     85 
     86 	ret[i] = '\0';
     87 	return ret;
     88 }
     89 
     90 int
     91 strisnum(char *str, int allowneg) {
     92 	if (!str)
     93 		return 0;
     94 
     95 	if ((allowneg && *str == '-') || *str == '+')
     96 		str += 1;
     97 
     98 	for (; *str; str++)
     99 		if (*str > '9' || *str < '0')
    100 			return 0;
    101 	return 1;
    102 }
    103 
    104 char *
    105 strntok(char *str, char *sep, int n) {
    106 	static char buf[8192];
    107 	char *ret, *save;
    108 
    109 	strlcpy(buf, str, sizeof(buf));
    110 
    111 	ret = strtok_r(buf, sep, &save);
    112 	if (--n == 0)
    113 		return ret;
    114 	while ((ret = strtok_r(NULL, sep, &save)) != NULL)
    115 		if (--n == 0)
    116 			return ret;
    117 	return NULL;
    118 }
    119 
    120 #define S_YEAR	31557600 /* 60*60*24*365.25 */
    121 #define S_MONTH	2629800  /* 60*60*24*(365.25 / 12) */
    122 #define S_WEEK	604800   /* 60*60*24*7 */
    123 #define S_DAY	86400    /* 60*60*24 */
    124 #define S_HOUR	3600     /* 60*60 */
    125 #define S_MIN	60
    126 
    127 char *
    128 strrdate(time_t secs) {
    129 	static char ret[1024];
    130 	size_t rc = 0;
    131 	long shrt = config_getl("rdate.short");
    132 	long avg  = config_getl("rdate.averages");
    133 	long verb = config_getl("rdate.verbose");
    134 	int years = 0, months = 0, weeks = 0,
    135 	    days  = 0, hours  = 0, mins  = 0;
    136 
    137 	if (avg) {
    138 		years  = secs   / S_YEAR;
    139 		secs  -= years  * S_YEAR;
    140 
    141 		months = secs   / S_MONTH;
    142 		secs  -= months * S_MONTH;
    143 	}
    144 
    145 	weeks = secs  / S_WEEK;
    146 	secs -= weeks * S_WEEK;
    147 
    148 	days  = secs  / S_DAY;
    149 	secs -= days  * S_DAY;
    150 
    151 	hours = secs  / S_HOUR;
    152 	secs -= hours * S_HOUR;
    153 
    154 	mins  = secs  / S_MIN;
    155 	secs -= mins  * S_MIN;
    156 
    157 	if (years || (verb && avg))
    158 		rc += snprintf(&ret[rc], sizeof(ret) - rc, "%d%s%s, ", years,
    159 				shrt ? "y" : " year", !shrt && years != 1 ? "s" : "");
    160 	if (months || (verb && avg))
    161 		rc += snprintf(&ret[rc], sizeof(ret) - rc, "%d%s%s, ", months,
    162 				shrt ? "mo" : " month", !shrt && months != 1 ? "s" : "");
    163 	if (weeks || verb)
    164 		rc += snprintf(&ret[rc], sizeof(ret) - rc, "%d%s%s, ", weeks,
    165 				shrt ? "w" : " week", !shrt && weeks != 1 ? "s" : "");
    166 	if (days || verb)
    167 		rc += snprintf(&ret[rc], sizeof(ret) - rc, "%d%s%s, ", days,
    168 				shrt ? "d" : " day", !shrt && days != 1 ? "s" : "");
    169 	if (hours || verb)
    170 		rc += snprintf(&ret[rc], sizeof(ret) - rc, "%d%s%s, ", hours,
    171 				shrt ? "h" : " hour", !shrt && hours != 1 ? "s" : "");
    172 	if (mins || verb)
    173 		rc += snprintf(&ret[rc], sizeof(ret) - rc, "%d%s%s, ", mins,
    174 				shrt ? "m" : " min", !shrt && mins != 1 ? "s" : "");
    175 	if (secs || verb)
    176 		rc += snprintf(&ret[rc], sizeof(ret) - rc, "%d%s%s, ", (int)secs,
    177 				shrt ? "s" : " sec", !shrt && secs != 1 ? "s" : "");
    178 	if (rc >= 2)
    179 		ret[rc - 2] = '\0';
    180 	else
    181 		ret[rc] = '\0';
    182 
    183 	return ret;
    184 }
    185 
    186 char *
    187 smprintf(size_t len, char *fmt, ...) {
    188 	char *ret;
    189 	va_list ap;
    190 
    191 	ret = emalloc(len);
    192 	va_start(ap, fmt);
    193 	vsnprintf(ret, len, fmt, ap);
    194 	va_end(ap);
    195 
    196 	return ret;
    197 }