aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/compiler/objectivec/objectivec_field.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/compiler/objectivec/objectivec_field.cc')
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_field.cc156
1 files changed, 95 insertions, 61 deletions
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_field.cc
index 09341820..7bb9837d 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_field.cc
@@ -28,6 +28,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#include <iostream>
+
#include <google/protobuf/compiler/objectivec/objectivec_field.h>
#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
#include <google/protobuf/compiler/objectivec/objectivec_enum_field.h>
@@ -75,7 +77,6 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
(*variables)["field_number_name"] =
classname + "_FieldNumber_" + capitalized_name;
(*variables)["field_number"] = SimpleItoa(descriptor->number());
- (*variables)["has_index"] = SimpleItoa(descriptor->index());
(*variables)["field_type"] = GetCapitalizedType(descriptor);
std::vector<string> field_flags;
if (descriptor->is_repeated()) field_flags.push_back("GPBFieldRepeated");
@@ -99,18 +100,9 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
(*variables)["dataTypeSpecific_name"] = "className";
(*variables)["dataTypeSpecific_value"] = "NULL";
- string field_options = descriptor->options().SerializeAsString();
- // Must convert to a standard byte order for packing length into
- // a cstring.
- uint32 length = ghtonl(field_options.length());
- if (length > 0) {
- string bytes((const char*)&length, sizeof(length));
- bytes.append(field_options);
- string options_str = "\"" + CEscape(bytes) + "\"";
- (*variables)["fieldoptions"] = "\"" + CEscape(bytes) + "\"";
- } else {
- (*variables)["fieldoptions"] = "";
- }
+ (*variables)["storage_offset_value"] =
+ "(uint32_t)offsetof(" + classname + "__storage_, " + camel_case_name + ")";
+ (*variables)["storage_offset_comment"] = "";
// Clear some common things so they can be set just when needed.
(*variables)["storage_attribute"] = "";
@@ -190,52 +182,54 @@ void FieldGenerator::DetermineForwardDeclarations(
}
void FieldGenerator::GenerateFieldDescription(
- io::Printer* printer) const {
- printer->Print(
- variables_,
- "{\n"
- " .name = \"$name$\",\n"
- " .number = $field_number_name$,\n"
- " .hasIndex = $has_index$,\n"
- " .flags = $fieldflags$,\n"
- " .dataType = GPBDataType$field_type$,\n"
- " .offset = offsetof($classname$__storage_, $name$),\n"
- " .defaultValue.$default_name$ = $default$,\n");
-
- // TODO(thomasvl): It might be useful to add a CPP wrapper to support
- // compiling away the EnumDescriptors. To do that, we'd need a #if here
- // to control setting the descriptor vs. the validator, and above in
- // SetCommonFieldVariables() we'd want to wrap how we add
- // GPBFieldHasDefaultValue to the flags.
-
- // " .dataTypeSpecific.value* = [something],"
- GenerateFieldDescriptionTypeSpecific(printer);
-
- const string& field_options(variables_.find("fieldoptions")->second);
- if (field_options.empty()) {
- printer->Print(" .fieldOptions = NULL,\n");
+ io::Printer* printer, bool include_default) const {
+ // Printed in the same order as the structure decl.
+ if (include_default) {
+ printer->Print(
+ variables_,
+ "{\n"
+ " .defaultValue.$default_name$ = $default$,\n"
+ " .core.name = \"$name$\",\n"
+ " .core.dataTypeSpecific.$dataTypeSpecific_name$ = $dataTypeSpecific_value$,\n"
+ " .core.number = $field_number_name$,\n"
+ " .core.hasIndex = $has_index$,\n"
+ " .core.offset = $storage_offset_value$,$storage_offset_comment$\n"
+ " .core.flags = $fieldflags$,\n"
+ " .core.dataType = GPBDataType$field_type$,\n"
+ "},\n");
} else {
- // Can't use PrintRaw() here to get the #if/#else/#endif lines completely
- // outdented because the need for indent captured on the previous
- // printing of a \n and there is no way to get the current indent level
- // to call the right number of Outdent()/Indents() to maintain state.
printer->Print(
variables_,
- "#if GPBOBJC_INCLUDE_FIELD_OPTIONS\n"
- " .fieldOptions = $fieldoptions$,\n"
- "#else\n"
- " .fieldOptions = NULL,\n"
- "#endif // GPBOBJC_INCLUDE_FIELD_OPTIONS\n");
+ "{\n"
+ " .name = \"$name$\",\n"
+ " .dataTypeSpecific.$dataTypeSpecific_name$ = $dataTypeSpecific_value$,\n"
+ " .number = $field_number_name$,\n"
+ " .hasIndex = $has_index$,\n"
+ " .offset = $storage_offset_value$,$storage_offset_comment$\n"
+ " .flags = $fieldflags$,\n"
+ " .dataType = GPBDataType$field_type$,\n"
+ "},\n");
}
+}
- printer->Print("},\n");
+void FieldGenerator::SetRuntimeHasBit(int has_index) {
+ variables_["has_index"] = SimpleItoa(has_index);
}
-void FieldGenerator::GenerateFieldDescriptionTypeSpecific(
- io::Printer* printer) const {
- printer->Print(
- variables_,
- " .dataTypeSpecific.$dataTypeSpecific_name$ = $dataTypeSpecific_value$,\n");
+void FieldGenerator::SetNoHasBit(void) {
+ variables_["has_index"] = "GPBNoHasBit";
+}
+
+int FieldGenerator::ExtraRuntimeHasBitsNeeded(void) const {
+ return 0;
+}
+
+void FieldGenerator::SetExtraRuntimeHasBitsBase(int index_base) {
+ // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
+ // error cases, so it seems to be ok to use as a back door for errors.
+ cerr << "Error: should have overriden SetExtraRuntimeHasBitsBase()." << endl;
+ cerr.flush();
+ abort();
}
void FieldGenerator::SetOneofIndexBase(int index_base) {
@@ -270,15 +264,15 @@ void SingleFieldGenerator::GenerateFieldStorageDeclaration(
void SingleFieldGenerator::GeneratePropertyDeclaration(
io::Printer* printer) const {
printer->Print(variables_, "$comments$");
+ printer->Print(
+ variables_,
+ "@property(nonatomic, readwrite) $property_type$ $name$;\n"
+ "\n");
if (WantsHasProperty()) {
printer->Print(
variables_,
"@property(nonatomic, readwrite) BOOL has$capitalized_name$;\n");
}
- printer->Print(
- variables_,
- "@property(nonatomic, readwrite) $property_type$ $name$;\n"
- "\n");
}
void SingleFieldGenerator::GeneratePropertyImplementation(
@@ -302,6 +296,14 @@ bool SingleFieldGenerator::WantsHasProperty(void) const {
return false;
}
+bool SingleFieldGenerator::RuntimeUsesHasBit(void) const {
+ if (descriptor_->containing_oneof() != NULL) {
+ // The oneof tracks what is set instead.
+ return false;
+ }
+ return true;
+}
+
ObjCObjFieldGenerator::ObjCObjFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
: SingleFieldGenerator(descriptor, options) {
@@ -326,14 +328,15 @@ void ObjCObjFieldGenerator::GeneratePropertyDeclaration(
// conventions (init*, new*, etc.)
printer->Print(variables_, "$comments$");
+ printer->Print(
+ variables_,
+ "@property(nonatomic, readwrite, $property_storage_attribute$, null_resettable) $property_type$ *$name$$storage_attribute$;\n");
if (WantsHasProperty()) {
printer->Print(
variables_,
+ "/// Test to see if @c $name$ has been set.\n"
"@property(nonatomic, readwrite) BOOL has$capitalized_name$;\n");
}
- printer->Print(
- variables_,
- "@property(nonatomic, readwrite, $property_storage_attribute$, null_resettable) $property_type$ *$name$$storage_attribute$;\n");
if (IsInitName(variables_.find("name")->second)) {
// If property name starts with init we need to annotate it to get past ARC.
// http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
@@ -346,8 +349,6 @@ void ObjCObjFieldGenerator::GeneratePropertyDeclaration(
RepeatedFieldGenerator::RepeatedFieldGenerator(
const FieldDescriptor* descriptor, const Options& options)
: ObjCObjFieldGenerator(descriptor, options) {
- // Repeated fields don't use the has index.
- variables_["has_index"] = "GPBNoHasBit";
// Default to no comment and let the cases needing it fill it in.
variables_["array_comment"] = "";
}
@@ -385,6 +386,7 @@ void RepeatedFieldGenerator::GeneratePropertyDeclaration(
"$comments$"
"$array_comment$"
"@property(nonatomic, readwrite, strong, null_resettable) $array_property_type$ *$name$$storage_attribute$;\n"
+ "/// The number of items in @c $name$ without causing the array to be created.\n"
"@property(nonatomic, readonly) NSUInteger $name$_Count;\n");
if (IsInitName(variables_.find("name")->second)) {
// If property name starts with init we need to annotate it to get past ARC.
@@ -400,6 +402,10 @@ bool RepeatedFieldGenerator::WantsHasProperty(void) const {
return false;
}
+bool RepeatedFieldGenerator::RuntimeUsesHasBit(void) const {
+ return false; // The array having anything is what is used.
+}
+
FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
const Options& options)
: descriptor_(descriptor),
@@ -430,12 +436,40 @@ const FieldGenerator& FieldGeneratorMap::get_extension(int index) const {
return *extension_generators_[index];
}
+int FieldGeneratorMap::CalculateHasBits(void) {
+ int total_bits = 0;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (field_generators_[i]->RuntimeUsesHasBit()) {
+ field_generators_[i]->SetRuntimeHasBit(total_bits);
+ ++total_bits;
+ } else {
+ field_generators_[i]->SetNoHasBit();
+ }
+ int extra_bits = field_generators_[i]->ExtraRuntimeHasBitsNeeded();
+ if (extra_bits) {
+ field_generators_[i]->SetExtraRuntimeHasBitsBase(total_bits);
+ total_bits += extra_bits;
+ }
+ }
+ return total_bits;
+}
+
void FieldGeneratorMap::SetOneofIndexBase(int index_base) {
for (int i = 0; i < descriptor_->field_count(); i++) {
field_generators_[i]->SetOneofIndexBase(index_base);
}
}
+bool FieldGeneratorMap::DoesAnyFieldHaveNonZeroDefault(void) const {
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (HasNonZeroDefaultValue(descriptor_->field(i))) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
} // namespace objectivec
} // namespace compiler
} // namespace protobuf