This is an automated email from the ASF dual-hosted git repository.
westonpace pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-cookbook.git
The following commit(s) were added to refs/heads/main by this push:
new d15e75c Initial C++ cookbook (#22)
d15e75c is described below
commit d15e75c1d15b22b27d634a4254ef9ee8c41a9737
Author: Weston Pace <[email protected]>
AuthorDate: Mon Aug 23 09:44:26 2021 -1000
Initial C++ cookbook (#22)
* Initial C++ cookbook
* Addressing PR feedback. Converted contributing doc from RST to MD (since
the extension was MD).
* Update cpp/CONTRIBUTING.md
Co-authored-by: David Li <[email protected]>
* Creating standalone section for code of conduct
* Update cpp/CONTRIBUTING.md
Co-authored-by: David Li <[email protected]>
* Addressing PR comments
Co-authored-by: David Li <[email protected]>
---
.github/workflows/deploy_cookbooks.yml | 44 ++++++++-
.gitignore | 6 ++
Makefile | 19 +++-
build/index.html | 1 +
cpp/CONTRIBUTING.md | 170 +++++++++++++++++++++++++++++++++
cpp/Makefile | 20 ++++
cpp/code/.clang-format | 20 ++++
cpp/code/.gitignore | 1 +
cpp/code/CMakeLists.txt | 47 +++++++++
cpp/code/basic_arrow.cc | 59 ++++++++++++
cpp/code/common.cc | 161 +++++++++++++++++++++++++++++++
cpp/code/common.h | 52 ++++++++++
cpp/code/creating_arrow_objects.cc | 55 +++++++++++
cpp/code/main.cc | 42 ++++++++
cpp/environment.yml | 115 ++++++++++++++++++++++
cpp/ext/recipeext.py | 102 ++++++++++++++++++++
cpp/make.bat | 35 +++++++
cpp/requirements.txt | 2 +
cpp/source/basic.rst | 49 ++++++++++
cpp/source/conf.py | 72 ++++++++++++++
cpp/source/create.rst | 49 ++++++++++
cpp/source/index.rst | 37 +++++++
22 files changed, 1155 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/deploy_cookbooks.yml
b/.github/workflows/deploy_cookbooks.yml
index f12ded9..07ca317 100644
--- a/.github/workflows/deploy_cookbooks.yml
+++ b/.github/workflows/deploy_cookbooks.yml
@@ -29,10 +29,47 @@ jobs:
name: build_book
path: build/
+ make_cpp:
+ name: build c++
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ shell: bash -l {0}
+ steps:
+ - uses: actions/checkout@v1
+ - name: Cache conda
+ uses: actions/cache@v2
+ env:
+ # Increase this value to reset cache if cpp/environment.yml has not
changed
+ CACHE_NUMBER: 0
+ with:
+ path: ~/conda_pkgs_dir
+ key:
+ ${{ runner.os }}-conda-${{ env.CACHE_NUMBER }}-${{
hashFiles('cpp/environment.yml') }}
+ - name: Setup environment
+ uses: conda-incubator/setup-miniconda@v2
+ with:
+ auto-update-conda: true
+ python-version: 3.9
+ activate-environment: cookbook-cpp
+ environment-file: cpp/environment.yml
+ auto-activate-base: false
+ - name: Test
+ run:
+ echo ${CONDA_PREFIX}
+ - name: Build cookbook
+ run:
+ make cpp
+ - name: Upload cpp book
+ uses: actions/upload-artifact@v1
+ with:
+ name: cpp_book
+ path: build/cpp
+
deploy_cookbooks:
name: deploy
runs-on: ubuntu-latest
- needs: make_cookbooks
+ needs: [make_cookbooks, make_cpp]
steps:
- name: Checkout repo
uses: actions/checkout@v2
@@ -47,6 +84,11 @@ jobs:
with:
name: build_book
path: .
+ - name: Download cpp book
+ uses: actions/[email protected]
+ with:
+ name: cpp_book
+ path: ./cpp
- name: Push changes to gh-pages/asf-site branch
run: |
git config --global user.name 'GitHub Actions'
diff --git a/.gitignore b/.gitignore
index 3e6a548..040bc4c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,12 @@
r/content/_book/**
+r/content/_main.Rmd
r/*.Rproj
*.Rproj
.Rproj.user
+*.idea/
+*.vscode/
+
*build/
*.parquet
@@ -10,3 +14,5 @@ r/*.Rproj
*.arrows
*.csv
*.feather
+
+*.pyc
diff --git a/Makefile b/Makefile
index ad2b473..2acc8df 100644
--- a/Makefile
+++ b/Makefile
@@ -2,10 +2,10 @@ all: html
html: py r
- @echo "\n\n>>> Cookbooks Available in ./build <<<"
+ @echo "\n\n>>> Cookbooks (except C++) Available in ./build <<<"
-test: pytest rtest
+test: pytest rtest
help:
@@ -48,8 +48,23 @@ r: rdeps
mkdir -p build/r
cp -r r/content/_book/* build/r
+
rtest: rdeps
@echo ">>> Testing R Cookbook <<<\n"
cd ./r && Rscript ./scripts/test.R
+cpptest:
+ @echo ">>> Running C++ Tests/Snippets <<<\n"
+ rm -rf cpp/recipe-test-build
+ mkdir cpp/recipe-test-build
+ cd cpp/recipe-test-build && cmake ../code -DCMAKE_BUILD_TYPE=Debug &&
cmake --build . && ctest -j 1
+ mkdir -p cpp/build
+ cp cpp/recipe-test-build/recipes_out.arrow cpp/build
+
+
+cpp: cpptest
+ @echo ">>> Building C++ Cookbook <<<\n"
+ cd cpp && make html
+ mkdir -p build/cpp
+ cp -r cpp/build/html/* build/cpp
diff --git a/build/index.html b/build/index.html
index d5ee952..a1a2a93 100644
--- a/build/index.html
+++ b/build/index.html
@@ -38,6 +38,7 @@
but some are specific to the language and environment in use.
</p>
<ul>
+ <li><a href="cpp/index.html">C++ Cookbook</a></li>
<li><a href="py/index.html">Python Cookbook</a></li>
<li><a href="r/index.html">R Cookbook</a></li>
</ul>
diff --git a/cpp/CONTRIBUTING.md b/cpp/CONTRIBUTING.md
new file mode 100644
index 0000000..153192e
--- /dev/null
+++ b/cpp/CONTRIBUTING.md
@@ -0,0 +1,170 @@
+# Bulding the C++ Cookbook
+
+The C++ cookbook combines output from a set of C++ test programs with
+an reStructuredText (RST) document tree rendered with Sphinx.
+
+Running `make py` from the cookbook root directory (the one where
+the `README.rst` exists) will install all necessary dependencies,
+run the tests to generate the output, and will compile the cookbook
+to HTML.
+
+You will see the compiled result inside the `build/cpp` directory.
+
+The above process requires conda to be installed and is primarily
+intended for build systems. See below for more information on setting
+up a development environment for developing recipes.
+
+# Developing C++ Recipes
+
+Every recipe is a combination of prose written in RST
+format using the [Sphinx](https://www.sphinx-doc.org/) documentation
+system and a snippet of a googletest test.
+
+New recipes can be added to one of the existing `.rst` files if
+they suit that section or you can create new sections by adding
+additional `.rst` files in the `source` directory. You just
+need to remember to add them to the `index.rst` file in the
+`toctree` for them to become visible.
+
+## Referencing a C++ Snippet
+
+Most recipes will reference a snippet of C++ code. For simplicity
+a custom `recipe` directive that can be used like so:
+
+```
+.. recipe:: ../code/creating_arrow_objects.cc CreatingArrays
+ :caption: Creating an array from C++ primitives
+ :dedent: 4
+```
+
+Each `recipe` directive has two requried arguments. The first is
+a path to the file containing the source file containing the snippet
+and the second is the name of the snippet and must correspond to a
+set of CreateRecipe/EndRecipe calls in the source file.
+
+The directive will generate two code blocks in the cookbook. The first
+code block will contain the source code itself and will be annotated
+with any (optional) caption specified on the recipe directive. The
+second block will contain the test output.
+
+The optional `dedent` argument should be used to remove leading white
+space from your source code.
+
+## Writing a C++ Snippet
+
+Each snippet source file contains a set of
+[googletest](https://github.com/google/googletest) tests. Feel free to
+use any googletest features needed to help setup and verify your test.
+To reference a snippet you need to surround it in `BeginRecipe` and
+`EndRecipe` calls. For example:
+
+```
+StartRecipe("CreatingArrays");
+arrow::Int32Builder builder;
+ASSERT_OK(builder.Append(1));
+ASSERT_OK(builder.Append(2));
+ASSERT_OK(builder.Append(3));
+ASSERT_OK_AND_ASSIGN(shared_ptr<arrow::Array> arr, builder.Finish())
+rout << arr->ToString() << endl;
+EndRecipe("CreatingArrays");
+```
+
+The variable `rout` is set to a `std::ostream` instance that is used to
+capture test output. Anything output to `rout` will show up in the recipe
+output block when the recipe is rendered into the cookbook.
+
+## Referencing Arrow C++ Documentation
+
+The Arrow project has its own documentation for the C++ implementation that
+is hosted at https://arrow.apache.org/docs/cpp/index.html. Fortunately,
+this documentation is also built with Sphinx and so we can use the extension
+`intersphinx` to reference sections of this documentation. To do so simply
+write a standard Sphinx reference like so:
+
+```
+Typed subclasses of :cpp:class:`arrow::ArrayBuilder` make it easy
+to efficiently create Arrow arrays from existing C++ data
+```
+
+A helpful command is
+`python -msphinx.ext.intersphinx https://arrow.apache.org/docs/objects.inv`
+which will list all of the possible targets to link to.
+
+# Development Workflow
+
+Running `make` at the top level can be rather slow as it will rebuild the
+entire environment each time. It is primarily intended for use in CI and
+requires you to have conda installed.
+
+For recipe development you are encouraged to create your own out-of-source
+cmake build. For example:
+
+```
+mkdir cpp/code/build
+cd cpp/code/build
+cmake ../code -DCMAKE_BUILD_TYPE=Debug
+cmake --build .
+ctest
+```
+
+Then you can rerun all of the tests with `ctest` and you can rebuild and
+rerun individual tests much more quickly with something like
+`cmake --build . --target creating_arrow_objects && ctest
creating_arrow_objects`.
+Everytime the cmake build is run it will update the recipe output file
+referenced by the sphinx build so after rerunning a test you can visualize the
+output by running `make html` in the `cpp` directory.
+
+## Using Conda
+
+If you are using conda then there is file `cpp/requirements.yml` which can be
+used to create an environment for recipe development with the command:
+
+```
+conda env create -n cookbook-cpp --file cpp/requirements.yml
+```
+
+# Development Philosophy
+
+## Everything is the Cookbook
+
+The entire document should serve as an example of how to use Arrow C++, not
just the
+referenced snippets. This means that the below style rules and guidelines
apply to
+source code that is not referenced by the cookbook itself.
+
+## Style
+
+This cookbook follows the same style rules as Arrow C++ which is the Google
style
+guide with a few exceptions described
+[here](https://arrow.apache.org/docs/developers/cpp/development.html#code-style-linting-and-ci)
+
+## Simple
+
+The examples should be as simple as possible. If complex code (e.g. templates)
can be
+used to do something more efficiently then there should be a simple,
inefficient version
+alongside the more complex version.
+
+Do not use `auto` in any of the templates unless you must (e.g. lambdas).
Cookbook
+viewers will be using a browser, not an IDE, and it is not always simple to
determine
+the inferred type.
+
+# The Custom Recipe Directive
+
+C++ is not, at the moment, a "notebook friendly" language and it does lend
itself well
+to being embedded inside an RST file. As such, we use a custom directive to
link the
+Googletest source files and the RST prose. The directive works with the helper
methods
+`BeginRecipe` and `EndRecipe` defined in `common.h`.
+
+The helper method `BeginRecipe` will begin capturing output to `rout`. The
helper method
+`EndRecipe` will append the captured output and recipe name to string arrays.
There is code
+in `main.cc` which runs after the tests run to dump these arrays to a .arrow
file (i.e. the
+arrays will be serialized as a table using the Arrow IPC format).
+
+When the sphinx build runs the directive `recipe` (defined in `cpp/ext`) will
be loaded.
+During this load the dataset of test outputs will be read. These test outputs
will be used
+whenever a recipe is referenced.
+
+# Code of Conduct
+
+All participation in the Apache Arrow project is governed by the Apache
+Software Foundation’s
+`code of conduct <https://www.apache.org/foundation/policies/conduct.html>`\_.
diff --git a/cpp/Makefile b/cpp/Makefile
new file mode 100644
index 0000000..a023ec1
--- /dev/null
+++ b/cpp/Makefile
@@ -0,0 +1,20 @@
+# Minimal makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line, and also
+# from the environment for the first two.
+SPHINXOPTS ?= -jauto
+SPHINXBUILD ?= sphinx-build
+SOURCEDIR = source
+BUILDDIR = build
+
+# Put it first so that "make" without argument is like "make help".
+help:
+ @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+.PHONY: help Makefile
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff --git a/cpp/code/.clang-format b/cpp/code/.clang-format
new file mode 100644
index 0000000..06453df
--- /dev/null
+++ b/cpp/code/.clang-format
@@ -0,0 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+---
+BasedOnStyle: Google
+DerivePointerAlignment: false
+ColumnLimit: 90
diff --git a/cpp/code/.gitignore b/cpp/code/.gitignore
new file mode 100644
index 0000000..78d1dfe
--- /dev/null
+++ b/cpp/code/.gitignore
@@ -0,0 +1 @@
+*-build*/
\ No newline at end of file
diff --git a/cpp/code/CMakeLists.txt b/cpp/code/CMakeLists.txt
new file mode 100644
index 0000000..213d48a
--- /dev/null
+++ b/cpp/code/CMakeLists.txt
@@ -0,0 +1,47 @@
+cmake_minimum_required(VERSION 3.19)
+project(arrow-cookbook)
+
+set(CMAKE_CXX_STANDARD 17)
+
+# Add googletest
+include(FetchContent)
+FetchContent_Declare(
+ googletest
+ GIT_REPOSITORY https://github.com/google/googletest.git
+ GIT_TAG e2239ee6043f73722e7aa812a459f54a28552929 # release-1.11.0
+)
+# For Windows: Prevent overriding the parent project's compiler/linker settings
+set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
+FetchContent_MakeAvailable(googletest)
+
+# Add Arrow
+find_package(Arrow REQUIRED)
+
+# Create test targets
+enable_testing()
+include(GoogleTest)
+add_executable(
+ creating_arrow_objects
+ creating_arrow_objects.cc
+ common.cc
+ main.cc
+)
+target_link_libraries(
+ creating_arrow_objects
+ arrow_shared
+ gtest
+)
+gtest_discover_tests(creating_arrow_objects)
+
+add_executable(
+ basic_arrow
+ basic_arrow.cc
+ common.cc
+ main.cc
+)
+target_link_libraries(
+ basic_arrow
+ arrow_shared
+ gtest
+)
+gtest_discover_tests(basic_arrow)
diff --git a/cpp/code/basic_arrow.cc b/cpp/code/basic_arrow.cc
new file mode 100644
index 0000000..9af8f41
--- /dev/null
+++ b/cpp/code/basic_arrow.cc
@@ -0,0 +1,59 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include <arrow/api.h>
+#include <gtest/gtest.h>
+
+#include "common.h"
+
+TEST(BasicArrow, ReturnNotOkNoMacro) {
+ StartRecipe("ReturnNotOkNoMacro");
+ std::function<arrow::Status()> test_fn = [] {
+ arrow::NullBuilder builder;
+ arrow::Status st = builder.Reserve(2);
+ // Tedious return value check
+ if (!st.ok()) {
+ return st;
+ }
+ st = builder.AppendNulls(-1);
+ // Tedious return value check
+ if (!st.ok()) {
+ return st;
+ }
+ rout << "Appended -1 null values?" << std::endl;
+ return arrow::Status::OK();
+ };
+ arrow::Status st = test_fn();
+ rout << st << std::endl;
+ EndRecipe("ReturnNotOkNoMacro");
+ ASSERT_FALSE(st.ok());
+}
+
+TEST(BasicArrow, ReturnNotOk) {
+ StartRecipe("ReturnNotOk");
+ std::function<arrow::Status()> test_fn = [] {
+ arrow::NullBuilder builder;
+ ARROW_RETURN_NOT_OK(builder.Reserve(2));
+ ARROW_RETURN_NOT_OK(builder.AppendNulls(-1));
+ rout << "Appended -1 null values?" << std::endl;
+ return arrow::Status::OK();
+ };
+ arrow::Status st = test_fn();
+ rout << st << std::endl;
+ EndRecipe("ReturnNotOk");
+ ASSERT_FALSE(st.ok());
+}
diff --git a/cpp/code/common.cc b/cpp/code/common.cc
new file mode 100644
index 0000000..0024c4c
--- /dev/null
+++ b/cpp/code/common.cc
@@ -0,0 +1,161 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include <sstream>
+#include <unordered_map>
+
+#include "arrow/api.h"
+#include "arrow/filesystem/api.h"
+#include "arrow/ipc/api.h"
+#include "gtest/gtest.h"
+
+#include "common.h"
+
+static arrow::StringBuilder test_names_builder;
+static arrow::StringBuilder test_output_builder;
+static std::string current_recipe;
+
+void StartRecipe(const std::string& recipe_name) {
+ if (!current_recipe.empty()) {
+ FAIL() << "Attempt to start a recipe " << recipe_name << " but the recipe "
+ << current_recipe << " has not been marked finished";
+ }
+ if (recipe_name.empty()) {
+ FAIL() << "Invalid empty recipe name";
+ }
+ current_recipe = recipe_name;
+ rout = std::stringstream();
+}
+
+void EndRecipe(const std::string& recipe_name) {
+ if (current_recipe != recipe_name) {
+ FAIL() << "Attempt to end a recipe " << recipe_name
+ << " but the recipe was not in progress";
+ }
+ std::string recipe_output = rout.str();
+
+ ASSERT_OK(test_names_builder.Append(recipe_name));
+ ASSERT_OK(test_output_builder.Append(recipe_output));
+
+ current_recipe = "";
+}
+
+std::shared_ptr<arrow::Schema> RecipesTableSchema() {
+ return arrow::schema({arrow::field("Recipe Name", arrow::utf8()),
+ arrow::field("Recipe Output", arrow::utf8())});
+}
+
+std::shared_ptr<arrow::Array> MakeEmptyStringArray() {
+ arrow::StringBuilder builder;
+ return builder.Finish().ValueOrDie();
+}
+
+arrow::Result<std::shared_ptr<arrow::Table>> MakeEmptyRecipesTable() {
+ std::shared_ptr<arrow::Schema> schema = RecipesTableSchema();
+ std::shared_ptr<arrow::RecordBatch> batch = arrow::RecordBatch::Make(
+ schema, 0, {MakeEmptyStringArray(), MakeEmptyStringArray()});
+ return arrow::Table::FromRecordBatches({batch});
+}
+
+arrow::Result<std::shared_ptr<arrow::Table>> ReadRecipeTable(
+ const std::shared_ptr<arrow::io::RandomAccessFile>& in_file) {
+ ARROW_ASSIGN_OR_RAISE(std::shared_ptr<arrow::ipc::RecordBatchStreamReader>
reader,
+ arrow::ipc::RecordBatchStreamReader::Open(in_file));
+ std::shared_ptr<arrow::Table> table;
+ ARROW_RETURN_NOT_OK(reader->ReadAll(&table));
+ return table;
+}
+
+arrow::Result<std::shared_ptr<arrow::Table>> LoadExistingRecipeOutputTable(
+ const std::string& filename) {
+ std::shared_ptr<arrow::fs::FileSystem> fs =
+ std::make_shared<arrow::fs::LocalFileSystem>();
+ arrow::Result<std::shared_ptr<arrow::io::RandomAccessFile>> maybe_in =
+ fs->OpenInputFile(filename);
+ if (!maybe_in.ok()) {
+ return MakeEmptyRecipesTable();
+ }
+ std::shared_ptr<arrow::io::RandomAccessFile> in = *maybe_in;
+ return ReadRecipeTable(in);
+}
+
+arrow::Result<std::shared_ptr<arrow::Table>> CreateRecipeOutputTable() {
+ ARROW_ASSIGN_OR_RAISE(std::shared_ptr<arrow::Array> test_names,
+ test_names_builder.Finish());
+ ARROW_ASSIGN_OR_RAISE(std::shared_ptr<arrow::Array> test_outputs,
+ test_output_builder.Finish());
+ std::shared_ptr<arrow::Schema> schema =
+ arrow::schema({arrow::field("Recipe Name", arrow::utf8()),
+ arrow::field("Recipe Output", arrow::utf8())});
+ std::shared_ptr<arrow::RecordBatch> batch =
+ arrow::RecordBatch::Make(schema, test_names->length(), {test_names,
test_outputs});
+ return arrow::Table::FromRecordBatches({batch});
+}
+
+void PopulateMap(const arrow::Table& table,
+ std::unordered_map<std::string, std::string>* values) {
+ if (table.num_rows() == 0) {
+ return;
+ }
+ std::shared_ptr<arrow::StringArray> table_names =
+ std::dynamic_pointer_cast<arrow::StringArray>(table.column(0)->chunk(0));
+ std::shared_ptr<arrow::StringArray> table_outputs =
+ std::dynamic_pointer_cast<arrow::StringArray>(table.column(1)->chunk(0));
+ for (int64_t i = 0; i < table.num_rows(); i++) {
+ values->insert({table_names->GetString(i), table_outputs->GetString(i)});
+ }
+}
+
+arrow::Result<std::shared_ptr<arrow::Table>> MergeRecipeTables(
+ std::shared_ptr<arrow::Table> old_table, std::shared_ptr<arrow::Table>
new_table) {
+ std::unordered_map<std::string, std::string> values;
+ PopulateMap(*old_table, &values);
+ PopulateMap(*new_table, &values);
+ arrow::StringBuilder names_builder;
+ arrow::StringBuilder outputs_builder;
+ for (auto pair : values) {
+ ARROW_RETURN_NOT_OK(names_builder.Append(pair.first));
+ ARROW_RETURN_NOT_OK(outputs_builder.Append(pair.second));
+ }
+ ARROW_ASSIGN_OR_RAISE(std::shared_ptr<arrow::Array> names_arr,
names_builder.Finish());
+ ARROW_ASSIGN_OR_RAISE(std::shared_ptr<arrow::Array> outputs_arr,
+ outputs_builder.Finish());
+ std::shared_ptr<arrow::Schema> schema = RecipesTableSchema();
+ std::shared_ptr<arrow::RecordBatch> batch =
+ arrow::RecordBatch::Make(schema, names_arr->length(), {names_arr,
outputs_arr});
+ return arrow::Table::FromRecordBatches({batch});
+}
+
+bool HasRecipeOutput() { return test_names_builder.length() > 0; }
+
+arrow::Status DumpRecipeOutput(const std::string& output_filename) {
+ ARROW_ASSIGN_OR_RAISE(std::shared_ptr<arrow::Table> new_table,
+ CreateRecipeOutputTable());
+ ARROW_ASSIGN_OR_RAISE(std::shared_ptr<arrow::Table> old_table,
+ LoadExistingRecipeOutputTable(output_filename));
+ ARROW_ASSIGN_OR_RAISE(std::shared_ptr<arrow::Table> merged_table,
+ MergeRecipeTables(old_table, new_table));
+ std::shared_ptr<arrow::fs::FileSystem> fs =
+ std::make_shared<arrow::fs::LocalFileSystem>();
+ ARROW_ASSIGN_OR_RAISE(std::shared_ptr<arrow::io::OutputStream> out_stream,
+ fs->OpenOutputStream(output_filename));
+ ARROW_ASSIGN_OR_RAISE(
+ std::shared_ptr<arrow::ipc::RecordBatchWriter> writer,
+ arrow::ipc::MakeStreamWriter(out_stream.get(), merged_table->schema()));
+ RETURN_NOT_OK(writer->WriteTable(*merged_table));
+ return writer->Close();
+}
\ No newline at end of file
diff --git a/cpp/code/common.h b/cpp/code/common.h
new file mode 100644
index 0000000..f7fef1a
--- /dev/null
+++ b/cpp/code/common.h
@@ -0,0 +1,52 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#ifndef ARROW_COOKBOOK_COMMON_H
+#define ARROW_COOKBOOK_COMMON_H
+
+#include <sstream>
+#include <string>
+
+#include <arrow/result.h>
+#include <arrow/status.h>
+
+#define ARROW_STRINGIFY(x) #x
+#define ARROW_CONCAT(x, y) x##y
+
+#define ARROW_ASSIGN_OR_RAISE_NAME(x, y) ARROW_CONCAT(x, y)
+
+#define ASSERT_OK(expr)
\
+ for (::arrow::Status _st = ::arrow::internal::GenericToStatus((expr));
!_st.ok();) \
+ FAIL() << "'" ARROW_STRINGIFY(expr) "' failed with " << _st.ToString()
+
+#define ASSIGN_OR_HANDLE_ERROR_IMPL(handle_error, status_name, lhs, rexpr) \
+ auto&& status_name = (rexpr); \
+ handle_error(status_name.status()); \
+ lhs = std::move(status_name).ValueOrDie();
+
+#define ASSERT_OK_AND_ASSIGN(lhs, rexpr) \
+ ASSIGN_OR_HANDLE_ERROR_IMPL( \
+ ASSERT_OK, ARROW_ASSIGN_OR_RAISE_NAME(_error_or_value, __COUNTER__),
lhs, rexpr);
+
+inline std::stringstream rout;
+
+void StartRecipe(const std::string& recipe_name);
+void EndRecipe(const std::string& recipe_name);
+arrow::Status DumpRecipeOutput(const std::string& output_filename);
+bool HasRecipeOutput();
+
+#endif // ARROW_COOKBOOK_COMMON_H
diff --git a/cpp/code/creating_arrow_objects.cc
b/cpp/code/creating_arrow_objects.cc
new file mode 100644
index 0000000..7e44b61
--- /dev/null
+++ b/cpp/code/creating_arrow_objects.cc
@@ -0,0 +1,55 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include <arrow/api.h>
+#include <gtest/gtest.h>
+
+#include "common.h"
+
+TEST(CreatingArrowObjects, CreateArrays) {
+ StartRecipe("CreatingArrays");
+ arrow::Int32Builder builder;
+ ASSERT_OK(builder.Append(1));
+ ASSERT_OK(builder.Append(2));
+ ASSERT_OK(builder.Append(3));
+ ASSERT_OK_AND_ASSIGN(std::shared_ptr<arrow::Array> arr, builder.Finish())
+ rout << arr->ToString() << std::endl;
+ EndRecipe("CreatingArrays");
+
+ StartRecipe("CreatingArraysPtr");
+ // Raw pointers
+ arrow::Int64Builder long_builder = arrow::Int64Builder();
+ std::array<int64_t, 4> values = {1, 2, 3, 4};
+ ASSERT_OK(long_builder.AppendValues(values.data(), values.size()));
+ ASSERT_OK_AND_ASSIGN(arr, long_builder.Finish());
+ rout << arr->ToString() << std::endl;
+
+ // Vectors
+ arrow::StringBuilder str_builder = arrow::StringBuilder();
+ std::vector<std::string> strvals = {"x", "y", "z"};
+ ASSERT_OK(str_builder.AppendValues(strvals));
+ ASSERT_OK_AND_ASSIGN(arr, str_builder.Finish());
+ rout << arr->ToString() << std::endl;
+
+ // Iterators
+ arrow::DoubleBuilder dbl_builder = arrow::DoubleBuilder();
+ std::set<double> dblvals = {1.1, 1.1, 2.3};
+ ASSERT_OK(dbl_builder.AppendValues(dblvals.begin(), dblvals.end()));
+ ASSERT_OK_AND_ASSIGN(arr, dbl_builder.Finish());
+ rout << arr->ToString() << std::endl;
+ EndRecipe("CreatingArraysPtr");
+}
diff --git a/cpp/code/main.cc b/cpp/code/main.cc
new file mode 100644
index 0000000..3fbe3ea
--- /dev/null
+++ b/cpp/code/main.cc
@@ -0,0 +1,42 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include <iostream>
+
+#include <filesystem>
+
+#include <arrow/status.h>
+#include "gtest/gtest.h"
+
+#include "common.h"
+
+int main(int argc, char** argv) {
+ testing::InitGoogleTest(&argc, argv);
+ int retval = RUN_ALL_TESTS();
+ if (retval == 0 && HasRecipeOutput()) {
+ arrow::Status st = DumpRecipeOutput("recipes_out.arrow");
+ if (!st.ok()) {
+ std::cerr << "Tests ran successfully but failed to dump recipe output: "
<< st
+ << std::endl;
+ return -1;
+ }
+ std::cout << "Created recipe file "
+ <<
std::filesystem::current_path().append("recipes_out.arrow").string()
+ << std::endl;
+ }
+ return retval;
+}
diff --git a/cpp/environment.yml b/cpp/environment.yml
new file mode 100644
index 0000000..690182a
--- /dev/null
+++ b/cpp/environment.yml
@@ -0,0 +1,115 @@
+name: cookbook-cpp
+channels:
+ - conda-forge
+dependencies:
+ - _libgcc_mutex=0.1=conda_forge
+ - _openmp_mutex=4.5=1_gnu
+ - abseil-cpp=20210324.2=h9c3ff4c_0
+ - alabaster=0.7.12=py_0
+ - arrow-cpp=5.0.0=py39h3d6947c_1_cpu
+ - aws-c-cal=0.5.11=h95a6274_0
+ - aws-c-common=0.6.2=h7f98852_0
+ - aws-c-event-stream=0.2.7=h3541f99_13
+ - aws-c-io=0.10.5=hfb6a706_0
+ - aws-checksums=0.1.11=ha31a3da_7
+ - aws-sdk-cpp=1.8.186=hb4091e7_3
+ - babel=2.9.1=pyh44b312d_0
+ - binutils_impl_linux-64=2.36.1=h193b22a_2
+ - brotlipy=0.7.0=py39h3811e60_1001
+ - bzip2=1.0.8=h7f98852_4
+ - c-ares=1.17.1=h7f98852_1
+ - ca-certificates=2021.5.30=ha878542_0
+ - certifi=2021.5.30=py39hf3d152e_0
+ - cffi=1.14.6=py39he32792d_0
+ - chardet=4.0.0=py39hf3d152e_1
+ - charset-normalizer=2.0.0=pyhd8ed1ab_0
+ - clang=11.1.0=ha770c72_1
+ - clang-11=11.1.0=default_ha53f305_1
+ - clangxx=11.1.0=default_ha53f305_1
+ - cmake=3.21.1=h8897547_0
+ - colorama=0.4.4=pyh9f0ad1d_0
+ - cryptography=3.4.7=py39hbca0aa6_0
+ - docutils=0.17.1=py39hf3d152e_0
+ - expat=2.4.1=h9c3ff4c_0
+ - gcc_impl_linux-64=11.1.0=h6b5115b_8
+ - gflags=2.2.2=he1b5a44_1004
+ - glog=0.5.0=h48cff8f_0
+ - grpc-cpp=1.39.0=h36ce80c_1
+ - idna=3.1=pyhd3deb0d_0
+ - imagesize=1.2.0=py_0
+ - jinja2=3.0.1=pyhd8ed1ab_0
+ - kernel-headers_linux-64=2.6.32=he073ed8_14
+ - krb5=1.19.2=hcc1bbae_0
+ - ld_impl_linux-64=2.36.1=hea4e1c9_2
+ - libblas=3.9.0=10_openblas
+ - libbrotlicommon=1.0.9=h7f98852_5
+ - libbrotlidec=1.0.9=h7f98852_5
+ - libbrotlienc=1.0.9=h7f98852_5
+ - libcblas=3.9.0=10_openblas
+ - libclang-cpp11.1=11.1.0=default_ha53f305_1
+ - libcurl=7.78.0=h2574ce0_0
+ - libedit=3.1.20191231=he28a2e2_2
+ - libev=4.33=h516909a_1
+ - libevent=2.1.10=hcdb4288_3
+ - libffi=3.3=h58526e2_2
+ - libgcc-devel_linux-64=11.1.0=h80e7780_8
+ - libgcc-ng=11.1.0=hc902ee8_8
+ - libgfortran-ng=11.1.0=h69a702a_8
+ - libgfortran5=11.1.0=h6c583b3_8
+ - libgomp=11.1.0=hc902ee8_8
+ - liblapack=3.9.0=10_openblas
+ - libllvm11=11.1.0=hf817b99_2
+ - libnghttp2=1.43.0=h812cca2_0
+ - libopenblas=0.3.17=pthreads_h8fe5266_1
+ - libprotobuf=3.16.0=h780b84a_0
+ - libsanitizer=11.1.0=h56837e0_8
+ - libssh2=1.9.0=ha56f1ee_6
+ - libstdcxx-ng=11.1.0=h56837e0_8
+ - libthrift=0.14.2=he6d91bd_1
+ - libutf8proc=2.6.1=h7f98852_0
+ - libuv=1.42.0=h7f98852_0
+ - lz4-c=1.9.3=h9c3ff4c_1
+ - make=4.3=hd18ef5c_1
+ - markupsafe=2.0.1=py39h3811e60_0
+ - ncurses=6.2=h58526e2_4
+ - numpy=1.21.1=py39hdbf815f_0
+ - openssl=1.1.1k=h7f98852_0
+ - orc=1.6.9=h58a87f1_0
+ - packaging=21.0=pyhd8ed1ab_0
+ - parquet-cpp=1.5.1=2
+ - pip=21.2.3=pyhd8ed1ab_0
+ - pyarrow=5.0.0=py39h3ebc44c_1_cpu
+ - pycparser=2.20=pyh9f0ad1d_2
+ - pygments=2.9.0=pyhd8ed1ab_0
+ - pyopenssl=20.0.1=pyhd8ed1ab_0
+ - pyparsing=2.4.7=pyh9f0ad1d_0
+ - pysocks=1.7.1=py39hf3d152e_3
+ - python=3.9.6=h49503c6_1_cpython
+ - python_abi=3.9=2_cp39
+ - pytz=2021.1=pyhd8ed1ab_0
+ - re2=2021.06.01=h9c3ff4c_0
+ - readline=8.1=h46c0cb4_0
+ - requests=2.26.0=pyhd8ed1ab_0
+ - rhash=1.4.1=h7f98852_0
+ - s2n=1.0.10=h9b69904_0
+ - setuptools=49.6.0=py39hf3d152e_3
+ - six=1.16.0=pyh6c4a22f_0
+ - snappy=1.1.8=he1b5a44_3
+ - snowballstemmer=2.1.0=pyhd8ed1ab_0
+ - sphinx=4.0.2=pyh6c4a22f_1
+ - sphinxcontrib-applehelp=1.0.2=py_0
+ - sphinxcontrib-devhelp=1.0.2=py_0
+ - sphinxcontrib-htmlhelp=2.0.0=pyhd8ed1ab_0
+ - sphinxcontrib-jsmath=1.0.1=py_0
+ - sphinxcontrib-qthelp=1.0.3=py_0
+ - sphinxcontrib-serializinghtml=1.1.5=pyhd8ed1ab_0
+ - sqlite=3.36.0=h9cd32fc_0
+ - sysroot_linux-64=2.12=he073ed8_14
+ - tk=8.6.10=h21135ba_1
+ - tzdata=2021a=he74cb21_1
+ - urllib3=1.26.6=pyhd8ed1ab_0
+ - wheel=0.36.2=pyhd3deb0d_0
+ - xz=5.2.5=h516909a_1
+ - zlib=1.2.11=h516909a_1010
+ - zstd=1.5.0=ha95c52a_0
+prefix: /home/pace/anaconda3/envs/cookbook
diff --git a/cpp/ext/recipeext.py b/cpp/ext/recipeext.py
new file mode 100644
index 0000000..618d4e8
--- /dev/null
+++ b/cpp/ext/recipeext.py
@@ -0,0 +1,102 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from pathlib import Path
+import os
+import pyarrow as pa
+import pyarrow.ipc as ipc
+
+from docutils.nodes import literal_block, caption, container
+from sphinx.util.docutils import SphinxDirective
+from sphinx.directives.code import LiteralInclude
+from sphinx.util import logging
+
+logger = logging.getLogger(__name__)
+test_names_to_output = {}
+
+
+class RecipeDirective(SphinxDirective):
+
+ required_arguments = 2
+ optional_arguments = 0
+ option_spec = LiteralInclude.option_spec
+
+ def run(self):
+ global test_names_to_output
+ filename, recipe_name = self.arguments
+ if recipe_name not in test_names_to_output:
+ raise Exception(
+ f'Could not locate recipe output for the recipe
{filename}:{recipe_name}')
+ recipe_output = test_names_to_output[recipe_name]
+
+ self.options['start-after'] = f'StartRecipe("{recipe_name}")'
+ self.options['end-before'] = f'EndRecipe("{recipe_name}")'
+ self.options['language'] = 'cpp'
+
+ out_nodes = LiteralInclude.run(self)
+
+ output_container = container('', literal_block=True, classes=[
+ 'literal-block-wrapper'])
+ literal_node = literal_block(recipe_output, recipe_output)
+ caption_node = caption('Code Output', 'Code Output')
+ output_container += caption_node
+ output_container += literal_node
+
+ return out_nodes + [output_container]
+
+
+def load_recipe_output(path):
+ global test_names_to_output
+ with ipc.open_stream(path) as reader:
+ table = reader.read_all()
+ recipe_names = table.column('Recipe Name').to_pylist()
+ recipe_outputs = table.column('Recipe Output').to_pylist()
+ for name, output in zip(recipe_names, recipe_outputs):
+ test_names_to_output[name] = output
+
+
+def locate_latest_recipe_outputs():
+ base_dir = os.path.join(os.path.dirname(__file__), '..')
+ matches = list(Path(base_dir).rglob('recipes_out.arrow'))
+ if len(matches) == 0:
+ raise Exception(
+ f"Could not find any recipes_out.arrow files in {base_dir}. Have
you run the C++ tests/recipes?")
+
+ matches_with_mtimes = [
+ {'path': str(match), 'mtime': os.path.getmtime(str(match))} for match
in matches]
+ sorted_matches = [match['path'] for match in sorted(
+ matches_with_mtimes, key=lambda x: x['mtime'])]
+ for match_with_mtime in matches_with_mtimes:
+ path = match_with_mtime['path']
+ mtime = match_with_mtime['mtime']
+ logger.info(f'Considering recipe file {path} last updated at {mtime}')
+ return sorted_matches[-1]
+
+
+def setup(app):
+
+ recipe_outputs_path = locate_latest_recipe_outputs()
+ logger.info(f'Located recipes file: {recipe_outputs_path}')
+
+ load_recipe_output(recipe_outputs_path)
+
+ app.add_directive('recipe', RecipeDirective)
+
+ return {
+ 'version': '0.1',
+ 'parallel_read_safe': True,
+ 'parallel_write_safe': True,
+ }
diff --git a/cpp/make.bat b/cpp/make.bat
new file mode 100644
index 0000000..6247f7e
--- /dev/null
+++ b/cpp/make.bat
@@ -0,0 +1,35 @@
+@ECHO OFF
+
+pushd %~dp0
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set SOURCEDIR=source
+set BUILDDIR=build
+
+if "%1" == "" goto help
+
+%SPHINXBUILD% >NUL 2>NUL
+if errorlevel 9009 (
+ echo.
+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+ echo.installed, then set the SPHINXBUILD environment variable to point
+ echo.to the full path of the 'sphinx-build' executable. Alternatively
you
+ echo.may add the Sphinx directory to PATH.
+ echo.
+ echo.If you don't have Sphinx installed, grab it from
+ echo.http://sphinx-doc.org/
+ exit /b 1
+)
+
+%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+goto end
+
+:help
+%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+
+:end
+popd
diff --git a/cpp/requirements.txt b/cpp/requirements.txt
new file mode 100644
index 0000000..4b9f125
--- /dev/null
+++ b/cpp/requirements.txt
@@ -0,0 +1,2 @@
+Sphinx>=4.0.2
+pyarrow>=4.0.0
diff --git a/cpp/source/basic.rst b/cpp/source/basic.rst
new file mode 100644
index 0000000..913781a
--- /dev/null
+++ b/cpp/source/basic.rst
@@ -0,0 +1,49 @@
+.. Licensed to the Apache Software Foundation (ASF) under one
+.. or more contributor license agreements. See the NOTICE file
+.. distributed with this work for additional information
+.. regarding copyright ownership. The ASF licenses this file
+.. to you under the Apache License, Version 2.0 (the
+.. "License"); you may not use this file except in compliance
+.. with the License. You may obtain a copy of the License at
+
+.. http://www.apache.org/licenses/LICENSE-2.0
+
+.. Unless required by applicable law or agreed to in writing,
+.. software distributed under the License is distributed on an
+.. "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+.. KIND, either express or implied. See the License for the
+.. specific language governing permissions and limitations
+.. under the License.
+===================================
+Working with the C++ Implementation
+===================================
+
+This section of the cookbook goes over basic concepts
+that will be needed regardless of how you intend to use
+the Arrow C++ implementation.
+
+.. contents::
+
+Working with Status and Result
+==============================
+
+C++ libraries often have to choose between throwing exceptions and
+returning error codes. Arrow chooses to return Status and Result
+objects as a middle ground. This makes it clear when a function
+can fail and is easier to use than integer arrow codes.
+
+It is important to always check the value of a returned Status object to
+ensure that the operation succeeded. However, this can quickly become
+tedious:
+
+.. recipe:: ../code/basic_arrow.cc ReturnNotOkNoMacro
+ :caption: Checking the status of every function manually
+ :dedent: 2
+
+The macro :c:macro:`ARROW_RETURN_NOT_OK` will take care of some of this
+boilerplate for you. It will run the contained expression and check the
resulting
+``Status`` or ``Result`` object. If it failed then it will return the failure.
+
+.. recipe:: ../code/basic_arrow.cc ReturnNotOk
+ :caption: Using ARROW_RETURN_NOT_OK to check the status
+ :dedent: 2
diff --git a/cpp/source/conf.py b/cpp/source/conf.py
new file mode 100644
index 0000000..fc5bf82
--- /dev/null
+++ b/cpp/source/conf.py
@@ -0,0 +1,72 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Configuration file for the Sphinx documentation builder.
+#
+# This file only contains a selection of the most common options. For a full
+# list see the documentation:
+# https://www.sphinx-doc.org/en/master/usage/configuration.html
+
+# -- Path setup --------------------------------------------------------------
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#
+import os
+import sys
+sys.path.append(os.path.abspath("../ext"))
+
+
+# -- Project information -----------------------------------------------------
+
+project = 'Apache Arrow C++ Cookbook'
+copyright = '2021, Apache Software Foundation'
+author = 'The Apache Software Foundation'
+
+
+# -- General configuration ---------------------------------------------------
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [
+ "sphinx.ext.intersphinx", "recipeext"
+]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This pattern also affects html_static_path and html_extra_path.
+exclude_patterns = []
+
+
+# -- Options for HTML output -------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+#
+html_theme = 'alabaster'
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = []
+
+
+intersphinx_mapping = {'cpparrow': ('https://arrow.apache.org/docs/', None)}
diff --git a/cpp/source/create.rst b/cpp/source/create.rst
new file mode 100644
index 0000000..5e5483c
--- /dev/null
+++ b/cpp/source/create.rst
@@ -0,0 +1,49 @@
+.. Licensed to the Apache Software Foundation (ASF) under one
+.. or more contributor license agreements. See the NOTICE file
+.. distributed with this work for additional information
+.. regarding copyright ownership. The ASF licenses this file
+.. to you under the Apache License, Version 2.0 (the
+.. "License"); you may not use this file except in compliance
+.. with the License. You may obtain a copy of the License at
+
+.. http://www.apache.org/licenses/LICENSE-2.0
+
+.. Unless required by applicable law or agreed to in writing,
+.. software distributed under the License is distributed on an
+.. "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+.. KIND, either express or implied. See the License for the
+.. specific language governing permissions and limitations
+.. under the License.
+======================
+Creating Arrow Objects
+======================
+
+Recipes related to the creation of Arrays, Tables,
+Tensors and all other Arrow entities.
+
+.. contents::
+
+Create Arrays from Standard C++
+===============================
+
+Typed subclasses of :cpp:class:`arrow::ArrayBuilder` make it easy
+to efficiently create Arrow arrays from existing C++ data:
+
+.. recipe:: ../code/creating_arrow_objects.cc CreatingArrays
+ :caption: Creating an array from C++ primitives
+ :dedent: 2
+
+.. note::
+
+ Builders will allocate data as needed and insertion should
+ have constant amortized time.
+
+Builders can also consume standard C++ containers:
+
+.. recipe:: ../code/creating_arrow_objects.cc CreatingArraysPtr
+ :dedent: 2
+
+.. note::
+
+ Builders will not take ownership of data in containers and will make a
+ copy of the underlying data.
\ No newline at end of file
diff --git a/cpp/source/index.rst b/cpp/source/index.rst
new file mode 100644
index 0000000..023f6c8
--- /dev/null
+++ b/cpp/source/index.rst
@@ -0,0 +1,37 @@
+.. Licensed to the Apache Software Foundation (ASF) under one
+.. or more contributor license agreements. See the NOTICE file
+.. distributed with this work for additional information
+.. regarding copyright ownership. The ASF licenses this file
+.. to you under the Apache License, Version 2.0 (the
+.. "License"); you may not use this file except in compliance
+.. with the License. You may obtain a copy of the License at
+
+.. http://www.apache.org/licenses/LICENSE-2.0
+
+.. Unless required by applicable law or agreed to in writing,
+.. software distributed under the License is distributed on an
+.. "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+.. KIND, either express or implied. See the License for the
+.. specific language governing permissions and limitations
+.. under the License.
+Apache Arrow C++ Cookbook
+=========================
+
+The Apache Arrow Cookbook is a collection of recipes which demonstrate
+how to solve many common tasks that users might need to perform
+when working with arrow data. The examples in this cookbook will also
+serve as robust and well performing solutions to those tasks.
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Contents:
+
+ basic
+ create
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`