build: use $CMAKE_INSTALL_LIBDIR instead of hardcoding "lib" (#1589)
[FMS.git] / string_utils / fms_string_utils_binding.c
blobda9a7dae6f6e87f91341f3a695fbc2a631eed687
1 /***********************************************************************
2 * GNU Lesser General Public License
4 * This file is part of the GFDL Flexible Modeling System (FMS).
6 * FMS is free software: you can redistribute it and/or modify it under
7 * the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or (at
9 * your option) any later version.
11 * FMS is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FMS. If not, see <http://www.gnu.org/licenses/>.
18 **********************************************************************/
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <math.h>
25 // struct to store a string and id associated with that string
26 typedef struct{
27 char arr_name[255];
28 int id;
29 }my_type;
31 // Compares two my_type types by the arr_name
32 static int arr_name_sorter(const void* p1, const void* p2)
34 const my_type *the_type1 = p1;
35 const my_type *the_type2 = p2;
37 return strcmp(the_type1->arr_name, the_type2->arr_name);
40 // Sorts an array of strings in alphabetical order
41 // Implements a binary search to search for a string in an array of strings
42 // arr -> pointer of character array
43 // n -> length of the array
44 // id - > indices of the character array
45 void fms_sort_this(char **arr, int* n, int* id)
47 int i; // For do loops
48 my_type *the_type;
50 // Save the array and the id into a struct
51 the_type = (my_type*)calloc(*n, sizeof(my_type));
52 for(i=0; i<*n; i++){
53 the_type[i].id = id[i];
54 strcpy(the_type[i].arr_name, arr[i]);
57 qsort(the_type, *n, sizeof(my_type), arr_name_sorter);
59 // Copy the sorted array and the sorted ids
60 for(i=0; i<*n; i++){
61 id[i] = the_type[i].id;
62 strcpy(arr[i], the_type[i].arr_name);
66 // Implements a binary search to search for a string in an array of strings
67 // arr -> pointer of character array
68 // n -> length of the array
69 // find me -> string to find
70 // np -> the number of times the string was found
71 // returns a string with the indices ;)
72 char* fms_find_my_string_binding(char** arr, int *n, char *find_me, int *np)
74 int L= 0; // Left bound
75 int R = *n; // Right bound
76 int m; // Middle of the bound
77 int mm; // Index currently looking at
78 int is_found; // Result from strcmp: 0 if string was found <0 if the string is "less" >0 if the string is "greater"
79 int *p; // Array to store the indices
80 int i; // For do loops
82 *np = 0;
83 is_found = -1;
84 while(L != R){
85 // Start looking in the midle of the array
86 m = ceil((L + R) / 2);
87 //printf("L is set to %i from L=%i and R=%i \n", m, L, R);
89 //printf("Checking %i:%s \n", m, (arr[m]));
90 is_found = strcmp(find_me,(arr[m]));
91 if (is_found == 0)
93 *np = 1;
94 p = malloc(sizeof(int) * *np);
95 p[*np-1] = m + 1; //Because fortran indices start at 1 ;)
96 //printf("Array found at %i %i %i \n", *np, m, p[*np-1]);
98 // The string can be found in multiple indices of the array, so look to the left of the index where the string
99 // was initially found
100 mm = m;
101 while (is_found == 0) {
102 if (mm != 0) { // Only look to the left if m is not the begining of the array
103 mm= mm -1;
104 is_found = strcmp(find_me,(arr[mm]));
105 if (is_found == 0 ) {
106 *np = *np + 1;
107 p = realloc(p, sizeof(int) * *np);
108 p[*np-1] = mm + 1;
109 //printf("Array found at %i %i %i\n", *np, mm, p[*np-1]);
111 } else {is_found = -999;} //Done looking
113 // The string can be found in multiple indices of the array, so look to the right of the index where the string was
114 // initially found
115 mm = m;
116 is_found =0;
117 while (is_found == 0) {
118 if (mm != *n-1) { // Only look to the right if m is not the end of the array
119 mm = mm + 1;
120 is_found = strcmp(find_me,(arr[mm]));
121 if (is_found == 0 ) {
122 *np = *np + 1;
123 p = realloc(p, sizeof(int) * *np);
124 p[*np-1] = mm + 1;
125 //printf("Array found at %i %i %i\n", *np, mm, p[*np-1]);
127 } else {is_found = -999;} //Done looking}
129 L = R;
130 // If find_me is greater than arr[m] (i.e find_me="potato" is greater than arr[m]="banana")
131 } else if (is_found > 0) {
132 // Set the lower bound to start in m (ignore the first half)
133 L = m + 1;
134 //printf("L is set to %i \n", L);
135 } else
136 // If find_me is less than arr[m] (i.e find_me="potato" is less than arr[m] = "soccer")
138 // Set the upper bound to start in m (ignore the lower half)
139 R = m;
140 //printf("R is set to %i \n", R);
145 // This is the magical part:
146 // Save the array of indices where the string was found into a string
147 // The fortran side is going to allocate the array to the correct size and read the string into the array
148 // The alternative (normal) way is to have a seperate function that gets the number of times the string is found
149 // The fortran side will allocate the array to the correct size and send that into another function that
150 // fill in that array. That will require you to search through the array twice ...
151 char string[255];
152 char *string_p;
154 strcpy(string, "");
156 for(i=0; i<*np; i++){
157 if (i == *np-1) {sprintf( &string[ strlen(string) ], "%d ", p[i] );}
158 else {sprintf( &string[ strlen(string) ], "%d ,", p[i] );}
161 string_p = (char*) malloc((strlen(string)+1)*sizeof(char));
162 strcpy(string_p, string);
163 return string_p;
167 * @brief Finds the number of unique strings in an array
168 * @param[in] arr Array of strings
169 * @param[in] n Size of the array
170 * @return Number of unique strings in an array
172 int fms_find_unique(char** arr, int *n)
174 int i; // For loops
175 int nfind; // Number of unique strings in an array
176 int * ids = calloc(*n, sizeof(int)); // Array of integers initialized to 0
178 fms_sort_this(arr, n, ids);
180 nfind=1;
181 for(i=1; i<*n; i++){
182 if (strcmp(arr[i], arr[i-1]) != 0){ nfind = nfind + 1;}
185 return nfind;
189 * @brief Returns a c string pointer
190 * @param[in] cs Input c string pointer
191 * @return c string pointer
193 char * cstring2cpointer (char * cs)
195 return cs;