Web Symbols: improve attribute descriptors calculation
[idea/community.git] / native / fsNotifier / linux / util.c
1 // Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2
3 #include "fsnotifier.h"
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8
9
10 #define REALLOC_FACTOR 2
11
12 struct array_str {
13   void** data;
14   int size;
15   int capacity;
16 };
17
18 static bool array_realloc(array* a) {
19   if (a->size == a->capacity) {
20     int new_cap = a->capacity * REALLOC_FACTOR;
21     void* new_ptr = realloc(a->data, sizeof(void*) * new_cap);
22     if (new_ptr == NULL) {
23       return false;
24     }
25     a->capacity = new_cap;
26     a->data = new_ptr;
27   }
28   return true;
29 }
30
31 array* array_create(int initial_capacity) {
32   array* a = calloc(1, sizeof(array));
33   if (a == NULL) {
34     return NULL;
35   }
36
37   a->data = calloc(initial_capacity, sizeof(void*));
38   if (a->data == NULL) {
39     free(a);
40     return NULL;
41   }
42
43   a->capacity = initial_capacity;
44   a->size = 0;
45
46   return a;
47 }
48
49 inline int array_size(array* a) {
50   return (a != NULL ? a->size : 0);
51 }
52
53 void* array_push(array* a, void* element) {
54   if (a == NULL || !array_realloc(a)) {
55     return NULL;
56   }
57   a->data[a->size++] = element;
58   return element;
59 }
60
61 void* array_pop(array* a) {
62   if (a != NULL && a->size > 0) {
63     return a->data[--a->size];
64   }
65   else {
66     return NULL;
67   }
68 }
69
70 void array_put(array* a, int index, void* element) {
71   if (a != NULL && index >=0 && index < a->capacity) {
72     a->data[index] = element;
73     if (a->size <= index) {
74       a->size = index + 1;
75     }
76   }
77 }
78
79 void* array_get(array* a, int index) {
80   if (a != NULL && index >= 0 && index < a->size) {
81     return a->data[index];
82   }
83   else {
84     return NULL;
85   }
86 }
87
88 void array_delete(array* a) {
89   if (a != NULL) {
90     free(a->data);
91     free(a);
92   }
93 }
94
95 void array_delete_vs_data(array* a) {
96   if (a != NULL) {
97     array_delete_data(a);
98     array_delete(a);
99   }
100 }
101
102 void array_delete_data(array* a) {
103   if (a != NULL) {
104     for (int i = 0; i < a->size; i++) {
105       if (a->data[i] != NULL) {
106         free(a->data[i]);
107       }
108     }
109     a->size = 0;
110   }
111 }
112
113
114 struct table_str {
115   void** data;
116   int capacity;
117 };
118
119 table* table_create(int capacity) {
120   table* t = calloc(1, sizeof(table));
121   if (t == NULL) {
122     return NULL;
123   }
124
125   t->data = calloc(capacity, sizeof(void*));
126   if (t->data == NULL) {
127     free(t);
128     return NULL;
129   }
130
131   t->capacity = capacity;
132
133   return t;
134 }
135
136 static inline int wrap(int key, table* t) {
137   return (t != NULL ? key % t->capacity : -1);
138 }
139
140 // todo: resolve collisions (?)
141 void* table_put(table* t, int key, void* value) {
142   int k = wrap(key, t);
143   if (k < 0 || (value != NULL && t->data[k] != NULL)) {
144     return NULL;
145   }
146   else {
147     return t->data[k] = value;
148   }
149 }
150
151 void* table_get(table* t, int key) {
152   int k = wrap(key, t);
153   if (k < 0) {
154     return NULL;
155   }
156   else {
157     return t->data[k];
158   }
159 }
160
161 void table_delete(table* t) {
162   if (t != NULL) {
163     free(t->data);
164     free(t);
165   }
166 }
167
168
169 #define INPUT_BUF_LEN 2048
170 static char input_buf[INPUT_BUF_LEN];
171
172 char* read_line(FILE* stream) {
173   char* result = fgets(input_buf, INPUT_BUF_LEN, stream);
174   if (result == NULL || feof(stream)) {
175     return NULL;
176   }
177   size_t pos = strlen(input_buf) - 1;
178   if (input_buf[pos] == '\n') {
179     input_buf[pos] = '\0';
180   }
181   return input_buf;
182 }
183
184
185 bool is_parent_path(const char* parent_path, const char* child_path) {
186   size_t parent_len = strlen(parent_path);
187   return strncmp(parent_path, child_path, parent_len) == 0 &&
188          (parent_len == strlen(child_path) || child_path[parent_len] == '/');
189 }