<commit_before>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/android/banners/app_banner_manager_android.h"

#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/command_line.h"
#include "base/metrics/field_trial.h"
#include "chrome/browser/android/banners/app_banner_data_fetcher_android.h"
#include "chrome/browser/banners/app_banner_metrics.h"
#include "chrome/common/chrome_constants.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/frame_navigate_params.h"
#include "jni/AppBannerManager_jni.h"

using base::android::ConvertJavaStringToUTF8;
using base::android::ConvertJavaStringToUTF16;
using base::android::ConvertUTF8ToJavaString;
using base::android::ConvertUTF16ToJavaString;

namespace {

const char kPlayPlatform[] = "play";
const char kReferrerName[] = "referrer";
const char kIdName[] = "id";

}  // anonymous namespace

namespace banners {

AppBannerManagerAndroid::AppBannerManagerAndroid(JNIEnv* env,
                                                 jobject obj,
                                                 int icon_size)
    : AppBannerManager(icon_size),
      weak_java_banner_view_manager_(env, obj) {
}

AppBannerManagerAndroid::~AppBannerManagerAndroid() {
}

void AppBannerManagerAndroid::Destroy(JNIEnv* env, jobject obj) {
  delete this;
}

void AppBannerManagerAndroid::ReplaceWebContents(JNIEnv* env,
                                                 jobject obj,
                                                 jobject jweb_contents) {
  content::WebContents* web_contents =
      content::WebContents::FromJavaWebContents(jweb_contents);
  AppBannerManager::ReplaceWebContents(web_contents);
}

bool AppBannerManagerAndroid::HandleNonWebApp(const std::string& platform,
                                              const GURL& url,
                                              const std::string& id) {
  if (!CheckPlatformAndId(platform, id))
    return false;

  banners::TrackDisplayEvent(DISPLAY_EVENT_NATIVE_APP_BANNER_REQUESTED);

  // Send the info to the Java side to get info about the app.
  JNIEnv* env = base::android::AttachCurrentThread();
  ScopedJavaLocalRef<jobject> jobj = weak_java_banner_view_manager_.get(env);
  if (jobj.is_null())
    return false;

  std::string id_from_app_url = ExtractQueryValueForName(url, kIdName);
  if (id_from_app_url.size() && id != id_from_app_url) {
    banners::OutputDeveloperDebugMessage(web_contents(),
                                         banners::kIgnoredIdsDoNotMatch);
    return false;
  }

  std::string referrer = ExtractQueryValueForName(url, kReferrerName);

  ScopedJavaLocalRef<jstring> jurl(
      ConvertUTF8ToJavaString(env, data_fetcher()->validated_url().spec()));
  ScopedJavaLocalRef<jstring> jpackage(
      ConvertUTF8ToJavaString(env, id));
  ScopedJavaLocalRef<jstring> jreferrer(
      ConvertUTF8ToJavaString(env, referrer));
  Java_AppBannerManager_fetchAppDetails(env, jobj.obj(), jurl.obj(),
                                        jpackage.obj(), jreferrer.obj(),
                                        ideal_icon_size());
  return true;
}

bool AppBannerManagerAndroid::CheckPlatformAndId(const std::string& platform,
                                                 const std::string& id) {
  if (platform != kPlayPlatform) {
    banners::OutputDeveloperDebugMessage(
        web_contents(), platform + banners::kIgnoredNotSupportedOnAndroid);
    return false;
  }
  if (id.empty()) {
    banners::OutputDeveloperDebugMessage(web_contents(), banners::kIgnoredNoId);
    return false;
  }
  return true;
}

bool AppBannerManagerAndroid::CheckFetcherMatchesContents() {
  if (!web_contents())
    return false;

  if (!data_fetcher() ||
      data_fetcher()->validated_url() != web_contents()->GetURL()) {
    banners::OutputDeveloperNotShownMessage(
        web_contents(), banners::kUserNavigatedBeforeBannerShown);
    return false;
  }
  return true;
}

std::string AppBannerManagerAndroid::ExtractQueryValueForName(
    const GURL& url,
    const std::string& name) {
  url::Component query = url.parsed_for_possibly_invalid_spec().query;
  url::Component key, value;
  const char* url_spec = url.spec().c_str();

  while (url::ExtractQueryKeyValue(url_spec, &query, &key, &value)) {
    std::string key_str(url_spec, key.begin, key.len);
    std::string value_str(url_spec, value.begin, value.len);
    if (key_str == name)
      return value_str;
  }
  return "";
}

AppBannerDataFetcher* AppBannerManagerAndroid::CreateAppBannerDataFetcher(
    base::WeakPtr<Delegate> weak_delegate,
    const int ideal_icon_size) {
  return new AppBannerDataFetcherAndroid(web_contents(), weak_delegate,
                                         ideal_icon_size);
}

bool AppBannerManagerAndroid::OnAppDetailsRetrieved(JNIEnv* env,
                                                    jobject obj,
                                                    jobject japp_data,
                                                    jstring japp_title,
                                                    jstring japp_package,
                                                    jstring jicon_url) {
  if (!CheckFetcherMatchesContents())
    return false;

  base::android::ScopedJavaLocalRef<jobject> native_app_data;
  native_app_data.Reset(env, japp_data);
  GURL image_url = GURL(ConvertJavaStringToUTF8(env, jicon_url));

  AppBannerDataFetcherAndroid* android_fetcher =
      static_cast<AppBannerDataFetcherAndroid*>(data_fetcher().get());
  return android_fetcher->ContinueFetching(
      ConvertJavaStringToUTF16(env, japp_title),
      ConvertJavaStringToUTF8(env, japp_package),
      native_app_data, image_url);
}

bool AppBannerManagerAndroid::IsFetcherActive(JNIEnv* env, jobject obj) {
  return AppBannerManager::IsFetcherActive();
}

// static
bool AppBannerManagerAndroid::Register(JNIEnv* env) {
  return RegisterNativesImpl(env);
}

jlong Init(JNIEnv* env, jobject obj, jint icon_size) {
  AppBannerManagerAndroid* manager =
      new AppBannerManagerAndroid(env, obj, icon_size);
  return reinterpret_cast<intptr_t>(manager);
}

void SetTimeDeltaForTesting(JNIEnv* env, jclass clazz, jint days) {
  AppBannerDataFetcher::SetTimeDeltaForTesting(days);
}

void DisableSecureSchemeCheckForTesting(JNIEnv* env, jclass clazz) {
  AppBannerManager::DisableSecureSchemeCheckForTesting();
}

void SetEngagementWeights(JNIEnv* env,
                          jclass clazz,
                          jdouble direct_engagement,
                          jdouble indirect_engagement) {
  AppBannerManager::SetEngagementWeights(direct_engagement,
                                         indirect_engagement);
}

jboolean IsEnabled(JNIEnv* env, jclass clazz) {
  return base::FieldTrialList::FindFullName("AppBanners") == "Enabled";
}

}  // namespace banners
<commit_msg>Append playinline=chrome_inline to the store referrer on native app banner install.<commit_after>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/android/banners/app_banner_manager_android.h"

#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/command_line.h"
#include "base/metrics/field_trial.h"
#include "chrome/browser/android/banners/app_banner_data_fetcher_android.h"
#include "chrome/browser/banners/app_banner_metrics.h"
#include "chrome/common/chrome_constants.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/frame_navigate_params.h"
#include "jni/AppBannerManager_jni.h"

using base::android::ConvertJavaStringToUTF8;
using base::android::ConvertJavaStringToUTF16;
using base::android::ConvertUTF8ToJavaString;
using base::android::ConvertUTF16ToJavaString;

namespace {

const char kPlayPlatform[] = "play";
const char kReferrerName[] = "referrer";
const char kIdName[] = "id";
const char kPlayInlineReferrer[] = "playinline=chrome_inline";

}  // anonymous namespace

namespace banners {

AppBannerManagerAndroid::AppBannerManagerAndroid(JNIEnv* env,
                                                 jobject obj,
                                                 int icon_size)
    : AppBannerManager(icon_size),
      weak_java_banner_view_manager_(env, obj) {
}

AppBannerManagerAndroid::~AppBannerManagerAndroid() {
}

void AppBannerManagerAndroid::Destroy(JNIEnv* env, jobject obj) {
  delete this;
}

void AppBannerManagerAndroid::ReplaceWebContents(JNIEnv* env,
                                                 jobject obj,
                                                 jobject jweb_contents) {
  content::WebContents* web_contents =
      content::WebContents::FromJavaWebContents(jweb_contents);
  AppBannerManager::ReplaceWebContents(web_contents);
}

bool AppBannerManagerAndroid::HandleNonWebApp(const std::string& platform,
                                              const GURL& url,
                                              const std::string& id) {
  if (!CheckPlatformAndId(platform, id))
    return false;

  banners::TrackDisplayEvent(DISPLAY_EVENT_NATIVE_APP_BANNER_REQUESTED);

  // Send the info to the Java side to get info about the app.
  JNIEnv* env = base::android::AttachCurrentThread();
  ScopedJavaLocalRef<jobject> jobj = weak_java_banner_view_manager_.get(env);
  if (jobj.is_null())
    return false;

  std::string id_from_app_url = ExtractQueryValueForName(url, kIdName);
  if (id_from_app_url.size() && id != id_from_app_url) {
    banners::OutputDeveloperDebugMessage(web_contents(),
                                         banners::kIgnoredIdsDoNotMatch);
    return false;
  }

  std::string referrer =
      ExtractQueryValueForName(url, kReferrerName);

  // Attach the chrome_inline referrer value, prefixed with "&" if the referrer
  // is non empty.
  if (referrer.empty())
    referrer = kPlayInlineReferrer;
  else
    referrer.append("&").append(kPlayInlineReferrer);

  ScopedJavaLocalRef<jstring> jurl(
      ConvertUTF8ToJavaString(env, data_fetcher()->validated_url().spec()));
  ScopedJavaLocalRef<jstring> jpackage(
      ConvertUTF8ToJavaString(env, id));
  ScopedJavaLocalRef<jstring> jreferrer(
      ConvertUTF8ToJavaString(env, referrer));
  Java_AppBannerManager_fetchAppDetails(env, jobj.obj(), jurl.obj(),
                                        jpackage.obj(), jreferrer.obj(),
                                        ideal_icon_size());
  return true;
}

bool AppBannerManagerAndroid::CheckPlatformAndId(const std::string& platform,
                                                 const std::string& id) {
  if (platform != kPlayPlatform) {
    banners::OutputDeveloperDebugMessage(
        web_contents(), platform + banners::kIgnoredNotSupportedOnAndroid);
    return false;
  }
  if (id.empty()) {
    banners::OutputDeveloperDebugMessage(web_contents(), banners::kIgnoredNoId);
    return false;
  }
  return true;
}

bool AppBannerManagerAndroid::CheckFetcherMatchesContents() {
  if (!web_contents())
    return false;

  if (!data_fetcher() ||
      data_fetcher()->validated_url() != web_contents()->GetURL()) {
    banners::OutputDeveloperNotShownMessage(
        web_contents(), banners::kUserNavigatedBeforeBannerShown);
    return false;
  }
  return true;
}

std::string AppBannerManagerAndroid::ExtractQueryValueForName(
    const GURL& url,
    const std::string& name) {
  url::Component query = url.parsed_for_possibly_invalid_spec().query;
  url::Component key, value;
  const char* url_spec = url.spec().c_str();

  while (url::ExtractQueryKeyValue(url_spec, &query, &key, &value)) {
    std::string key_str(url_spec, key.begin, key.len);
    std::string value_str(url_spec, value.begin, value.len);
    if (key_str == name)
      return value_str;
  }
  return "";
}

AppBannerDataFetcher* AppBannerManagerAndroid::CreateAppBannerDataFetcher(
    base::WeakPtr<Delegate> weak_delegate,
    const int ideal_icon_size) {
  return new AppBannerDataFetcherAndroid(web_contents(), weak_delegate,
                                         ideal_icon_size);
}

bool AppBannerManagerAndroid::OnAppDetailsRetrieved(JNIEnv* env,
                                                    jobject obj,
                                                    jobject japp_data,
                                                    jstring japp_title,
                                                    jstring japp_package,
                                                    jstring jicon_url) {
  if (!CheckFetcherMatchesContents())
    return false;

  base::android::ScopedJavaLocalRef<jobject> native_app_data;
  native_app_data.Reset(env, japp_data);
  GURL image_url = GURL(ConvertJavaStringToUTF8(env, jicon_url));

  AppBannerDataFetcherAndroid* android_fetcher =
      static_cast<AppBannerDataFetcherAndroid*>(data_fetcher().get());
  return android_fetcher->ContinueFetching(
      ConvertJavaStringToUTF16(env, japp_title),
      ConvertJavaStringToUTF8(env, japp_package),
      native_app_data, image_url);
}

bool AppBannerManagerAndroid::IsFetcherActive(JNIEnv* env, jobject obj) {
  return AppBannerManager::IsFetcherActive();
}

// static
bool AppBannerManagerAndroid::Register(JNIEnv* env) {
  return RegisterNativesImpl(env);
}

jlong Init(JNIEnv* env, jobject obj, jint icon_size) {
  AppBannerManagerAndroid* manager =
      new AppBannerManagerAndroid(env, obj, icon_size);
  return reinterpret_cast<intptr_t>(manager);
}

void SetTimeDeltaForTesting(JNIEnv* env, jclass clazz, jint days) {
  AppBannerDataFetcher::SetTimeDeltaForTesting(days);
}

void DisableSecureSchemeCheckForTesting(JNIEnv* env, jclass clazz) {
  AppBannerManager::DisableSecureSchemeCheckForTesting();
}

void SetEngagementWeights(JNIEnv* env,
                          jclass clazz,
                          jdouble direct_engagement,
                          jdouble indirect_engagement) {
  AppBannerManager::SetEngagementWeights(direct_engagement,
                                         indirect_engagement);
}

jboolean IsEnabled(JNIEnv* env, jclass clazz) {
  return base::FieldTrialList::FindFullName("AppBanners") == "Enabled";
}

}  // namespace banners
<|endoftext|>


