cpp/src/phonenumbers/phonenumberutil.cc
// Helper method to check a number against possible lengths for this number
// type, and determine whether it matches, or is too short or too long.
Helper method to check a number against possible lengths for this number
type, and determine whether it matches, or is too short or too long.
Helper method to check a number against possible lengths for this number type and determine whether it matches or is too short or too long .
PhoneNumberUtil::ValidationResult TestNumberLength(
    const string& number, const PhoneMetadata& metadata,
    PhoneNumberUtil::PhoneNumberType type) {
  const PhoneNumberDesc* desc_for_type = GetNumberDescByType(metadata, type);
  RepeatedField<int> possible_lengths =
      desc_for_type->possible_length_size() == 0
          ? metadata.general_desc().possible_length()
          : desc_for_type->possible_length();
  RepeatedField<int> local_lengths =
      desc_for_type->possible_length_local_only();
  if (type == PhoneNumberUtil::FIXED_LINE_OR_MOBILE) {
    const PhoneNumberDesc* fixed_line_desc =
        GetNumberDescByType(metadata, PhoneNumberUtil::FIXED_LINE);
    if (!DescHasPossibleNumberData(*fixed_line_desc)) {
      return TestNumberLength(number, metadata, PhoneNumberUtil::MOBILE);
    } else {
      const PhoneNumberDesc* mobile_desc =
          GetNumberDescByType(metadata, PhoneNumberUtil::MOBILE);
      if (DescHasPossibleNumberData(*mobile_desc)) {
        possible_lengths.MergeFrom(
            mobile_desc->possible_length_size() == 0
            ? metadata.general_desc().possible_length()
            : mobile_desc->possible_length());
        std::sort(possible_lengths.begin(), possible_lengths.end());
        if (local_lengths.size() == 0) {
          local_lengths = mobile_desc->possible_length_local_only();
        } else {
          local_lengths.MergeFrom(mobile_desc->possible_length_local_only());
          std::sort(local_lengths.begin(), local_lengths.end());
        }
      }
    }
  }
  if (possible_lengths.Get(0) == -1) {
    return PhoneNumberUtil::INVALID_LENGTH;
  }
  int actual_length = static_cast<int>(number.length());
  if (std::find(local_lengths.begin(), local_lengths.end(), actual_length) !=
      local_lengths.end()) {
    return PhoneNumberUtil::IS_POSSIBLE_LOCAL_ONLY;
  }
  int minimum_length = possible_lengths.Get(0);
  if (minimum_length == actual_length) {
    return PhoneNumberUtil::IS_POSSIBLE;
  } else if (minimum_length > actual_length) {
    return PhoneNumberUtil::TOO_SHORT;
  } else if (*(possible_lengths.end() - 1) < actual_length) {
    return PhoneNumberUtil::TOO_LONG;
  }
  return std::find(possible_lengths.begin() + 1, possible_lengths.end(),
                   actual_length) != possible_lengths.end()
             ? PhoneNumberUtil::IS_POSSIBLE
             : PhoneNumberUtil::INVALID_LENGTH;
}
PhoneNumberUtil :: ValidationResult TestNumberLength ( const string & number , const PhoneMetadata & metadata , PhoneNumberUtil :: PhoneNumberType type ) { const PhoneNumberDesc * desc_for_type = GetNumberDescByType ( metadata , type ) ; RepeatedField < int > possible_lengths = desc_for_type -> possible_length_size ( ) == 0 ? metadata . general_desc ( ) . possible_length ( ) : desc_for_type -> possible_length ( ) ; RepeatedField < int > local_lengths = desc_for_type -> possible_length_local_only ( ) ; if ( type == PhoneNumberUtil :: FIXED_LINE_OR_MOBILE ) { const PhoneNumberDesc * fixed_line_desc = GetNumberDescByType ( metadata , PhoneNumberUtil :: FIXED_LINE ) ; if ( ! DescHasPossibleNumberData ( * fixed_line_desc ) ) { return TestNumberLength ( number , metadata , PhoneNumberUtil :: MOBILE ) ; } else { const PhoneNumberDesc * mobile_desc = GetNumberDescByType ( metadata , PhoneNumberUtil :: MOBILE ) ; if ( DescHasPossibleNumberData ( * mobile_desc ) ) { possible_lengths . MergeFrom ( mobile_desc -> possible_length_size ( ) == 0 ? metadata . general_desc ( ) . possible_length ( ) : mobile_desc -> possible_length ( ) ) ; std :: sort ( possible_lengths . begin ( ) , possible_lengths . end ( ) ) ; if ( local_lengths . size ( ) == 0 ) { local_lengths = mobile_desc -> possible_length_local_only ( ) ; } else { local_lengths . MergeFrom ( mobile_desc -> possible_length_local_only ( ) ) ; std :: sort ( local_lengths . begin ( ) , local_lengths . end ( ) ) ; } } } } if ( possible_lengths . Get ( 0 ) == -1 ) { return PhoneNumberUtil :: INVALID_LENGTH ; } int actual_length = static_cast < int > ( number . length ( ) ) ; if ( std :: find ( local_lengths . begin ( ) , local_lengths . end ( ) , actual_length ) != local_lengths . end ( ) ) { return PhoneNumberUtil :: IS_POSSIBLE_LOCAL_ONLY ; } int minimum_length = possible_lengths . Get ( 0 ) ; if ( minimum_length == actual_length ) { return PhoneNumberUtil :: IS_POSSIBLE ; } else if ( minimum_length > actual_length ) { return PhoneNumberUtil :: TOO_SHORT ; } else if ( * ( possible_lengths . end ( ) - 1 ) < actual_length ) { return PhoneNumberUtil :: TOO_LONG ; } return std :: find ( possible_lengths . begin ( ) + 1 , possible_lengths . end ( ) , actual_length ) != possible_lengths . end ( ) ? PhoneNumberUtil :: IS_POSSIBLE : PhoneNumberUtil :: INVALID_LENGTH ; }
Helper method to check a number against possible lengths for this number
type, and determine whether it matches, or is too short or too long.
Helper method to check a number against possible lengths for this number type and determine whether it matches or is too short or too long .
// There should always be "possibleLengths" set for every element. This is // declared in the XML schema which is verified by // PhoneNumberMetadataSchemaTest. For size efficiency, where a // sub-description (e.g. fixed-line) has the same possibleLengths as the // parent, this is missing, so we fall back to the general desc (where no // numbers of the type exist at all, there is one possible length (-1) which // is guaranteed not to match the length of any real phone number). // The rare case has been encountered where no fixedLine data is available // (true for some non-geographical entities), so we just check mobile. // Merge the mobile data in if there was any. Note that when adding the // possible lengths from mobile, we have to again check they aren't // empty since if they are this indicates they are the same as the // general desc and should be obtained from there. // If the type is not suported at all (indicated by the possible lengths // containing -1 at this point) we return invalid length. // This is safe because there is never an overlap beween the possible lengths // and the local-only lengths; this is checked at build time. // We skip the first element; we've already checked it.