Como fazer Parser de Toml com C++

Com 11 exemplos práticos de como implementar


Como fazer Parser de Toml com C++

Toml é um formato de arquivo de configuração criado para ser mais legível para humanos usando uma sintaxe mínima, semelhante ao arquivo INI. O nome é um acrônimo para “Tom’s Obvious, Minimal Language” (em português: “Linguagem Mínima e Óbvia do Tom”). O formato foi desenvolvido para mapear de forma inequívoca para tabelas hash.

Apesar de sua especificação ainda ser considerada instável pelo autor, é usado pelo Cargo, ferramenta de produtividade oficial da linguagem Rust, a ferramenta de dependências da linguagem Go, GitLab Runner e InfluxDB e entre outros projetos. Possui implementações nas principais linguagens de programação. Saiba+ .


Toml++ é um analisador de arquivo de configuração TOML e serializador para C++17 e posterior.

Recursos da biblioteca Toml++:

  • Header-only
  • Suporta a versão TOML mais recente (v1.0.0), além de suporte opcional para alguns recursos de linguagem TOML não lançados;
  • C++17 (mais alguns recursos C++20 quando disponíveis, por exemplo, suporte experimental para strings char8_t);
  • Manuseio adequado de UTF-8 (incl. BOM);
  • Funciona com ou sem exceções;
  • Não requer RTTI;
  • Suporte de primeira classe serializando para JSON;
  • Testado no Clang(6+), GCC(7+) e MSVC(VS2019);
  • Testado em x64, x86 e ARM.

Instalação

Instale o subversion

Exemplos para cada distro:

sudo emerge subversion # Gentoo, Funtoo e Portage baseds
sudo apt install subversion # Debian, Ubuntu, Linux Mint APT baseds
sudo pacman -S subversion # Arch Linux, Manjaro e PacMan baseds
sudo yum install subversion # Fedora, Red Hat, CentOS e YUM baseds

Crie e entre no diretório do seu projeto, exemplo:

mkdir meu-projeto
cd meu-projeto

Utilize um arquivo Toml de exemplo:

vim exemplo.md

Conteúdo do exemplo.toml

# Este é um documento TOML.

titulo = "Terminal Root"

[proprietario]
nome = "Marcos Oliveira"
tempo = 2021-09-09T07:32:00-08:00 # Datas sem espaços

[base]
ip = "192.168.1.1"
portas = [8000, 8001, 8002]
max = 5000
ativado = true

[servidores]

   # O recuo (tabulações e/ou espaços) é permitido, mas não obrigatório
   [servidores.alpha]
   ip = "10.0.0.1"
   dc = "eqdc10"

   [servidores.beta]
   ip = "10.0.0.2"
   dc = "eqdc10"

[clientes]
dados = [["gama", "delta"], [1, 2]]

# As quebras de linha estão OK quando dentro de arrays
hosts = [
   "alfa",
   "omega"
]

Clone o subdiretório com o comando:

svn export https://github.com/marzer/tomlplusplus/trunk/include/toml++

Esse procedimento é para cada projeto que você for criar. Se quiser que fique disponível no seu sistema, rode o comando:

sudo cp -r toml++/ /usr/local/include/


Utilização

Vamos ver 11 exemplos de utilização do Toml++.

01. Fazendo o parser básico:

vim main.cpp

Se você instalou no sistema com sudo, use assim:

#include <toml++/toml.h>

Se só clonou com svn dentro do seu projeto, mas não instalou no sistema, use assim:

#include "toml++/toml.h"

Insira isso no seu main.cpp

#include <iostream>
#include <toml++/toml.h>

int main(int argc, char** argv){

  if( argc <= 1 ){
    std::cerr << "Informe o arquivo. Exemplo: " << argv[0] << " exemplo.toml\n";
    return 1;
  } 

  toml::table tbl;
  try{
    tbl = toml::parse_file(argv[1]);
    std::cout << tbl << "\n";
  }
  catch (const toml::parse_error& err){
    std::cerr << "Falha ao fazer parser:\n" << err << "\n";
    return 1;
  }

  return 0;
}

Compile com C++17:

g++ -std=c++17 main.cpp

02. Obtendo um dado único