<commit_before>#include "pch.h"
#include "axl_io_SockAddrParser.h"
#include "axl_err_Error.h"

namespace axl {
namespace io {

//.............................................................................

void
SockAddrParser::initialize (
	const char* p,
	size_t length
	)
{
	if (length == -1)
		length = p ? strlen (p) : 0;

	m_p = p;
	m_end = p + length;
}

bool
SockAddrParser::parse (in_addr* addr)
{
	bool result;

	uchar_t* ip = (uchar_t*) addr;
	for (size_t i = 0;; i++)
	{
		uint_t octet;
		result = parseInt (&octet, 10);
		if (!result)
			return false;

		ip [i] = octet;

		if (i >= 3)
			break;

		result = expectChar ('.');
		if (!result)
			return false;
	}

	return true;
}

bool
SockAddrParser::parse (sockaddr_in* addr)
{
	bool result;

	memset (addr, 0, sizeof (sockaddr_in));
	addr->sin_family = AF_INET;

	const char* p0 = m_p;
	result = parse (&addr->sin_addr);
	if (!result) // rollback and try single port
	{
		m_p = p0;

		uint_t port;
		result = parseInt (&port, 10);
		if (!result)
			return false;

		skipWhiteSpace ();
		if (m_p != m_end)
		{
			err::setError (err::SystemErrorCode_InvalidAddress);
			return false;
		}

		*(uint32_t*) &addr->sin_addr = 0;
		addr->sin_port = rtl::swapByteOrder16 ((uint16_t) port);
		return true;
	}

	result = tryChar (':');
	if (result)
	{
		uint_t port;
		result = parseInt (&port, 10);
		if (!result)
			return false;

		addr->sin_port = rtl::swapByteOrder16 ((uint16_t) port);
	}

	return true;
}

bool
SockAddrParser::parse (in6_addr* addr)
{
	bool result;

	uint16_t* ip = (uint16_t*) addr;

	size_t zeroRunIdx = -1;
	bool isIp4 = false;
	uchar_t ip4 [4];

	tryChar (':');

	size_t i = 0;
	while (i < 8)
	{
		result = tryChar (':');
		if (result)
			zeroRunIdx = i;

		skipWhiteSpace ();

		if (m_p >= m_end || !isxdigit (*m_p))
			break;

		uint_t word;
		result = parseInt (&word, 16);
		if (!result)
			return false;

		result = tryChar (':');
		if (!result)
		{
			result = tryChar ('.');
			if (result)
			{
				if (i > 6)
				{
					err::setError (err::SystemErrorCode_InvalidAddress);
					return false;
				}

				ip4 [0] = (uchar_t)
					((word & 0x0f) +
					((word & 0xf0) >> 4) * 10 +
					((word & 0xf00) >> 8) * 100);

				isIp4 = true;
				break;
			}
		}

		ip [i] = rtl::swapByteOrder16 ((uint16_t) word);
		i++;

		if (!result)
			break;
	}

	if (isIp4)
	{
		for (size_t j = 1;; j++)
		{
			uint_t octet;
			result = parseInt (&octet, 10);
			if (!result)
				return false;

			ip4 [j] = (uchar_t) octet;

			if (j >= 3)
				break;

			result = expectChar ('.');
			if (!result)
				return false;
		}

		ASSERT (i <= 6);
		ip [i] = ip4 [0] + (ip4 [1] << 8);
		ip [i + 1] = ip4 [2] + (ip4 [3] << 8);
		i += 2;
	}

	if (zeroRunIdx != -1)
	{
		ASSERT (i <= 8 && zeroRunIdx <= i);

		size_t zeroRunLength = 8 - i;

		if (zeroRunIdx < i)
		{
			memmove (&ip [zeroRunIdx + zeroRunLength], &ip [zeroRunIdx], (i - zeroRunIdx) * sizeof (uint16_t));
			memset (&ip [zeroRunIdx], 0, zeroRunLength * sizeof (uint16_t));
		}
	}
	else if (i != 8)
	{
		err::setError (err::SystemErrorCode_InvalidAddress);
		return false;
	}

	return true;
}

bool
SockAddrParser::parse (sockaddr_in6* addr)
{
	bool result;

	memset (addr, 0, sizeof (sockaddr_in6));
	addr->sin6_family = AF_INET6;

	bool hasBrackets = tryChar ('[');

	result = parse (&addr->sin6_addr);
	if (!result)
		return false;

	result = tryChar ('%');
	if (result)
	{
		uint_t scope;
		result = parseInt (&scope, 10);
		if (!result)
			return false;

		addr->sin6_scope_id = scope;
	}

	if (hasBrackets)
	{
		result = expectChar (']');
		if (!result)
			return false;

		result = tryChar (':');
		if (result)
		{
			uint_t port;
			result = parseInt (&port, 10);
			if (!result)
				return false;

			addr->sin6_port = rtl::swapByteOrder16 ((uint16_t) port);
		}
	}

	return true;
}

bool
SockAddrParser::parse (
	sockaddr* addr,
	size_t size
	)
{
	skipWhiteSpace ();

	SockAddrParser clone = *this;

	if (trySockAddr_ip4 ())
	{
		if (size < sizeof (sockaddr_in))
		{
			err::setError (err::SystemErrorCode_BufferTooSmall);
			return false;
		}

		*this = clone;
		return parse ((sockaddr_in*) addr);
	}

	*this = clone;

	if (trySockAddr_ip6 ())
	{
		if (size < sizeof (sockaddr_in6))
		{
			err::setError (err::SystemErrorCode_BufferTooSmall);
			return false;
		}

		*this = clone;
		return parse ((sockaddr_in6*) addr);
	}

	err::setError (err::SystemErrorCode_InvalidAddress);
	return false;
}

bool
SockAddrParser::tryAddr_ip4 ()
{
	bool result;

	for (size_t i = 0;; i++)
	{
		result = tryInt (10);
		if (!result)
			return false;

		if (i >= 3)
			break;

		result = tryChar ('.');
		if (!result)
			return false;
	}

	return true;
}

bool
SockAddrParser::tryAddr_ip6 ()
{
	bool result;

	bool hasZeroRun = false;
	bool isIp4 = false;

	tryChar (':');

	size_t i = 0;
	while (i < 8)
	{
		result = tryChar (':');
		if (result)
			hasZeroRun = true;

		skipWhiteSpace ();

		if (m_p >= m_end || !isxdigit (*m_p))
			break;

		result = tryInt (16);
		if (!result)
			return false;

		result = tryChar (':');
		if (!result)
		{
			result = tryChar ('.');
			if (result)
			{
				if (i > 6)
					return false;

				isIp4 = true;
				break;
			}
		}

		i++;

		if (!result)
			break;
	}

	if (isIp4)
	{
		for (size_t j = 1;; j++)
		{
			result = tryInt (10);
			if (!result)
				return false;

			if (j >= 3)
				break;

			result = tryChar ('.');
			if (!result)
				return false;
		}

		i += 2;
	}

	if (!hasZeroRun && i != 8)
		return false;

	return true;
}

bool
SockAddrParser::trySockAddr_ip4 ()
{
	const char* p0 = m_p;

	bool result = tryAddr_ip4 ();
	if (!result) // rollback and try single port
	{
		m_p = p0;
		result = tryInt (10);
		if (!result)
			return false;

		skipWhiteSpace ();
		return m_p == m_end;
	}

	result = tryChar (':');
	if (result)
	{
		result = tryInt (10);
		if (!result)
			return false;
	}

	return true;
}

bool
SockAddrParser::trySockAddr_ip6 ()
{
	bool result;
	bool hasBrackets = tryChar ('[');

	result = tryAddr_ip6 ();
	if (!result)
		return false;

	result = tryChar ('%');
	if (result)
	{
		result = tryInt (10);
		if (!result)
			return false;
	}

	if (hasBrackets)
	{
		result = tryChar (']');
		if (!result)
			return false;

		result = tryChar (':');
		if (result)
		{
			result = tryInt (10);
			if (!result)
				return false;
		}
	}

	return true;
}

void
SockAddrParser::skipWhiteSpace ()
{
	while (m_p < m_end && isspace (*m_p))
		m_p++;
}

bool
SockAddrParser::parseInt (
	uint_t* p,
	int radix
	)
{
	skipWhiteSpace ();

	char* end;
	*p = (uint_t) strtoul (m_p, &end, radix);

	if (end == m_p)
	{
		err::setError (err::SystemErrorCode_InvalidAddress);
		return false;
	}

	m_p = end;
	return true;
}

bool
SockAddrParser::tryInt (int radix)
{
	skipWhiteSpace ();

	const char* p = m_p;

	if (radix == 16)
	{
		while (p < m_end && isxdigit (*p))
			p++;
	}
	else
	{
		while (p < m_end && isdigit (*p))
			p++;
	}

	if (m_p == p)
		return false;

	m_p = p;
	return true;
}

bool
SockAddrParser::expectChar (char c)
{
	bool result = tryChar (c);

	if (!result)
	{
		err::setError (err::SystemErrorCode_InvalidAddress);
		return false;
	}

	return true;
}

bool
SockAddrParser::tryChar (char c)
{
	skipWhiteSpace ();

	if (m_p >= m_end || *m_p != c)
		return false;

	m_p++;
	return true;
}

//.............................................................................

} // namespace io
} // namespace axl
<commit_msg>[axl] io::parseSocketAddress with empty string now yields zero'ed ip4<commit_after>#include "pch.h"
#include "axl_io_SockAddrParser.h"
#include "axl_err_Error.h"

