vrpn 07.35
Virtual Reality Peripheral Network
 
Loading...
Searching...
No Matches
vrpn_Shared.h
Go to the documentation of this file.
1#pragma once
2
3// Horrible hack for old HPUX compiler
4#ifdef hpux
5#ifndef true
6#define bool int
7#define true 1
8#define false 0
9#endif
10#endif
11
12// Definitions needed by several included files.
13#define VRPN_PI (3.14159265358979323846)
14#define VRPN_INCHES_TO_METERS (2.54/100.0)
15#define VRPN_DEGREES_TO_RADIANS (VRPN_PI/180.0)
16
17#include "vrpn_Configure.h" // for VRPN_API
18#include "vrpn_Types.h" // for vrpn_int32, vrpn_float64, etc
19#include "vrpn_Thread.h"
20#include <string.h> // for memcpy(), strncpy()
21#include <stdio.h> // for fprintf()
22
23#if defined(__ANDROID__)
24#include <bitset>
25#endif
26
27// IWYU pragma: no_include <bits/time.h>
28
29// Oct 2000: Sang-Uok changed because vrpn code was compiling but giving
30// runtime errors with cygwin 1.1. I changed the code so it only uses unix
31// code. I had to change includes in various files.
32
33// jan 2000: jeff changing the way sockets are used with cygwin. I made this
34// change because I realized that we were using winsock stuff in some places,
35// and cygwin stuff in others. Discovered this when our code wouldn't compile
36// in cygwin-1.0 (but it did in cygwin-b20.1).
37
38// let's start with a clean slate
39#undef VRPN_USE_WINSOCK_SOCKETS
40
41// Does cygwin use winsock sockets or unix sockets
42//#define VRPN_CYGWIN_USES_WINSOCK_SOCKETS
43
44#if defined(_WIN32) && \
45 (!defined(__CYGWIN__) || defined(VRPN_CYGWIN_USES_WINSOCK_SOCKETS))
46#define VRPN_USE_WINSOCK_SOCKETS
47#endif
48
49#ifndef VRPN_USE_WINSOCK_SOCKETS
50// On Win32, this constant is defined as ~0 (sockets are unsigned ints)
51#define INVALID_SOCKET -1
52#define SOCKET int
53#endif
54
55#if !(defined(_WIN32) && defined(VRPN_USE_WINSOCK_SOCKETS))
56#include <sys/select.h> // for select
57#include <netinet/in.h> // for htonl, htons
58#endif
59
60#ifdef _WIN32_WCE
61#define perror(x) fprintf(stderr, "%s\n", x);
62#endif
63
64// comment from vrpn_Connection.h reads :
65//
66// gethostbyname() fails on SOME Windows NT boxes, but not all,
67// if given an IP octet string rather than a true name.
68// Until we figure out WHY, we have this extra clause in here.
69// It probably wouldn't hurt to enable it for non-NT systems
70// as well.
71#ifdef _WIN32
72#define VRPN_USE_WINDOWS_GETHOSTBYNAME_HACK
73#endif
74
75//--------------------------------------------------------------
76// Timeval defines. These are a bit hairy. The basic problem is
77// that Windows doesn't implement gettimeofday(), nor does it
78// define "struct timezone", although Winsock.h does define
79// "struct timeval". The painful solution has been to define a
80// vrpn_gettimeofday() function that takes a void * as a second
81// argument (the timezone) and have all VRPN code call this function
82// rather than gettimeofday(). On non-WINSOCK implementations,
83// we alias vrpn_gettimeofday() right back to gettimeofday(), so
84// that we are calling the system routine. On Windows, we will
85// be using vrpn_gettimofday(). So far so good, but now user code
86// would like to not have to know the difference under windows, so
87// we have an optional VRPN configuration setting in vrpn_Configure.h
88// that exports vrpn_gettimeofday() as gettimeofday() and also
89// exports a "struct timezone" definition. Yucky, but it works and
90// lets user code use the VRPN one as if it were the system call
91// on Windows.
92
93#if (!defined(VRPN_USE_WINSOCK_SOCKETS))
94#include <sys/time.h> // for timeval, timezone, gettimeofday
95// If we're using std::chrono, then we implement a new
96// vrpn_gettimeofday() on top of it in a platform-independent
97// manner. Otherwise, we just use the system call.
98#ifndef VRPN_USE_STD_CHRONO
99 #define vrpn_gettimeofday gettimeofday
100#else
101 extern "C" VRPN_API int vrpn_gettimeofday(struct timeval *tp,
102 void *tzp = NULL);
103#endif
104#else // winsock sockets
105
106// These are a pair of horrible hacks that instruct Windows include
107// files to (1) not define min() and max() in a way that messes up
108// standard-library calls to them, and (2) avoids pulling in a large
109// number of Windows header files. They are not used directly within
110// the VRPN library, but rather within the Windows include files to
111// change the way they behave.
112
113#ifndef NOMINMAX
114#define NOMINMAX
115#endif
116#ifndef WIN32_LEAN_AND_MEAN
117#define WIN32_LEAN_AND_MEAN
118#endif
119#include <windows.h>
120#ifndef _WIN32_WCE
121#include <sys/timeb.h>
122#endif
123#ifdef VRPN_USE_WINSOCK2
124#include <winsock2.h> // struct timeval is defined here
125#else
126#include <winsock.h> // struct timeval is defined here
127#endif
128
129// Whether or not we export gettimeofday, we declare the
130// vrpn_gettimeofday() function on Windows.
131extern "C" VRPN_API int vrpn_gettimeofday(struct timeval *tp,
132 void *tzp = NULL);
133
134// If compiling under Cygnus Solutions Cygwin then these get defined by
135// including sys/time.h. So, we will manually define only for _WIN32
136// Only do this if the Configure file has set VRPN_EXPORT_GETTIMEOFDAY,
137// so that application code can get at it. All VRPN routines should be
138// calling vrpn_gettimeofday() directly.
139
140#if defined(VRPN_EXPORT_GETTIMEOFDAY)
141
142// manually define this too. _WIN32 sans cygwin doesn't have gettimeofday
143#define gettimeofday vrpn_gettimeofday
144
145#endif
146#endif
147
148//--------------------------------------------------------------
149// vrpn_* timeval utility functions
150
151// IMPORTANT: timevals must be normalized to make any sense
152//
153// * normalized means abs(tv_usec) is less than 1,000,000
154//
155// * TimevalSum and TimevalDiff do not do the right thing if
156// their inputs are not normalized
157//
158// * TimevalScale now normalizes it's results [9/1999 it didn't before]
159
160// make sure tv_usec is less than 1,000,000
161extern VRPN_API struct timeval vrpn_TimevalNormalize(const struct timeval &tv);
162
163extern VRPN_API struct timeval vrpn_TimevalSum(const struct timeval &tv1,
164 const struct timeval &tv2);
165extern VRPN_API struct timeval vrpn_TimevalDiff(const struct timeval &tv1,
166 const struct timeval &tv2);
167extern VRPN_API struct timeval vrpn_TimevalScale(const struct timeval &tv,
168 double scale);
169
171extern VRPN_API unsigned long vrpn_TimevalDuration(struct timeval endT,
172 struct timeval startT);
173
176extern VRPN_API double vrpn_TimevalDurationSeconds(struct timeval endT,
177 struct timeval startT);
178
179extern VRPN_API bool vrpn_TimevalGreater(const struct timeval &tv1,
180 const struct timeval &tv2);
181extern VRPN_API bool vrpn_TimevalEqual(const struct timeval &tv1,
182 const struct timeval &tv2);
183
184extern VRPN_API double vrpn_TimevalMsecs(const struct timeval &tv1);
185
186extern VRPN_API struct timeval vrpn_MsecsTimeval(const double dMsecs);
187extern VRPN_API void vrpn_SleepMsecs(double dMilliSecs);
188
189//--------------------------------------------------------------
190// vrpn_* buffer util functions and endian-ness related
191// definitions and functions.
192
193// xform a double to/from network order -- like htonl and htons
194extern VRPN_API vrpn_float64 vrpn_htond(vrpn_float64 d);
195extern VRPN_API vrpn_float64 vrpn_ntohd(vrpn_float64 d);
196
197// From this we get the variable "vrpn_big_endian" set to true if the machine we
198// are
199// on is big endian and to false if it is little endian. This can be used by
200// custom packing and unpacking code to bypass the buffer and unbuffer routines
201// for cases that have to be particularly fast (like video data). It is also
202// used
203// internally by the vrpn_htond() function.
204
205static const int vrpn_int_data_for_endian_test = 1;
206static const char *vrpn_char_data_for_endian_test =
207 static_cast<const char*>(static_cast<const void *>((&vrpn_int_data_for_endian_test)));
208static const bool vrpn_big_endian = (vrpn_char_data_for_endian_test[0] != 1);
209
210// Read and write strings (not single items).
211extern VRPN_API int vrpn_buffer(char **insertPt, vrpn_int32 *buflen,
212 const char *string, vrpn_int32 length);
213extern VRPN_API int vrpn_unbuffer(const char **buffer, char *string,
214 vrpn_int32 length);
215
216// Read and write timeval.
217extern VRPN_API int vrpn_unbuffer(const char **buffer, timeval *t);
218extern VRPN_API int vrpn_buffer(char **insertPt, vrpn_int32 *buflen,
219 const timeval t);
220
221// To read and write the atomic types defined in vrpn_Types, you use the
222// templated
223// buffer and unbuffer routines below. These have the same form as the ones for
224// timeval, but they use types vrpn_int, vrpn_uint, vrpn_int16, vrpn_uint16,
225// vrpn_int32, vrpn_uint32, vrpn_float32, and vrpn_float64.
226
240
241// Copyright Iowa State University 2011.
242// Distributed under the Boost Software License, Version 1.0.
243// (See accompanying file LICENSE_1_0.txt or copy at
244// http://www.boost.org/LICENSE_1_0.txt)
245
246// Tested in the context of vrpn_server and vrpn_print_devices running between
247// an SGI running Irix 6.5 MIPS 32-bit (big endian) and Mac OSX intel 64-bit
248// (little endian) machine with a NULL tracker and it worked using the SGI
249// repaired commits from 3/17/2012.
250
254 namespace vrpn_detail {
256 template <int TypeSize> struct uint_traits;
257
258 template <> struct uint_traits<1> {
259 typedef vrpn_uint8 type;
260 };
261 template <> struct uint_traits<2> {
262 typedef vrpn_uint16 type;
263 };
264 template <> struct uint_traits<4> {
265 typedef vrpn_uint32 type;
266 };
267 } // end of namespace vrpn_detail
268
270 inline vrpn_uint8 hton(vrpn_uint8 hostval) { return hostval; }
271
273 inline vrpn_uint8 ntoh(vrpn_uint8 netval) { return netval; }
274
276 inline vrpn_uint16 hton(vrpn_uint16 hostval) { return htons(hostval); }
277
279 inline vrpn_uint16 ntoh(vrpn_uint16 netval) { return ntohs(netval); }
280
282 inline vrpn_uint32 hton(vrpn_uint32 hostval) { return htonl(hostval); }
283
285 inline vrpn_uint32 ntoh(vrpn_uint32 netval) { return ntohl(netval); }
286
288 inline vrpn_float64 hton(vrpn_float64 hostval) { return vrpn_htond(hostval); }
289
291 inline vrpn_float64 ntoh(vrpn_float64 netval) { return vrpn_ntohd(netval); }
292
295 template <typename T> inline T hton(T input)
296 {
297 union {
298 T asInput;
299 typename vrpn_detail::uint_traits<sizeof(T)>::type asInt;
300 } inVal, outVal;
301 inVal.asInput = input;
302 outVal.asInt = hton(inVal.asInt);
303 return outVal.asInput;
304 }
305
308 template <typename T> inline T ntoh(T input)
309 {
310 union {
311 T asInput;
312 typename vrpn_detail::uint_traits<sizeof(T)>::type asInt;
313 } inVal, outVal;
314 inVal.asInput = input;
315 outVal.asInt = ntoh(inVal.asInt);
316 return outVal.asInput;
317 }
318} // end of namespace vrpn_byte_order
319
320namespace vrpn_detail {
321 template <typename T> struct remove_const {
322 typedef T type;
323 };
324
325 template <typename T> struct remove_const<const T> {
326 typedef T type;
327 };
328
329 template <bool Condition> struct vrpn_static_assert {
330 };
331
333 template <> struct vrpn_static_assert<true> {
335 };
336} // end of namespace vrpn_detail
337
338#ifdef VRPN_USE_STATIC_ASSERTIONS
341#if defined(__GXX_EXPERIMENTAL_CXX0X__) || \
342 (defined(_MSC_VER) && (_MSC_VER >= 1600))
343#define VRPN_STATIC_ASSERT(CONDITION, MESSAGE) \
344 static_assert(CONDITION, #MESSAGE)
345#else
346#define VRPN_STATIC_ASSERT(CONDITION, MESSAGE) \
347 (void)(::vrpn_detail::vrpn_static_assert<CONDITION>::MESSAGE)
348#endif
349#else
351#include <assert.h>
352#define VRPN_STATIC_ASSERT(CONDITION, MESSAGE) assert((CONDITION) && #MESSAGE)
353#endif
354
359template <typename T, typename ByteT>
360static inline T vrpn_unbuffer_from_little_endian(ByteT *&input)
361{
362 using namespace vrpn_byte_order;
363
364 VRPN_STATIC_ASSERT(sizeof(ByteT) == 1, SIZE_OF_BUFFER_ITEM_IS_NOT_ONE_BYTE);
365
367 union {
368 typename ::vrpn_detail::remove_const<ByteT>::type bytes[sizeof(T)];
369 T typed;
370 } value;
371
373 for (unsigned int i = 0, j = sizeof(T) - 1; i < sizeof(T); ++i, --j) {
374 value.bytes[i] = input[j];
375 }
376
378 input += sizeof(T);
379
381 return ntoh(value.typed);
382}
383
388template <typename T, typename ByteT> inline T vrpn_unbuffer(ByteT *&input)
389{
390 using namespace vrpn_byte_order;
391
392 VRPN_STATIC_ASSERT(sizeof(ByteT) == 1, SIZE_OF_BUFFER_ITEM_IS_NOT_ONE_BYTE);
393
395 union {
396 typename ::vrpn_detail::remove_const<ByteT>::type bytes[sizeof(T)];
397 T typed;
398 } value;
399
401 memcpy(value.bytes, input, sizeof(T));
402
404 input += sizeof(T);
405
407 return ntoh(value.typed);
408}
409
414template <typename T, typename ByteT>
415inline int vrpn_buffer_to_little_endian(ByteT **insertPt, vrpn_int32 *buflen, const T inVal)
416{
417 using namespace vrpn_byte_order;
418
419 VRPN_STATIC_ASSERT(sizeof(ByteT) == 1, SIZE_OF_BUFFER_ITEM_IS_NOT_ONE_BYTE);
420
421 if ((insertPt == NULL) || (buflen == NULL)) {
422 fprintf(stderr, "vrpn_buffer: NULL pointer\n");
423 return -1;
424 }
425
426 if (sizeof(T) > static_cast<size_t>(*buflen)) {
427 fprintf(stderr, "vrpn_buffer: buffer not large enough\n");
428 return -1;
429 }
430
432 union {
433 typename ::vrpn_detail::remove_const<ByteT>::type bytes[sizeof(T)];
434 T typed;
435 } value;
436
438 value.typed = hton(inVal);
439
441 for (unsigned int i = 0, j = sizeof(T) - 1; i < sizeof(T); ++i, --j) {
442 (*insertPt)[i] = value.bytes[j];
443 }
444
446 *insertPt += sizeof(T);
448 *buflen -= sizeof(T);
449
450 return 0;
451}
452
457template <typename T, typename ByteT>
458inline int vrpn_buffer(ByteT **insertPt, vrpn_int32 *buflen, const T inVal)
459{
460 using namespace vrpn_byte_order;
461
462 VRPN_STATIC_ASSERT(sizeof(ByteT) == 1, SIZE_OF_BUFFER_ITEM_IS_NOT_ONE_BYTE);
463
464 if ((insertPt == NULL) || (buflen == NULL)) {
465 fprintf(stderr, "vrpn_buffer: NULL pointer\n");
466 return -1;
467 }
468
469 if (sizeof(T) > static_cast<size_t>(*buflen)) {
470 fprintf(stderr, "vrpn_buffer: buffer not large enough\n");
471 return -1;
472 }
473
475 union {
476 typename ::vrpn_detail::remove_const<ByteT>::type bytes[sizeof(T)];
477 T typed;
478 } value;
479
481 value.typed = hton(inVal);
482
484 memcpy(*insertPt, value.bytes, sizeof(T));
485
487 *insertPt += sizeof(T);
489 *buflen -= sizeof(T);
490
491 return 0;
492}
493
494template <typename T, typename ByteT>
495inline int vrpn_unbuffer(ByteT **input, T *lvalue)
496{
497 *lvalue = ::vrpn_unbuffer<T, ByteT>(*input);
498 return 0;
499}
500
501// Returns true if tests work and false if they do not.
502extern bool vrpn_test_pack_unpack(void);
503
509
510template <size_t charCount> void vrpn_strcpy(char (&to)[charCount], const char* pSrc)
511{
512 // Copy the string - don't copy too many bytes.
513#ifdef _WIN32
514 strncpy_s(to, pSrc, charCount);
515#else
516 strncpy(to, pSrc, charCount - 1);
517#endif
518 // Ensure null-termination.
519 to[charCount - 1] = 0;
520}
Internal header providing unbuffering facilities for a number of types.
vrpn_uint8 hton(vrpn_uint8 hostval)
host to network byte order for 8-bit uints is a no-op
vrpn_uint8 ntoh(vrpn_uint8 netval)
network to host byte order for 8-bit uints is a no-op
Traits class to get the uint type of a given size.
#define VRPN_API
timeval vrpn_TimevalScale(const timeval &tv, double scale)
vrpn_float64 vrpn_ntohd(vrpn_float64 d)
vrpn_float64 vrpn_htond(vrpn_float64 d)
timeval vrpn_TimevalDiff(const timeval &tv1, const timeval &tv2)
timeval vrpn_TimevalNormalize(const timeval &in_tv)
Definition vrpn_Shared.C:43
timeval vrpn_MsecsTimeval(const double dMsecs)
timeval vrpn_TimevalSum(const timeval &tv1, const timeval &tv2)
Definition vrpn_Shared.C:54
VRPN_API int vrpn_buffer(char **insertPt, vrpn_int32 *buflen, const char *string, vrpn_int32 length)
Utility routine for placing a character string of given length into a buffer that is to be sent as a ...
void vrpn_strcpy(char(&to)[charCount], const char *pSrc)
Null-terminated-string copy function that both guarantees not to overrun the buffer and guarantees th...
VRPN_API unsigned long vrpn_TimevalDuration(struct timeval endT, struct timeval startT)
Return number of microseconds between startT and endT.
VRPN_API vrpn_float64 vrpn_htond(vrpn_float64 d)
bool vrpn_test_pack_unpack(void)
#define VRPN_STATIC_ASSERT(CONDITION, MESSAGE)
Fall back to normal asserts.
VRPN_API vrpn_float64 vrpn_ntohd(vrpn_float64 d)
VRPN_API void vrpn_SleepMsecs(double dMilliSecs)
VRPN_API int vrpn_unbuffer(const char **buffer, char *string, vrpn_int32 length)
Utility routine for taking a string of specified length from a buffer that was sent as a message.
VRPN_API double vrpn_TimevalMsecs(const struct timeval &tv1)
#define vrpn_gettimeofday
Definition vrpn_Shared.h:99
int vrpn_buffer_to_little_endian(ByteT **insertPt, vrpn_int32 *buflen, const T inVal)
Function template to buffer values to a buffer stored in little- endian order. Specify the type to bu...
VRPN_API double vrpn_TimevalDurationSeconds(struct timeval endT, struct timeval startT)
Return the number of seconds between startT and endT as a floating-point value.
VRPN_API bool vrpn_TimevalEqual(const struct timeval &tv1, const struct timeval &tv2)
VRPN_API bool vrpn_TimevalGreater(const struct timeval &tv1, const struct timeval &tv2)
Header containing vrpn_Thread, vrpn_Semaphore (formerly in vrpn_Shared.h), as well as a lock-guard cl...