Por exemplo, saber qual o valor de titulo

tbl = toml::parse_file(argv[1]);
auto titulo = tbl["titulo"];
std::cout << "Título: " << titulo << "\n";

03. Utilizando com o xmake

Se quiser para não ficar digitando o comando para compilar toda hora, utilize esse xmake : vim xmake.lua

add_rules("mode.debug", "mode.release")
set_config("cxxflags", "-std=c++17")
add_cflags("-g", "-Wall", {force = true})

target("parsertomlpp")
  set_kind("binary")
  add_files("main.cpp")

Compile e rode:

xmake -q && xmake run parsertomlpp $(pwd)/exemplo.toml

04. Remover as aspas simples da saída:

std::optional<std::string> titulo = tbl["titulo"].value<std::string>();
std::cout << *titulo << '\n';

Saída será:

Terminal Root

05. Convertendo para std::string

std::string& titulo = tbl["titulo"].ref<std::string>();
std::cout << titulo << '\n';


06. Obtendo sub dados

No exemplo.toml note que a propriedade ip faz parte de [base], mas também faz parte de [servidores](alpha e beta).

Suponha que você deseja obter os dados da [base]:

auto ip = tbl["base"]["ip"];
std::cout << ip << '\n';

Caso você quisesse agora o ip de [servidores] e de alpha:

auto ip = tbl["servidores"]["alpha"]["ip"];
std::cout << ip << '\n';

07. Verificar qual a segunda porta disponível

auto porta = tbl["base"]["portas"][1];
std::cout << porta << '\n';

08. Verifica qual o tipo de dado de portas

auto portas = tbl["base"]["portas"];
std::cout << portas.type() << '\n';

Saída: array

Qual o tipo de dado de uma porta de portas

auto porta = tbl["base"]["portas"][0];
std::cout << porta.type() << '\n';

Saída: integer


09. Descobrindo quantos elementos tem uma tabela do Toml

Exemplo, quantos elementos tem em hosts

auto host = tbl["clientes"]["hosts"];
unsigned int i = {0};
toml::array* arr = host.as_array();
for (toml::node& elem : *arr){
  ++i;
}
std::cout << "Hosts tem: " << i << " elemento(s)." << '\n';

10. Verificando se um elemento existe em uma tabela

Por exemplo, a tabela ["clientes"]["hosts"] só tem: alfa e omega, mas caso não soubéssemos, vamos verificar se beta existe nessa tabela:

auto hosts = tbl["clientes"]["hosts"];
bool its = false;

if (toml::array* arr = hosts.as_array()){
  for (toml::node& elem : *arr){
    std::string& str = elem.ref<std::string>();
    if( str == "beta" ){
      its = true;
    } 
  }
}

std::cout << ( its ? "Disponível" : "Indisponível" ) << '\n';

Saída: Indisponível.


11. Adicionando um elemento à uma tabela

Adicionando beta à [clientes.hosts]:

auto hosts = tbl["clientes"]["hosts"];
toml::array* arr = hosts.as_array();
arr->push_back("beta");
std::cout << hosts << '\n';

Saída: [ 'alfa', 'omega', 'beta' ]


Para mais informações acesse o site oficial e o repositório no GitHUb:

https://marzer.github.io/tomlplusplus/

https://github.com/marzer/tomlplusplus/


Acompanhe o cpp::daily

Deseja aprender C++ e criar seus programas Gráficos e para Terminal com portabilidade para Linux e Windows?

Então se inscreva nos nossos Cursos de C++ Moderno . Você aprender criar:

Acesse o endereço:

https://terminalroot.com.br/cpp/ e saiba mais!


cpp cppdaily


Compartilhe


Nosso canal no Youtube

Inscreva-se


Marcos Oliveira

Marcos Oliveira

Desenvolvedor de software
https://github.com/terroo


Crie Aplicativos Gráficos para Linux e Windows com C++

Aprenda C++ Moderno e crie Games, Programas CLI, GUI e TUI de forma fácil.

Saiba Mais

Receba as novidades no seu e-mail!

Após cadastro e confirmação do e-mail, enviaremos semanalmente resumos e também sempre que houver novidades por aqui para que você mantenha-se atualizado!