namespace axl {
namespace io {

//.............................................................................

void
SockAddrParser::initialize (
	const char* p,
	size_t length
	)
{
	if (length == -1)
		length = p ? strlen (p) : 0;

	m_p = p;
	m_end = p + length;
}

bool
SockAddrParser::parse (in_addr* addr)
{
	bool result;

	uchar_t* ip = (uchar_t*) addr;
	for (size_t i = 0;; i++)
	{
		uint_t octet;
		result = parseInt (&octet, 10);
		if (!result)
			return false;

		ip [i] = octet;

		if (i >= 3)
			break;

		result = expectChar ('.');
		if (!result)
			return false;
	}

	return true;
}

bool
SockAddrParser::parse (sockaddr_in* addr)
{
	bool result;

	memset (addr, 0, sizeof (sockaddr_in));
	addr->sin_family = AF_INET;

	const char* p0 = m_p;
	result = parse (&addr->sin_addr);
	if (!result) // rollback and try single port
	{
		m_p = p0;

		uint_t port;
		result = parseInt (&port, 10);
		if (!result)
			return false;

		skipWhiteSpace ();
		if (m_p != m_end)
		{
			err::setError (err::SystemErrorCode_InvalidAddress);
			return false;
		}

		*(uint32_t*) &addr->sin_addr = 0;
		addr->sin_port = rtl::swapByteOrder16 ((uint16_t) port);
		return true;
	}

	result = tryChar (':');
	if (result)
	{
		uint_t port;
		result = parseInt (&port, 10);
		if (!result)
			return false;

		addr->sin_port = rtl::swapByteOrder16 ((uint16_t) port);
	}

	return true;
}

bool
SockAddrParser::parse (in6_addr* addr)
{
	bool result;

	uint16_t* ip = (uint16_t*) addr;

	size_t zeroRunIdx = -1;
	bool isIp4 = false;
	uchar_t ip4 [4];

	tryChar (':');

	size_t i = 0;
	while (i < 8)
	{
		result = tryChar (':');
		if (result)
			zeroRunIdx = i;

		skipWhiteSpace ();

		if (m_p >= m_end || !isxdigit (*m_p))
			break;

		uint_t word;
		result = parseInt (&word, 16);
		if (!result)
			return false;

		result = tryChar (':');
		if (!result)
		{
			result = tryChar ('.');
			if (result)
			{
				if (i > 6)
				{
					err::setError (err::SystemErrorCode_InvalidAddress);
					return false;
				}

				ip4 [0] = (uchar_t)
					((word & 0x0f) +
					((word & 0xf0) >> 4) * 10 +
					((word & 0xf00) >> 8) * 100);

				isIp4 = true;
				break;
			}
		}

		ip [i] = rtl::swapByteOrder16 ((uint16_t) word);
		i++;

		if (!result)
			break;
	}

	if (isIp4)
	{
		for (size_t j = 1;; j++)
		{
			uint_t octet;
			result = parseInt (&octet, 10);
			if (!result)
				return false;

			ip4 [j] = (uchar_t) octet;

			if (j >= 3)
				break;

			result = expectChar ('.');
			if (!result)
				return false;
		}

		ASSERT (i <= 6);
		ip [i] = ip4 [0] + (ip4 [1] << 8);
		ip [i + 1] = ip4 [2] + (ip4 [3] << 8);
		i += 2;
	}

	if (zeroRunIdx != -1)
	{
		ASSERT (i <= 8 && zeroRunIdx <= i);

		size_t zeroRunLength = 8 - i;

		if (zeroRunIdx < i)
		{
			memmove (&ip [zeroRunIdx + zeroRunLength], &ip [zeroRunIdx], (i - zeroRunIdx) * sizeof (uint16_t));
			memset (&ip [zeroRunIdx], 0, zeroRunLength * sizeof (uint16_t));
		}
	}
	else if (i != 8)
	{
		err::setError (err::SystemErrorCode_InvalidAddress);
		return false;
	}

	return true;
}

bool
SockAddrParser::parse (sockaddr_in6* addr)
{
	bool result;

	memset (addr, 0, sizeof (sockaddr_in6));
	addr->sin6_family = AF_INET6;

	bool hasBrackets = tryChar ('[');

	result = parse (&addr->sin6_addr);
	if (!result)
		return false;

	result = tryChar ('%');
	if (result)
	{
		uint_t scope;
		result = parseInt (&scope, 10);
		if (!result)
			return false;

		addr->sin6_scope_id = scope;
	}

	if (hasBrackets)
	{
		result = expectChar (']');
		if (!result)
			return false;

		result = tryChar (':');
		if (result)
		{
			uint_t port;
			result = parseInt (&port, 10);
			if (!result)
				return false;

			addr->sin6_port = rtl::swapByteOrder16 ((uint16_t) port);
		}
	}

	return true;
}

bool
SockAddrParser::parse (
	sockaddr* addr,
	size_t size
	)
{
	skipWhiteSpace ();
	if (m_p == m_end)
	{
		memset (addr, 0, sizeof (sockaddr_in));
		((sockaddr_in*) addr)->sin_family = AF_INET;
		return true;
	}

	SockAddrParser clone = *this;

	if (trySockAddr_ip4 ())
	{
		if (size < sizeof (sockaddr_in))
		{
			err::setError (err::SystemErrorCode_BufferTooSmall);
			return false;
		}

		*this = clone;
		return parse ((sockaddr_in*) addr);
	}

	*this = clone;

	if (trySockAddr_ip6 ())
	{
		if (size < sizeof (sockaddr_in6))
		{
			err::setError (err::SystemErrorCode_BufferTooSmall);
			return false;
		}

		*this = clone;
		return parse ((sockaddr_in6*) addr);
	}

	err::setError (err::SystemErrorCode_InvalidAddress);
	return false;
}

bool
SockAddrParser::tryAddr_ip4 ()
{
	bool result;

	for (size_t i = 0;; i++)
	{
		result = tryInt (10);
		if (!result)
			return false;

		if (i >= 3)
			break;

		result = tryChar ('.');
		if (!result)
			return false;
	}

	return true;
}

bool
SockAddrParser::tryAddr_ip6 ()
{
	bool result;

	bool hasZeroRun = false;
	bool isIp4 = false;

	tryChar (':');

	size_t i = 0;
	while (i < 8)
	{
		result = tryChar (':');
		if (result)
			hasZeroRun = true;

		skipWhiteSpace ();

		if (m_p >= m_end || !isxdigit (*m_p))
			break;

		result = tryInt (16);
		if (!result)
			return false;

		result = tryChar (':');
		if (!result)
		{
			result = tryChar ('.');
			if (result)
			{
				if (i > 6)
					return false;

				isIp4 = true;
				break;
			}
		}

		i++;

		if (!result)
			break;
	}

	if (isIp4)
	{
		for (size_t j = 1;; j++)
		{
			result = tryInt (10);
			if (!result)
				return false;

			if (j >= 3)
				break;

			result = tryChar ('.');
			if (!result)
				return false;
		}

		i += 2;
	}

	if (!hasZeroRun && i != 8)
		return false;

	return true;
}

bool
SockAddrParser::trySockAddr_ip4 ()
{
	const char* p0 = m_p;

	bool result = tryAddr_ip4 ();
	if (!result) // rollback and try single port
	{
		m_p = p0;
		result = tryInt (10);
		if (!result)
			return false;

		skipWhiteSpace ();
		return m_p == m_end;
	}

	result = tryChar (':');
	if (result)
	{
		result = tryInt (10);
		if (!result)
			return false;
	}

	return true;
}

bool
SockAddrParser::trySockAddr_ip6 ()
{
	bool result;
	bool hasBrackets = tryChar ('[');

	result = tryAddr_ip6 ();
	if (!result)
		return false;

	result = tryChar ('%');
	if (result)
	{
		result = tryInt (10);
		if (!result)
			return false;
	}

	if (hasBrackets)
	{
		result = tryChar (']');
		if (!result)
			return false;

		result = tryChar (':');
		if (result)
		{
			result = tryInt (10);
			if (!result)
				return false;
		}
	}

	return true;
}

void
SockAddrParser::skipWhiteSpace ()
{
	while (m_p < m_end && isspace (*m_p))
		m_p++;
}

bool
SockAddrParser::parseInt (
	uint_t* p,
	int radix
	)
{
	skipWhiteSpace ();

	char* end;
	*p = (uint_t) strtoul (m_p, &end, radix);

	if (end == m_p)
	{
		err::setError (err::SystemErrorCode_InvalidAddress);
		return false;
	}

	m_p = end;
	return true;
}

bool
SockAddrParser::tryInt (int radix)
{
	skipWhiteSpace ();

	const char* p = m_p;

	if (radix == 16)
	{
		while (p < m_end && isxdigit (*p))
			p++;
	}
	else
	{
		while (p < m_end && isdigit (*p))
			p++;
	}

	if (m_p == p)
		return false;

	m_p = p;
	return true;
}

bool
SockAddrParser::expectChar (char c)
{
	bool result = tryChar (c);

	if (!result)
	{
		err::setError (err::SystemErrorCode_InvalidAddress);
		return false;
	}

	return true;
}

bool
SockAddrParser::tryChar (char c)
{
	skipWhiteSpace ();

	if (m_p >= m_end || *m_p != c)
		return false;

	m_p++;
	return true;
}

//.............................................................................

} // namespace io
} // namespace axl
<|endoftext|>


<commit_before>/*
 * Copyright 2011, Blender Foundation.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "mesh.h"
#include "object.h"
#include "scene.h"

#include "blender_sync.h"
#include "blender_util.h"

#include "subd_mesh.h"
#include "subd_patch.h"
#include "subd_split.h"

#include "util_foreach.h"

CCL_NAMESPACE_BEGIN

/* Find/Add */

static bool mesh_need_attribute(Scene *scene, Mesh *mesh, Attribute::Standard std)
{
	if(std == Attribute::STD_NONE)
		return false;

	foreach(uint shader, mesh->used_shaders)
		if(scene->shaders[shader]->attributes.find(std))
			return true;

	return false;
}

static bool mesh_need_attribute(Scene *scene, Mesh *mesh, ustring name)
{
	if(name == ustring())
		return false;

	foreach(uint shader, mesh->used_shaders)
		if(scene->shaders[shader]->attributes.find(name))
			return true;

	return false;
}

static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<uint>& used_shaders)
{
	/* create vertices */
	BL::Mesh::vertices_iterator v;

	for(v = b_mesh.vertices.begin(); v != b_mesh.vertices.end(); ++v)
		mesh->verts.push_back(get_float3(v->co()));

	/* create faces */
	BL::Mesh::faces_iterator f;
	vector<int> nverts;

	for(f = b_mesh.faces.begin(); f != b_mesh.faces.end(); ++f) {
		int4 vi = get_int4(f->vertices_raw());
		int n= (vi[3] == 0)? 3: 4;
		int shader = used_shaders[f->material_index()];
		bool smooth = f->use_smooth();

		mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);

		if(n == 4)
			mesh->add_triangle(vi[0], vi[2], vi[3], shader, smooth);

		nverts.push_back(n);
	}

	/* create generated coordinates. todo: we should actually get the orco
	   coordinates from modifiers, for now we use texspace loc/size which
	   is available in the api. */
	if(mesh_need_attribute(scene, mesh, Attribute::STD_GENERATED)) {
		Attribute *attr = mesh->attributes.add(Attribute::STD_GENERATED);
		float3 loc = get_float3(b_mesh.texspace_location());
		float3 size = get_float3(b_mesh.texspace_size());

		if(size.x != 0.0f) size.x = 0.5f/size.x;
		if(size.y != 0.0f) size.y = 0.5f/size.y;
		if(size.z != 0.0f) size.z = 0.5f/size.z;

		loc = loc*size - make_float3(0.5f, 0.5f, 0.5f);

		float3 *fdata = attr->data_float3();
		BL::Mesh::vertices_iterator v;
		size_t i = 0;

		for(v = b_mesh.vertices.begin(); v != b_mesh.vertices.end(); ++v)
			fdata[i++] = get_float3(v->co())*size - loc;
	}

	/* create vertex color attributes */
	{
		BL::Mesh::vertex_colors_iterator l;

		for(l = b_mesh.vertex_colors.begin(); l != b_mesh.vertex_colors.end(); ++l) {
			if(!mesh_need_attribute(scene, mesh, ustring(l->name())))
				continue;

			Attribute *attr = mesh->attributes.add(
				ustring(l->name()), TypeDesc::TypeColor, Attribute::CORNER);

			BL::MeshColorLayer::data_iterator c;
			float3 *fdata = attr->data_float3();
			size_t i = 0;

			for(c = l->data.begin(); c != l->data.end(); ++c, ++i) {
				fdata[0] =  get_float3(c->color1());
				fdata[1] =  get_float3(c->color2());
				fdata[2] =  get_float3(c->color3());
				fdata += 3;

				if(nverts[i] == 4) {
					fdata[0] =  get_float3(c->color1());
					fdata[1] =  get_float3(c->color3());
					fdata[2] =  get_float3(c->color4());
					fdata += 3;
				}
			}
		}
	}

	/* create uv layer attributes */
	{
		BL::Mesh::uv_textures_iterator l;

		for(l = b_mesh.uv_textures.begin(); l != b_mesh.uv_textures.end(); ++l) {
			Attribute::Standard std = (l->active_render())? Attribute::STD_UV: Attribute::STD_NONE;
			ustring name = ustring(l->name());

			if(!(mesh_need_attribute(scene, mesh, name) || mesh_need_attribute(scene, mesh, std)))
				continue;

			Attribute *attr;

			if(l->active_render())
				attr = mesh->attributes.add(std, name);
			else
				attr = mesh->attributes.add(name, TypeDesc::TypePoint, Attribute::CORNER);

			BL::MeshTextureFaceLayer::data_iterator t;
			float3 *fdata = attr->data_float3();
			size_t i = 0;

			for(t = l->data.begin(); t != l->data.end(); ++t, ++i) {
				fdata[0] =  get_float3(t->uv1());
				fdata[1] =  get_float3(t->uv2());
				fdata[2] =  get_float3(t->uv3());
				fdata += 3;

				if(nverts[i] == 4) {
					fdata[0] =  get_float3(t->uv1());
					fdata[1] =  get_float3(t->uv3());
					fdata[2] =  get_float3(t->uv4());
					fdata += 3;
				}
			}
		}
	}
}

static void create_subd_mesh(Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, const vector<uint>& used_shaders)
{
	/* create subd mesh */
	SubdMesh sdmesh;

	/* create vertices */
	BL::Mesh::vertices_iterator v;

	for(v = b_mesh.vertices.begin(); v != b_mesh.vertices.end(); ++v)
		sdmesh.add_vert(get_float3(v->co()));

	/* create faces */
	BL::Mesh::faces_iterator f;

	for(f = b_mesh.faces.begin(); f != b_mesh.faces.end(); ++f) {
		int4 vi = get_int4(f->vertices_raw());
		int n= (vi[3] == 0)? 3: 4;
		//int shader = used_shaders[f->material_index()];

		if(n == 4)
			sdmesh.add_face(vi[0], vi[1], vi[2], vi[3]);
		/*else
			sdmesh.add_face(vi[0], vi[1], vi[2]);*/
	}

	/* finalize subd mesh */
	sdmesh.link_boundary();

	/* subdivide */
	DiagSplit dsplit;
	dsplit.camera = NULL;
	dsplit.dicing_rate = RNA_float_get(cmesh, "dicing_rate");

	sdmesh.tesselate(&dsplit, false, mesh, used_shaders[0], true);
}

