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
Merged

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

merged 12 commits into from
Jan 9, 2018

Conversation

zxu123
Copy link
Contributor

@zxu123 zxu123 commented Jan 3, 2018

Discussion

go/firestorecpplogassert

Testing

unit test (for each platform)

API Changes

not applicable

Copy link
Contributor

@wilhuff wilhuff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall structure looks good (knowing that the API largely comes from existing Firebase C++).

@@ -24,22 +24,45 @@ add_library(
log_stdio.cc
)

# log_apple can only built and tested on apple plaforms
# assert_stdio can be built and tested everywhere
add_library(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just save complexity here I think it's safe to put the log_foo and assert_foo implementations in the same library.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack, solved w/ merged


// Assert condition is true otherwise display the specified expression,
// message and abort. Compiled out of release builds.
#if !defined(NDEBUG)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above: let's make #ifdef NDEBUG the first case to avoid a double-negative.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


// Translates a C format string to the equivalent NSString without making a
// copy.
NSString* CStringToNSString(const char* format) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a function we're going to use a lot when interoperating with platform native APIs on iOS.

Let's put this in a separate utility. As a separate utility we should make it clear that this is merely wrapping the C string rather than copying it. Maybe WrapNSStringNoCopy?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


#import <Foundation/Foundation.h>

#include <string>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not appear to use C++ strings at all.

Perhaps you meant <string.h>?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_ASSERT_H_
#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_ASSERT_H_

#include <cstdlib>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this required? If so we probably want <stdlib.h> since we've been using the C headers directly elsewhere.

Also there should be a newline between the system headers and our own headers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


// 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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realize this is in the upstream but it's better to avoid a double-negative for readability's sake. Let's reorder this to put the production branch first.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

vfprintf(stderr, format, args);
va_end(args);
fprintf(stderr, "\n");
throw std::exception();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's just abort rather than throwing. We're going to end up needing to compile under -fno-exceptions.

Also we should throw the exception with the assertion text included.

Maybe we can include absl/base/config.h and then do the following:

std::string message;
// compute assertion message using snprintf and vsnprintf (see notes below)

#if ABSL_HAVE_EXCEPTIONS
throw std::exception(message);
#else
fprintf(stderr, "%s\n", message.c_str());
abort();
#endif

Note that as of Visual Studio 2013 we can do the following to compute the required size of the buffer for the message:

size_t size = vsnprintf(nullptr, 0, format.c_str(), args);

And you can write directly into string's buffer as of C++11 (see stack overflow for discussion).

std::string message;
message.resize(size + 1);  // include space for terminating null

vsnprintf(&message[0], message.size(), format.c_str(), args);

message.resize(size);

Depending on how frequently we end up using this, we might consider moving this latter part out to a separate std::string FormatString(const char* format, va_list args) function.

Also consider if this is the right exception type. Perhaps logic_error might be better?

See https://github.com/abseil/abseil-cpp/blob/master/absl/base/internal/throw_delegate.cc for more ideas about handing this with exceptions disabled.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactored w/ the new StringPrintf() helpers.

Copy link
Contributor Author

@zxu123 zxu123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated. Please take another look.


// Translates a C format string to the equivalent NSString without making a
// copy.
NSString* CStringToNSString(const char* format) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

vfprintf(stderr, format, args);
va_end(args);
fprintf(stderr, "\n");
throw std::exception();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactored w/ the new StringPrintf() helpers.

@@ -24,22 +24,45 @@ add_library(
log_stdio.cc
)

# log_apple can only built and tested on apple plaforms
# assert_stdio can be built and tested everywhere
add_library(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack, solved w/ merged

#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_ASSERT_H_
#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_ASSERT_H_

#include <cstdlib>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


// 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)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


// Assert condition is true otherwise display the specified expression,
// message and abort. Compiled out of release builds.
#if !defined(NDEBUG)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


#import <Foundation/Foundation.h>

#include <string>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


#import <Foundation/Foundation.h>

#include <stdarg.h>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't do anything with varargs or C++ strings. Probably we can just #import Foundation and that's all we need, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

* limitations under the License.
*/

#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_STRING_IOS_UTIL_H_
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This macro should end with STRING_APPLE_H_.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

namespace util {

NSString* WrapNSStringNoCopy(const char* c_str) {
return [[NSString alloc] initWithBytesNoCopy:(void*)c_str
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer modern C++ casts (const_cast, static_cast, and reinterpret_cast) to old-style C casts.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

namespace firestore {
namespace util {

NSString* WrapNSStringNoCopy(const char* c_str) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that this is just wrapping this call to the NSString initializer, should we make this implementation inline in the header?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@wilhuff wilhuff assigned zxu123 and unassigned wilhuff Jan 8, 2018
Copy link
Contributor Author

@zxu123 zxu123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

* limitations under the License.
*/

#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_UTIL_STRING_IOS_UTIL_H_
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


#import <Foundation/Foundation.h>

#include <stdarg.h>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Contributor

@wilhuff wilhuff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@wilhuff wilhuff merged commit 64d1e6b into master Jan 9, 2018
@wilhuff wilhuff deleted the cpp/assert branch January 9, 2018 01:48
minafarid pushed a commit to minafarid/firebase-ios-sdk that referenced this pull request Jun 6, 2018
* implement C++ assert (stdio, apple)

* Update tests for firebase_firestore_util renames

* renaming `assert.h` to `firebase_assert.h`

* refactoring to a common `WrapNSStringNoCopy()`
@firebase firebase locked and limited conversation to collaborators Nov 9, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants