1 /* AirScan (a.k.a. eSCL) backend for SANE
2  *
3  * Copyright (C) 2019 and up by Alexander Pevzner (pzz@apevzner.com)
4  * See LICENSE for license terms and conditions
5  *
6  * SANE_Word/SANE_String/SANE_Device* arrays
7  */
8 
9 #include "airscan.h"
10 
11 #include <stdlib.h>
12 #include <string.h>
13 
14 /* Compare function for sane_word_array_sort
15  */
16 static int
sane_word_array_sort_cmp(const void * p1,const void * p2)17 sane_word_array_sort_cmp(const void *p1, const void *p2)
18 {
19     return *(SANE_Word*) p1 - *(SANE_Word*) p2;
20 }
21 
22 /* Drop array elements that outside of specified boundary
23  */
24 void
sane_word_array_bound(SANE_Word * a,SANE_Word min,SANE_Word max)25 sane_word_array_bound (SANE_Word *a, SANE_Word min, SANE_Word max)
26 {
27     SANE_Word len = a[0];
28     SANE_Word i, o;
29 
30     for (i = o = 1; i < len + 1; i ++) {
31         if (min <= a[i] && a[i] <= max) {
32             a[o ++] = a[i];
33         }
34     }
35 
36     a[0] = o - 1;
37     mem_shrink(a, o);
38 }
39 
40 /* Sort array of SANE_Word in increasing order
41  */
42 void
sane_word_array_sort(SANE_Word * a)43 sane_word_array_sort(SANE_Word *a)
44 {
45     SANE_Word len = a[0];
46 
47     if (len) {
48         qsort(a + 1, len, sizeof(SANE_Word), sane_word_array_sort_cmp);
49     }
50 }
51 
52 /* Intersect two sorted arrays.
53  */
54 SANE_Word*
sane_word_array_intersect_sorted(const SANE_Word * a1,const SANE_Word * a2)55 sane_word_array_intersect_sorted (const SANE_Word *a1, const SANE_Word *a2)
56 {
57     const SANE_Word *end1 = a1 + sane_word_array_len(a1) + 1;
58     const SANE_Word *end2 = a2 + sane_word_array_len(a2) + 1;
59     SANE_Word       *out = sane_word_array_new();
60 
61     a1 ++;
62     a2 ++;
63 
64     while (a1 < end1 && a2 < end2) {
65         if (*a1 < *a2) {
66             a1 ++;
67         } else if (*a1 > *a2) {
68             a2 ++;
69         } else {
70             out = sane_word_array_append(out, *a1);
71             a1 ++;
72             a2 ++;
73         }
74     }
75 
76     return out;
77 }
78 
79 /* Compute max string length in array of strings
80  */
81 size_t
sane_string_array_max_strlen(const SANE_String * a)82 sane_string_array_max_strlen(const SANE_String *a)
83 {
84     size_t max_len = 0;
85 
86     for (; *a != NULL; a ++) {
87         size_t len = strlen(*a);
88         if (len > max_len) {
89             max_len = len;
90         }
91     }
92 
93     return max_len;
94 }
95 
96 /* vim:ts=8:sw=4:et
97  */
98