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