]> git.mxchange.org Git - simgear.git/blob - simgear/io/sg_netChat.cxx
Fix VS2010 lack of fminf
[simgear.git] / simgear / io / sg_netChat.cxx
1 /*
2     Copied from PLIB into SimGear
3     
4      PLIB - A Suite of Portable Game Libraries
5      Copyright (C) 1998,2002  Steve Baker
6  
7      This library is free software; you can redistribute it and/or
8      modify it under the terms of the GNU Library General Public
9      License as published by the Free Software Foundation; either
10      version 2 of the License, or (at your option) any later version.
11  
12      This library is distributed in the hope that it will be useful,
13      but WITHOUT ANY WARRANTY; without even the implied warranty of
14      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15      Library General Public License for more details.
16  
17      You should have received a copy of the GNU Library General Public
18      License along with this library; if not, write to the Free Software
19      Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
20  
21      For further information visit http://plib.sourceforge.net
22
23      $Id: NetChat.cxx 2117 2007-09-13 23:21:09Z fayjf $
24 */
25
26 #include <simgear/io/sg_netChat.hxx>
27
28 #include <cstring>
29 #include <cstdlib>
30
31 namespace  simgear {
32
33 void
34 NetChat::setTerminator(const std::string& t)
35 {
36   terminator = t;
37   bytesToCollect = -1;
38 }
39
40 const char*
41 NetChat::getTerminator() const
42 {
43   return terminator.c_str();
44 }
45
46
47 void
48 NetChat::setByteCount(int count)
49 {
50     terminator.clear();
51     bytesToCollect = count;
52 }
53
54 // return the size of the largest prefix of needle at the end
55 // of haystack
56
57 #define MAX(a,b) (((a)>(b))?(a):(b))
58
59 static int
60 find_prefix_at_end(const NetBuffer& haystack, const std::string& needle)
61 {
62   const char* hd = haystack.getData();
63   int hl = haystack.getLength();
64   int nl = needle.length();
65   
66   for (int i = MAX (nl-hl, 0); i < nl; i++) {
67     //if (haystack.compare (needle, hl-(nl-i), nl-i) == 0) {
68     if (memcmp(needle.c_str(), &hd[hl-(nl-i)], nl-i) == 0) {
69       return (nl-i);
70     }
71   }
72   return 0;
73 }
74
75 static int
76 find_terminator(const NetBuffer& haystack, const std::string& needle)
77 {
78   if( !needle.empty() )
79   {
80     const char* data = haystack.getData();
81     const char* ptr = strstr(data,needle.c_str());
82     if (ptr != NULL)
83       return(ptr-data);
84   }
85   return -1;
86 }
87
88 bool NetChat::push (const char* s)
89 {
90   return bufferSend ( s, strlen(s) ) ;
91 }
92
93 void
94 NetChat::handleBufferRead (NetBuffer& in_buffer)
95 {
96   // Continue to search for terminator in in_buffer,
97   // while calling collect_incoming_data.  The while loop is
98   // necessary because we might read several data+terminator combos
99   // with a single recv().
100   
101   while (in_buffer.getLength()) {      
102     // special case where we're not using a terminator
103     if ( terminator.empty() ) {
104         if ( bytesToCollect > 0) {
105             const int toRead = std::min(in_buffer.getLength(), bytesToCollect);
106             collectIncomingData(in_buffer.getData(), toRead);
107             in_buffer.remove(0, toRead);
108             bytesToCollect -= toRead;
109             if (bytesToCollect ==  0) { // read all requested bytes
110                 foundTerminator();
111             }
112         } else { // read the whole lot
113             collectIncomingData (in_buffer.getData(),in_buffer.getLength());
114             in_buffer.remove ();
115         }
116         
117         continue;
118     }
119     
120     int index = find_terminator ( in_buffer, terminator ) ;
121     
122     // 3 cases:
123     // 1) end of buffer matches terminator exactly:
124     //    collect data, transition
125     // 2) end of buffer matches some prefix:
126     //    collect data to the prefix
127     // 3) end of buffer does not match any prefix:
128     //    collect data
129     
130     if (index != -1) {
131       // we found the terminator
132       collectIncomingData ( in_buffer.getData(), index ) ;
133       in_buffer.remove (0, index + terminator.length());
134       foundTerminator();
135     } else {
136       // check for a prefix of the terminator
137       int num = find_prefix_at_end (in_buffer, terminator);
138       if (num) {
139         int bl = in_buffer.getLength();
140         // we found a prefix, collect up to the prefix
141         collectIncomingData ( in_buffer.getData(), bl - num ) ;
142         in_buffer.remove (0, bl - num);
143         break;
144       } else {
145         // no prefix, collect it all
146         collectIncomingData (in_buffer.getData(), in_buffer.getLength());
147         in_buffer.remove();
148       }
149     }
150   }
151 }
152
153 } // of namespace simgear
154
155