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 }