/* Sync */

Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated)
{
	/* test if we can instance or if the object is modified */
	BL::ID b_ob_data = b_ob.data();
	BL::ID key = (object_is_modified(b_ob))? b_ob: b_ob_data;

	/* find shader indices */
	vector<uint> used_shaders;

	BL::Object::material_slots_iterator slot;
	for(slot = b_ob.material_slots.begin(); slot != b_ob.material_slots.end(); ++slot)
		find_shader(slot->material(), used_shaders);

	if(used_shaders.size() == 0)
		used_shaders.push_back(scene->default_surface);

	/* test if we need to sync */
	Mesh *mesh;

	if(!mesh_map.sync(&mesh, key)) {
		/* if transform was applied to mesh, need full update */
		if(object_updated && mesh->transform_applied);
		/* test if shaders changed, these can be object level so mesh
		   does not get tagged for recalc */
		else if(mesh->used_shaders != used_shaders);
		else {
			/* even if not tagged for recalc, we may need to sync anyway
			 * because the shader needs different mesh attributes */
			bool attribute_recalc = false;

			foreach(uint shader, mesh->used_shaders)
				if(scene->shaders[shader]->need_update_attributes)
					attribute_recalc = true;

			if(!attribute_recalc)
				return mesh;
		}
	}

	/* ensure we only sync instanced meshes once */
	if(mesh_synced.find(mesh) != mesh_synced.end())
		return mesh;

	mesh_synced.insert(mesh);

	/* create derived mesh */
	BL::Mesh b_mesh = object_to_mesh(b_ob, b_scene, true, !preview);
	/* todo: this will crash on non-mesh types! */
	PointerRNA cmesh = RNA_pointer_get(&b_ob_data.ptr, "cycles");

	vector<Mesh::Triangle> oldtriangle = mesh->triangles;

	mesh->clear();
	mesh->used_shaders = used_shaders;
	mesh->name = ustring(b_ob_data.name());

	if(cmesh.data && RNA_boolean_get(&cmesh, "use_subdivision"))
		create_subd_mesh(mesh, b_mesh, &cmesh, used_shaders);
	else
		create_mesh(scene, mesh, b_mesh, used_shaders);

	/* free derived mesh */
	object_remove_mesh(b_data, b_mesh);

	/* displacement method */
	if(cmesh.data) {
		int method = RNA_enum_get(&cmesh, "displacement_method");

		if(method == 0)
			mesh->displacement_method = Mesh::DISPLACE_BUMP;
		else if(method == 1)
			mesh->displacement_method = Mesh::DISPLACE_TRUE;
		else
			mesh->displacement_method = Mesh::DISPLACE_BOTH;
	}

	/* tag update */
	bool rebuild = false;

	if(oldtriangle.size() != mesh->triangles.size())
		rebuild = true;
	else if(memcmp(&oldtriangle[0], &mesh->triangles[0], sizeof(Mesh::Triangle)*oldtriangle.size()) != 0)
		rebuild = true;

	mesh->tag_update(scene, rebuild);

	return mesh;
}

CCL_NAMESPACE_END

<commit_msg>Cycles: fix crash syncing curve/text object with no verts/faces.<commit_after>/*
 * Copyright 2011, Blender Foundation.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "mesh.h"
#include "object.h"
#include "scene.h"

#include "blender_sync.h"
#include "blender_util.h"

#include "subd_mesh.h"
#include "subd_patch.h"
#include "subd_split.h"

#include "util_foreach.h"

CCL_NAMESPACE_BEGIN

/* Find/Add */

static bool mesh_need_attribute(Scene *scene, Mesh *mesh, Attribute::Standard std)
{
	if(std == Attribute::STD_NONE)
		return false;

	foreach(uint shader, mesh->used_shaders)
		if(scene->shaders[shader]->attributes.find(std))
			return true;

	return false;
}

static bool mesh_need_attribute(Scene *scene, Mesh *mesh, ustring name)
{
	if(name == ustring())
		return false;

	foreach(uint shader, mesh->used_shaders)
		if(scene->shaders[shader]->attributes.find(name))
			return true;

	return false;
}

static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<uint>& used_shaders)
{
	/* create vertices */
	BL::Mesh::vertices_iterator v;

	for(v = b_mesh.vertices.begin(); v != b_mesh.vertices.end(); ++v)
		mesh->verts.push_back(get_float3(v->co()));

	/* create faces */
	BL::Mesh::faces_iterator f;
	vector<int> nverts;

	for(f = b_mesh.faces.begin(); f != b_mesh.faces.end(); ++f) {
		int4 vi = get_int4(f->vertices_raw());
		int n= (vi[3] == 0)? 3: 4;
		int shader = used_shaders[f->material_index()];
		bool smooth = f->use_smooth();

		mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);

		if(n == 4)
			mesh->add_triangle(vi[0], vi[2], vi[3], shader, smooth);

		nverts.push_back(n);
	}

	/* create generated coordinates. todo: we should actually get the orco
	   coordinates from modifiers, for now we use texspace loc/size which
	   is available in the api. */
	if(mesh_need_attribute(scene, mesh, Attribute::STD_GENERATED)) {
		Attribute *attr = mesh->attributes.add(Attribute::STD_GENERATED);
		float3 loc = get_float3(b_mesh.texspace_location());
		float3 size = get_float3(b_mesh.texspace_size());

		if(size.x != 0.0f) size.x = 0.5f/size.x;
		if(size.y != 0.0f) size.y = 0.5f/size.y;
		if(size.z != 0.0f) size.z = 0.5f/size.z;

		loc = loc*size - make_float3(0.5f, 0.5f, 0.5f);

		float3 *fdata = attr->data_float3();
		BL::Mesh::vertices_iterator v;
		size_t i = 0;

		for(v = b_mesh.vertices.begin(); v != b_mesh.vertices.end(); ++v)
			fdata[i++] = get_float3(v->co())*size - loc;
	}

	/* create vertex color attributes */
	{
		BL::Mesh::vertex_colors_iterator l;

		for(l = b_mesh.vertex_colors.begin(); l != b_mesh.vertex_colors.end(); ++l) {
			if(!mesh_need_attribute(scene, mesh, ustring(l->name())))
				continue;

			Attribute *attr = mesh->attributes.add(
				ustring(l->name()), TypeDesc::TypeColor, Attribute::CORNER);

			BL::MeshColorLayer::data_iterator c;
			float3 *fdata = attr->data_float3();
			size_t i = 0;

			for(c = l->data.begin(); c != l->data.end(); ++c, ++i) {
				fdata[0] =  get_float3(c->color1());
				fdata[1] =  get_float3(c->color2());
				fdata[2] =  get_float3(c->color3());
				fdata += 3;

				if(nverts[i] == 4) {
					fdata[0] =  get_float3(c->color1());
					fdata[1] =  get_float3(c->color3());
					fdata[2] =  get_float3(c->color4());
					fdata += 3;
				}
			}
		}
	}

	/* create uv layer attributes */
	{
		BL::Mesh::uv_textures_iterator l;

		for(l = b_mesh.uv_textures.begin(); l != b_mesh.uv_textures.end(); ++l) {
			Attribute::Standard std = (l->active_render())? Attribute::STD_UV: Attribute::STD_NONE;
			ustring name = ustring(l->name());

			if(!(mesh_need_attribute(scene, mesh, name) || mesh_need_attribute(scene, mesh, std)))
				continue;

			Attribute *attr;

			if(l->active_render())
				attr = mesh->attributes.add(std, name);
			else
				attr = mesh->attributes.add(name, TypeDesc::TypePoint, Attribute::CORNER);

			BL::MeshTextureFaceLayer::data_iterator t;
			float3 *fdata = attr->data_float3();
			size_t i = 0;

			for(t = l->data.begin(); t != l->data.end(); ++t, ++i) {
				fdata[0] =  get_float3(t->uv1());
				fdata[1] =  get_float3(t->uv2());
				fdata[2] =  get_float3(t->uv3());
				fdata += 3;

				if(nverts[i] == 4) {
					fdata[0] =  get_float3(t->uv1());
					fdata[1] =  get_float3(t->uv3());
					fdata[2] =  get_float3(t->uv4());
					fdata += 3;
				}
			}
		}
	}
}

static void create_subd_mesh(Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, const vector<uint>& used_shaders)
{
	/* create subd mesh */
	SubdMesh sdmesh;

	/* create vertices */
	BL::Mesh::vertices_iterator v;

	for(v = b_mesh.vertices.begin(); v != b_mesh.vertices.end(); ++v)
		sdmesh.add_vert(get_float3(v->co()));

	/* create faces */
	BL::Mesh::faces_iterator f;

	for(f = b_mesh.faces.begin(); f != b_mesh.faces.end(); ++f) {
		int4 vi = get_int4(f->vertices_raw());
		int n= (vi[3] == 0)? 3: 4;
		//int shader = used_shaders[f->material_index()];

		if(n == 4)
			sdmesh.add_face(vi[0], vi[1], vi[2], vi[3]);
		/*else
			sdmesh.add_face(vi[0], vi[1], vi[2]);*/
	}

	/* finalize subd mesh */
	sdmesh.link_boundary();

	/* subdivide */
	DiagSplit dsplit;
	dsplit.camera = NULL;
	dsplit.dicing_rate = RNA_float_get(cmesh, "dicing_rate");

	sdmesh.tesselate(&dsplit, false, mesh, used_shaders[0], true);
}

/* Sync */

Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated)
{
	/* test if we can instance or if the object is modified */
	BL::ID b_ob_data = b_ob.data();
	BL::ID key = (object_is_modified(b_ob))? b_ob: b_ob_data;

	/* find shader indices */
	vector<uint> used_shaders;

	BL::Object::material_slots_iterator slot;
	for(slot = b_ob.material_slots.begin(); slot != b_ob.material_slots.end(); ++slot)
		find_shader(slot->material(), used_shaders);

	if(used_shaders.size() == 0)
		used_shaders.push_back(scene->default_surface);

	/* test if we need to sync */
	Mesh *mesh;

	if(!mesh_map.sync(&mesh, key)) {
		/* if transform was applied to mesh, need full update */
		if(object_updated && mesh->transform_applied);
		/* test if shaders changed, these can be object level so mesh
		   does not get tagged for recalc */
		else if(mesh->used_shaders != used_shaders);
		else {
			/* even if not tagged for recalc, we may need to sync anyway
			 * because the shader needs different mesh attributes */
			bool attribute_recalc = false;

			foreach(uint shader, mesh->used_shaders)
				if(scene->shaders[shader]->need_update_attributes)
					attribute_recalc = true;

			if(!attribute_recalc)
				return mesh;
		}
	}

	/* ensure we only sync instanced meshes once */
	if(mesh_synced.find(mesh) != mesh_synced.end())
		return mesh;

	mesh_synced.insert(mesh);

	/* create derived mesh */
	BL::Mesh b_mesh = object_to_mesh(b_ob, b_scene, true, !preview);
	PointerRNA cmesh = RNA_pointer_get(&b_ob_data.ptr, "cycles");

	vector<Mesh::Triangle> oldtriangle = mesh->triangles;

	mesh->clear();
	mesh->used_shaders = used_shaders;
	mesh->name = ustring(b_ob_data.name());

	if(b_mesh) {
		if(cmesh.data && RNA_boolean_get(&cmesh, "use_subdivision"))
			create_subd_mesh(mesh, b_mesh, &cmesh, used_shaders);
		else
			create_mesh(scene, mesh, b_mesh, used_shaders);

		/* free derived mesh */
		object_remove_mesh(b_data, b_mesh);
	}

	/* displacement method */
	if(cmesh.data) {
		int method = RNA_enum_get(&cmesh, "displacement_method");

		if(method == 0)
			mesh->displacement_method = Mesh::DISPLACE_BUMP;
		else if(method == 1)
			mesh->displacement_method = Mesh::DISPLACE_TRUE;
		else
			mesh->displacement_method = Mesh::DISPLACE_BOTH;
	}

	/* tag update */
	bool rebuild = false;

	if(oldtriangle.size() != mesh->triangles.size())
		rebuild = true;
	else if(memcmp(&oldtriangle[0], &mesh->triangles[0], sizeof(Mesh::Triangle)*oldtriangle.size()) != 0)
		rebuild = true;

	mesh->tag_update(scene, rebuild);

	return mesh;
}

CCL_NAMESPACE_END

<|endoftext|>


<commit_before>#include <LightGBM/dataset.h>

#include <LightGBM/feature.h>

#include <omp.h>

#include <cstdio>
#include <unordered_map>
#include <limits>
#include <vector>
#include <utility>
#include <string>
#include <sstream>

