1/*
2 * libjingle
3 * Copyright 2004--2009, Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 *  1. Redistributions of source code must retain the above copyright notice,
9 *     this list of conditions and the following disclaimer.
10 *  2. Redistributions in binary form must reproduce the above copyright notice,
11 *     this list of conditions and the following disclaimer in the documentation
12 *     and/or other materials provided with the distribution.
13 *  3. The name of the author may not be used to endorse or promote products
14 *     derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#ifdef OSX
29
30#include <CoreFoundation/CoreFoundation.h>
31
32#include "talk/base/logging.h"
33#include "talk/base/macconversion.h"
34
35bool p_convertHostCFStringRefToCPPString(
36  const CFStringRef cfstr, std::string& cppstr) {
37  bool result = false;
38
39  // First this must be non-null,
40  if (NULL != cfstr) {
41    // it must actually *be* a CFString, and not something just masquerading
42    // as one,
43    if (CFGetTypeID(cfstr) == CFStringGetTypeID()) {
44      // and we must be able to get the characters out of it.
45      // (The cfstr owns this buffer; it came from somewhere else,
46      // so someone else gets to take care of getting rid of the cfstr,
47      // and then this buffer will go away automatically.)
48      unsigned length = CFStringGetLength(cfstr);
49      char* buf = new char[1 + length];
50      if (CFStringGetCString(cfstr, buf, 1 + length, kCFStringEncodingASCII)) {
51        if (strlen(buf) == length) {
52          cppstr.assign(buf);
53          result = true;
54        }
55      }
56      delete [] buf;
57    }
58  }
59
60  return result;
61}
62
63bool p_convertCFNumberToInt(CFNumberRef cfn, int* i) {
64  bool converted = false;
65
66  // It must not be null.
67  if (NULL != cfn) {
68    // It must actually *be* a CFNumber and not something just masquerading
69    // as one.
70    if (CFGetTypeID(cfn) == CFNumberGetTypeID()) {
71      CFNumberType ntype = CFNumberGetType(cfn);
72      switch (ntype) {
73        case kCFNumberSInt8Type:
74          SInt8 sint8;
75          converted = CFNumberGetValue(cfn, ntype, static_cast<void*>(&sint8));
76          if (converted) *i = static_cast<int>(sint8);
77          break;
78        case kCFNumberSInt16Type:
79          SInt16 sint16;
80          converted = CFNumberGetValue(cfn, ntype, static_cast<void*>(&sint16));
81          if (converted) *i = static_cast<int>(sint16);
82          break;
83        case kCFNumberSInt32Type:
84          SInt32 sint32;
85          converted = CFNumberGetValue(cfn, ntype, static_cast<void*>(&sint32));
86          if (converted) *i = static_cast<int>(sint32);
87          break;
88        case kCFNumberSInt64Type:
89          SInt64 sint64;
90          converted = CFNumberGetValue(cfn, ntype, static_cast<void*>(&sint64));
91          if (converted) *i = static_cast<int>(sint64);
92          break;
93        case kCFNumberFloat32Type:
94          Float32 float32;
95          converted = CFNumberGetValue(cfn, ntype,
96                                       static_cast<void*>(&float32));
97          if (converted) *i = static_cast<int>(float32);
98          break;
99        case kCFNumberFloat64Type:
100          Float64 float64;
101          converted = CFNumberGetValue(cfn, ntype,
102                                       static_cast<void*>(&float64));
103          if (converted) *i = static_cast<int>(float64);
104          break;
105        case kCFNumberCharType:
106          char charvalue;
107          converted = CFNumberGetValue(cfn, ntype,
108                                       static_cast<void*>(&charvalue));
109          if (converted) *i = static_cast<int>(charvalue);
110          break;
111        case kCFNumberShortType:
112          short shortvalue;
113          converted = CFNumberGetValue(cfn, ntype,
114                                       static_cast<void*>(&shortvalue));
115          if (converted) *i = static_cast<int>(shortvalue);
116          break;
117        case kCFNumberIntType:
118          int intvalue;
119          converted = CFNumberGetValue(cfn, ntype,
120                                       static_cast<void*>(&intvalue));
121          if (converted) *i = static_cast<int>(intvalue);
122          break;
123        case kCFNumberLongType:
124          long longvalue;
125          converted = CFNumberGetValue(cfn, ntype,
126                     static_cast<void*>(&longvalue));
127          if (converted) *i = static_cast<int>(longvalue);
128          break;
129        case kCFNumberLongLongType:
130          long long llvalue;
131          converted = CFNumberGetValue(cfn, ntype,
132                                       static_cast<void*>(&llvalue));
133          if (converted) *i = static_cast<int>(llvalue);
134          break;
135        case kCFNumberFloatType:
136          float floatvalue;
137          converted = CFNumberGetValue(cfn, ntype,
138                                       static_cast<void*>(&floatvalue));
139          if (converted) *i = static_cast<int>(floatvalue);
140          break;
141        case kCFNumberDoubleType:
142          double doublevalue;
143          converted = CFNumberGetValue(cfn, ntype,
144                                       static_cast<void*>(&doublevalue));
145          if (converted) *i = static_cast<int>(doublevalue);
146          break;
147        case kCFNumberCFIndexType:
148          CFIndex cfindex;
149          converted = CFNumberGetValue(cfn, ntype,
150                                       static_cast<void*>(&cfindex));
151          if (converted) *i = static_cast<int>(cfindex);
152          break;
153        default:
154          LOG(LS_ERROR) << "got unknown type.";
155          break;
156      }
157    }
158  }
159
160  return converted;
161}
162
163bool p_isCFNumberTrue(CFNumberRef cfn) {
164  // We assume it's false until proven otherwise.
165  bool result = false;
166  int asInt;
167  bool converted = p_convertCFNumberToInt(cfn, &asInt);
168
169  if (converted && (0 != asInt)) {
170    result = true;
171  }
172
173  return result;
174}
175
176#endif  // OSX
177