// This file is generated by ErrorSupport_cpp.template.

// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//#include "ErrorSupport.h"

{% for namespace in config.protocol.namespace %}
namespace {{namespace}} {
{% endfor %}

ErrorSupport::ErrorSupport() { }
ErrorSupport::~ErrorSupport() { }

void ErrorSupport::setName(const char* name)
{
    setName(String(name));
}

void ErrorSupport::setName(const String& name)
{
    DCHECK(m_path.size());
    m_path[m_path.size() - 1] = name;
}

void ErrorSupport::push()
{
    m_path.push_back(String());
}

void ErrorSupport::pop()
{
    m_path.pop_back();
}

void ErrorSupport::addError(const char* error)
{
    addError(String(error));
}

void ErrorSupport::addError(const String& error)
{
    StringBuilder builder;
    for (size_t i = 0; i < m_path.size(); ++i) {
        if (i)
            StringUtil::builderAppend(builder, '.');
        StringUtil::builderAppend(builder, m_path[i]);
    }
    StringUtil::builderAppend(builder, ": ");
    StringUtil::builderAppend(builder, error);
    m_errors.push_back(StringUtil::builderToString(builder));
}

bool ErrorSupport::hasErrors()
{
    return !!m_errors.size();
}

String ErrorSupport::errors()
{
    StringBuilder builder;
    for (size_t i = 0; i < m_errors.size(); ++i) {
        if (i)
            StringUtil::builderAppend(builder, "; ");
        StringUtil::builderAppend(builder, m_errors[i]);
    }
    return StringUtil::builderToString(builder);
}

{% for namespace in config.protocol.namespace %}
} // namespace {{namespace}}
{% endfor %}
