added concrete implementations of putc(), getc(), getchar() and gets()
[tangerine.git] / workbench / c / Sort.c
blob77fea4628f603fbecd66f4a67acb8e881b3f9a4d
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Sorts the contents of a file
6 Lang: English
7 */
8 /*****************************************************************************
10 NAME
12 Sort
14 SYNOPSIS
16 FROM/A,TO/A,COLSTART/K,CASE/S,NUMERIC/S
18 LOCATION
20 Workbench:C/
22 FUNCTION
24 Sorts the contents of a text file
26 INPUTS
28 FROM -- file to read from
29 TO -- file to output to
30 COLSTART -- column at which the comparison begins
31 CASE -- sort is case sensitive. Uppercase items are output first
32 NUMERIC -- lines are interpreted as numbers
34 RESULT
36 EXAMPLE
38 BUGS
40 SEE ALSO
42 INTERNALS
44 HISTORY
46 ******************************************************************************/
48 #include <clib/macros.h>
49 #include <exec/memory.h>
50 #include <exec/types.h>
51 #include <dos/dos.h>
52 #include <dos/exall.h>
53 #include <proto/dos.h>
54 #include <proto/exec.h>
55 #include <proto/utility.h>
56 #include <proto/locale.h>
57 #include <libraries/locale.h>
58 #include <utility/tagitem.h>
60 #define DEBUG 0
61 #include <aros/debug.h>
63 #include <string.h>
65 #define TEMPLATE "FROM/A,TO/A,COLSTART/K,CASE/S,NUMERIC/S"
67 #define ARG_FROM 0
68 #define ARG_TO 1
69 #define ARG_COLSTART 2
70 #define ARG_CASE 3
71 #define ARG_NUMERIC 4
73 #define ARG_NUM 5
75 struct sorted_data
77 struct sorted_data * next;
78 UBYTE * data;
79 ULONG len; // length of line including '\n'.
82 struct Locale * locale;
84 int compare(struct sorted_data * sd1,
85 struct sorted_data * sd2,
86 ULONG col,
87 BOOL case_on)
89 ULONG len = MIN(sd1->len, sd2->len);
91 #warning It seems like StrnCmp of locale does not work.
92 #if 1
93 LONG retval = 0;
95 if (TRUE == case_on)
97 int i = col;
99 while (i < len)
101 BOOL a,b;
102 a = IsUpper(locale,(ULONG)*(sd1->data+col+i));
103 b = IsUpper(locale,(ULONG)*(sd2->data+col+i));
105 if (a == b)
107 if (0 != (retval = StrnCmp(locale,
108 sd1->data+col,
109 sd2->data+col,
111 SC_COLLATE2)));
112 break;
114 else
116 retval = b - a;
117 break;
120 i++;
123 else
126 retval=StrnCmp(locale,
127 sd1->data+col,
128 sd2->data+col,
129 len,
130 SC_COLLATE2);
132 if (0 == retval)
134 if (sd1->len < sd2->len)
135 retval = -100;
136 else
137 retval = +100;
141 return retval;
143 #else
144 int i = col;
145 char * str1 = sd1->data;
146 char * str2 = sd2->data;
148 while (i < len)
150 if (str1[i] != str2[i])
151 return (int)(str1[i] - str2[i]);
153 i++;
156 return (int)sd1->len - (int)sd2->len;
157 #endif
161 struct sorted_data * sort(UBYTE * data,
162 ULONG data_len,
163 STRPTR colstart,
164 BOOL case_on,
165 BOOL is_numeric)
167 ULONG pos = 0;
168 ULONG col = 0;
169 struct sorted_data * first = NULL;
170 struct sorted_data * cur = NULL;
171 struct sorted_data * tooshort = NULL;
172 struct sorted_data * tooshort_last = NULL;
174 if (colstart)
176 while (*colstart >= '0' && *colstart <= '9')
177 col = col * 10 + *colstart++ - '0';
178 if (col > 0)
179 col-=1;
182 while (pos < data_len)
184 ULONG begin = pos;
185 ULONG len;
187 while (pos < data_len && data[pos] != 0x0a)
188 pos++;
190 if (data[pos] == 0x0a || pos == data_len)
191 len = pos++ - begin;
192 else
193 len = ++pos - begin;
195 cur = AllocMem(sizeof(struct sorted_data), MEMF_ANY|MEMF_CLEAR);
197 if (cur)
199 cur->data = data + begin;
200 cur->len = len;
202 if (len > col)
205 ** Insert it into the list of sorted lines
207 if (NULL != first)
210 ** To be first in the list?
212 if (compare(cur, first, col, case_on) < 0)
214 cur->next = first;
215 first = cur;
217 else
219 struct sorted_data * _cur = first;
221 while (1)
224 ** Insert it after the current one and before the
225 ** next one?
227 if (NULL == _cur->next)
229 _cur->next = cur;
230 break;
232 if (compare(cur, _cur->next, col, case_on) < 0)
234 cur -> next = _cur->next;
235 _cur-> next = cur;
236 break;
239 _cur = _cur->next;
242 } /* if (NULL != first) */
243 else
244 first = cur;
246 else
248 /* this line is too short to sort it in */
249 if (NULL == tooshort)
251 tooshort = cur;
252 tooshort_last = cur;
254 else
256 tooshort_last->next = cur;
257 tooshort_last = cur;
260 } /* if (cur) */
264 if (NULL != tooshort)
266 tooshort_last->next = first;
267 first = tooshort;
270 return first;
274 ULONG write_data(struct sorted_data * start, BPTR file_out)
276 BOOL write = TRUE;
277 ULONG error = 0;
279 while (start)
281 struct sorted_data * next = start->next;
283 if (TRUE == write)
285 error = Write(file_out, start->data, start->len);
286 if (-1 != error && start->data[start->len-1] != 0x0a)
287 error = Write(file_out, "\n", 1);
290 if (-1 == error)
291 write = FALSE;
293 FreeMem(start, sizeof(struct sorted_data));
294 start = next;
297 if (FALSE == write)
298 return error;
300 return 0;
303 int __nocommandline;
305 int main (void)
307 IPTR args[ARG_NUM] = { (IPTR) NULL, (IPTR) NULL, (IPTR) NULL, FALSE, FALSE};
308 struct RDArgs *rda;
309 ULONG error = 0;
311 locale = OpenLocale(NULL);
312 if (!locale)
314 PutStr("Could not open locale!\n");
315 return -1;
318 rda = ReadArgs(TEMPLATE, args, NULL);
319 if (rda)
321 BPTR lock_in;
322 lock_in = Lock((STRPTR)args[ARG_FROM], ACCESS_READ);
324 if (lock_in)
326 BPTR file_out = Open((STRPTR)args[ARG_TO], MODE_NEWFILE);
328 if (NULL != file_out)
330 struct FileInfoBlock fib;
331 UBYTE * data = NULL;
332 BOOL success = Examine(lock_in, &fib);
335 ** Read the input file into memory
337 if (fib.fib_Size && DOSTRUE == success)
338 data = AllocVec(fib.fib_Size, MEMF_ANY);
340 if (data)
342 ULONG read = Read(lock_in, data, fib.fib_Size);
344 if (-1 != read)
346 struct sorted_data * sd;
347 sd = sort(data,
348 fib.fib_Size,
349 (STRPTR)args[ARG_COLSTART],
350 (BOOL)args[ARG_CASE],
351 (BOOL)args[ARG_NUMERIC]);
353 error = write_data(sd, file_out);
355 FreeVec(data);
356 }/* if (data) */
358 Close(file_out);
359 } /* if (file_out) */
360 UnLock(lock_in);
361 } /* if (lock_in) */
362 FreeArgs(rda);
364 else
365 error=RETURN_FAIL;
367 if (error)
368 PrintFault(IoErr(), "Sort");
370 return error;