|
1 /* contrib/arm-neon/linux.c |
|
2 * |
|
3 * Copyright (c) 2014 Glenn Randers-Pehrson |
|
4 * Written by John Bowler, 2014. |
|
5 * Last changed in libpng 1.6.10 [March 6, 2014] |
|
6 * |
|
7 * This code is released under the libpng license. |
|
8 * For conditions of distribution and use, see the disclaimer |
|
9 * and license in png.h |
|
10 * |
|
11 * SEE contrib/arm-neon/README before reporting bugs |
|
12 * |
|
13 * STATUS: SUPPORTED |
|
14 * BUG REPORTS: png-mng-implement@sourceforge.net |
|
15 * |
|
16 * png_have_neon implemented for Linux by reading the widely available |
|
17 * pseudo-file /proc/cpuinfo. |
|
18 * |
|
19 * This code is strict ANSI-C and is probably moderately portable, it does |
|
20 * however use <stdio.h> and assumes that /proc/cpuinfo is never localized. |
|
21 */ |
|
22 #include <stdio.h> |
|
23 |
|
24 static int |
|
25 png_have_neon(png_structp png_ptr) |
|
26 { |
|
27 FILE *f = fopen("/proc/cpuinfo", "rb"); |
|
28 |
|
29 if (f != NULL) |
|
30 { |
|
31 /* This is a simple state machine which reads the input byte-by-byte until |
|
32 * it gets a match on the 'neon' feature or reaches the end of the stream. |
|
33 */ |
|
34 static const char ch_feature[] = { 70, 69, 65, 84, 85, 82, 69, 83 }; |
|
35 static const char ch_neon[] = { 78, 69, 79, 78 }; |
|
36 |
|
37 enum |
|
38 { |
|
39 StartLine, Feature, Colon, StartTag, Neon, HaveNeon, SkipTag, SkipLine |
|
40 } state; |
|
41 int counter; |
|
42 |
|
43 for (state=StartLine, counter=0;;) |
|
44 { |
|
45 int ch = fgetc(f); |
|
46 |
|
47 if (ch == EOF) |
|
48 { |
|
49 /* EOF means error or end-of-file, return false; neon at EOF is |
|
50 * assumed to be a mistake. |
|
51 */ |
|
52 fclose(f); |
|
53 return 0; |
|
54 } |
|
55 |
|
56 switch (state) |
|
57 { |
|
58 case StartLine: |
|
59 /* Match spaces at the start of line */ |
|
60 if (ch <= 32) /* skip control characters and space */ |
|
61 break; |
|
62 |
|
63 counter=0; |
|
64 state = Feature; |
|
65 /* FALL THROUGH */ |
|
66 |
|
67 case Feature: |
|
68 /* Match 'FEATURE', ASCII case insensitive. */ |
|
69 if ((ch & ~0x20) == ch_feature[counter]) |
|
70 { |
|
71 if (++counter == (sizeof ch_feature)) |
|
72 state = Colon; |
|
73 break; |
|
74 } |
|
75 |
|
76 /* did not match 'feature' */ |
|
77 state = SkipLine; |
|
78 /* FALL THROUGH */ |
|
79 |
|
80 case SkipLine: |
|
81 skipLine: |
|
82 /* Skip everything until we see linefeed or carriage return */ |
|
83 if (ch != 10 && ch != 13) |
|
84 break; |
|
85 |
|
86 state = StartLine; |
|
87 break; |
|
88 |
|
89 case Colon: |
|
90 /* Match any number of space or tab followed by ':' */ |
|
91 if (ch == 32 || ch == 9) |
|
92 break; |
|
93 |
|
94 if (ch == 58) /* i.e. ':' */ |
|
95 { |
|
96 state = StartTag; |
|
97 break; |
|
98 } |
|
99 |
|
100 /* Either a bad line format or a 'feature' prefix followed by |
|
101 * other characters. |
|
102 */ |
|
103 state = SkipLine; |
|
104 goto skipLine; |
|
105 |
|
106 case StartTag: |
|
107 /* Skip space characters before a tag */ |
|
108 if (ch == 32 || ch == 9) |
|
109 break; |
|
110 |
|
111 state = Neon; |
|
112 counter = 0; |
|
113 /* FALL THROUGH */ |
|
114 |
|
115 case Neon: |
|
116 /* Look for 'neon' tag */ |
|
117 if ((ch & ~0x20) == ch_neon[counter]) |
|
118 { |
|
119 if (++counter == (sizeof ch_neon)) |
|
120 state = HaveNeon; |
|
121 break; |
|
122 } |
|
123 |
|
124 state = SkipTag; |
|
125 /* FALL THROUGH */ |
|
126 |
|
127 case SkipTag: |
|
128 /* Skip non-space characters */ |
|
129 if (ch == 10 || ch == 13) |
|
130 state = StartLine; |
|
131 |
|
132 else if (ch == 32 || ch == 9) |
|
133 state = StartTag; |
|
134 break; |
|
135 |
|
136 case HaveNeon: |
|
137 /* Have seen a 'neon' prefix, but there must be a space or new |
|
138 * line character to terminate it. |
|
139 */ |
|
140 if (ch == 10 || ch == 13 || ch == 32 || ch == 9) |
|
141 { |
|
142 fclose(f); |
|
143 return 1; |
|
144 } |
|
145 |
|
146 state = SkipTag; |
|
147 break; |
|
148 |
|
149 default: |
|
150 png_error(png_ptr, "png_have_neon: internal error (bug)"); |
|
151 } |
|
152 } |
|
153 } |
|
154 |
|
155 else |
|
156 png_warning(png_ptr, "/proc/cpuinfo open failed"); |
|
157 |
|
158 return 0; |
|
159 } |