Adds a modified copy of talk/base to webrtc/base. It is the first step in
migrating talk/base to webrtc/base.

BUG=N/A
R=niklas.enbom@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/17479005

git-svn-id: http://webrtc.googlecode.com/svn/trunk@6129 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/base/macutils.cc b/webrtc/base/macutils.cc
new file mode 100644
index 0000000..6e436d4
--- /dev/null
+++ b/webrtc/base/macutils.cc
@@ -0,0 +1,221 @@
+/*
+ *  Copyright 2007 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <sstream>
+
+#include "webrtc/base/common.h"
+#include "webrtc/base/logging.h"
+#include "webrtc/base/macutils.h"
+#include "webrtc/base/scoped_ptr.h"
+#include "webrtc/base/stringutils.h"
+
+namespace rtc {
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool ToUtf8(const CFStringRef str16, std::string* str8) {
+  if ((NULL == str16) || (NULL == str8)) {
+    return false;
+  }
+  size_t maxlen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str16),
+                                                    kCFStringEncodingUTF8) + 1;
+  scoped_ptr<char[]> buffer(new char[maxlen]);
+  if (!buffer || !CFStringGetCString(str16, buffer.get(), maxlen,
+                                     kCFStringEncodingUTF8)) {
+    return false;
+  }
+  str8->assign(buffer.get());
+  return true;
+}
+
+bool ToUtf16(const std::string& str8, CFStringRef* str16) {
+  if (NULL == str16) {
+    return false;
+  }
+  *str16 = CFStringCreateWithBytes(kCFAllocatorDefault,
+                                   reinterpret_cast<const UInt8*>(str8.data()),
+                                   str8.length(), kCFStringEncodingUTF8,
+                                   false);
+  return NULL != *str16;
+}
+
+#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
+void DecodeFourChar(UInt32 fc, std::string* out) {
+  std::stringstream ss;
+  ss << '\'';
+  bool printable = true;
+  for (int i = 3; i >= 0; --i) {
+    char ch = (fc >> (8 * i)) & 0xFF;
+    if (isprint(static_cast<unsigned char>(ch))) {
+      ss << ch;
+    } else {
+      printable = false;
+      break;
+    }
+  }
+  if (printable) {
+    ss << '\'';
+  } else {
+    ss.str("");
+    ss << "0x" << std::hex << fc;
+  }
+  out->append(ss.str());
+}
+
+static bool GetGestalt(OSType ostype, int* value) {
+  ASSERT(NULL != value);
+  SInt32 native_value;
+  OSStatus result = Gestalt(ostype, &native_value);
+  if (noErr == result) {
+    *value = native_value;
+    return true;
+  }
+  std::string str;
+  DecodeFourChar(ostype, &str);
+  LOG_E(LS_ERROR, OS, result) << "Gestalt(" << str << ")";
+  return false;
+}
+
+bool GetOSVersion(int* major, int* minor, int* bugfix) {
+  ASSERT(major && minor && bugfix);
+  if (!GetGestalt(gestaltSystemVersion, major)) {
+    return false;
+  }
+  if (*major < 0x1040) {
+    *bugfix = *major & 0xF;
+    *minor = (*major >> 4) & 0xF;
+    *major = (*major >> 8);
+    return true;
+  }
+  return GetGestalt(gestaltSystemVersionMajor, major) &&
+         GetGestalt(gestaltSystemVersionMinor, minor) &&
+         GetGestalt(gestaltSystemVersionBugFix, bugfix);
+}
+
+MacOSVersionName GetOSVersionName() {
+  int major = 0, minor = 0, bugfix = 0;
+  if (!GetOSVersion(&major, &minor, &bugfix)) {
+    return kMacOSUnknown;
+  }
+  if (major > 10) {
+    return kMacOSNewer;
+  }
+  if ((major < 10) || (minor < 3)) {
+    return kMacOSOlder;
+  }
+  switch (minor) {
+    case 3:
+      return kMacOSPanther;
+    case 4:
+      return kMacOSTiger;
+    case 5:
+      return kMacOSLeopard;
+    case 6:
+      return kMacOSSnowLeopard;
+    case 7:
+      return kMacOSLion;
+    case 8:
+      return kMacOSMountainLion;
+    case 9:
+      return kMacOSMavericks;
+  }
+  return kMacOSNewer;
+}
+
+bool GetQuickTimeVersion(std::string* out) {
+  int ver;
+  if (!GetGestalt(gestaltQuickTimeVersion, &ver)) {
+    return false;
+  }
+
+  std::stringstream ss;
+  ss << std::hex << ver;
+  *out = ss.str();
+  return true;
+}
+
+bool RunAppleScript(const std::string& script) {
+  // TODO(thaloun): Add a .mm file that contains something like this:
+  // NSString source from script
+  // NSAppleScript* appleScript = [[NSAppleScript alloc] initWithSource:&source]
+  // if (appleScript != nil) {
+  //   [appleScript executeAndReturnError:nil]
+  //   [appleScript release]
+#ifndef CARBON_DEPRECATED
+  ComponentInstance component = NULL;
+  AEDesc script_desc;
+  AEDesc result_data;
+  OSStatus err;
+  OSAID script_id, result_id;
+
+  AECreateDesc(typeNull, NULL, 0, &script_desc);
+  AECreateDesc(typeNull, NULL, 0, &result_data);
+  script_id = kOSANullScript;
+  result_id = kOSANullScript;
+
+  component = OpenDefaultComponent(kOSAComponentType, typeAppleScript);
+  if (component == NULL) {
+    LOG(LS_ERROR) << "Failed opening Apple Script component";
+    return false;
+  }
+  err = AECreateDesc(typeUTF8Text, script.data(), script.size(), &script_desc);
+  if (err != noErr) {
+    CloseComponent(component);
+    LOG(LS_ERROR) << "Failed creating Apple Script description";
+    return false;
+  }
+
+  err = OSACompile(component, &script_desc, kOSAModeCanInteract, &script_id);
+  if (err != noErr) {
+    AEDisposeDesc(&script_desc);
+    if (script_id != kOSANullScript) {
+      OSADispose(component, script_id);
+    }
+    CloseComponent(component);
+    LOG(LS_ERROR) << "Error compiling Apple Script";
+    return false;
+  }
+
+  err = OSAExecute(component, script_id, kOSANullScript, kOSAModeCanInteract,
+                   &result_id);
+
+  if (err == errOSAScriptError) {
+    LOG(LS_ERROR) << "Error when executing Apple Script: " << script;
+    AECreateDesc(typeNull, NULL, 0, &result_data);
+    OSAScriptError(component, kOSAErrorMessage, typeChar, &result_data);
+    int len = AEGetDescDataSize(&result_data);
+    char* data = (char*) malloc(len);
+    if (data != NULL) {
+      err = AEGetDescData(&result_data, data, len);
+      LOG(LS_ERROR) << "Script error: " << data;
+    }
+    AEDisposeDesc(&script_desc);
+    AEDisposeDesc(&result_data);
+    return false;
+  }
+  AEDisposeDesc(&script_desc);
+  if (script_id != kOSANullScript) {
+    OSADispose(component, script_id);
+  }
+  if (result_id != kOSANullScript) {
+    OSADispose(component, result_id);
+  }
+  CloseComponent(component);
+  return true;
+#else
+  // TODO(thaloun): Support applescripts with the NSAppleScript API.
+  return false;
+#endif  // CARBON_DEPRECATED
+}
+#endif  // WEBRTC_MAC && !defined(WEBRTC_IOS)
+
+///////////////////////////////////////////////////////////////////////////////
+
+}  // namespace rtc