namespace LightGBM {

const char* Dataset::binary_file_token = "______LightGBM_Binary_File_Token______\n";

Dataset::Dataset() {
  num_class_ = 1;
  num_data_ = 0;
}

Dataset::Dataset(data_size_t num_data, int num_class) {
  num_class_ = num_class;
  num_data_ = num_data;
  metadata_.Init(num_data_, num_class_, -1, -1);
}

Dataset::~Dataset() {

}

void Dataset::FinishLoad() {
#pragma omp parallel for schedule(guided)
  for (int i = 0; i < num_features_; ++i) {
    features_[i]->FinishLoad();
  }
}

void Dataset::CopyFeatureMapperFrom(const Dataset* dataset, bool is_enable_sparse) {
  features_.clear();
  // copy feature bin mapper data
  for (const auto& feature : dataset->features_) {
    features_.emplace_back(std::unique_ptr<Feature>(
      new Feature(feature->feature_index(),
        new BinMapper(*feature->bin_mapper()),
        num_data_,
        is_enable_sparse)
      ));
  }
  features_.shrink_to_fit();
  num_class_ = dataset->num_class_;
  used_feature_map_ = dataset->used_feature_map_;
  num_features_ = static_cast<int>(features_.size());
  num_total_features_ = dataset->num_total_features_;
  feature_names_ = dataset->feature_names_;
  label_idx_ = dataset->label_idx_;
}

Dataset* Dataset::Subset(const data_size_t* used_indices, data_size_t num_used_indices, bool is_enable_sparse) const {
  auto ret = std::unique_ptr<Dataset>(new Dataset(num_used_indices, num_class_));
  ret->CopyFeatureMapperFrom(this, is_enable_sparse);
#pragma omp parallel for schedule(guided)
  for (int fidx = 0; fidx < num_features_; ++fidx) {
    auto iterator = features_[fidx]->bin_data()->GetIterator(0);
    for (data_size_t i = 0; i < num_used_indices; ++i) {
      ret->features_[fidx]->PushBin(0, i, iterator->Get(used_indices[i]));
    }
  }
  ret->metadata_.Init(metadata_, used_indices, num_used_indices);
  return ret.release();
}

bool Dataset::SetFloatField(const char* field_name, const float* field_data, data_size_t num_element) {
  std::string name(field_name);
  name = Common::Trim(name);
  if (name == std::string("label") || name == std::string("target")) {
    metadata_.SetLabel(field_data, num_element);
  } else if (name == std::string("weight") || name == std::string("weights")) {
    metadata_.SetWeights(field_data, num_element);
  } else if (name == std::string("init_score")) {
    metadata_.SetInitScore(field_data, num_element);
  } else {
    return false;
  }
  return true;
}

bool Dataset::SetIntField(const char* field_name, const int* field_data, data_size_t num_element) {
  std::string name(field_name);
  name = Common::Trim(name);
  if (name == std::string("query") || name == std::string("group")) {
    metadata_.SetQuery(field_data, num_element);
  } else if (name == std::string("query_id") || name == std::string("group_id")) {
    metadata_.SetQueryId(field_data, num_element);
  } else {
    return false;
  }
  return true;
}

bool Dataset::GetFloatField(const char* field_name, int64_t* out_len, const float** out_ptr) {
  std::string name(field_name);
  name = Common::Trim(name);
  if (name == std::string("label") || name == std::string("target")) {
    *out_ptr = metadata_.label();
    *out_len = num_data_;
  } else if (name == std::string("weight") || name == std::string("weights")) {
    *out_ptr = metadata_.weights();
    *out_len = num_data_;
  } else if (name == std::string("init_score")) {
    *out_ptr = metadata_.init_score();
    *out_len = num_data_;
  } else {
    return false;
  }
  return true;
}

bool Dataset::GetIntField(const char* field_name, int64_t* out_len, const int** out_ptr) {
  std::string name(field_name);
  name = Common::Trim(name);
  if (name == std::string("query") || name == std::string("group")) {
    *out_ptr = metadata_.query_boundaries();
    *out_len = metadata_.num_queries();
  } else {
    return false;
  }
  return true;
}

void Dataset::SaveBinaryFile(const char* bin_filename) {
  if (bin_filename != nullptr
      && std::string(bin_filename) == std::string(data_filename_)) {
    Log::Warning("Bianry file %s already existed", bin_filename);
    return;
  }
  // if not pass a filename, just append ".bin" of original file
  std::string bin_filename_str(data_filename_);
  if (bin_filename == nullptr || bin_filename[0] == '\0') {
    bin_filename_str.append(".bin");
    bin_filename = bin_filename_str.c_str();
  }
  bool is_file_existed = false;
  FILE* file;
#ifdef _MSC_VER
  fopen_s(&file, bin_filename, "rb");
#else
  file = fopen(bin_filename, "rb");
#endif

  if (file != NULL) {
    is_file_existed = true;
    Log::Warning("File %s existed, cannot save binary to it", bin_filename);
    fclose(file);
  }

  if (!is_file_existed) {
#ifdef _MSC_VER
    fopen_s(&file, bin_filename, "wb");
#else
    file = fopen(bin_filename, "wb");
#endif
    if (file == NULL) {
      Log::Fatal("Cannot write binary data to %s ", bin_filename);
    }
    Log::Info("Saving data to binary file %s", bin_filename);
    size_t size_of_token = std::strlen(binary_file_token);
    fwrite(binary_file_token, sizeof(char), size_of_token, file);
    // get size of header
    size_t size_of_header = sizeof(num_data_) + sizeof(num_class_) + sizeof(num_features_) + sizeof(num_total_features_)
      + sizeof(size_t) + sizeof(int) * used_feature_map_.size();
    // size of feature names
    for (int i = 0; i < num_total_features_; ++i) {
      size_of_header += feature_names_[i].size() + sizeof(int);
    }
    fwrite(&size_of_header, sizeof(size_of_header), 1, file);
    // write header
    fwrite(&num_data_, sizeof(num_data_), 1, file);
    fwrite(&num_class_, sizeof(num_class_), 1, file);
    fwrite(&num_features_, sizeof(num_features_), 1, file);
    fwrite(&num_total_features_, sizeof(num_features_), 1, file);
    size_t num_used_feature_map = used_feature_map_.size();
    fwrite(&num_used_feature_map, sizeof(num_used_feature_map), 1, file);
    fwrite(used_feature_map_.data(), sizeof(int), num_used_feature_map, file);

    // write feature names
    for (int i = 0; i < num_total_features_; ++i) {
      int str_len = static_cast<int>(feature_names_[i].size());
      fwrite(&str_len, sizeof(int), 1, file);
      const char* c_str = feature_names_[i].c_str();
      fwrite(c_str, sizeof(char), str_len, file);
    }

    // get size of meta data
    size_t size_of_metadata = metadata_.SizesInByte();
    fwrite(&size_of_metadata, sizeof(size_of_metadata), 1, file);
    // write meta data
    metadata_.SaveBinaryToFile(file);

    // write feature data
    for (int i = 0; i < num_features_; ++i) {
      // get size of feature
      size_t size_of_feature = features_[i]->SizesInByte();
      fwrite(&size_of_feature, sizeof(size_of_feature), 1, file);
      // write feature
      features_[i]->SaveBinaryToFile(file);
    }
    fclose(file);
  }
}

}  // namespace LightGBM
<commit_msg>bug fix in get_group<commit_after>#include <LightGBM/dataset.h>

#include <LightGBM/feature.h>

#include <omp.h>

#include <cstdio>
#include <unordered_map>
#include <limits>
#include <vector>
#include <utility>
#include <string>
#include <sstream>

namespace LightGBM {

const char* Dataset::binary_file_token = "______LightGBM_Binary_File_Token______\n";

Dataset::Dataset() {
  num_class_ = 1;
  num_data_ = 0;
}

Dataset::Dataset(data_size_t num_data, int num_class) {
  num_class_ = num_class;
  num_data_ = num_data;
  metadata_.Init(num_data_, num_class_, -1, -1);
}

Dataset::~Dataset() {

}

void Dataset::FinishLoad() {
#pragma omp parallel for schedule(guided)
  for (int i = 0; i < num_features_; ++i) {
    features_[i]->FinishLoad();
  }
}

void Dataset::CopyFeatureMapperFrom(const Dataset* dataset, bool is_enable_sparse) {
  features_.clear();
  // copy feature bin mapper data
  for (const auto& feature : dataset->features_) {
    features_.emplace_back(std::unique_ptr<Feature>(
      new Feature(feature->feature_index(),
        new BinMapper(*feature->bin_mapper()),
        num_data_,
        is_enable_sparse)
      ));
  }
  features_.shrink_to_fit();
  num_class_ = dataset->num_class_;
  used_feature_map_ = dataset->used_feature_map_;
  num_features_ = static_cast<int>(features_.size());
  num_total_features_ = dataset->num_total_features_;
  feature_names_ = dataset->feature_names_;
  label_idx_ = dataset->label_idx_;
}

Dataset* Dataset::Subset(const data_size_t* used_indices, data_size_t num_used_indices, bool is_enable_sparse) const {
  auto ret = std::unique_ptr<Dataset>(new Dataset(num_used_indices, num_class_));
  ret->CopyFeatureMapperFrom(this, is_enable_sparse);
#pragma omp parallel for schedule(guided)
  for (int fidx = 0; fidx < num_features_; ++fidx) {
    auto iterator = features_[fidx]->bin_data()->GetIterator(0);
    for (data_size_t i = 0; i < num_used_indices; ++i) {
      ret->features_[fidx]->PushBin(0, i, iterator->Get(used_indices[i]));
    }
  }
  ret->metadata_.Init(metadata_, used_indices, num_used_indices);
  return ret.release();
}

bool Dataset::SetFloatField(const char* field_name, const float* field_data, data_size_t num_element) {
  std::string name(field_name);
  name = Common::Trim(name);
  if (name == std::string("label") || name == std::string("target")) {
    metadata_.SetLabel(field_data, num_element);
  } else if (name == std::string("weight") || name == std::string("weights")) {
    metadata_.SetWeights(field_data, num_element);
  } else if (name == std::string("init_score")) {
    metadata_.SetInitScore(field_data, num_element);
  } else {
    return false;
  }
  return true;
}

bool Dataset::SetIntField(const char* field_name, const int* field_data, data_size_t num_element) {
  std::string name(field_name);
  name = Common::Trim(name);
  if (name == std::string("query") || name == std::string("group")) {
    metadata_.SetQuery(field_data, num_element);
  } else if (name == std::string("query_id") || name == std::string("group_id")) {
    metadata_.SetQueryId(field_data, num_element);
  } else {
    return false;
  }
  return true;
}

bool Dataset::GetFloatField(const char* field_name, int64_t* out_len, const float** out_ptr) {
  std::string name(field_name);
  name = Common::Trim(name);
  if (name == std::string("label") || name == std::string("target")) {
    *out_ptr = metadata_.label();
    *out_len = num_data_;
  } else if (name == std::string("weight") || name == std::string("weights")) {
    *out_ptr = metadata_.weights();
    *out_len = num_data_;
  } else if (name == std::string("init_score")) {
    *out_ptr = metadata_.init_score();
    *out_len = num_data_;
  } else {
    return false;
  }
  return true;
}

bool Dataset::GetIntField(const char* field_name, int64_t* out_len, const int** out_ptr) {
  std::string name(field_name);
  name = Common::Trim(name);
  if (name == std::string("query") || name == std::string("group")) {
    *out_ptr = metadata_.query_boundaries();
    *out_len = metadata_.num_queries() + 1;
  } else {
    return false;
  }
  return true;
}

void Dataset::SaveBinaryFile(const char* bin_filename) {
  if (bin_filename != nullptr
      && std::string(bin_filename) == std::string(data_filename_)) {
    Log::Warning("Bianry file %s already existed", bin_filename);
    return;
  }
  // if not pass a filename, just append ".bin" of original file
  std::string bin_filename_str(data_filename_);
  if (bin_filename == nullptr || bin_filename[0] == '\0') {
    bin_filename_str.append(".bin");
    bin_filename = bin_filename_str.c_str();
  }
  bool is_file_existed = false;
  FILE* file;
#ifdef _MSC_VER
  fopen_s(&file, bin_filename, "rb");
#else
  file = fopen(bin_filename, "rb");
#endif

  if (file != NULL) {
    is_file_existed = true;
    Log::Warning("File %s existed, cannot save binary to it", bin_filename);
    fclose(file);
  }

  if (!is_file_existed) {
#ifdef _MSC_VER
    fopen_s(&file, bin_filename, "wb");
#else
    file = fopen(bin_filename, "wb");
#endif
    if (file == NULL) {
      Log::Fatal("Cannot write binary data to %s ", bin_filename);
    }
    Log::Info("Saving data to binary file %s", bin_filename);
    size_t size_of_token = std::strlen(binary_file_token);
    fwrite(binary_file_token, sizeof(char), size_of_token, file);
    // get size of header
    size_t size_of_header = sizeof(num_data_) + sizeof(num_class_) + sizeof(num_features_) + sizeof(num_total_features_)
      + sizeof(size_t) + sizeof(int) * used_feature_map_.size();
    // size of feature names
    for (int i = 0; i < num_total_features_; ++i) {
      size_of_header += feature_names_[i].size() + sizeof(int);
    }
    fwrite(&size_of_header, sizeof(size_of_header), 1, file);
    // write header
    fwrite(&num_data_, sizeof(num_data_), 1, file);
    fwrite(&num_class_, sizeof(num_class_), 1, file);
    fwrite(&num_features_, sizeof(num_features_), 1, file);
    fwrite(&num_total_features_, sizeof(num_features_), 1, file);
    size_t num_used_feature_map = used_feature_map_.size();
    fwrite(&num_used_feature_map, sizeof(num_used_feature_map), 1, file);
    fwrite(used_feature_map_.data(), sizeof(int), num_used_feature_map, file);

    // write feature names
    for (int i = 0; i < num_total_features_; ++i) {
      int str_len = static_cast<int>(feature_names_[i].size());
      fwrite(&str_len, sizeof(int), 1, file);
      const char* c_str = feature_names_[i].c_str();
      fwrite(c_str, sizeof(char), str_len, file);
    }

    // get size of meta data
    size_t size_of_metadata = metadata_.SizesInByte();
    fwrite(&size_of_metadata, sizeof(size_of_metadata), 1, file);
    // write meta data
    metadata_.SaveBinaryToFile(file);

    // write feature data
    for (int i = 0; i < num_features_; ++i) {
      // get size of feature
      size_t size_of_feature = features_[i]->SizesInByte();
      fwrite(&size_of_feature, sizeof(size_of_feature), 1, file);
      // write feature
      features_[i]->SaveBinaryToFile(file);
    }
    fclose(file);
  }
}

}  // namespace LightGBM
<|endoftext|>


<commit_before>/*!
 *  Copyright (c) 2015 by Contributors
 * \file iter_csv.cc
 * \brief define a CSV Reader to read in arrays
 */
#include <mxnet/io.h>
#include <dmlc/base.h>
#include <dmlc/logging.h>
#include <dmlc/parameter.h>
#include <dmlc/data.h>
#include "./iter_prefetcher.h"
#include "./iter_batchloader.h"

