extract method: logging for possible NPE later
[idea/community.git] / native / fsNotifier / linux / util.c
1 /*
2  * Copyright 2000-2016 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "fsnotifier.h"
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22
23
24 #define REALLOC_FACTOR 2
25
26 struct __array {
27   void** data;
28   int size;
29   int capacity;
30 };
31
32 static bool array_realloc(array* a) {
33   if (a->size == a->capacity) {
34     int new_cap = a->capacity * REALLOC_FACTOR;
35     void* new_ptr = realloc(a->data, sizeof(void*) * new_cap);
36     if (new_ptr == NULL) {
37       return false;
38     }
39     a->capacity = new_cap;
40     a->data = new_ptr;
41   }
42   return true;
43 }
44
45 array* array_create(int initial_capacity) {
46   array* a = calloc(1, sizeof(array));
47   if (a == NULL) {
48     return NULL;
49   }
50
51   a->data = calloc(initial_capacity, sizeof(void*));
52   if (a->data == NULL) {
53     free(a);
54     return NULL;
55   }
56
57   a->capacity = initial_capacity;
58   a->size = 0;
59
60   return a;
61 }
62
63 inline int array_size(array* a) {
64   return (a != NULL ? a->size : 0);
65 }
66
67 void* array_push(array* a, void* element) {
68   if (a == NULL || !array_realloc(a)) {
69     return NULL;
70   }
71   a->data[a->size++] = element;
72   return element;
73 }
74
75 void* array_pop(array* a) {
76   if (a != NULL && a->size > 0) {
77     return a->data[--a->size];
78   }
79   else {
80     return NULL;
81   }
82 }
83
84 void array_put(array* a, int index, void* element) {
85   if (a != NULL && index >=0 && index < a->capacity) {
86     a->data[index] = element;
87     if (a->size <= index) {
88       a->size = index + 1;
89     }
90   }
91 }
92
93 void* array_get(array* a, int index) {
94   if (a != NULL && index >= 0 && index < a->size) {
95     return a->data[index];
96   }
97   else {
98     return NULL;
99   }
100 }
101
102 void array_delete(array* a) {
103   if (a != NULL) {
104     free(a->data);
105     free(a);
106   }
107 }
108
109 void array_delete_vs_data(array* a) {
110   if (a != NULL) {
111     array_delete_data(a);
112     array_delete(a);
113   }
114 }
115
116 void array_delete_data(array* a) {
117   if (a != NULL) {
118     for (int i=0; i<a->size; i++) {
119       if (a->data[i] != NULL) {
120         free(a->data[i]);
121       }
122     }
123     a->size = 0;
124   }
125 }
126
127
128 struct __table {
129   void** data;
130   int capacity;
131 };
132
133 table* table_create(int capacity) {
134   table* t = calloc(1, sizeof(table));
135   if (t == NULL) {
136     return NULL;
137   }
138
139   t->data = calloc(capacity, sizeof(void*));
140   if (t->data == NULL) {
141     free(t);
142     return NULL;
143   }
144
145   t->capacity = capacity;
146
147   return t;
148 }
149
150 static inline int wrap(int key, table* t) {
151   return (t != NULL ? key % t->capacity : -1);
152 }
153
154 // todo: resolve collisions (?)
155 void* table_put(table* t, int key, void* value) {
156   int k = wrap(key, t);
157   if (k < 0 || (value != NULL && t->data[k] != NULL)) {
158     return NULL;
159   }
160   else {
161     return t->data[k] = value;
162   }
163 }
164
165 void* table_get(table* t, int key) {
166   int k = wrap(key, t);
167   if (k < 0) {
168     return NULL;
169   }
170   else {
171     return t->data[k];
172   }
173 }
174
175 void table_delete(table* t) {
176   if (t != NULL) {
177     free(t->data);
178     free(t);
179   }
180 }
181
182
183 #define INPUT_BUF_LEN 2048
184 static char input_buf[INPUT_BUF_LEN];
185
186 char* read_line(FILE* stream) {
187   char* retval = fgets(input_buf, INPUT_BUF_LEN, stream);
188   if (retval == NULL || feof(stream)) {
189     return NULL;
190   }
191   int pos = strlen(input_buf) - 1;
192   if (input_buf[pos] == '\n') {
193     input_buf[pos] = '\0';
194   }
195   return input_buf;
196 }
197
198
199 bool is_parent_path(const char* parent_path, const char* child_path) {
200   size_t parent_len = strlen(parent_path);
201   return strncmp(parent_path, child_path, parent_len) == 0 &&
202          (parent_len == strlen(child_path) || child_path[parent_len] == '/');
203 }