static void add_polygon_error(char osm_type, osmid_t osm_id,
                              const char *key_class, const char *type,
                              struct keyval *names, const char *countrycode,
                              const char *wkt)
{
   int first;
   struct keyval *name;
   char sql[2048];

   /* Output a copy line for this place */
   sprintf(sql, "%c\t%" PRIdOSMID "\t", osm_type, osm_id);
   copy_error_data(sql);

   escape(sql, sizeof(sql), key_class);
   copy_error_data(sql);
   copy_error_data("\t");

   escape(sql, sizeof(sql), type);
   copy_error_data(sql);
   copy_error_data("\t");

   /* start name array */
   if (keyval::listHasData(names))
   {
      first = 1;
      for (name = keyval::firstItem(names); name; name = keyval::nextItem(names, name))
      {
         if (first) first = 0;
         else copy_error_data(", ");

         copy_error_data("\"");

         escape_array_record(sql, sizeof(sql), name->key);
         copy_error_data(sql);

         copy_error_data("\"=>\"");

         escape_array_record(sql, sizeof(sql), name->value);
         copy_error_data(sql);

         copy_error_data("\"");
      }
      copy_error_data("\t");
   }
   else
   {
      copy_error_data("\\N\t");
   }

   if (countrycode)
   {
      escape(sql, sizeof(sql), countrycode);
      copy_error_data(sql);
      copy_error_data("\t");
   }
   else
   {
     copy_error_data("\\N\t");
   }

   copy_error_data("now\tNot a polygon\t\\N\t");

   sprintf(sql, "SRID=%d;", SRID);
   copy_error_data(sql);
   copy_error_data(wkt);

   copy_error_data("\n");


   return;
}
void place_tag_processor::copy_out(char osm_type, osmid_t osm_id,
                                   const std::string &geom,
                                   std::string &buffer)
{
    for (const auto& place: places) {
        std::string name;
        if (place.key == "bridge" || place.key == "tunnel") {
            name = domain_name(place.key);
            if (name.empty())
                continue; // don't include unnamed bridges and tunnels
        }

        // osm_type
        buffer += osm_type;
        buffer += '\t';
        // osm_id
        buffer += (single_fmt % osm_id).str();
        // class
        escape(place.key, buffer);
        buffer += '\t';
        // type
        escape(place.value, buffer);
        buffer += '\t';
        // names
        if (!name.empty()) {
            buffer += name;
            buffer += '\t';
        } else if (!names.empty()) {
            bool first = true;
            // operator will be ignored on anything but these classes
            // (amenity for restaurant and fuel)
            bool shop = (place.key == "shop") ||
                        (place.key == "amenity") ||
                        (place.key == "tourism");
            for (const auto entry: names) {
                if (!shop && (entry->key == "operator"))
                    continue;

                if (first)
                    first = false;
                else
                    buffer += ',';

                buffer += "\"";
                escape_array_record(entry->key, buffer);
                buffer += "\"=>\"";
                escape_array_record(entry->value, buffer);
                buffer += "\"";
            }
            buffer += '\t';
        } else
            buffer += "\\N\t";
        // admin_level
        buffer += (single_fmt % admin_level).str();
        // house number
        buffer += housenumber;
        buffer += '\t';
        // street
        copy_opt_string(street, buffer);
        // addr_place
        copy_opt_string(addr_place, buffer);
        // isin
        if (!address.empty()) {
            for (const auto entry: address) {
                if (entry->key == "tiger:county") {
                    escape(std::string(entry->value, 0, entry->value.find(",")),
                           buffer);
                    buffer += " county";
                } else {
                    escape(entry->value, buffer);
                }
                buffer += ',';
            }
            buffer[buffer.length() - 1] = '\t';
        } else
            buffer += "\\N\t";
        // postcode
        copy_opt_string(postcode, buffer);
        // country code
        copy_opt_string(countrycode, buffer);
        // extra tags
        if (extratags.empty()) {
            buffer += "\\N\t";
        } else {
            bool first = true;
            for (const auto entry: extratags) {
                if (first)
                    first = false;
                else
                    buffer += ',';

                buffer += "\"";
                escape_array_record(entry->key, buffer);
                buffer += "\"=>\"";
                escape_array_record(entry->value, buffer);
                buffer += "\"";
            }
            buffer += "\t";
        }
        // geometry
        buffer += srid_str;
        buffer += geom;
        buffer += '\n';
    }
}
void output_gazetteer_t::add_place(char osm_type, osmid_t osm_id, const char *key_class, const char *type, struct keyval *names, struct keyval *extratags,
   int adminlevel, struct keyval *housenumber, struct keyval *street, struct keyval *addr_place, const char *isin, struct keyval *postcode, struct keyval *countrycode, const char *wkt)
{
   int first;
   struct keyval *name;
   char sql[2048];

   /* Output a copy line for this place */
   sprintf(sql, "%c\t%" PRIdOSMID "\t", osm_type, osm_id);
   copy_data(sql);

   escape(sql, sizeof(sql), key_class);
   copy_data(sql);
   copy_data("\t");

   escape(sql, sizeof(sql), type);
   copy_data(sql);
   copy_data("\t");

   /* start name array */
   if (keyval::listHasData(names))
   {
      first = 1;
      for (name = keyval::firstItem(names); name; name = keyval::nextItem(names, name))
      {
         if (first) first = 0;
         else copy_data(", ");

         copy_data("\"");

         escape_array_record(sql, sizeof(sql), name->key);
         copy_data(sql);

         copy_data("\"=>\"");

         escape_array_record(sql, sizeof(sql), name->value);
         copy_data(sql);

         copy_data("\"");
      }
      copy_data("\t");
   }
   else
   {
      copy_data("\\N\t");
   }

   sprintf(sql, "%d\t", adminlevel);
   copy_data(sql);

   if (housenumber)
   {
      escape(sql, sizeof(sql), housenumber->value);
      copy_data(sql);
      copy_data("\t");
   }
   else
   {
      copy_data("\\N\t");
   }

   if (street)
   {
      escape(sql, sizeof(sql), street->value);
      copy_data(sql);
      copy_data("\t");
   }
   else
   {
      copy_data("\\N\t");
   }

   if (addr_place)
   {
      escape(sql, sizeof(sql), addr_place->value);
      copy_data(sql);
      copy_data("\t");
   }
   else
   {
      copy_data("\\N\t");
   }

   if (isin)
   {
       /* Skip the leading ',' from the contactination */
      escape(sql, sizeof(sql), isin+1);
      copy_data(sql);
      copy_data("\t");
   }
   else
   {
      copy_data("\\N\t");
   }

   if (postcode)
   {
      escape(sql, sizeof(sql), postcode->value);
      copy_data(sql);
      copy_data("\t");
   }
   else
   {
      copy_data("\\N\t");
   }

   if (countrycode)
   {
      escape(sql, sizeof(sql), countrycode->value);
      copy_data(sql);
      copy_data("\t");
   }
   else
   {
     copy_data("\\N\t");
   }

   /* extra tags array */
   if (keyval::listHasData(extratags))
   {
      first = 1;
      for (name = keyval::firstItem(extratags); name; name = keyval::nextItem(extratags, name))
      {
         if (first) first = 0;
         else copy_data(", ");

         copy_data("\"");

         escape_array_record(sql, sizeof(sql), name->key);
         copy_data(sql);

         copy_data("\"=>\"");

         escape_array_record(sql, sizeof(sql), name->value);
         copy_data(sql);

         copy_data("\"");
      }
      copy_data("\t");
   }
   else
   {
      copy_data("\\N\t");
   }

   sprintf(sql, "SRID=%d;", SRID);
   copy_data(sql);
   copy_data(wkt);

   copy_data("\n");


   return;
}