namespace mxnet {
namespace io {
// CSV parameters
struct CSVIterParam : public dmlc::Parameter<CSVIterParam> {
  /*! \brief path to data csv file */
  std::string data_csv;
  /*! \brief data shape */
  TShape data_shape;
  /*! \brief path to label csv file */
  std::string label_csv;
  /*! \brief label shape */
  TShape label_shape;
  // declare parameters
  DMLC_DECLARE_PARAMETER(CSVIterParam) {
    DMLC_DECLARE_FIELD(data_csv)
        .describe("The input CSV file or a directory path.");
    DMLC_DECLARE_FIELD(data_shape)
        .describe("The shape of one example.");
    DMLC_DECLARE_FIELD(label_csv).set_default("NULL")
        .describe("The input CSV file or a directory path. "
                  "If NULL, all labels will be returned as 0.");
    index_t shape1[] = {1};
    DMLC_DECLARE_FIELD(label_shape).set_default(TShape(shape1, shape1 + 1))
        .describe("The shape of one label.");
  }
};

class CSVIter: public IIterator<DataInst> {
 public:
  CSVIter() {
    out_.data.resize(2);
  }
  virtual ~CSVIter() {}

  // intialize iterator loads data in
  virtual void Init(const std::vector<std::pair<std::string, std::string> >& kwargs) {
    param_.InitAllowUnknown(kwargs);
    data_parser_.reset(dmlc::Parser<uint32_t>::Create(param_.data_csv.c_str(), 0, 1, "csv"));
    if (param_.label_csv != "NULL") {
      label_parser_.reset(dmlc::Parser<uint32_t>::Create(param_.label_csv.c_str(), 0, 1, "csv"));
    } else {
      dummy_label.set_pad(false);
      dummy_label.Resize(mshadow::Shape1(1));
      dummy_label = 0.0f;
    }
  }

  virtual void BeforeFirst() {
    data_parser_->BeforeFirst();
    if (label_parser_.get() != nullptr) {
      label_parser_->BeforeFirst();
    }
    data_ptr_ = label_ptr_ = 0;
    data_size_ = label_size_ = 0;
    inst_counter_ = 0;
    end_ = false;
  }

  virtual bool Next() {
    if (end_) return false;
    while (data_ptr_ >= data_size_) {
      if (!data_parser_->Next()) {
        end_ = true; return false;
      }
      data_ptr_ = 0;
      data_size_ = data_parser_->Value().size;
    }
    out_.index = inst_counter_++;
    CHECK_LT(data_ptr_, data_size_);
    out_.data[0] = AsTBlob(data_parser_->Value()[data_ptr_++], param_.data_shape);

    if (label_parser_.get() != nullptr) {
      while (label_ptr_ >= label_size_) {
        CHECK(label_parser_->Next())
            << "Data CSV's row is smaller than the number of rows in label_csv";
        label_ptr_ = 0;
        label_size_ = label_parser_->Value().size;
      }
      CHECK_LT(label_ptr_, label_size_);
      out_.data[1] = AsTBlob(label_parser_->Value()[label_ptr_++], param_.label_shape);
    } else {
      out_.data[1] = dummy_label;
    }
    return true;
  }

  virtual const DataInst &Value(void) const {
    return out_;
  }

 private:
  inline TBlob AsTBlob(const dmlc::Row<uint32_t>& row, const TShape& shape) {
    CHECK_EQ(row.length, shape.Size())
        << "The data size in CSV do not match size of shape: "
        << "specified shape=" << shape << ", the csv row-length=" << row.length;
    const real_t* ptr = row.value;
    return TBlob((real_t*)ptr, shape, cpu::kDevMask, 0);  // NOLINT(*)
  }

  CSVIterParam param_;
  // output instance
  DataInst out_;
  // internal instance counter
  unsigned inst_counter_{0};
  // at end
  bool end_{false};
  // dummy label
  mshadow::TensorContainer<cpu, 1, real_t> dummy_label;
  // label parser
  size_t label_ptr_{0}, label_size_{0};
  size_t data_ptr_{0}, data_size_{0};
  std::unique_ptr<dmlc::Parser<uint32_t> > label_parser_;
  std::unique_ptr<dmlc::Parser<uint32_t> > data_parser_;
};

DMLC_REGISTER_PARAMETER(CSVIterParam);

MXNET_REGISTER_IO_ITER(CSVIter)
.describe(R"code(Returns the CSV file iterator.

In this function, the `data_shape` parameter is used to set the shape of each line of the input data.
If a row in an input file is `1,2,3,4,5,6`` and `data_shape` is (3,2), that row
will be reshaped, yielding the array [[1,2],[3,4],[5,6]] of shape (3,2).

By default, the `CSVIter` has `round_batch` parameter set to ``True``. So, if `batch_size`
is 3 and there are 4 total rows in CSV file, 2 more examples
are consumed at the first round. If `reset` function is called after first round,
the call is ignored and remaining examples are returned in the second round.

If one wants all the instances in the second round after calling `reset`, make sure
to set `round_batch` to False.

If ``data_csv = 'data/'`` is set, then all the files in this directory will be read.

Examples::

  // Contents of CSV file ``data/data.csv``.
  1,2,3
  2,3,4
  3,4,5
  4,5,6

  // Creates a `CSVIter` with `batch_size`=2 and default `round_batch`=True.
  CSVIter = mx.io.CSVIter(data_csv = 'data/data.csv', data_shape = (3,),
  batch_size = 2)

  // Two batches read from the above iterator are as follows:
  [[ 1.  2.  3.]
  [ 2.  3.  4.]]
  [[ 3.  4.  5.]
  [ 4.  5.  6.]]

  // Creates a `CSVIter` with default `round_batch` set to True.
  CSVIter = mx.io.CSVIter(data_csv = 'data/data.csv', data_shape = (3,),
  batch_size = 3)

  // Two batches read from the above iterator in the first pass are as follows:
  [[1.  2.  3.]
  [2.  3.  4.]
  [3.  4.  5.]]

  [[4.  5.  6.]
  [2.  3.  4.]
  [3.  4.  5.]]

  // Now, `reset` method is called.
  CSVIter.reset()

  // Batch read from the above iterator in the second pass is as follows:
  [[ 3.  4.  5.]
  [ 4.  5.  6.]
  [ 1.  2.  3.]]

  // Creates a `CSVIter` with `round_batch`=False.
  CSVIter = mx.io.CSVIter(data_csv = 'data/data.csv', data_shape = (3,),
  batch_size = 3, round_batch=False)

  // Contents of two batches read from the above iterator in both passes, after calling
  // `reset` method before second pass, is as follows:
  [[1.  2.  3.]
  [2.  3.  4.]
  [3.  4.  5.]]

  [[4.  5.  6.]
  [2.  3.  4.]
  [3.  4.  5.]]

)code" ADD_FILELINE)
.add_arguments(CSVIterParam::__FIELDS__())
.add_arguments(BatchParam::__FIELDS__())
.add_arguments(PrefetcherParam::__FIELDS__())
.set_body([]() {
    return new PrefetcherIter(
        new BatchLoader(
            new CSVIter()));
  });

}  // namespace io
}  // namespace mxnet
<commit_msg>round batch should start with first element. (#6684)<commit_after>/*!
 *  Copyright (c) 2015 by Contributors
 * \file iter_csv.cc
 * \brief define a CSV Reader to read in arrays
 */
#include <mxnet/io.h>
#include <dmlc/base.h>
#include <dmlc/logging.h>
#include <dmlc/parameter.h>
#include <dmlc/data.h>
#include "./iter_prefetcher.h"
#include "./iter_batchloader.h"

namespace mxnet {
namespace io {
// CSV parameters
struct CSVIterParam : public dmlc::Parameter<CSVIterParam> {
  /*! \brief path to data csv file */
  std::string data_csv;
  /*! \brief data shape */
  TShape data_shape;
  /*! \brief path to label csv file */
  std::string label_csv;
  /*! \brief label shape */
  TShape label_shape;
  // declare parameters
  DMLC_DECLARE_PARAMETER(CSVIterParam) {
    DMLC_DECLARE_FIELD(data_csv)
        .describe("The input CSV file or a directory path.");
    DMLC_DECLARE_FIELD(data_shape)
        .describe("The shape of one example.");
    DMLC_DECLARE_FIELD(label_csv).set_default("NULL")
        .describe("The input CSV file or a directory path. "
                  "If NULL, all labels will be returned as 0.");
    index_t shape1[] = {1};
    DMLC_DECLARE_FIELD(label_shape).set_default(TShape(shape1, shape1 + 1))
        .describe("The shape of one label.");
  }
};

class CSVIter: public IIterator<DataInst> {
 public:
  CSVIter() {
    out_.data.resize(2);
  }
  virtual ~CSVIter() {}

  // intialize iterator loads data in
  virtual void Init(const std::vector<std::pair<std::string, std::string> >& kwargs) {
    param_.InitAllowUnknown(kwargs);
    data_parser_.reset(dmlc::Parser<uint32_t>::Create(param_.data_csv.c_str(), 0, 1, "csv"));
    if (param_.label_csv != "NULL") {
      label_parser_.reset(dmlc::Parser<uint32_t>::Create(param_.label_csv.c_str(), 0, 1, "csv"));
    } else {
      dummy_label.set_pad(false);
      dummy_label.Resize(mshadow::Shape1(1));
      dummy_label = 0.0f;
    }
  }

  virtual void BeforeFirst() {
    data_parser_->BeforeFirst();
    if (label_parser_.get() != nullptr) {
      label_parser_->BeforeFirst();
    }
    data_ptr_ = label_ptr_ = 0;
    data_size_ = label_size_ = 0;
    inst_counter_ = 0;
    end_ = false;
  }

  virtual bool Next() {
    if (end_) return false;
    while (data_ptr_ >= data_size_) {
      if (!data_parser_->Next()) {
        end_ = true; return false;
      }
      data_ptr_ = 0;
      data_size_ = data_parser_->Value().size;
    }
    out_.index = inst_counter_++;
    CHECK_LT(data_ptr_, data_size_);
    out_.data[0] = AsTBlob(data_parser_->Value()[data_ptr_++], param_.data_shape);

    if (label_parser_.get() != nullptr) {
      while (label_ptr_ >= label_size_) {
        CHECK(label_parser_->Next())
            << "Data CSV's row is smaller than the number of rows in label_csv";
        label_ptr_ = 0;
        label_size_ = label_parser_->Value().size;
      }
      CHECK_LT(label_ptr_, label_size_);
      out_.data[1] = AsTBlob(label_parser_->Value()[label_ptr_++], param_.label_shape);
    } else {
      out_.data[1] = dummy_label;
    }
    return true;
  }

  virtual const DataInst &Value(void) const {
    return out_;
  }

 private:
  inline TBlob AsTBlob(const dmlc::Row<uint32_t>& row, const TShape& shape) {
    CHECK_EQ(row.length, shape.Size())
        << "The data size in CSV do not match size of shape: "
        << "specified shape=" << shape << ", the csv row-length=" << row.length;
    const real_t* ptr = row.value;
    return TBlob((real_t*)ptr, shape, cpu::kDevMask, 0);  // NOLINT(*)
  }

  CSVIterParam param_;
  // output instance
  DataInst out_;
  // internal instance counter
  unsigned inst_counter_{0};
  // at end
  bool end_{false};
  // dummy label
  mshadow::TensorContainer<cpu, 1, real_t> dummy_label;
  // label parser
  size_t label_ptr_{0}, label_size_{0};
  size_t data_ptr_{0}, data_size_{0};
  std::unique_ptr<dmlc::Parser<uint32_t> > label_parser_;
  std::unique_ptr<dmlc::Parser<uint32_t> > data_parser_;
};

DMLC_REGISTER_PARAMETER(CSVIterParam);

MXNET_REGISTER_IO_ITER(CSVIter)
.describe(R"code(Returns the CSV file iterator.

In this function, the `data_shape` parameter is used to set the shape of each line of the input data.
If a row in an input file is `1,2,3,4,5,6`` and `data_shape` is (3,2), that row
will be reshaped, yielding the array [[1,2],[3,4],[5,6]] of shape (3,2).

By default, the `CSVIter` has `round_batch` parameter set to ``True``. So, if `batch_size`
is 3 and there are 4 total rows in CSV file, 2 more examples
are consumed at the first round. If `reset` function is called after first round,
the call is ignored and remaining examples are returned in the second round.

If one wants all the instances in the second round after calling `reset`, make sure
to set `round_batch` to False.

If ``data_csv = 'data/'`` is set, then all the files in this directory will be read.

Examples::

  // Contents of CSV file ``data/data.csv``.
  1,2,3
  2,3,4
  3,4,5
  4,5,6

  // Creates a `CSVIter` with `batch_size`=2 and default `round_batch`=True.
  CSVIter = mx.io.CSVIter(data_csv = 'data/data.csv', data_shape = (3,),
  batch_size = 2)

  // Two batches read from the above iterator are as follows:
  [[ 1.  2.  3.]
  [ 2.  3.  4.]]
  [[ 3.  4.  5.]
  [ 4.  5.  6.]]

  // Creates a `CSVIter` with default `round_batch` set to True.
  CSVIter = mx.io.CSVIter(data_csv = 'data/data.csv', data_shape = (3,),
  batch_size = 3)

  // Two batches read from the above iterator in the first pass are as follows:
  [[1.  2.  3.]
  [2.  3.  4.]
  [3.  4.  5.]]

  [[4.  5.  6.]
  [1.  2.  3.]
  [2.  3.  4.]]

  // Now, `reset` method is called.
  CSVIter.reset()

  // Batch read from the above iterator in the second pass is as follows:
  [[ 3.  4.  5.]
  [ 4.  5.  6.]
  [ 1.  2.  3.]]

  // Creates a `CSVIter` with `round_batch`=False.
  CSVIter = mx.io.CSVIter(data_csv = 'data/data.csv', data_shape = (3,),
  batch_size = 3, round_batch=False)

  // Contents of two batches read from the above iterator in both passes, after calling
  // `reset` method before second pass, is as follows:
  [[1.  2.  3.]
  [2.  3.  4.]
  [3.  4.  5.]]

  [[4.  5.  6.]
  [2.  3.  4.]
  [3.  4.  5.]]

)code" ADD_FILELINE)
.add_arguments(CSVIterParam::__FIELDS__())
.add_arguments(BatchParam::__FIELDS__())
.add_arguments(PrefetcherParam::__FIELDS__())
.set_body([]() {
    return new PrefetcherIter(
        new BatchLoader(
            new CSVIter()));
  });

}  // namespace io
}  // namespace mxnet
<|endoftext|>


