1 //
2 // ipv2_karray.cc
3 //
4 // Copyright (C) 1996 Limit Point Systems, Inc.
5 //
6 // Author: Curtis Janssen <cljanss@limitpt.com>
7 // Maintainer: LPS
8 //
9 // This file is part of the SC Toolkit.
10 //
11 // The SC Toolkit is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU Library General Public License as published by
13 // the Free Software Foundation; either version 2, or (at your option)
14 // any later version.
15 //
16 // The SC Toolkit is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 // GNU Library General Public License for more details.
20 //
21 // You should have received a copy of the GNU Library General Public License
22 // along with the SC Toolkit; see the file COPYING.LIB.  If not, write to
23 // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24 //
25 // The U.S. Government is granted a limited license as per AL 91-7.
26 //
27 
28 /* These routines manipulate keyword arrays.  A keyword
29  * array differs from a data array in that its indices are indicated
30  * by a keyword segment.  For example: array:0:1 = 6 is a keyword
31  * array element.  The count is the upper bound plus 1. */
32 
33 /* NOTE: If these routines are used to access keyword arrays, then
34  * only the first place in the cwk in which a keyword array name is
35  * found will be used. */
36 
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <stdarg.h>
40 #include <string.h>
41 #include <util/keyval/ipv2.h>
42 
43 using namespace sc;
44 
45 void
ip_cwk_karray_add_v(int n,int * v)46 IPV2::ip_cwk_karray_add_v(int n,int*v)
47 {
48   int i;
49   char indices[110],index[10];
50 
51   if (n>10) {
52     warn("ip_cwk_karray_add_v: too many indices");
53     return;
54     }
55   indices[0] = '\0';
56   for (i=0; i<n; i++) {
57     if (v[i] > 999999999 || v[i] < 0) {
58       warn("ip_cwk_karray_add_v: an index is too large or small");
59       return;
60       }
61     sprintf(index,"%d",v[i]);
62     strcpy(indices,index);
63     if (i!=n-1) strcpy(indices,":");
64     }
65   cwk_add(indices);
66   return;
67   }
68 
69 void
ip_cwk_karray_add(int n,...)70 IPV2::ip_cwk_karray_add(int n,...)
71 {
72   va_list args;
73   int i;
74   int *v;
75 
76   if (n==0) {
77     ip_cwk_karray_add_v(n,NULL);
78     return;
79     }
80   else {
81     v = (int *) malloc(sizeof(int)*n);
82     if (!v) {
83       warn("ip_cwk_karray_add: problem with malloc");
84       return;
85       }
86     va_start(args, n);
87     for (i=0; i<n; i++) {
88       v[i] = va_arg(args,int);
89       }
90     va_end(args);
91     free(v);
92     ip_cwk_karray_add_v(n,v);
93     return;
94     }
95   }
96 
97 ip_keyword_tree_t*
ip_karray_descend_v(ip_keyword_tree_t * kt,int n,int * v)98 IPV2::ip_karray_descend_v(ip_keyword_tree_t*kt,int n,int*v)
99 {
100   ip_keyword_tree_t *r;
101   int i;
102   char index[10];
103 
104   if (!kt) return NULL;
105 
106   /* kt starts off at the array so we must first descend to the first
107    * level of indices. */
108   r = kt->down;
109   if (!r) return NULL;
110 
111   for (i=0; i<n; i++) {
112     if (!r) return r;
113     if (v[i] > 999999999 || v[i] < 0) {
114       warn("ip_karray_descend_v: an index is too large or small");
115       return NULL;
116       }
117     sprintf(index,"%d",v[i]);
118     r = ip_descend_tree(r,index);
119     if (r) r=r->down;
120     }
121   return r;
122   }
123 
124 ip_keyword_tree_t*
ip_karray_descend(ip_keyword_tree_t * kt,int n,...)125 IPV2::ip_karray_descend(ip_keyword_tree_t*kt,int n,...)
126 {
127   va_list args;
128   int i;
129   int *v;
130 
131   if (n==0) {
132     return ip_karray_descend_v(kt,n,NULL);
133     }
134   else {
135     v = (int *) malloc(sizeof(int)*n);
136     if (!v) {
137       warn("ip_karray_descend: problem with malloc");
138       return NULL;
139       }
140     va_start(args, n);
141     for (i=0; i<n; i++) {
142       v[i] = va_arg(args,int);
143       }
144     va_end(args);
145     free(v);
146     return ip_karray_descend_v(kt,n,v);
147     }
148   }
149 
150 IPV2::Status
count_v(const char * keyword,int * karray_count,int n,int * v)151 IPV2::count_v(const char* keyword,int*karray_count,int n,int*v)
152 {
153   ip_keyword_tree_t *kt,*I;
154   int index;
155   int max;
156 
157   /* Descend the keyword tree to keyword. */
158   kt = ip_cwk_descend_tree(keyword);
159   if (kt == NULL) return KeyNotFound;
160 
161   /* Descend the tree to the indices. */
162   kt = ip_karray_descend_v(kt,n,v);
163   if (kt == NULL) return NotAnArray;
164 
165   /* Go thru the keyword array and examine the indices. */
166   I = kt;
167   max = 0;
168   do {
169     if (sscanf(I->keyword,"%d",&index) != 1) return OutOfBounds;
170     if (index<0) return OutOfBounds;
171     if (index+1 > max) max = index + 1;
172     } while ((I = I->across) != kt);
173 
174   *karray_count = max;
175   return OK;
176   }
177 
178 /* This counts the number of elements in a keyword array. */
179 IPV2::Status
count(const char * keyword,int * karray_count,int n,...)180 IPV2::count(const char *keyword,int *karray_count,int n,...)
181 {
182   va_list args;
183   int i;
184   int *v;
185   Status r;
186 
187   if (n==0) {
188     return count_v(keyword,karray_count,n,NULL);
189     }
190   else {
191     v = (int *) malloc(sizeof(int)*n);
192     if (!v) return Malloc;
193     va_start(args, n);
194     for (i=0; i<n; i++) {
195       v[i] = va_arg(args,int);
196       }
197     va_end(args);
198     r = count_v(keyword,karray_count,n,v);
199     free(v);
200     return r;
201     }
202   }
203