| /* |
| * Copyright 2000-2012 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "fsnotifier.h" |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| |
| #define REALLOC_FACTOR 2 |
| |
| struct __array { |
| void** data; |
| int size; |
| int capacity; |
| }; |
| |
| static bool array_realloc(array* a) { |
| if (a->size == a->capacity) { |
| int new_cap = a->capacity * REALLOC_FACTOR; |
| void* new_ptr = realloc(a->data, sizeof(void*) * new_cap); |
| if (new_ptr == NULL) { |
| return false; |
| } |
| a->capacity = new_cap; |
| a->data = new_ptr; |
| } |
| return true; |
| } |
| |
| array* array_create(int initial_capacity) { |
| array* a = (array*) malloc(sizeof(array)); |
| if (a == NULL) { |
| return NULL; |
| } |
| |
| a->data = calloc(sizeof(void*), initial_capacity); |
| if (a->data == NULL) { |
| free(a); |
| return NULL; |
| } |
| |
| a->capacity = initial_capacity; |
| a->size = 0; |
| |
| return a; |
| } |
| |
| inline int array_size(array* a) { |
| return (a != NULL ? a->size : 0); |
| } |
| |
| void* array_push(array* a, void* element) { |
| if (a == NULL || !array_realloc(a)) { |
| return NULL; |
| } |
| a->data[a->size++] = element; |
| return element; |
| } |
| |
| void* array_pop(array* a) { |
| if (a != NULL && a->size > 0) { |
| return a->data[--a->size]; |
| } |
| else { |
| return NULL; |
| } |
| } |
| |
| void array_put(array* a, int index, void* element) { |
| if (a != NULL && index >=0 && index < a->capacity) { |
| a->data[index] = element; |
| if (a->size <= index) { |
| a->size = index + 1; |
| } |
| } |
| } |
| |
| void* array_get(array* a, int index) { |
| if (a != NULL && index >= 0 && index < a->size) { |
| return a->data[index]; |
| } |
| else { |
| return NULL; |
| } |
| } |
| |
| void array_delete(array* a) { |
| if (a != NULL) { |
| free(a->data); |
| free(a); |
| } |
| } |
| |
| void array_delete_vs_data(array* a) { |
| if (a != NULL) { |
| array_delete_data(a); |
| array_delete(a); |
| } |
| } |
| |
| void array_delete_data(array* a) { |
| if (a != NULL) { |
| for (int i=0; i<a->size; i++) { |
| if (a->data[i] != NULL) { |
| free(a->data[i]); |
| } |
| } |
| a->size = 0; |
| } |
| } |
| |
| |
| struct __table { |
| void** data; |
| int capacity; |
| }; |
| |
| table* table_create(int capacity) { |
| table* t = malloc(sizeof(table)); |
| if (t == NULL) { |
| return NULL; |
| } |
| |
| t->data = calloc(sizeof(void*), capacity); |
| if (t->data == NULL) { |
| free(t); |
| return NULL; |
| } |
| memset(t->data, 0, sizeof(void*) * capacity); |
| |
| t->capacity = capacity; |
| |
| return t; |
| } |
| |
| static inline int wrap(int key, table* t) { |
| return (t != NULL ? key % t->capacity : -1); |
| } |
| |
| // todo: resolve collisions (?) |
| void* table_put(table* t, int key, void* value) { |
| int k = wrap(key, t); |
| if (k < 0 || (value != NULL && t->data[k] != NULL)) { |
| return NULL; |
| } |
| else { |
| return t->data[k] = value; |
| } |
| } |
| |
| void* table_get(table* t, int key) { |
| int k = wrap(key, t); |
| if (k < 0) { |
| return NULL; |
| } |
| else { |
| return t->data[k]; |
| } |
| } |
| |
| void table_delete(table* t) { |
| if (t != NULL) { |
| free(t->data); |
| free(t); |
| } |
| } |
| |
| |
| #define INPUT_BUF_LEN 2048 |
| static char input_buf[INPUT_BUF_LEN]; |
| |
| char* read_line(FILE* stream) { |
| char* retval = fgets(input_buf, INPUT_BUF_LEN, stream); |
| if (retval == NULL || feof(stream)) { |
| return NULL; |
| } |
| int pos = strlen(input_buf) - 1; |
| if (input_buf[pos] == '\n') { |
| input_buf[pos] = '\0'; |
| } |
| return input_buf; |
| } |
| |
| |
| bool is_parent_path(const char* parent_path, const char* child_path) { |
| size_t parent_len = strlen(parent_path); |
| return strncmp(parent_path, child_path, parent_len) == 0 && |
| (parent_len == strlen(child_path) || child_path[parent_len] == '/'); |
| } |