Library to use Arduino USB host shield on mbed
ArduinoのUSB Host Shield 2.0をmbedで使えるようにしたライブラリです。
大体のコードがArduinoからそのまま移植可能です。
Arduino UNOやMega用のホストシールド以外にもミニサイズのホストシールドでも使用可能です
シールドについて
3.3VのI/O用にシールドの改造が必要になりますがネット上に記事がたくさんあるのでそちらを参考にしてください
接続例
使い方
Arduinoのコードと違うのはUSBのインスタンスの宣言部分のみです。
ピンを自分で指定できるようにしたので使いやすくなりました。
仕様
- Arduinoのmillis関数、micros関数の移植のために内部でTimerクラスを使用しています。
main.cpp
#include "mbed.h" #include <PS3BT.h> #include <usbhub.h> Serial pc(USBTX, USBRX, 115200); //Nucleo f303k8用 USB Usb(A6, A5, A4, A3, A2); // mosi, miso, sclk, ssel, intr BTD Btd(&Usb); PS3BT PS3(&Btd); int main() { bool printAngle = false; if (Usb.Init() == -1) { pc.printf("\r\nOSC did not start"); while (1); // Halt } pc.printf("\r\nPS3 USB Library Started"); while (1) { Usb.Task(); if (PS3.PS3Connected || PS3.PS3NavigationConnected) { if (PS3.getAnalogHat(LeftHatX) > 137 || PS3.getAnalogHat(LeftHatX) < 117 || PS3.getAnalogHat(LeftHatY) > 137 || PS3.getAnalogHat(LeftHatY) < 117 || PS3.getAnalogHat(RightHatX) > 137 || PS3.getAnalogHat(RightHatX) < 117 || PS3.getAnalogHat(RightHatY) > 137 || PS3.getAnalogHat(RightHatY) < 117) { pc.printf("\r\nLeftHatX: %d", PS3.getAnalogHat(LeftHatX)); pc.printf("\tLeftHatY: %d", PS3.getAnalogHat(LeftHatY)); if (PS3.PS3Connected) { // The Navigation controller only have one joystick pc.printf("\tRightHatX: %d", PS3.getAnalogHat(RightHatX)); pc.printf("\tRightHatY: %d", PS3.getAnalogHat(RightHatY)); } } // Analog button values can be read from almost all buttons if (PS3.getAnalogButton(L2) || PS3.getAnalogButton(R2)) { pc.printf("\r\nL2: %d", PS3.getAnalogButton(L2)); if (!PS3.PS3NavigationConnected) { pc.printf("\tR2: %d", PS3.getAnalogButton(R2)); } } if (PS3.getButtonClick(PS)) { PS3.disconnect(); pc.printf("\r\nPS"); } if (PS3.getButtonClick(TRIANGLE)) pc.printf("\r\nTriangle"); if (PS3.getButtonClick(CIRCLE)) pc.printf("\r\nCircle"); if (PS3.getButtonClick(CROSS)) pc.printf("\r\nCross"); if (PS3.getButtonClick(SQUARE)) pc.printf("\r\nSquare"); if (PS3.getButtonClick(UP)) { pc.printf("\r\nUp"); PS3.setLedOff(); PS3.setLedOn(CONTROLLER_LED4); } if (PS3.getButtonClick(RIGHT)) { pc.printf("\r\nRight"); PS3.setLedOff(); PS3.setLedOn(CONTROLLER_LED1); } if (PS3.getButtonClick(DOWN)) { pc.printf("\r\nDown"); PS3.setLedOff(); PS3.setLedOn(CONTROLLER_LED2); } if (PS3.getButtonClick(LEFT)) { pc.printf("\r\nLeft"); PS3.setLedOff(); PS3.setLedOn(CONTROLLER_LED3); } if (PS3.getButtonClick(L1)) pc.printf("\r\nL1"); if (PS3.getButtonClick(L3)) pc.printf("\r\nL3"); if (PS3.getButtonClick(R1)) pc.printf("\r\nR1"); if (PS3.getButtonClick(R3)) pc.printf("\r\nR3"); if (PS3.getButtonClick(SELECT)) { pc.printf("\r\nSelect - "); PS3.printStatusString(); } if (PS3.getButtonClick(START)) { pc.printf("\r\nStart"); printAngle = !printAngle; } if (printAngle) { pc.printf("\r\nPitch: %.3lf", PS3.getAngle(Pitch)); pc.printf("\tRoll: %.3lf", PS3.getAngle(Roll)); } } else { pc.printf("not connect\n"); } } }
Arduino_lib/arStream.cpp@1:da31140f2a1c, 2020-05-02 (annotated)
- Committer:
- robo_ichinoseki_a
- Date:
- Sat May 02 05:56:48 2020 +0000
- Revision:
- 1:da31140f2a1c
- Parent:
- 0:b1ce54272580
update
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
kotakku | 0:b1ce54272580 | 1 | /* |
kotakku | 0:b1ce54272580 | 2 | arStream.cpp - adds parsing methods to arStream class |
kotakku | 0:b1ce54272580 | 3 | Copyright (c) 2008 David A. Mellis. All right reserved. |
kotakku | 0:b1ce54272580 | 4 | |
kotakku | 0:b1ce54272580 | 5 | This library is free software; you can redistribute it and/or |
kotakku | 0:b1ce54272580 | 6 | modify it under the terms of the GNU Lesser General Public |
kotakku | 0:b1ce54272580 | 7 | License as published by the Free Software Foundation; either |
kotakku | 0:b1ce54272580 | 8 | version 2.1 of the License, or (at your option) any later version. |
kotakku | 0:b1ce54272580 | 9 | |
kotakku | 0:b1ce54272580 | 10 | This library is distributed in the hope that it will be useful, |
kotakku | 0:b1ce54272580 | 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
kotakku | 0:b1ce54272580 | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
kotakku | 0:b1ce54272580 | 13 | Lesser General Public License for more details. |
kotakku | 0:b1ce54272580 | 14 | |
kotakku | 0:b1ce54272580 | 15 | You should have received a copy of the GNU Lesser General Public |
kotakku | 0:b1ce54272580 | 16 | License along with this library; if not, write to the Free Software |
kotakku | 0:b1ce54272580 | 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
kotakku | 0:b1ce54272580 | 18 | |
kotakku | 0:b1ce54272580 | 19 | Created July 2011 |
kotakku | 0:b1ce54272580 | 20 | parsing functions based on TextFinder library by Michael Margolis |
kotakku | 0:b1ce54272580 | 21 | |
kotakku | 0:b1ce54272580 | 22 | findMulti/findUntil routines written by Jim Leonard/Xuth |
kotakku | 0:b1ce54272580 | 23 | */ |
kotakku | 0:b1ce54272580 | 24 | |
kotakku | 0:b1ce54272580 | 25 | #include "Arduino.h" |
kotakku | 0:b1ce54272580 | 26 | #include "arStream.h" |
kotakku | 0:b1ce54272580 | 27 | #include "Usb.h" |
kotakku | 0:b1ce54272580 | 28 | |
kotakku | 0:b1ce54272580 | 29 | #define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait |
kotakku | 0:b1ce54272580 | 30 | #define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field |
kotakku | 0:b1ce54272580 | 31 | |
robo_ichinoseki_a | 1:da31140f2a1c | 32 | //extern Timer USB::arduinoTimer; |
kotakku | 0:b1ce54272580 | 33 | |
kotakku | 0:b1ce54272580 | 34 | // private method to read stream with timeout |
kotakku | 0:b1ce54272580 | 35 | int arStream::timedRead() |
kotakku | 0:b1ce54272580 | 36 | { |
kotakku | 0:b1ce54272580 | 37 | int c; |
kotakku | 0:b1ce54272580 | 38 | _startMillis = millis(); |
kotakku | 0:b1ce54272580 | 39 | do { |
kotakku | 0:b1ce54272580 | 40 | c = read(); |
kotakku | 0:b1ce54272580 | 41 | if (c >= 0) return c; |
kotakku | 0:b1ce54272580 | 42 | } while(millis() - _startMillis < _timeout); |
kotakku | 0:b1ce54272580 | 43 | return -1; // -1 indicates timeout |
kotakku | 0:b1ce54272580 | 44 | } |
kotakku | 0:b1ce54272580 | 45 | |
kotakku | 0:b1ce54272580 | 46 | // private method to peek stream with timeout |
kotakku | 0:b1ce54272580 | 47 | int arStream::timedPeek() |
kotakku | 0:b1ce54272580 | 48 | { |
kotakku | 0:b1ce54272580 | 49 | int c; |
kotakku | 0:b1ce54272580 | 50 | _startMillis = millis(); |
kotakku | 0:b1ce54272580 | 51 | do { |
kotakku | 0:b1ce54272580 | 52 | c = peek(); |
kotakku | 0:b1ce54272580 | 53 | if (c >= 0) return c; |
kotakku | 0:b1ce54272580 | 54 | } while(millis() - _startMillis < _timeout); |
kotakku | 0:b1ce54272580 | 55 | return -1; // -1 indicates timeout |
kotakku | 0:b1ce54272580 | 56 | } |
kotakku | 0:b1ce54272580 | 57 | |
kotakku | 0:b1ce54272580 | 58 | // returns peek of the next digit in the stream or -1 if timeout |
kotakku | 0:b1ce54272580 | 59 | // discards non-numeric characters |
kotakku | 0:b1ce54272580 | 60 | int arStream::peekNextDigit() |
kotakku | 0:b1ce54272580 | 61 | { |
kotakku | 0:b1ce54272580 | 62 | int c; |
kotakku | 0:b1ce54272580 | 63 | while (1) { |
kotakku | 0:b1ce54272580 | 64 | c = timedPeek(); |
kotakku | 0:b1ce54272580 | 65 | if (c < 0) return c; // timeout |
kotakku | 0:b1ce54272580 | 66 | if (c == '-') return c; |
kotakku | 0:b1ce54272580 | 67 | if (c >= '0' && c <= '9') return c; |
kotakku | 0:b1ce54272580 | 68 | read(); // discard non-numeric |
kotakku | 0:b1ce54272580 | 69 | } |
kotakku | 0:b1ce54272580 | 70 | } |
kotakku | 0:b1ce54272580 | 71 | |
kotakku | 0:b1ce54272580 | 72 | // Public Methods |
kotakku | 0:b1ce54272580 | 73 | ////////////////////////////////////////////////////////////// |
kotakku | 0:b1ce54272580 | 74 | |
kotakku | 0:b1ce54272580 | 75 | void arStream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait |
kotakku | 0:b1ce54272580 | 76 | { |
kotakku | 0:b1ce54272580 | 77 | _timeout = timeout; |
kotakku | 0:b1ce54272580 | 78 | } |
kotakku | 0:b1ce54272580 | 79 | |
kotakku | 0:b1ce54272580 | 80 | // find returns true if the target string is found |
kotakku | 0:b1ce54272580 | 81 | bool arStream::find(char *target) |
kotakku | 0:b1ce54272580 | 82 | { |
kotakku | 0:b1ce54272580 | 83 | return findUntil(target, strlen(target), NULL, 0); |
kotakku | 0:b1ce54272580 | 84 | } |
kotakku | 0:b1ce54272580 | 85 | |
kotakku | 0:b1ce54272580 | 86 | // reads data from the stream until the target string of given length is found |
kotakku | 0:b1ce54272580 | 87 | // returns true if target string is found, false if timed out |
kotakku | 0:b1ce54272580 | 88 | bool arStream::find(char *target, size_t length) |
kotakku | 0:b1ce54272580 | 89 | { |
kotakku | 0:b1ce54272580 | 90 | return findUntil(target, length, NULL, 0); |
kotakku | 0:b1ce54272580 | 91 | } |
kotakku | 0:b1ce54272580 | 92 | |
kotakku | 0:b1ce54272580 | 93 | // as find but search ends if the terminator string is found |
kotakku | 0:b1ce54272580 | 94 | bool arStream::findUntil(char *target, char *terminator) |
kotakku | 0:b1ce54272580 | 95 | { |
kotakku | 0:b1ce54272580 | 96 | return findUntil(target, strlen(target), terminator, strlen(terminator)); |
kotakku | 0:b1ce54272580 | 97 | } |
kotakku | 0:b1ce54272580 | 98 | |
kotakku | 0:b1ce54272580 | 99 | // reads data from the stream until the target string of the given length is found |
kotakku | 0:b1ce54272580 | 100 | // search terminated if the terminator string is found |
kotakku | 0:b1ce54272580 | 101 | // returns true if target string is found, false if terminated or timed out |
kotakku | 0:b1ce54272580 | 102 | bool arStream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen) |
kotakku | 0:b1ce54272580 | 103 | { |
kotakku | 0:b1ce54272580 | 104 | if (terminator == NULL) { |
kotakku | 0:b1ce54272580 | 105 | MultiTarget t[1] = {{target, targetLen, 0}}; |
kotakku | 0:b1ce54272580 | 106 | return findMulti(t, 1) == 0 ? true : false; |
kotakku | 0:b1ce54272580 | 107 | } else { |
kotakku | 0:b1ce54272580 | 108 | MultiTarget t[2] = {{target, targetLen, 0}, {terminator, termLen, 0}}; |
kotakku | 0:b1ce54272580 | 109 | return findMulti(t, 2) == 0 ? true : false; |
kotakku | 0:b1ce54272580 | 110 | } |
kotakku | 0:b1ce54272580 | 111 | } |
kotakku | 0:b1ce54272580 | 112 | |
kotakku | 0:b1ce54272580 | 113 | |
kotakku | 0:b1ce54272580 | 114 | // returns the first valid (long) integer value from the current position. |
kotakku | 0:b1ce54272580 | 115 | // initial characters that are not digits (or the minus sign) are skipped |
kotakku | 0:b1ce54272580 | 116 | // function is terminated by the first character that is not a digit. |
kotakku | 0:b1ce54272580 | 117 | long arStream::parseInt() |
kotakku | 0:b1ce54272580 | 118 | { |
kotakku | 0:b1ce54272580 | 119 | return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout) |
kotakku | 0:b1ce54272580 | 120 | } |
kotakku | 0:b1ce54272580 | 121 | |
kotakku | 0:b1ce54272580 | 122 | // as above but a given skipChar is ignored |
kotakku | 0:b1ce54272580 | 123 | // this allows format characters (typically commas) in values to be ignored |
kotakku | 0:b1ce54272580 | 124 | long arStream::parseInt(char skipChar) |
kotakku | 0:b1ce54272580 | 125 | { |
kotakku | 0:b1ce54272580 | 126 | bool isNegative = false; |
kotakku | 0:b1ce54272580 | 127 | long value = 0; |
kotakku | 0:b1ce54272580 | 128 | int c; |
kotakku | 0:b1ce54272580 | 129 | |
kotakku | 0:b1ce54272580 | 130 | c = peekNextDigit(); |
kotakku | 0:b1ce54272580 | 131 | // ignore non numeric leading characters |
kotakku | 0:b1ce54272580 | 132 | if(c < 0) |
kotakku | 0:b1ce54272580 | 133 | return 0; // zero returned if timeout |
kotakku | 0:b1ce54272580 | 134 | |
kotakku | 0:b1ce54272580 | 135 | do{ |
kotakku | 0:b1ce54272580 | 136 | if(c == skipChar) |
kotakku | 0:b1ce54272580 | 137 | ; // ignore this charactor |
kotakku | 0:b1ce54272580 | 138 | else if(c == '-') |
kotakku | 0:b1ce54272580 | 139 | isNegative = true; |
kotakku | 0:b1ce54272580 | 140 | else if(c >= '0' && c <= '9') // is c a digit? |
kotakku | 0:b1ce54272580 | 141 | value = value * 10 + c - '0'; |
kotakku | 0:b1ce54272580 | 142 | read(); // consume the character we got with peek |
kotakku | 0:b1ce54272580 | 143 | c = timedPeek(); |
kotakku | 0:b1ce54272580 | 144 | } |
kotakku | 0:b1ce54272580 | 145 | while( (c >= '0' && c <= '9') || c == skipChar ); |
kotakku | 0:b1ce54272580 | 146 | |
kotakku | 0:b1ce54272580 | 147 | if(isNegative) |
kotakku | 0:b1ce54272580 | 148 | value = -value; |
kotakku | 0:b1ce54272580 | 149 | return value; |
kotakku | 0:b1ce54272580 | 150 | } |
kotakku | 0:b1ce54272580 | 151 | |
kotakku | 0:b1ce54272580 | 152 | |
kotakku | 0:b1ce54272580 | 153 | // as parseInt but returns a floating point value |
kotakku | 0:b1ce54272580 | 154 | float arStream::parseFloat() |
kotakku | 0:b1ce54272580 | 155 | { |
kotakku | 0:b1ce54272580 | 156 | return parseFloat(NO_SKIP_CHAR); |
kotakku | 0:b1ce54272580 | 157 | } |
kotakku | 0:b1ce54272580 | 158 | |
kotakku | 0:b1ce54272580 | 159 | // as above but the given skipChar is ignored |
kotakku | 0:b1ce54272580 | 160 | // this allows format characters (typically commas) in values to be ignored |
kotakku | 0:b1ce54272580 | 161 | float arStream::parseFloat(char skipChar){ |
kotakku | 0:b1ce54272580 | 162 | bool isNegative = false; |
kotakku | 0:b1ce54272580 | 163 | bool isFraction = false; |
kotakku | 0:b1ce54272580 | 164 | long value = 0; |
kotakku | 0:b1ce54272580 | 165 | char c; |
kotakku | 0:b1ce54272580 | 166 | float fraction = 1.0; |
kotakku | 0:b1ce54272580 | 167 | |
kotakku | 0:b1ce54272580 | 168 | c = peekNextDigit(); |
kotakku | 0:b1ce54272580 | 169 | // ignore non numeric leading characters |
kotakku | 0:b1ce54272580 | 170 | if(c < 0) |
kotakku | 0:b1ce54272580 | 171 | return 0; // zero returned if timeout |
kotakku | 0:b1ce54272580 | 172 | |
kotakku | 0:b1ce54272580 | 173 | do{ |
kotakku | 0:b1ce54272580 | 174 | if(c == skipChar) |
kotakku | 0:b1ce54272580 | 175 | ; // ignore |
kotakku | 0:b1ce54272580 | 176 | else if(c == '-') |
kotakku | 0:b1ce54272580 | 177 | isNegative = true; |
kotakku | 0:b1ce54272580 | 178 | else if (c == '.') |
kotakku | 0:b1ce54272580 | 179 | isFraction = true; |
kotakku | 0:b1ce54272580 | 180 | else if(c >= '0' && c <= '9') { // is c a digit? |
kotakku | 0:b1ce54272580 | 181 | value = value * 10 + c - '0'; |
kotakku | 0:b1ce54272580 | 182 | if(isFraction) |
kotakku | 0:b1ce54272580 | 183 | fraction *= 0.1; |
kotakku | 0:b1ce54272580 | 184 | } |
kotakku | 0:b1ce54272580 | 185 | read(); // consume the character we got with peek |
kotakku | 0:b1ce54272580 | 186 | c = timedPeek(); |
kotakku | 0:b1ce54272580 | 187 | } |
kotakku | 0:b1ce54272580 | 188 | while( (c >= '0' && c <= '9') || c == '.' || c == skipChar ); |
kotakku | 0:b1ce54272580 | 189 | |
kotakku | 0:b1ce54272580 | 190 | if(isNegative) |
kotakku | 0:b1ce54272580 | 191 | value = -value; |
kotakku | 0:b1ce54272580 | 192 | if(isFraction) |
kotakku | 0:b1ce54272580 | 193 | return value * fraction; |
kotakku | 0:b1ce54272580 | 194 | else |
kotakku | 0:b1ce54272580 | 195 | return value; |
kotakku | 0:b1ce54272580 | 196 | } |
kotakku | 0:b1ce54272580 | 197 | |
kotakku | 0:b1ce54272580 | 198 | // read characters from stream into buffer |
kotakku | 0:b1ce54272580 | 199 | // terminates if length characters have been read, or timeout (see setTimeout) |
kotakku | 0:b1ce54272580 | 200 | // returns the number of characters placed in the buffer |
kotakku | 0:b1ce54272580 | 201 | // the buffer is NOT null terminated. |
kotakku | 0:b1ce54272580 | 202 | // |
kotakku | 0:b1ce54272580 | 203 | size_t arStream::readBytes(char *buffer, size_t length) |
kotakku | 0:b1ce54272580 | 204 | { |
kotakku | 0:b1ce54272580 | 205 | size_t count = 0; |
kotakku | 0:b1ce54272580 | 206 | while (count < length) { |
kotakku | 0:b1ce54272580 | 207 | int c = timedRead(); |
kotakku | 0:b1ce54272580 | 208 | if (c < 0) break; |
kotakku | 0:b1ce54272580 | 209 | *buffer++ = (char)c; |
kotakku | 0:b1ce54272580 | 210 | count++; |
kotakku | 0:b1ce54272580 | 211 | } |
kotakku | 0:b1ce54272580 | 212 | return count; |
kotakku | 0:b1ce54272580 | 213 | } |
kotakku | 0:b1ce54272580 | 214 | |
kotakku | 0:b1ce54272580 | 215 | |
kotakku | 0:b1ce54272580 | 216 | // as readBytes with terminator character |
kotakku | 0:b1ce54272580 | 217 | // terminates if length characters have been read, timeout, or if the terminator character detected |
kotakku | 0:b1ce54272580 | 218 | // returns the number of characters placed in the buffer (0 means no valid data found) |
kotakku | 0:b1ce54272580 | 219 | |
kotakku | 0:b1ce54272580 | 220 | size_t arStream::readBytesUntil(char terminator, char *buffer, size_t length) |
kotakku | 0:b1ce54272580 | 221 | { |
kotakku | 0:b1ce54272580 | 222 | if (length < 1) return 0; |
kotakku | 0:b1ce54272580 | 223 | size_t index = 0; |
kotakku | 0:b1ce54272580 | 224 | while (index < length) { |
kotakku | 0:b1ce54272580 | 225 | int c = timedRead(); |
kotakku | 0:b1ce54272580 | 226 | if (c < 0 || c == terminator) break; |
kotakku | 0:b1ce54272580 | 227 | *buffer++ = (char)c; |
kotakku | 0:b1ce54272580 | 228 | index++; |
kotakku | 0:b1ce54272580 | 229 | } |
kotakku | 0:b1ce54272580 | 230 | return index; // return number of characters, not including null terminator |
kotakku | 0:b1ce54272580 | 231 | } |
kotakku | 0:b1ce54272580 | 232 | |
kotakku | 0:b1ce54272580 | 233 | String arStream::readString() |
kotakku | 0:b1ce54272580 | 234 | { |
kotakku | 0:b1ce54272580 | 235 | String ret; |
kotakku | 0:b1ce54272580 | 236 | int c = timedRead(); |
kotakku | 0:b1ce54272580 | 237 | while (c >= 0) |
kotakku | 0:b1ce54272580 | 238 | { |
kotakku | 0:b1ce54272580 | 239 | ret += (char)c; |
kotakku | 0:b1ce54272580 | 240 | c = timedRead(); |
kotakku | 0:b1ce54272580 | 241 | } |
kotakku | 0:b1ce54272580 | 242 | return ret; |
kotakku | 0:b1ce54272580 | 243 | } |
kotakku | 0:b1ce54272580 | 244 | |
kotakku | 0:b1ce54272580 | 245 | String arStream::readStringUntil(char terminator) |
kotakku | 0:b1ce54272580 | 246 | { |
kotakku | 0:b1ce54272580 | 247 | String ret; |
kotakku | 0:b1ce54272580 | 248 | int c = timedRead(); |
kotakku | 0:b1ce54272580 | 249 | while (c >= 0 && c != terminator) |
kotakku | 0:b1ce54272580 | 250 | { |
kotakku | 0:b1ce54272580 | 251 | ret += (char)c; |
kotakku | 0:b1ce54272580 | 252 | c = timedRead(); |
kotakku | 0:b1ce54272580 | 253 | } |
kotakku | 0:b1ce54272580 | 254 | return ret; |
kotakku | 0:b1ce54272580 | 255 | } |
kotakku | 0:b1ce54272580 | 256 | |
kotakku | 0:b1ce54272580 | 257 | int arStream::findMulti( struct arStream::MultiTarget *targets, int tCount) { |
kotakku | 0:b1ce54272580 | 258 | // any zero length target string automatically matches and would make |
kotakku | 0:b1ce54272580 | 259 | // a mess of the rest of the algorithm. |
kotakku | 0:b1ce54272580 | 260 | for (struct MultiTarget *t = targets; t < targets+tCount; ++t) { |
kotakku | 0:b1ce54272580 | 261 | if (t->len <= 0) |
kotakku | 0:b1ce54272580 | 262 | return t - targets; |
kotakku | 0:b1ce54272580 | 263 | } |
kotakku | 0:b1ce54272580 | 264 | |
kotakku | 0:b1ce54272580 | 265 | while (1) { |
kotakku | 0:b1ce54272580 | 266 | int c = timedRead(); |
kotakku | 0:b1ce54272580 | 267 | if (c < 0) |
kotakku | 0:b1ce54272580 | 268 | return -1; |
kotakku | 0:b1ce54272580 | 269 | |
kotakku | 0:b1ce54272580 | 270 | for (struct MultiTarget *t = targets; t < targets+tCount; ++t) { |
kotakku | 0:b1ce54272580 | 271 | // the simple case is if we match, deal with that first. |
kotakku | 0:b1ce54272580 | 272 | if (c == t->str[t->index]) { |
kotakku | 0:b1ce54272580 | 273 | if (++t->index == t->len) |
kotakku | 0:b1ce54272580 | 274 | return t - targets; |
kotakku | 0:b1ce54272580 | 275 | else |
kotakku | 0:b1ce54272580 | 276 | continue; |
kotakku | 0:b1ce54272580 | 277 | } |
kotakku | 0:b1ce54272580 | 278 | |
kotakku | 0:b1ce54272580 | 279 | // if not we need to walk back and see if we could have matched further |
kotakku | 0:b1ce54272580 | 280 | // down the stream (ie '1112' doesn't match the first position in '11112' |
kotakku | 0:b1ce54272580 | 281 | // but it will match the second position so we can't just reset the current |
kotakku | 0:b1ce54272580 | 282 | // index to 0 when we find a mismatch. |
kotakku | 0:b1ce54272580 | 283 | if (t->index == 0) |
kotakku | 0:b1ce54272580 | 284 | continue; |
kotakku | 0:b1ce54272580 | 285 | |
kotakku | 0:b1ce54272580 | 286 | int origIndex = t->index; |
kotakku | 0:b1ce54272580 | 287 | do { |
kotakku | 0:b1ce54272580 | 288 | --t->index; |
kotakku | 0:b1ce54272580 | 289 | // first check if current char works against the new current index |
kotakku | 0:b1ce54272580 | 290 | if (c != t->str[t->index]) |
kotakku | 0:b1ce54272580 | 291 | continue; |
kotakku | 0:b1ce54272580 | 292 | |
kotakku | 0:b1ce54272580 | 293 | // if it's the only char then we're good, nothing more to check |
kotakku | 0:b1ce54272580 | 294 | if (t->index == 0) { |
kotakku | 0:b1ce54272580 | 295 | t->index++; |
kotakku | 0:b1ce54272580 | 296 | break; |
kotakku | 0:b1ce54272580 | 297 | } |
kotakku | 0:b1ce54272580 | 298 | |
kotakku | 0:b1ce54272580 | 299 | // otherwise we need to check the rest of the found string |
kotakku | 0:b1ce54272580 | 300 | int diff = origIndex - t->index; |
kotakku | 0:b1ce54272580 | 301 | size_t i; |
kotakku | 0:b1ce54272580 | 302 | for (i = 0; i < t->index; ++i) { |
kotakku | 0:b1ce54272580 | 303 | if (t->str[i] != t->str[i + diff]) |
kotakku | 0:b1ce54272580 | 304 | break; |
kotakku | 0:b1ce54272580 | 305 | } |
kotakku | 0:b1ce54272580 | 306 | |
kotakku | 0:b1ce54272580 | 307 | // if we successfully got through the previous loop then our current |
kotakku | 0:b1ce54272580 | 308 | // index is good. |
kotakku | 0:b1ce54272580 | 309 | if (i == t->index) { |
kotakku | 0:b1ce54272580 | 310 | t->index++; |
kotakku | 0:b1ce54272580 | 311 | break; |
kotakku | 0:b1ce54272580 | 312 | } |
kotakku | 0:b1ce54272580 | 313 | |
kotakku | 0:b1ce54272580 | 314 | // otherwise we just try the next index |
kotakku | 0:b1ce54272580 | 315 | } while (t->index); |
kotakku | 0:b1ce54272580 | 316 | } |
kotakku | 0:b1ce54272580 | 317 | } |
kotakku | 0:b1ce54272580 | 318 | // unreachable |
kotakku | 0:b1ce54272580 | 319 | return -1; |
kotakku | 0:b1ce54272580 | 320 | } |
kotakku | 0:b1ce54272580 | 321 |