std::vector< const Candidate * > CandidateRepository::GetCandidatesForStrings(
  const std::vector< std::string > &strings ) {
  std::vector< const Candidate * > candidates;
  candidates.reserve( strings.size() );

  {
    boost::lock_guard< boost::mutex > locker( holder_mutex_ );

    foreach ( const std::string & candidate_text, strings ) {
      const Candidate *&candidate = GetValueElseInsert( candidate_holder_,
                                                        candidate_text,
                                                        NULL );

      if ( !candidate )
        candidate = new Candidate( candidate_text );

      candidates.push_back( candidate );
    }
  }

  return candidates;
}
std::vector< const Candidate * > CandidateRepository::GetCandidatesForStrings(
  const std::vector< CompletionData > &datas ) {
  std::vector< const Candidate * > candidates;
  candidates.reserve( datas.size() );

  {
    boost::lock_guard< boost::mutex > locker( holder_mutex_ );

    foreach ( const CompletionData & data, datas ) {
      const Candidate *&candidate = GetValueElseInsert( candidate_holder_,
                                                        data.original_string_,
                                                        NULL );

      if ( !candidate )
        candidate = new Candidate( data.original_string_ );

      candidates.push_back( candidate );
    }
  }

  return candidates;
}
std::vector< CompletionData > ToCompletionDataVector(
  CXCodeCompleteResults *results ) {
  std::vector< CompletionData > completions;

  if ( !results || !results->Results )
    return completions;

  completions.reserve( results->NumResults );
  unordered_map< std::string, uint > seen_data;

  for ( uint i = 0; i < results->NumResults; ++i ) {
    CXCompletionResult completion_result = results->Results[ i ];

    if ( !CompletionStringAvailable( completion_result.CompletionString ) )
      continue;

    CompletionData data( completion_result );
    uint index = GetValueElseInsert( seen_data,
                                     data.original_string_,
                                     completions.size() );

    if ( index == completions.size() ) {
      completions.push_back( boost::move( data ) );
    }

    else {
      // If we have already seen this completion, then this is an overload of a
      // function we have seen. We add the signature of the overload to the
      // detailed information.
      completions[ index ].detailed_info_
      .append( data.return_type_ )
      .append( " " )
      .append( data.everything_except_return_type_ )
      .append( "\n" );
    }
  }

  return completions;
}