<commit_before>int main()
{
	return 0;
}<commit_msg>upadated main.cpp<commit_after>#include <SFML\Graphics.hpp>

#include "Environment.hpp"
#include "logger.hpp"

#include <iostream>

int main()
{
	logger::INFO("Initlializing Atraxian " ENVIRONMENT_VERSION "...");

	Environment *atraxia = new Environment(sf::VideoMode(1080, 720), "AtraxiaN-" ENVIRONMENT_VERSION);
	atraxia->main();

	delete atraxia;

	logger::INFO("exiting...");
	return 0;
}<|endoftext|>


<commit_before>#include <types.h>
#include <isa/vexISA.h>
#include <string.h>
#include <iomanip>
#include <sstream>

#ifndef __NIOS

#include <strings.h>

uint32 assembleIInstruction(uint7 opcode, uint19 imm19, uint6 regA){
	ac_int<32, false> result = 0;
	result.set_slc(0, opcode);
	result.set_slc(7, imm19);
	result.set_slc(26, regA);
	return result;
}

uint32 assembleRInstruction(uint7 opcode, uint6 regDest, uint6 regA, uint6 regB){
	ac_int<32, false> result = 0;
	ac_int<1, false> const0 = 0;
	result.set_slc(0, opcode);
	result.set_slc(7, const0); //Immediate bit is equal to zero
	result.set_slc(14, regDest);
	result.set_slc(20, regB);
	result.set_slc(26, regA);
	return result;
}

uint32 assembleRiInstruction(uint7 opcode, uint6 regDest, uint6 regA, uint13 imm13){
	ac_int<32, false> result = 0;
	result.set_slc(0, opcode);
	result.set_slc(7, imm13);
	result.set_slc(20, regDest);
	result.set_slc(26, regA);
	return result;
}
#else

uint32 assembleIInstruction(uint7 opcode, uint19 imm19, uint6 regA){
	uint32 result = 0;
	result += opcode & 0x7f;
	result += (imm19 & 0x7ffff)<<7;
	result += (regA & 0x3f) << 26;
	return result;
}

uint32 assembleRInstruction(uint7 opcode, uint6 regDest, uint6 regA, uint6 regB){
	uint32 result = 0;
	result += opcode & 0x7f;
	result += (regDest & 0x3f) << 14;
	result += (regB & 0x3f) << 20;
	result += (regA & 0x3f) << 26;
	return result;
}

uint32 assembleRiInstruction(uint7 opcode, uint6 regDest, uint6 regA, uint13 imm13){
	uint32 result = 0;
	result += opcode & 0x7f;
	result += (imm13 & 0x1fff) << 7;
	result += (regDest & 0x3f) << 20;
	result += (regA & 0x3f) << 26;
	return result;
}

#endif

#ifndef __NIOS
const char* opcodeNames[128] = {
		"NOP", "MPYLL", "MPYLLU", "MPYLH", "MPYLHU", "MPYHH", "MPYHHU", "MPYL", "DIVW", "MPYW", "MPYHU", "MPYHS", "MPYLO", "MPYHI", "DIVLO", "DIVHI",
		"LDD", "LDW", "LDH", "LDHU", "LDB", "LDBU","LDWU", "?", "STB", "STH", "STW", "STD", "?", "?", "?", "?",
		"?", "GOTO", "IGOTO", "CALL", "ICALL", "BR", "BRF", "RETURN", "MOVI", "AUIPC", "RECONFFS", "RECONFEXECUNIT", "SETCOND", "SETCONDF", "?", "STOP",
		"SETc", "SETFc", "?", "?", "?", "?", "?", "?", "SLCT", "?", "?", "?", "?", "?", "?", "?",
		"?", "ADD", "NOR", "AND", "ANDC", "CMPLT", "CMPLTU", "CMPNE", "NOT", "OR", "ORC", "SH1ADD", "SH2ADD", "SH3ADD", "SH4ADD", "SLL",
		"SRL", "SRA", "SUB", "XOR", "ADDW", "SUBW", "SLLW", "SRLW", "SRAW", "CMPEQ", "CMPGE", "CMPGEU", "CMPGT", "CMPGTU", "CMPLE", "CMPLEU",
		"?", "ADDi", "NORi", "ANDi", "ANDCi", "CMPLTi", "CMPLTUi", "CMPNEi", "NOTi", "ORi", "ORCi", "SH1ADDi", "SH2ADDi", "SH3ADDi", "SH4ADDi", "SLLi",
		"SRLi", "SRAi", "SUBi", "XORi", "ADDWi", "?", "SLLWi", "SRLWi", "SRAWi", "CMPEQi", "CMPGEi", "CMPGEUi", "CMPGTi", "CMPGTUi", "CMPLEi", "CMPLEUi"};

std::string printDecodedInstr(ac_int<32, false> instruction){
	ac_int<6, false> RA = instruction.slc<6>(26);
	ac_int<6, false> RB = instruction.slc<6>(20);
	ac_int<6, false> RC = instruction.slc<6>(14);
	ac_int<19, true> IMM19 = instruction.slc<19>(7);
	ac_int<13, false> IMM13 = instruction.slc<13>(7);
	ac_int<13, true> IMM13_signed = instruction.slc<13>(7);

	ac_int<7, false> OP = instruction.slc<7>(0);
	ac_int<3, false> BEXT = instruction.slc<3>(8);
	ac_int<9, false> IMM9 = instruction.slc<9>(11);

	ac_int<1, false> isIType = (OP.slc<3>(4) == 2);
	ac_int<1, false> isImm = OP.slc<3>(4) == 1 || OP.slc<3>(4) == 6 || OP.slc<3>(4) == 7;

	std::stringstream stream;

	stream << opcodeNames[OP];
	if (OP == 0){
	}
	else if (isIType)
		stream << " r" << RA << ", "  << IMM19;
	else if (isImm){
		stream << " r" << RB << "  = r" << RA << " 0x";
		stream << std::hex << IMM13_signed;
	}
	else
		stream << " r" << RC << "  = r" << RA << " r" << RB;

	std::string result(stream.str());
	for (int addedSpace = result.size(); addedSpace < 20; addedSpace++)
		result.append(" ");

	return result;
}
#endif
<commit_msg>Correcting opcode names for mult/div/rem<commit_after>#include <types.h>
#include <isa/vexISA.h>
#include <string.h>
#include <iomanip>
#include <sstream>

#ifndef __NIOS

#include <strings.h>

uint32 assembleIInstruction(uint7 opcode, uint19 imm19, uint6 regA){
	ac_int<32, false> result = 0;
	result.set_slc(0, opcode);
	result.set_slc(7, imm19);
	result.set_slc(26, regA);
	return result;
}

uint32 assembleRInstruction(uint7 opcode, uint6 regDest, uint6 regA, uint6 regB){
	ac_int<32, false> result = 0;
	ac_int<1, false> const0 = 0;
	result.set_slc(0, opcode);
	result.set_slc(7, const0); //Immediate bit is equal to zero
	result.set_slc(14, regDest);
	result.set_slc(20, regB);
	result.set_slc(26, regA);
	return result;
}

uint32 assembleRiInstruction(uint7 opcode, uint6 regDest, uint6 regA, uint13 imm13){
	ac_int<32, false> result = 0;
	result.set_slc(0, opcode);
	result.set_slc(7, imm13);
	result.set_slc(20, regDest);
	result.set_slc(26, regA);
	return result;
}
#else

uint32 assembleIInstruction(uint7 opcode, uint19 imm19, uint6 regA){
	uint32 result = 0;
	result += opcode & 0x7f;
	result += (imm19 & 0x7ffff)<<7;
	result += (regA & 0x3f) << 26;
	return result;
}

uint32 assembleRInstruction(uint7 opcode, uint6 regDest, uint6 regA, uint6 regB){
	uint32 result = 0;
	result += opcode & 0x7f;
	result += (regDest & 0x3f) << 14;
	result += (regB & 0x3f) << 20;
	result += (regA & 0x3f) << 26;
	return result;
}

uint32 assembleRiInstruction(uint7 opcode, uint6 regDest, uint6 regA, uint13 imm13){
	uint32 result = 0;
	result += opcode & 0x7f;
	result += (imm13 & 0x1fff) << 7;
	result += (regDest & 0x3f) << 20;
	result += (regA & 0x3f) << 26;
	return result;
}

#endif

#ifndef __NIOS
const char* opcodeNames[128] = {
		"NOP", "-", "-", "MPYW", "DIVW", "DIVUW", "REMW", "REMUW", "MPYH", "MPYHSU", "MPYHU", "MPY", "DIV", "DIVU", "REM", "REMU",
		"LDD", "LDW", "LDH", "LDHU", "LDB", "LDBU","LDWU", "?", "STB", "STH", "STW", "STD", "?", "?", "?", "?",
		"?", "GOTO", "IGOTO", "CALL", "ICALL", "BR", "BRF", "RETURN", "MOVI", "AUIPC", "RECONFFS", "RECONFEXECUNIT", "SETCOND", "SETCONDF", "?", "STOP",
		"SETc", "SETFc", "?", "?", "?", "?", "?", "?", "SLCT", "?", "?", "?", "?", "?", "?", "?",
		"?", "ADD", "NOR", "AND", "ANDC", "CMPLT", "CMPLTU", "CMPNE", "NOT", "OR", "ORC", "SH1ADD", "SH2ADD", "SH3ADD", "SH4ADD", "SLL",
		"SRL", "SRA", "SUB", "XOR", "ADDW", "SUBW", "SLLW", "SRLW", "SRAW", "CMPEQ", "CMPGE", "CMPGEU", "CMPGT", "CMPGTU", "CMPLE", "CMPLEU",
		"?", "ADDi", "NORi", "ANDi", "ANDCi", "CMPLTi", "CMPLTUi", "CMPNEi", "NOTi", "ORi", "ORCi", "SH1ADDi", "SH2ADDi", "SH3ADDi", "SH4ADDi", "SLLi",
		"SRLi", "SRAi", "SUBi", "XORi", "ADDWi", "?", "SLLWi", "SRLWi", "SRAWi", "CMPEQi", "CMPGEi", "CMPGEUi", "CMPGTi", "CMPGTUi", "CMPLEi", "CMPLEUi"};

std::string printDecodedInstr(ac_int<32, false> instruction){
	ac_int<6, false> RA = instruction.slc<6>(26);
	ac_int<6, false> RB = instruction.slc<6>(20);
	ac_int<6, false> RC = instruction.slc<6>(14);
	ac_int<19, true> IMM19 = instruction.slc<19>(7);
	ac_int<13, false> IMM13 = instruction.slc<13>(7);
	ac_int<13, true> IMM13_signed = instruction.slc<13>(7);

	ac_int<7, false> OP = instruction.slc<7>(0);
	ac_int<3, false> BEXT = instruction.slc<3>(8);
	ac_int<9, false> IMM9 = instruction.slc<9>(11);

	ac_int<1, false> isIType = (OP.slc<3>(4) == 2);
	ac_int<1, false> isImm = OP.slc<3>(4) == 1 || OP.slc<3>(4) == 6 || OP.slc<3>(4) == 7;

	std::stringstream stream;

	stream << opcodeNames[OP];
	if (OP == 0){
	}
	else if (isIType)
		stream << " r" << RA << ", "  << IMM19;
	else if (isImm){
		stream << " r" << RB << "  = r" << RA << " 0x";
		stream << std::hex << IMM13_signed;
	}
	else
		stream << " r" << RC << "  = r" << RA << " r" << RB;

	std::string result(stream.str());
	for (int addedSpace = result.size(); addedSpace < 20; addedSpace++)
		result.append(" ");

	return result;
}
#endif
<|endoftext|>


<commit_before>#include "dispatch_queue.h"

#include <thread>
#include <queue>

struct dispatch_queue_t::impl
{
    impl();
    static void dispatch_thread_proc(impl *self);

    std::queue< std::function< void() > > queue;
    std::mutex queue_mtx;
    std::condition_variable queue_cond;
    std::atomic< bool > quit;
    std::thread queue_thread;

    using queue_lock_t = std::unique_lock< decltype(queue_mtx) >;
};

