00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <microfeed-common/microfeedmisc.h>
00021
00022 #include <stdio.h>
00023 #include <string.h>
00024 #include <stdarg.h>
00025 #include <stdlib.h>
00026 #include <sys/stat.h>
00027 #include <errno.h>
00028 #include <libgen.h>
00029
00030 struct _MicrofeedWeakReference {
00031 void* referenced;
00032 unsigned int reference_count;
00033 };
00034
00035 void* microfeed_memory_allocate_bytes(size_t size) {
00036 void* pointer;
00037
00038 if (!(pointer = malloc(size))) {
00039 fprintf(stderr, "ERROR: Failed to allocate memory.\n");
00040
00041 exit(126);
00042 }
00043 memset(pointer, 0, size);
00044
00045 return pointer;
00046 }
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 void microfeed_memory_free(void* pointer) {
00089 free(pointer);
00090 }
00091
00092 char* microfeed_util_string_concatenate(const char* s, ...) {
00093 char* result;
00094 size_t size;
00095 size_t length;
00096 va_list argp;
00097
00098 size = strlen(s);
00099 length = size + 1;
00100 result = (char*)malloc(length);
00101 memcpy(result, s, length);
00102 va_start(argp, s);
00103 while ((s = va_arg(argp, const char*))) {
00104 length = strlen(s);
00105 result = realloc(result, size + length + 1);
00106 memcpy(result + size, s, length + 1);
00107 size += length;
00108 }
00109 va_end(argp);
00110
00111 return result;
00112 }
00113
00114 char* microfeed_util_string_base64_encode(const char* s, size_t length) {
00115 static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00116 char* result;
00117 size_t result_length;
00118 const unsigned char* from;
00119 const unsigned char* end;
00120 char* to;
00121
00122 result_length = ((length + 2) / 3) * 4;
00123 result = (char*)malloc(result_length + 1);
00124 result[result_length] = 0;
00125 for (from = (const unsigned char*)s, to = result, end = from + length; from + 2 < end; from += 3, to += 4) {
00126 to[0] = base64[from[0] >> 2];
00127 to[1] = base64[((from[0] & 0x3) << 4) | ((from[1] & 0xf0) >> 4)];
00128 to[2] = base64[((from[1] & 0xf) << 2) | ((from[2] & 0xc0) >> 6)];
00129 to[3] = base64[from[2] & 0x3f];
00130 }
00131 if (from + 1 < end) {
00132 to[0] = base64[from[0] >> 2];
00133 to[1] = base64[((from[0] & 0x3) << 4) | ((from[1] & 0xf0) >> 4)];
00134 to[2] = base64[((from[1] & 0xf) << 2)];
00135 to[3] = '=';
00136 } else if (from < end) {
00137 to[0] = base64[from[0] >> 2];
00138 to[1] = base64[(from[0] & 0x3) << 4];
00139 to[2] = '=';
00140 to[3] = '=';
00141 }
00142
00143 return result;
00144 }
00145
00146
00147 size_t microfeed_util_string_starts_with(const char* s, const char* prefix) {
00148 size_t length = 0;
00149 const char* p;
00150
00151 p = prefix;
00152 while (*s && *p && *s == *p) {
00153 s++;
00154 p++;
00155 }
00156 if (*p == 0) {
00157 length = p - prefix;
00158 }
00159
00160 return length;
00161 }
00162
00163 static int hexadecimal_char_to_int(char c) {
00164 int retvalue = -1;
00165
00166 if (c >= '0' && c <= '9') {
00167 retvalue = c - '0';
00168 } else if (c >= 'a' && c <= 'f') {
00169 retvalue = c - 'a' + 10;
00170 } else if (c >= 'A' && c <= 'F') {
00171 retvalue = c - 'A' + 10;
00172 }
00173
00174 return retvalue;
00175 }
00176
00177 char* microfeed_util_string_percent_encoding_escape(const char* s) {
00178 static const char hex[] = "0123456789ABCDEF";
00179 char* result;
00180 size_t length;
00181 const char* from;
00182 char* to;
00183 size_t offset;
00184
00185 length = strlen(s) + 1;
00186 result = (char*)malloc(length);
00187
00188 for (to = result, from = s; *from; from++, to++) {
00189 if ((*from >= 'a' && *from <= 'z') || (*from >= 'A' && *from <= 'Z') || (*from >= '0' && *from <= '9') ||
00190 *from == '-' || *from == '_' || *from == '.' || *from == '~') {
00191 *to = *from;
00192 } else {
00193 length += 2;
00194 offset = to - result;
00195 result = realloc(result, length);
00196 to = result + offset;
00197 *to++ = '%';
00198 *to++ = hex[((unsigned char)*from) >> 4];
00199 *to = hex[((unsigned char)*from) & 0xf];
00200 }
00201 }
00202 *to = 0;
00203
00204 return result;
00205 }
00206
00207 char* microfeed_util_string_percent_encoding_unescape(const char* s) {
00208 char* result;
00209 const char* from;
00210 char* to;
00211 int tempvalue;
00212 int value;
00213
00214 result = (char*)malloc(strlen(s) + 1);
00215 for (to = result, from = s; *from; from++, to++) {
00216 if (*from == '%') {
00217 if ((tempvalue = hexadecimal_char_to_int(from[1])) == -1) {
00218 free(result);
00219 result = NULL;
00220 break;
00221 }
00222 if ((value = hexadecimal_char_to_int(from[2])) == -1) {
00223 free(result);
00224 result = NULL;
00225 break;
00226 }
00227 value |= tempvalue << 4;
00228 if ((value >= 'a' && value <= 'z') || (value >= 'A' && value <= 'Z') || (value >= '0' && value <= '9') ||
00229 value == '-' || value == '_' || value == '.' || value == '~') {
00230 *to = value;
00231 } else {
00232 *to++ = *from++;
00233 *to++ = *from++;
00234 *to = *from;
00235 }
00236 } else {
00237 *to = *from;
00238 }
00239 }
00240 if (result) {
00241 *to++ = 0;
00242 result = (char*)realloc(result, result - to);
00243 }
00244
00245 return result;
00246 }
00247
00248 MicrofeedWeakReference* microfeed_weak_reference_new(void* referenced, MicrofeedWeakReference* existing_weak_reference) {
00249 if (existing_weak_reference) {
00250 existing_weak_reference->reference_count++;
00251 } else {
00252 existing_weak_reference = microfeed_memory_allocate(MicrofeedWeakReference);
00253 existing_weak_reference->referenced = referenced;
00254 existing_weak_reference->reference_count = 1;
00255 }
00256
00257 return existing_weak_reference;
00258 }
00259
00260 void microfeed_weak_reference_free(MicrofeedWeakReference* weak_reference) {
00261 weak_reference->reference_count--;
00262 if (weak_reference->reference_count == 0) {
00263 weak_reference->referenced = NULL;
00264 microfeed_memory_free(weak_reference);
00265 }
00266 }
00267
00268 void* microfeed_weak_reference_get_impl(MicrofeedWeakReference* weak_reference) {
00269
00270 return weak_reference->referenced;
00271 }
00272
00273 void microfeed_weak_reference_invalidate(MicrofeedWeakReference* weak_reference) {
00274 if (weak_reference) {
00275 weak_reference->referenced = NULL;
00276 }
00277 }
00278
00279 int microfeed_util_create_directory_recursively(const char* directory) {
00280 int retval = 0;
00281 char* s1;
00282 char* s2;
00283
00284
00285 if (mkdir(directory, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == 0 || errno == EEXIST) {
00286 retval = 1;
00287 } if (errno == ENOENT) {
00288 s1 = strdup(directory);
00289 s2 = dirname(s1);
00290 if (strcmp(s2, ".") && strcmp(s2, "/")) {
00291 if (microfeed_util_create_directory_recursively(s2) && mkdir(directory, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == 0) {
00292 retval = 1;
00293 }
00294 }
00295 free(s1);
00296 }
00297
00298 return retval;
00299 }