]> git.mxchange.org Git - simgear.git/blob - simgear/io/sg_netChat.cxx
Compile SGReaderWriterOptions.cxx under Windows
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 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> // for strdup
29 #include <cstdlib>
30
31 namespace  simgear {
32
33 void
34 NetChat::setTerminator (const char* t)
35 {
36   if (terminator) free(terminator);
37   terminator = strdup(t);
38   bytesToCollect = -1;
39 }
40
41 const char*
42 NetChat::getTerminator (void)
43 {
44   return terminator;
45 }
46
47
48 void
49 NetChat::setByteCount(int count)
50 {
51     if (terminator) free(terminator);
52     terminator = NULL;
53     bytesToCollect = count;
54 }
55
56 // return the size of the largest prefix of needle at the end
57 // of haystack
58
59 #define MAX(a,b) (((a)>(b))?(a):(b))
60
61 static int
62 find_prefix_at_end (const NetBuffer& haystack, const char* needle)
63 {
64   const char* hd = haystack.getData();
65   int hl = haystack.getLength();
66   int nl = strlen(needle);
67   
68   for (int i = MAX (nl-hl, 0); i < nl; i++) {
69     //if (haystack.compare (needle, hl-(nl-i), nl-i) == 0) {
70     if (memcmp(needle, &hd[hl-(nl-i)], nl-i) == 0) {
71       return (nl-i);
72     }
73   }
74   return 0;
75 }
76
77 static int
78 find_terminator (const NetBuffer& haystack, const char* needle)
79 {
80   if (needle && *needle)
81   {
82     const char* data = haystack.getData();
83     const char* ptr = strstr(data,needle);
84     if (ptr != NULL)
85       return(ptr-data);
86   }
87   return -1;
88 }
89
90 bool NetChat::push (const char* s)
91 {
92   return bufferSend ( s, strlen(s) ) ;
93 }
94
95 void
96 NetChat::handleBufferRead (NetBuffer& in_buffer)
97 {
98   // Continue to search for terminator in in_buffer,
99   // while calling collect_incoming_data.  The while loop is
100   // necessary because we might read several data+terminator combos
101   // with a single recv().
102   
103   while (in_buffer.getLength()) {      
104     // special case where we're not using a terminator
105     if (terminator == 0 || *terminator == 0) {        
106         if ( bytesToCollect > 0) {
107             const int toRead = std::min(in_buffer.getLength(), bytesToCollect);
108             collectIncomingData(in_buffer.getData(), toRead);
109             in_buffer.remove(0, toRead);
110             bytesToCollect -= toRead;
111             if (bytesToCollect ==  0) { // read all requested bytes
112                 foundTerminator();
113             }
114         } else { // read the whole lot
115             collectIncomingData (in_buffer.getData(),in_buffer.getLength());
116             in_buffer.remove ();
117         }
118         
119         continue;
120     }
121     
122     int terminator_len = strlen(terminator);
123     
124     int index = find_terminator ( in_buffer, terminator ) ;
125     
126     // 3 cases:
127     // 1) end of buffer matches terminator exactly:
128     //    collect data, transition
129     // 2) end of buffer matches some prefix:
130     //    collect data to the prefix
131     // 3) end of buffer does not match any prefix:
132     //    collect data
133     
134     if (index != -1) {
135       // we found the terminator
136       collectIncomingData ( in_buffer.getData(), index ) ;
137       in_buffer.remove (0, index + terminator_len);
138       foundTerminator();
139     } else {
140       // check for a prefix of the terminator
141       int num = find_prefix_at_end (in_buffer, terminator);
142       if (num) {
143         int bl = in_buffer.getLength();
144         // we found a prefix, collect up to the prefix
145         collectIncomingData ( in_buffer.getData(), bl - num ) ;
146         in_buffer.remove (0, bl - num);
147         break;
148       } else {
149         // no prefix, collect it all
150         collectIncomingData (in_buffer.getData(), in_buffer.getLength());
151         in_buffer.remove();
152       }
153     }
154   }
155 }
156
157 } // of namespace simgear
158
159