1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /**************************************************************************
4 *
5 *   Copyright (C) 2000-2016, International Business Machines
6 *   Corporation and others.  All Rights Reserved.
7 *
8 ***************************************************************************
9 *   file name:  pkgdata.c
10 *   encoding:   ANSI X3.4 (1968)
11 *   tab size:   8 (not used)
12 *   indentation:4
13 *
14 *   created on: 2000may16
15 *   created by: Steven \u24C7 Loomis
16 *
17 *  common types for pkgdata
18 */
19 
20 #include <stdbool.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include "unicode/utypes.h"
24 #include "unicode/putil.h"
25 #include "cmemory.h"
26 #include "cstring.h"
27 #include "pkgtypes.h"
28 #include "putilimp.h"
29 
pkg_writeCharListWrap(FileStream * s,CharList * l,const char * delim,const char * brk,int32_t quote)30 const char *pkg_writeCharListWrap(FileStream *s, CharList *l, const char *delim, const char *brk, int32_t quote)
31 {
32     int32_t ln = 0;
33     char buffer[1024];
34     while(l != NULL)
35     {
36         if(l->str)
37         {
38             uprv_strncpy(buffer, l->str, 1020);
39             buffer[1019]=0;
40 
41             if(quote < 0) { /* remove quotes */
42                 if(buffer[uprv_strlen(buffer)-1] == '"') {
43                     buffer[uprv_strlen(buffer)-1] = '\0';
44                 }
45                 if(buffer[0] == '"') {
46                     uprv_strcpy(buffer, buffer+1);
47                 }
48             } else if(quote > 0) { /* add quotes */
49                 if(l->str[0] != '"') {
50                     uprv_strcpy(buffer, "\"");
51                     uprv_strncat(buffer, l->str,1020);
52                 }
53                 if(l->str[uprv_strlen(l->str)-1] != '"') {
54                     uprv_strcat(buffer, "\"");
55                 }
56             }
57             T_FileStream_write(s, buffer, (int32_t)uprv_strlen(buffer));
58 
59             ln += (int32_t)uprv_strlen(l->str);
60         }
61 
62         if(l->next && delim)
63         {
64             if(ln > 60 && brk) {
65                 ln  = 0;
66                 T_FileStream_write(s, brk, (int32_t)uprv_strlen(brk));
67             }
68             T_FileStream_write(s, delim, (int32_t)uprv_strlen(delim));
69         }
70         l = l->next;
71     }
72     return NULL;
73 }
74 
75 
pkg_writeCharList(FileStream * s,CharList * l,const char * delim,int32_t quote)76 const char *pkg_writeCharList(FileStream *s, CharList *l, const char *delim, int32_t quote)
77 {
78     char buffer[1024];
79     while(l != NULL)
80     {
81         if(l->str)
82         {
83             uprv_strncpy(buffer, l->str, 1023);
84             buffer[1023]=0;
85             if(uprv_strlen(l->str) >= 1023)
86             {
87                 fprintf(stderr, "%s:%d: Internal error, line too long (greater than 1023 chars)\n",
88                         __FILE__, __LINE__);
89                 exit(0);
90             }
91             if(quote < 0) { /* remove quotes */
92                 if(buffer[uprv_strlen(buffer)-1] == '"') {
93                     buffer[uprv_strlen(buffer)-1] = '\0';
94                 }
95                 if(buffer[0] == '"') {
96                     uprv_strcpy(buffer, buffer+1);
97                 }
98             } else if(quote > 0) { /* add quotes */
99                 if(l->str[0] != '"') {
100                     uprv_strcpy(buffer, "\"");
101                     uprv_strcat(buffer, l->str);
102                 }
103                 if(l->str[uprv_strlen(l->str)-1] != '"') {
104                     uprv_strcat(buffer, "\"");
105                 }
106             }
107             T_FileStream_write(s, buffer, (int32_t)uprv_strlen(buffer));
108         }
109 
110         if(l->next && delim)
111         {
112             T_FileStream_write(s, delim, (int32_t)uprv_strlen(delim));
113         }
114         l = l->next;
115     }
116     return NULL;
117 }
118 
119 
120 /*
121  * Count items . 0 if null
122  */
pkg_countCharList(CharList * l)123 uint32_t pkg_countCharList(CharList *l)
124 {
125   uint32_t c = 0;
126   while(l != NULL)
127   {
128     c++;
129     l = l->next;
130   }
131 
132   return c;
133 }
134 
135 /*
136  * Prepend string to CharList
137  */
pkg_prependToList(CharList * l,const char * str)138 CharList *pkg_prependToList(CharList *l, const char *str)
139 {
140   CharList *newList;
141   newList = uprv_malloc(sizeof(CharList));
142 
143   /* test for NULL */
144   if(newList == NULL) {
145     return NULL;
146   }
147 
148   newList->str = str;
149   newList->next = l;
150   return newList;
151 }
152 
153 /*
154  * append string to CharList. *end or even end can be null if you don't
155  * know it.[slow]
156  * Str is adopted!
157  */
pkg_appendToList(CharList * l,CharList ** end,const char * str)158 CharList *pkg_appendToList(CharList *l, CharList** end, const char *str)
159 {
160   CharList *endptr = NULL, *tmp;
161 
162   if(end == NULL)
163   {
164     end = &endptr;
165   }
166 
167   /* FIND the end */
168   if((*end == NULL) && (l != NULL))
169   {
170     tmp = l;
171     while(tmp->next)
172     {
173       tmp = tmp->next;
174     }
175 
176     *end = tmp;
177   }
178 
179   /* Create a new empty list and append it */
180   if(l == NULL)
181     {
182       l = pkg_prependToList(NULL, str);
183     }
184   else
185     {
186       (*end)->next = pkg_prependToList(NULL, str);
187     }
188 
189   /* Move the end pointer. */
190   if(*end)
191     {
192       (*end) = (*end)->next;
193     }
194   else
195     {
196       *end = l;
197     }
198 
199   return l;
200 }
201 
convertToNativePathSeparators(char * path)202 char * convertToNativePathSeparators(char *path) {
203 #if defined(U_MAKE_IS_NMAKE)
204     char *itr;
205     while ((itr = uprv_strchr(path, U_FILE_ALT_SEP_CHAR))) {
206         *itr = U_FILE_SEP_CHAR;
207     }
208 #endif
209     return path;
210 }
211 
pkg_appendUniqueDirToList(CharList * l,CharList ** end,const char * strAlias)212 CharList *pkg_appendUniqueDirToList(CharList *l, CharList** end, const char *strAlias) {
213     char aBuf[1024];
214     char *rPtr;
215     rPtr = uprv_strrchr(strAlias, U_FILE_SEP_CHAR);
216 #if (U_FILE_SEP_CHAR != U_FILE_ALT_SEP_CHAR)
217     {
218         char *aPtr = uprv_strrchr(strAlias, U_FILE_ALT_SEP_CHAR);
219         if(!rPtr || /* regular char wasn't found or.. */
220             (aPtr && (aPtr > rPtr)))
221         { /* alt ptr exists and is to the right of r ptr */
222             rPtr = aPtr; /* may copy NULL which is OK */
223         }
224     }
225 #endif
226     if(!rPtr) {
227         return l; /* no dir path */
228     }
229     if((rPtr-strAlias) >= UPRV_LENGTHOF(aBuf)) {
230         fprintf(stderr, "## ERR: Path too long [%d chars]: %s\n", (int)sizeof(aBuf), strAlias);
231         return l;
232     }
233     strncpy(aBuf, strAlias,(rPtr-strAlias));
234     aBuf[rPtr-strAlias]=0;  /* no trailing slash */
235     convertToNativePathSeparators(aBuf);
236 
237     if(!pkg_listContains(l, aBuf)) {
238         return pkg_appendToList(l, end, uprv_strdup(aBuf));
239     } else {
240         return l; /* already found */
241     }
242 }
243 
244 #if 0
245 static CharList *
246 pkg_appendFromStrings(CharList *l, CharList** end, const char *s, int32_t len)
247 {
248   CharList *endptr = NULL;
249   const char *p;
250   char *t;
251   const char *targ;
252   if(end == NULL) {
253     end = &endptr;
254   }
255 
256   if(len==-1) {
257     len = uprv_strlen(s);
258   }
259   targ = s+len;
260 
261   while(*s && s<targ) {
262     while(s<targ&&isspace(*s)) s++;
263     for(p=s;s<targ&&!isspace(*p);p++);
264     if(p!=s) {
265       t = uprv_malloc(p-s+1);
266       uprv_strncpy(t,s,p-s);
267       t[p-s]=0;
268       l=pkg_appendToList(l,end,t);
269       fprintf(stderr, " P %s\n", t);
270     }
271     s=p;
272   }
273 
274   return l;
275 }
276 #endif
277 
278 
279 /*
280  * Delete list
281  */
pkg_deleteList(CharList * l)282 void pkg_deleteList(CharList *l)
283 {
284   CharList *tmp;
285   while(l != NULL)
286   {
287     uprv_free((void*)l->str);
288     tmp = l;
289     l = l->next;
290     uprv_free(tmp);
291   }
292 }
293 
pkg_listContains(CharList * l,const char * str)294 UBool  pkg_listContains(CharList *l, const char *str)
295 {
296   for(;l;l=l->next){
297     if(!uprv_strcmp(l->str, str)) {
298       return true;
299     }
300   }
301 
302   return false;
303 }
304