2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
5 Desc: Sorts the contents of a file
8 /*****************************************************************************
16 FROM/A,TO/A,COLSTART/K,CASE/S,NUMERIC/S
24 Sorts the contents of a text file
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
46 ******************************************************************************/
48 #include <clib/macros.h>
49 #include <exec/memory.h>
50 #include <exec/types.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>
61 #include <aros/debug.h>
65 #define TEMPLATE "FROM/A,TO/A,COLSTART/K,CASE/S,NUMERIC/S"
69 #define ARG_COLSTART 2
75 const TEXT version
[] = "$VER: Sort 41.2 (3.4.2014)";
79 struct sorted_data
* next
;
81 ULONG len
; // length of line including '\n'.
84 struct Locale
* locale
;
86 int compare(struct sorted_data
* sd1
,
87 struct sorted_data
* sd2
,
91 ULONG len
= MIN(sd1
->len
, sd2
->len
);
93 /* FIXME: It seems like StrnCmp of locale does not work. */
104 a
= IsUpper(locale
,(ULONG
)*(sd1
->data
+col
+i
));
105 b
= IsUpper(locale
,(ULONG
)*(sd2
->data
+col
+i
));
109 if (0 != (retval
= StrnCmp(locale
,
128 retval
=StrnCmp(locale
,
136 if (sd1
->len
< sd2
->len
)
147 char * str1
= sd1
->data
;
148 char * str2
= sd2
->data
;
152 if (str1
[i
] != str2
[i
])
153 return (int)(str1
[i
] - str2
[i
]);
158 return (int)sd1
->len
- (int)sd2
->len
;
163 struct sorted_data
* sort(UBYTE
* data
,
171 struct sorted_data
* first
= NULL
;
172 struct sorted_data
* cur
= NULL
;
173 struct sorted_data
* tooshort
= NULL
;
174 struct sorted_data
* tooshort_last
= NULL
;
178 while (*colstart
>= '0' && *colstart
<= '9')
179 col
= col
* 10 + *colstart
++ - '0';
184 while (pos
< data_len
)
189 while (pos
< data_len
&& data
[pos
] != 0x0a)
192 if (data
[pos
] == 0x0a || pos
== data_len
)
197 cur
= AllocMem(sizeof(struct sorted_data
), MEMF_ANY
|MEMF_CLEAR
);
201 cur
->data
= data
+ begin
;
207 ** Insert it into the list of sorted lines
212 ** To be first in the list?
214 if (compare(cur
, first
, col
, case_on
) < 0)
221 struct sorted_data
* _cur
= first
;
226 ** Insert it after the current one and before the
229 if (NULL
== _cur
->next
)
234 if (compare(cur
, _cur
->next
, col
, case_on
) < 0)
236 cur
-> next
= _cur
->next
;
244 } /* if (NULL != first) */
250 /* this line is too short to sort it in */
251 if (NULL
== tooshort
)
258 tooshort_last
->next
= cur
;
266 if (NULL
!= tooshort
)
268 tooshort_last
->next
= first
;
276 LONG
write_data(struct sorted_data
* start
, BPTR file_out
)
284 struct sorted_data
* next
= start
->next
;
288 count
= Write(file_out
, start
->data
, start
->len
);
289 if (count
!= -1 && start
->data
[start
->len
-1] != 0x0a)
290 count
= Write(file_out
, "\n", 1);
298 FreeMem(start
, sizeof(struct sorted_data
));
309 IPTR args
[ARG_NUM
] = { (IPTR
) NULL
, (IPTR
) NULL
, (IPTR
) NULL
, FALSE
, FALSE
};
311 LONG result
= RETURN_OK
;
314 locale
= OpenLocale(NULL
);
317 PutStr("Could not open locale!\n");
321 rda
= ReadArgs(TEMPLATE
, args
, NULL
);
325 lock_in
= Lock((STRPTR
)args
[ARG_FROM
], ACCESS_READ
);
329 BPTR file_out
= Open((STRPTR
)args
[ARG_TO
], MODE_NEWFILE
);
330 if (file_out
== BNULL
)
332 struct FileInfoBlock
*fib
= AllocDosObject(DOS_FIB
, NULL
);
339 BOOL success
= Examine(lock_in
, fib
);
342 ** Read the input file into memory
344 if (fib
->fib_Size
&& success
)
345 data
= AllocVec(fib
->fib_Size
, MEMF_ANY
);
350 if ((in
= OpenFromLock(lock_in
))) {
351 ULONG read
= Read(in
, data
, fib
->fib_Size
);
355 struct sorted_data
* sd
;
358 (STRPTR
)args
[ARG_COLSTART
],
359 (BOOL
)args
[ARG_CASE
],
360 (BOOL
)args
[ARG_NUMERIC
]);
362 error
= write_data(sd
, file_out
);
374 FreeDosObject(DOS_FIB
, fib
);
387 PrintFault(error
, "Sort");
388 result
= RETURN_FAIL
;