Skip to content

implement C++ assert (stdio, apple) #612

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Jan 9, 2018
4 changes: 3 additions & 1 deletion Firestore/core/src/firebase/firestore/util/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,14 @@ add_library(
)
target_link_libraries(
firebase_firestore_util_base
PRIVATE
PUBLIC
absl_base
)

# stdio-dependent bits can be built and tested everywhere
add_library(
firebase_firestore_util_stdio
assert_stdio.cc
log_stdio.cc
)
target_link_libraries(
Expand All @@ -42,6 +43,7 @@ target_link_libraries(
if(APPLE)
add_library(
firebase_firestore_util_apple
assert_apple.mm
log_apple.mm
)
target_compile_options(
Expand Down
44 changes: 44 additions & 0 deletions Firestore/core/src/firebase/firestore/util/assert_apple.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright 2018 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "Firestore/core/src/firebase/firestore/util/firebase_assert.h"

#import <Foundation/Foundation.h>

#include <string.h>

#include "Firestore/core/src/firebase/firestore/util/string_apple.h"

namespace firebase {
namespace firestore {
namespace util {

void FailAssert(const char* file, const char* func, const int line, const char* format, ...) {
va_list args;
va_start(args, format);
NSString *description = [[NSString alloc] initWithFormat:WrapNSStringNoCopy(format) arguments:args];
va_end(args);
[[NSAssertionHandler currentHandler]
handleFailureInFunction:WrapNSStringNoCopy(func)
file:WrapNSStringNoCopy(file)
lineNumber:line
description:@"FIRESTORE INTERNAL ASSERTION FAILED: %@", description];
abort();
}

} // namespace util
} // namespace firestore
} // namespace firebase
53 changes: 53 additions & 0 deletions Firestore/core/src/firebase/firestore/util/assert_stdio.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright 2018 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "Firestore/core/src/firebase/firestore/util/firebase_assert.h"

#include <stdarg.h>

#include <exception>
#include <string>

#include <absl/base/config.h>

#include "Firestore/core/src/firebase/firestore/util/string_printf.h"

namespace firebase {
namespace firestore {
namespace util {

void FailAssert(const char* file, const char* func, const int line,
const char* format, ...) {
std::string message;
StringAppendF(&message, "ASSERT: %s(%d) %s: ", file, line, func);

va_list args;
va_start(args, format);
StringAppendV(&message, format, args);
va_end(args);

#if ABSL_HAVE_EXCEPTIONS
throw std::logic_error(message);

#else
fprintf(stderr, "%s\n", message.c_str());
std::terminate();
#endif
}

} // namespace util
} // namespace firestore
} // namespace firebase
102 changes: 102 additions & 0 deletions Firestore/core/src/firebase/firestore/util/firebase_assert.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Copyright 2018 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

// To avoid naming-collision, this header is called firebase_assert.h instead
// of assert.h.

#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_FIREBASE_ASSERT_H_
#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_FIREBASE_ASSERT_H_

#include <stdlib.h>

#include "Firestore/core/src/firebase/firestore/util/log.h"

#define FIREBASE_EXPAND_STRINGIFY_(X) #X
#define FIREBASE_EXPAND_STRINGIFY(X) FIREBASE_EXPAND_STRINGIFY_(X)

// FIREBASE_ASSERT_* macros are not compiled out of release builds. They should
// be used for assertions that need to be propagated to end-users of SDKs.
// FIREBASE_DEV_ASSERT_* macros are compiled out of release builds, similar to
// the C assert() macro. They should be used for internal assertions that are
// only shown to SDK developers.

// Assert condition is true, if it's false log an assert with the specified
// expression as a string.
#define FIREBASE_ASSERT_WITH_EXPRESSION(condition, expression) \
do { \
if (!(condition)) { \
firebase::firestore::util::FailAssert( \
__FILE__, __PRETTY_FUNCTION__, __LINE__, \
FIREBASE_EXPAND_STRINGIFY(expression)); \
} \
} while(0)

// Assert condition is true, if it's false log an assert with the specified
// expression as a string. Compiled out of release builds.
#if defined(NDEBUG)
#define FIREBASE_DEV_ASSERT_WITH_EXPRESSION(condition, expression) \
{ (void)(condition); }
#else
#define FIREBASE_DEV_ASSERT_WITH_EXPRESSION(condition, expression) \
FIREBASE_ASSERT_WITH_EXPRESSION(condition, expression)
#endif // !defined(NDEBUG)

// Custom assert() implementation that is not compiled out in release builds.
#define FIREBASE_ASSERT(expression) \
FIREBASE_ASSERT_WITH_EXPRESSION(expression, expression)

// Custom assert() implementation that is compiled out in release builds.
// Compiled out of release builds.
#define FIREBASE_DEV_ASSERT(expression) \
FIREBASE_DEV_ASSERT_WITH_EXPRESSION(expression, expression)

// Assert condition is true otherwise display the specified expression,
// message and abort.
#define FIREBASE_ASSERT_MESSAGE_WITH_EXPRESSION(condition, expression, ...) \
do { \
if (!(condition)) { \
firebase::firestore::util::LogError( \
FIREBASE_EXPAND_STRINGIFY(expression)); \
firebase::firestore::util::FailAssert( \
__FILE__, __PRETTY_FUNCTION__, __LINE__, __VA_ARGS__); \
} \
} while(0)

// Assert condition is true otherwise display the specified expression,
// message and abort. Compiled out of release builds.
#if defined(NDEBUG)
#define FIREBASE_DEV_ASSERT_MESSAGE_WITH_EXPRESSION(condition, expression, \
...) \
{ (void)(condition); }
#else
#define FIREBASE_DEV_ASSERT_MESSAGE_WITH_EXPRESSION(condition, expression, \
...) \
FIREBASE_ASSERT_MESSAGE_WITH_EXPRESSION(condition, expression, __VA_ARGS__)
#endif // !defined(NDEBUG)

namespace firebase {
namespace firestore {
namespace util {

// A no-return helper function. To raise an assertion, use Macro instead.
void FailAssert(const char* file, const char* func, const int line,
const char* format, ...);

} // namespace util
} // namespace firestore
} // namespace firebase

#endif // FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_FIREBASE_ASSERT_H_
21 changes: 7 additions & 14 deletions Firestore/core/src/firebase/firestore/util/log_apple.mm
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,14 @@

#include <string>

#include "Firestore/core/src/firebase/firestore/util/string_apple.h"

namespace firebase {
namespace firestore {
namespace util {

namespace {

// Translates a C format string to the equivalent NSString without making a
// copy.
NSString* FormatString(const char* format) {
return [[NSString alloc] initWithBytesNoCopy:(void*)format
length:strlen(format)
encoding:NSUTF8StringEncoding
freeWhenDone:NO];
}

// Translates a C++ LogLevel to the equivalent Objective-C FIRLoggerLevel
FIRLoggerLevel ToFIRLoggerLevel(LogLevel level) {
switch (level) {
Expand Down Expand Up @@ -85,37 +78,37 @@ void LogDebug(const char* format, ...) {
va_list list;
va_start(list, format);
FIRLogBasic(FIRLoggerLevelDebug, kFIRLoggerFirestore, @"I-FST000001",
FormatString(format), list);
WrapNSStringNoCopy(format), list);
va_end(list);
}

void LogInfo(const char* format, ...) {
va_list list;
va_start(list, format);
FIRLogBasic(FIRLoggerLevelInfo, kFIRLoggerFirestore, @"I-FST000001",
FormatString(format), list);
WrapNSStringNoCopy(format), list);
va_end(list);
}

void LogWarning(const char* format, ...) {
va_list list;
va_start(list, format);
FIRLogBasic(FIRLoggerLevelWarning, kFIRLoggerFirestore, @"I-FST000001",
FormatString(format), list);
WrapNSStringNoCopy(format), list);
va_end(list);
}

void LogError(const char* format, ...) {
va_list list;
va_start(list, format);
FIRLogBasic(FIRLoggerLevelError, kFIRLoggerFirestore, @"I-FST000001",
FormatString(format), list);
WrapNSStringNoCopy(format), list);
va_end(list);
}

void LogMessageV(LogLevel log_level, const char* format, va_list args) {
FIRLogBasic(ToFIRLoggerLevel(log_level), kFIRLoggerFirestore, @"I-FST000001",
FormatString(format), args);
WrapNSStringNoCopy(format), args);
}

void LogMessage(LogLevel log_level, const char* format, ...) {
Expand Down
39 changes: 39 additions & 0 deletions Firestore/core/src/firebase/firestore/util/string_apple.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright 2018 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_STRING_APPLE_H_
#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_STRING_APPLE_H_

#import <Foundation/Foundation.h>

namespace firebase {
namespace firestore {
namespace util {

// Translates a C string to the equivalent NSString without making a copy.
inline NSString* WrapNSStringNoCopy(const char* c_str) {
return [[NSString alloc] initWithBytesNoCopy:const_cast<void*>(static_cast<const void*>(c_str))
length:strlen(c_str)
encoding:NSUTF8StringEncoding
freeWhenDone:NO];
}


} // namespace util
} // namespace firestore
} // namespace firebase

#endif // FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_STRING_APPLE_H_
2 changes: 2 additions & 0 deletions Firestore/core/test/firebase/firestore/util/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ target_link_libraries(
if(APPLE)
cc_test(
firebase_firestore_util_apple_test
assert_test.cc
log_test.cc
)
target_link_libraries(
Expand All @@ -36,6 +37,7 @@ endif(APPLE)

cc_test(
firebase_firestore_util_stdio_test
assert_test.cc
log_test.cc
)
target_link_libraries(
Expand Down
Loading