1 /** @file
2 Various utility functions for use by applications
3
4 Copyright (C) 2015 Tommy Vestermark
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 */
11
12 #include "r_util.h"
13 #include "fatal.h"
14 #include <stdlib.h>
15 #include <stdio.h>
16 #include <string.h>
17
get_time_now(struct timeval * tv)18 void get_time_now(struct timeval *tv)
19 {
20 int ret = gettimeofday(tv, NULL);
21 if (ret)
22 perror("gettimeofday");
23 }
24
format_time_str(char * buf,char const * format,int with_tz,time_t time_secs)25 char *format_time_str(char *buf, char const *format, int with_tz, time_t time_secs)
26 {
27 time_t etime;
28 struct tm tm_info;
29
30 if (time_secs == 0) {
31 time(&etime);
32 }
33 else {
34 etime = time_secs;
35 }
36
37 #ifdef _WIN32 /* MinGW might have localtime_r but apparently not MinGW64 */
38 localtime_s(&tm_info, &etime); // win32 doesn't have localtime_r()
39 #else
40 localtime_r(&etime, &tm_info); // thread-safe
41 #endif
42
43 if (!format || !*format)
44 format = "%Y-%m-%d %H:%M:%S";
45
46 size_t l = strftime(buf, LOCAL_TIME_BUFLEN, format, &tm_info);
47 if (with_tz) {
48 strftime(buf + l, LOCAL_TIME_BUFLEN - l, "%z", &tm_info);
49 if (!strcmp(buf + l, "+0000"))
50 strcpy(buf + l, "Z");
51 }
52 return buf;
53 }
54
usecs_time_str(char * buf,char const * format,int with_tz,struct timeval * tv)55 char *usecs_time_str(char *buf, char const *format, int with_tz, struct timeval *tv)
56 {
57 struct timeval now;
58 struct tm tm_info;
59
60 if (!tv) {
61 tv = &now;
62 get_time_now(tv);
63 }
64
65 time_t t_secs = tv->tv_sec;
66 #ifdef _WIN32 /* MinGW might have localtime_r but apparently not MinGW64 */
67 localtime_s(&tm_info, &t_secs); // win32 doesn't have localtime_r()
68 #else
69 localtime_r(&t_secs, &tm_info); // thread-safe
70 #endif
71
72 if (!format || !*format)
73 format = "%Y-%m-%d %H:%M:%S";
74
75 size_t l = strftime(buf, LOCAL_TIME_BUFLEN, format, &tm_info);
76 l += snprintf(buf + l, LOCAL_TIME_BUFLEN - l, ".%06ld", (long)tv->tv_usec);
77 if (with_tz) {
78 strftime(buf + l, LOCAL_TIME_BUFLEN - l, "%z", &tm_info);
79 if (!strcmp(buf + l, "+0000"))
80 strcpy(buf + l, "Z");
81 }
82 return buf;
83 }
84
sample_pos_str(float sample_file_pos,char * buf)85 char *sample_pos_str(float sample_file_pos, char *buf)
86 {
87 snprintf(buf, LOCAL_TIME_BUFLEN, "@%fs", sample_file_pos);
88 return buf;
89 }
90
celsius2fahrenheit(float celsius)91 float celsius2fahrenheit(float celsius)
92 {
93 return celsius * (9.0f / 5.0f) + 32;
94 }
95
96
fahrenheit2celsius(float fahrenheit)97 float fahrenheit2celsius(float fahrenheit)
98 {
99 return (fahrenheit - 32) * (5.0f / 9.0f);
100 }
101
102
kmph2mph(float kmph)103 float kmph2mph(float kmph)
104 {
105 return kmph * (1.0f / 1.609344f);
106 }
107
mph2kmph(float mph)108 float mph2kmph(float mph)
109 {
110 return mph * 1.609344f;
111 }
112
113
mm2inch(float mm)114 float mm2inch(float mm)
115 {
116 return mm * 0.039370f;
117 }
118
inch2mm(float inch)119 float inch2mm(float inch)
120 {
121 return inch * 25.4f;
122 }
123
124
kpa2psi(float kpa)125 float kpa2psi(float kpa)
126 {
127 return kpa * (1.0f / 6.89475729f);
128 }
129
psi2kpa(float psi)130 float psi2kpa(float psi)
131 {
132 return psi * 6.89475729f;
133 }
134
135
hpa2inhg(float hpa)136 float hpa2inhg(float hpa)
137 {
138 return hpa * (1.0f / 33.8639f);
139 }
140
inhg2hpa(float inhg)141 float inhg2hpa(float inhg)
142 {
143 return inhg * 33.8639f;
144 }
145
146
str_endswith(char const * restrict str,char const * restrict suffix)147 bool str_endswith(char const *restrict str, char const *restrict suffix)
148 {
149 int str_len = strlen(str);
150 int suffix_len = strlen(suffix);
151
152 return (str_len >= suffix_len) &&
153 (0 == strcmp(str + (str_len - suffix_len), suffix));
154 }
155
156 // Original string replacement function was found here:
157 // https://stackoverflow.com/questions/779875/what-is-the-function-to-replace-string-in-c/779960#779960
158 //
159 // You must free the result if result is non-NULL.
str_replace(char const * orig,char const * rep,char const * with)160 char *str_replace(char const *orig, char const *rep, char const *with)
161 {
162 char *result; // the return string
163 char const *ins; // the next insert point
164 char *tmp; // varies
165 int len_rep; // length of rep (the string to remove)
166 int len_with; // length of with (the string to replace rep with)
167 int len_front; // distance between rep and end of last rep
168 int count; // number of replacements
169
170 // sanity checks and initialization
171 if (!orig || !rep)
172 return NULL;
173 len_rep = strlen(rep);
174 if (len_rep == 0)
175 return NULL; // empty rep causes infinite loop during count
176 if (!with)
177 with = "";
178 len_with = strlen(with);
179
180 // count the number of replacements needed
181 ins = orig;
182 for (count = 0; (tmp = strstr(ins, rep)); ++count) {
183 ins = tmp + len_rep;
184 }
185
186 tmp = result = malloc(strlen(orig) + (len_with - len_rep) * (size_t)count + 1);
187 if (!result) {
188 WARN_MALLOC("str_replace()");
189 return NULL; // NOTE: returns NULL on alloc failure.
190 }
191
192 // first time through the loop, all the variables are set correctly
193 // from here on,
194 // tmp points to the end of the result string
195 // ins points to the next occurrence of rep in orig
196 // orig points to the remainder of orig after "end of rep"
197 while (count--) {
198 ins = strstr(orig, rep);
199 len_front = ins - orig;
200 tmp = strncpy(tmp, orig, len_front) + len_front;
201 tmp = strcpy(tmp, with) + len_with;
202 orig += len_front + len_rep; // move to next "end of rep"
203 }
204 strcpy(tmp, orig);
205 return result;
206 }
207
208 // Make a more readable string for a frequency.
nice_freq(double freq)209 char const *nice_freq (double freq)
210 {
211 static char buf[30];
212
213 if (freq >= 1E9)
214 snprintf (buf, sizeof(buf), "%.3fGHz", freq/1E9);
215 else if (freq >= 1E6)
216 snprintf (buf, sizeof(buf), "%.3fMHz", freq/1E6);
217 else if (freq >= 1E3)
218 snprintf (buf, sizeof(buf), "%.3fkHz", freq/1E3);
219 else
220 snprintf (buf, sizeof(buf), "%f", freq);
221 return (buf);
222 }
223