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