]> git.tdb.fi Git - ext/libpng.git/blob - contrib/arm-neon/linux.c
Import libpng 1.6.39
[ext/libpng.git] / contrib / arm-neon / linux.c
1 /* contrib/arm-neon/linux.c
2  *
3  * Copyright (c) 2014, 2017 Glenn Randers-Pehrson
4  * Written by John Bowler, 2014, 2017.
5  *
6  * This code is released under the libpng license.
7  * For conditions of distribution and use, see the disclaimer
8  * and license in png.h
9  *
10  * SEE contrib/arm-neon/README before reporting bugs
11  *
12  * STATUS: SUPPORTED
13  * BUG REPORTS: png-mng-implement@sourceforge.net
14  *
15  * png_have_neon implemented for Linux by reading the widely available
16  * pseudo-file /proc/cpuinfo.
17  *
18  * This code is strict ANSI-C and is probably moderately portable; it does
19  * however use <stdio.h> and it assumes that /proc/cpuinfo is never localized.
20  */
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                /* FALLTHROUGH */
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                /* FALLTHROUGH */
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                /* FALLTHROUGH */
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                /* FALLTHROUGH */
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 #ifdef PNG_WARNINGS_SUPPORTED
156    else
157       png_warning(png_ptr, "/proc/cpuinfo open failed");
158 #endif
159
160    return 0;
161 }