void dispatch_queue_t::impl::dispatch_thread_proc(dispatch_queue_t::impl *self)
{
    using queue_size_t = decltype(self->queue)::size_type;

    while (self->quit == false)
    {
        queue_lock_t queue_lock(self->queue_mtx);
        queue_size_t n = self->queue.size();

        while (n == 0) {
            self->queue_cond.wait(queue_lock);
            n = self->queue.size();
        }

        for (queue_size_t i = 0; i < n; ++i) {
            auto dispatch_func = self->queue.front();
            self->queue.pop();

            queue_lock.unlock();
            dispatch_func();
            queue_lock.lock();
        }
    }
}

dispatch_queue_t::impl::impl()
    : quit(false)
    , queue_thread(&dispatch_thread_proc, this)
{
}

dispatch_queue_t::dispatch_queue_t()
    : m(new impl)
{
}

dispatch_queue_t::~dispatch_queue_t()
{
    dispatch_async([this] { m->quit = true; });
    m->queue_thread.join();
}

void dispatch_queue_t::dispatch_async(std::function< void() > func)
{
    impl::queue_lock_t queue_lock(m->queue_mtx);
    m->queue.push(func);
    m->queue_cond.notify_one();
}

void dispatch_queue_t::dispatch_sync(std::function< void() > func)
{
    std::mutex sync_mtx;
    impl::queue_lock_t sync_lock(sync_mtx);
    std::condition_variable sync_cond;
    auto completed = false;

    {
        impl::queue_lock_t queue_lock(m->queue_mtx);
        m->queue.push(func);
        m->queue.push([&]() {
            std::unique_lock< decltype(sync_mtx) > sync_cb_lock(sync_mtx);
            completed = true;
            sync_cond.notify_one();
        });

        m->queue_cond.notify_one();
    }

    while (!completed) {
        sync_cond.wait(sync_lock);
    }
}

void dispatch_queue_t::dispatch_flush()
{
    dispatch_sync([]{});
}

<commit_msg>use lambdas for condition variable predicate checking.<commit_after>#include "dispatch_queue.h"

#include <thread>
#include <queue>

struct dispatch_queue_t::impl
{
    impl();
    static void dispatch_thread_proc(impl *self);

    std::queue< std::function< void() > > queue;
    std::mutex queue_mtx;
    std::condition_variable queue_cond;
    std::atomic< bool > quit;
    std::thread queue_thread;

    using queue_lock_t = std::unique_lock< decltype(queue_mtx) >;
};

void dispatch_queue_t::impl::dispatch_thread_proc(dispatch_queue_t::impl *self)
{
    using queue_size_t = decltype(self->queue)::size_type;

    while (self->quit == false)
    {
        queue_lock_t queue_lock(self->queue_mtx);
        queue_size_t n = self->queue.size();

        self->queue_cond.wait(queue_lock, [&self]() { return self->queue.size() > 0; });

        for (queue_size_t i = 0; i < n; ++i) {
            auto dispatch_func = self->queue.front();
            self->queue.pop();

            queue_lock.unlock();
            dispatch_func();
            queue_lock.lock();
        }
    }
}

dispatch_queue_t::impl::impl()
    : quit(false)
    , queue_thread(&dispatch_thread_proc, this)
{
}

dispatch_queue_t::dispatch_queue_t()
    : m(new impl)
{
}

dispatch_queue_t::~dispatch_queue_t()
{
    dispatch_async([this] { m->quit = true; });
    m->queue_thread.join();
}

void dispatch_queue_t::dispatch_async(std::function< void() > func)
{
    impl::queue_lock_t queue_lock(m->queue_mtx);
    m->queue.push(func);
    m->queue_cond.notify_one();
}

void dispatch_queue_t::dispatch_sync(std::function< void() > func)
{
    std::mutex sync_mtx;
    impl::queue_lock_t sync_lock(sync_mtx);
    std::condition_variable sync_cond;
    auto completed = false;

    {
        impl::queue_lock_t queue_lock(m->queue_mtx);
        m->queue.push(func);
        m->queue.push([&]() {
            std::unique_lock< decltype(sync_mtx) > sync_cb_lock(sync_mtx);
            completed = true;
            sync_cond.notify_one();
        });

        m->queue_cond.notify_one();
    }

    sync_cond.wait(sync_lock, [&completed]() { return completed; });
}

void dispatch_queue_t::dispatch_flush()
{
    dispatch_sync([]{});
}

<|endoftext|>


<commit_before>/**
 * @file TeamCommEncoder.cpp
 *
 * @author Xu, Yuan
 *
 * @brief encoder our team message (protobuf) to ANSCII, and decode from it
 * M essage may consist of 20 characters, which may be taken from the ASCII printing character
 * subset [0x20, 0x7E] except the white space character and the normal brackets ( and ).
 */

#include "TeamCommEncoder.h"
#include <Messages/Messages.pb.h>
#include "Tools/DataConversion.h"

using namespace std;
using namespace naoth;

TeamCommEncoder::TeamCommEncoder()
  :maxSize(22000, 15000) // TODO: this should be the same as field at least
{
  anglePiece = Math::fromDegrees(5.0);
}

// from protobuf to ASCII
string TeamCommEncoder::encode(const string& data)
{
  naothmessages::TeamCommMessage msg;
  msg.ParseFromString(data);

  string anscii;
  anscii += encoder.encode(static_cast<unsigned int>(msg.teamnumber()), 1);
  anscii += encoder.encode(static_cast<unsigned int>(msg.playernumber()), 1);
  anscii += encoder.encode(static_cast<unsigned int>(msg.wasstriker()), 1);

  // robot pose
  Pose2D pose;
  DataConversion::fromMessage(msg.positiononfield(), pose);
  pose.translation.x = Math::clamp(pose.translation.x, -maxSize.x, maxSize.x);
  pose.translation.y = Math::clamp(pose.translation.y, -maxSize.y, maxSize.y);
  anscii += encoder.encode(pose, maxSize, anglePiece, 4);

  // ball
  anscii += encoder.encode(static_cast<unsigned int> (msg.timesinceballwasseen())/60, 2); // 60 is vision frame rate

  Vector2d ballLocal(msg.ballposition().x(), msg.ballposition().y());
  Vector2d ballOnField = pose * ballLocal;
  ballOnField.x = Math::clamp(ballOnField.x, -maxSize.x, maxSize.x);
  ballOnField.y = Math::clamp(ballOnField.y, -maxSize.y, maxSize.y);
  anscii += encoder.encode(ballOnField, maxSize, 3);

        /*
          s += encoder.encode(static_cast<unsigned int>(msg.isfallendown()), 1);

          // ball

          s += encoder.encode(static_cast<unsigned int> (msg.timetoball())/20, 2);
          if (msg.has_ballposition())
          {

          }

          if ( msg.has_opponent() )
          {
            unsigned int num = msg.opponent().number();
            Pose2D pose(msg.opponent().poseonfield().rotation(),
              msg.opponent().poseonfield().translation().x(),
              msg.opponent().poseonfield().translation().y());
            pose.translation.x = Math::clamp(pose.translation.x, -fieldSize.x, fieldSize.x);
            pose.translation.y = Math::clamp(pose.translation.y, -fieldSize.y, fieldSize.y);

            s += encoder.encode(num, 1);
            s += encoder.encode(pose, fieldSize, anglePiece, 4);
          }*/

  return anscii;
}

/* The encode:
  0: team number
  1: player number
  2: was striker
  3-6: robot pose
  7-8: time ball was seen
  9-11: ball on field
 */

// from ASCII to protobuf
string TeamCommEncoder::decode(const string& anscii)
{
  naothmessages::TeamCommMessage msg;
  msg.set_teamnumber( encoder.decodeUnsigned(anscii.substr(0, 1)) );
  msg.set_playernumber( encoder.decodeUnsigned(anscii.substr(1, 1)) );
  msg.set_ispenalized(false); // no penalize rule in SimSpark
  msg.set_bodyid(DataConversion::toStr(msg.playernumber())); // the same as player number
  msg.set_wasstriker(encoder.decodeUnsigned(anscii.substr(2, 1)) != 0);

  // robot pose
  Pose2D pose = encoder.decodePose2D(anscii.substr(3, 4), maxSize, anglePiece);
  DataConversion::toMessage(pose, *(msg.mutable_positiononfield()));

  // ball
  msg.set_timesinceballwasseen(encoder.decodeUnsigned(anscii.substr(7, 2))*60); // 60 is vision frame rate
  Vector2d ballOnField = encoder.decodeVector2D(anscii.substr(9, 3), maxSize);
  Vector2d ballLocal = pose.invert() * ballOnField;
  DataConversion::toMessage(ballLocal, *(msg.mutable_ballposition()));

  return msg.SerializeAsString();
}
<commit_msg>check the message size<commit_after>/**
 * @file TeamCommEncoder.cpp
 *
 * @author Xu, Yuan
 *
 * @brief encoder our team message (protobuf) to ANSCII, and decode from it
 * M essage may consist of 20 characters, which may be taken from the ASCII printing character
 * subset [0x20, 0x7E] except the white space character and the normal brackets ( and ).
 */

#include "TeamCommEncoder.h"
#include <Messages/Messages.pb.h>
#include "Tools/DataConversion.h"

using namespace std;
using namespace naoth;

TeamCommEncoder::TeamCommEncoder()
  :maxSize(22000, 15000) // TODO: this should be the same as field at least
{
  anglePiece = Math::fromDegrees(5.0);
}

// from protobuf to ASCII
string TeamCommEncoder::encode(const string& data)
{
  naothmessages::TeamCommMessage msg;
  msg.ParseFromString(data);

  string anscii;
  anscii += encoder.encode(static_cast<unsigned int>(msg.teamnumber()), 1);
  anscii += encoder.encode(static_cast<unsigned int>(msg.playernumber()), 1);
  anscii += encoder.encode(static_cast<unsigned int>(msg.wasstriker()), 1);

  // robot pose
  Pose2D pose;
  DataConversion::fromMessage(msg.positiononfield(), pose);
  pose.translation.x = Math::clamp(pose.translation.x, -maxSize.x, maxSize.x);
  pose.translation.y = Math::clamp(pose.translation.y, -maxSize.y, maxSize.y);
  anscii += encoder.encode(pose, maxSize, anglePiece, 4);

  // ball
  anscii += encoder.encode(static_cast<unsigned int> (msg.timesinceballwasseen())/60, 2); // 60 is vision frame rate

  Vector2d ballLocal(msg.ballposition().x(), msg.ballposition().y());
  Vector2d ballOnField = pose * ballLocal;
  ballOnField.x = Math::clamp(ballOnField.x, -maxSize.x, maxSize.x);
  ballOnField.y = Math::clamp(ballOnField.y, -maxSize.y, maxSize.y);
  anscii += encoder.encode(ballOnField, maxSize, 3);

  anscii += encoder.encode(static_cast<unsigned int>(msg.isfallendown()), 1);

        /*

          // ball

          s += encoder.encode(static_cast<unsigned int> (msg.timetoball())/20, 2);
          if (msg.has_ballposition())
          {

          }

          if ( msg.has_opponent() )
          {
            unsigned int num = msg.opponent().number();
            Pose2D pose(msg.opponent().poseonfield().rotation(),
              msg.opponent().poseonfield().translation().x(),
              msg.opponent().poseonfield().translation().y());
            pose.translation.x = Math::clamp(pose.translation.x, -fieldSize.x, fieldSize.x);
            pose.translation.y = Math::clamp(pose.translation.y, -fieldSize.y, fieldSize.y);

            s += encoder.encode(num, 1);
            s += encoder.encode(pose, fieldSize, anglePiece, 4);
          }*/

  ASSERT(anscii.size()==13);

  return anscii;
}

/* The encode:
  0: team number
  1: player number
  2: was striker
  3-6: robot pose
  7-8: time ball was seen
  9-11: ball on field
  12: is fallen down
 */

// from ASCII to protobuf
string TeamCommEncoder::decode(const string& anscii)
{
  unsigned int messageSize = anscii.size();
  ASSERT(messageSize==13);

  if ( messageSize != 13 )
    return "";

  naothmessages::TeamCommMessage msg;
  msg.set_teamnumber( encoder.decodeUnsigned(anscii.substr(0, 1)) );
  msg.set_playernumber( encoder.decodeUnsigned(anscii.substr(1, 1)) );
  msg.set_ispenalized(false); // no penalize rule in SimSpark
  msg.set_bodyid(DataConversion::toStr(msg.playernumber())); // the same as player number
  msg.set_wasstriker(encoder.decodeUnsigned(anscii.substr(2, 1)) != 0);

  // robot pose
  Pose2D pose = encoder.decodePose2D(anscii.substr(3, 4), maxSize, anglePiece);
  DataConversion::toMessage(pose, *(msg.mutable_positiononfield()));

  // ball
  msg.set_timesinceballwasseen(encoder.decodeUnsigned(anscii.substr(7, 2))*60); // 60 is vision frame rate
  Vector2d ballOnField = encoder.decodeVector2D(anscii.substr(9, 3), maxSize);
  Vector2d ballLocal = pose.invert() * ballOnField;
  DataConversion::toMessage(ballLocal, *(msg.mutable_ballposition()));
  msg.set_isfallendown(encoder.decodeUnsigned(anscii.substr(12, 1)));

  return msg.SerializeAsString();
}
<|endoftext|>