<commit_before>////////////////////////////////////////////////////////////////////////////////
/// @brief legends for shaped JSON objects to make them self-contained
///
/// @file
/// Code for legends.
///
/// DISCLAIMER
///
/// Copyright 2014 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// Licensed 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Max Neunhoeffer
/// @author Copyright 2014-2014, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "ShapedJson/Legends.h"

using namespace std;
using namespace triagens;
using namespace triagens::basics;

////////////////////////////////////////////////////////////////////////////////
/// Data format of a legend in memory:
///
/// Rough overview description:
///
///   - attribute-ID table
///   - shape table
///   - attribute-ID string data
///   - padding to achieve 8-byte alignment
///   - shape data
///   - padding to achieve 8-byte alignment
///
/// Description of the attribute-ID table (actual binary types in
/// [square brackets]):
///
///   - number of entries [TRI_shape_size_t]
///   - each entry consists of:
///
///       - attribute ID (aid) [TRI_shape_aid_t]
///       - offset to string value, measured from the beginning of the legend
///         [TRI_shape_size_t]
///
/// The entries in the attribute-ID table are sorted by ascending order of
/// shape IDs to allow for binary search if needed.
///
/// Description of the shape table:
///
///   - number of entries [TRI_shape_size_t]
///   - each entry consists of:
///
///       - shape ID (sid) [TRI_shape_sid_t]
///       - offset to shape data, measured from the beginning of the legend
///         [TRI_shape_size_t]
///       - size in bytes of the shape data for this shape ID [TRI_shape_size_t]
///
/// The entries in the shape table are sorted by ascending order of
/// shape IDs to allow for binary search if needed.
///
/// The strings for the attribute IDs are stored one after another, each
/// including a terminating zero byte. At the end of the string data follow
/// zero bytes to pad to a total length that is divisible by 8.
///
/// The actual entries of the shape data is stored one after another. Alignment
/// for each entry is automatically given by the length of the shape data. At
/// the end there is padding to make the length of the total legend divisible
/// by 8.
///
/// Note that the builtin shapes are never dumped and that proper legends
/// contain all attribute IDs
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// @brief clear all data to build a new legend, keep shaper
////////////////////////////////////////////////////////////////////////////////

void JsonLegend::clear () {
  _have_attribute.clear();
  _attribs.clear();
  _att_data.clear();
  _have_shape.clear();
  _shapes.clear();
  _shape_data.clear();
}

////////////////////////////////////////////////////////////////////////////////
/// @brief add an attribute ID to the legend
////////////////////////////////////////////////////////////////////////////////

int JsonLegend::addAttributeId (TRI_shape_aid_t aid) {
  unordered_set<TRI_shape_aid_t>::const_iterator it = _have_attribute.find(aid);
  if (it != _have_attribute.end()) {
    return TRI_ERROR_NO_ERROR;
  }

  char const* p = _shaper->lookupAttributeId(_shaper, aid);
  if (nullptr == p) {
    return TRI_ERROR_AID_NOT_FOUND;
  }

  _have_attribute.insert(it, aid);
  size_t len = strlen(p);
  _attribs.emplace_back(aid, _att_data.length());
  _att_data.appendText(p, len + 1);   // including the zero byte
  return TRI_ERROR_NO_ERROR;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief add a shape to the legend
////////////////////////////////////////////////////////////////////////////////

int JsonLegend::addShape (TRI_shape_sid_t sid,
                          char const* data,
                          uint32_t len) {
  // data and len must always be given, because in general we might have
  // to sniff recursively into the subobjects. :-(
  int res = TRI_ERROR_NO_ERROR;

  TRI_ASSERT(data != nullptr);

  TRI_shape_t const* shape = nullptr;

  // First the trivial cases:
  if (sid < TRI_FirstCustomShapeIdShaper()) {
    shape = TRI_LookupSidBasicShapeShaper(sid);

    TRI_ASSERT(shape != nullptr);
  }
  else {
    shape = _shaper->lookupShapeId(_shaper, sid);

    if (nullptr == shape) {
      return TRI_ERROR_LEGEND_INCOMPLETE;
    }

    unordered_set<TRI_shape_sid_t>::const_iterator it = _have_shape.find(sid);

    if (it == _have_shape.end()) {
      _have_shape.insert(it, sid);
      Shape sh(sid, _shape_data.length(), shape->_size);
      _shapes.push_back(sh);
      _shape_data.appendText(reinterpret_cast<char const*>(shape), shape->_size);
    }
  }

  // Now we have to add all attribute IDs and all shapes used by this
  // one recursively, note that the data of this object is in a
  // consistent state, such that we can call ourselves recursively.

  if (shape->_type == TRI_SHAPE_HOMOGENEOUS_SIZED_LIST) {
    // Handle a homogeneous list with equal size entries. Note that
    // this does not imply that no subobject contains any array or
    // inhomogeneous list, because they could be lists that have the
    // same size by sheer coincidence. Therefore we have to visit them
    // all recursively. :-(
    auto shape_spec = reinterpret_cast<TRI_homogeneous_sized_list_shape_t const*>(shape);
    auto len = reinterpret_cast<TRI_shape_length_list_t const*>(data);
    auto ptr = reinterpret_cast<char const*>(len+1);
    res = TRI_ERROR_NO_ERROR;  // just in case the length is 0
    TRI_shape_length_list_t i;
    for (i = 0; i < *len; i++) {
      res = addShape(shape_spec->_sidEntry, ptr, static_cast<uint32_t>(shape_spec->_sizeEntry));
      ptr += shape_spec->_sizeEntry;
      if (res != TRI_ERROR_NO_ERROR) {
        break;
      }
    }
  }
  else if (shape->_type == TRI_SHAPE_HOMOGENEOUS_LIST) {
    // Handle a homogeneous list: Only one sid, but the subobjects can
    // contain inhomogeneous lists.
    auto shape_spec = reinterpret_cast<TRI_homogeneous_list_shape_t const*> (shape);
    res = TRI_ERROR_NO_ERROR;  // just in case the length is 0
    auto len = reinterpret_cast<TRI_shape_length_list_t const*>(data);
    auto offsets = reinterpret_cast<TRI_shape_size_t const*>(len + 1);
    TRI_shape_length_list_t i;
    for (i = 0; i < *len; i++) {
      res = addShape(shape_spec->_sidEntry, data + offsets[i], static_cast<uint32_t>(offsets[i + 1] - offsets[i]));
      if (res != TRI_ERROR_NO_ERROR) {
        break;
      }
    }
  }
  else if (shape->_type == TRI_SHAPE_LIST) {
    // Handle an inhomogeneous list:
    // We have to scan recursively all entries of the list since they
    // contain sids in the data area.
    res = TRI_ERROR_NO_ERROR;  // just in case the length is 0
    auto len = reinterpret_cast<TRI_shape_length_list_t const*>(data);
    auto sids = reinterpret_cast<TRI_shape_sid_t const*>(len + 1);
    auto offsets = reinterpret_cast<TRI_shape_size_t const*>(sids + *len);
    TRI_shape_length_list_t i;

    for (i = 0; i < *len; i++) {
      res = addShape(sids[i], data + offsets[i], static_cast<uint32_t>(offsets[i + 1] - offsets[i]));
      if (res != TRI_ERROR_NO_ERROR) {
        break;
      }
    }
  }
  else if (shape->_type == TRI_SHAPE_ARRAY) {
    // Handle an array:
    // Distinguish between fixed size subobjects and variable size
    // subobjects. The fixed ones cannot contain inhomogeneous lists.
    auto shape_spec = reinterpret_cast<TRI_array_shape_t const*>(shape);
    auto sids = reinterpret_cast<TRI_shape_sid_t const*>(shape_spec + 1);
    auto aids = reinterpret_cast<TRI_shape_aid_t const*>(sids + (shape_spec->_fixedEntries + shape_spec->_variableEntries));
    auto offsetsF = reinterpret_cast<TRI_shape_size_t const*>(aids + (shape_spec->_fixedEntries + shape_spec->_variableEntries));
    auto offsetsV = reinterpret_cast<TRI_shape_size_t const*>(data);

    TRI_shape_size_t i;
    for (i = 0; res == TRI_ERROR_NO_ERROR &&
                i < shape_spec->_fixedEntries + shape_spec->_variableEntries;
         i++) {
      res = addAttributeId(aids[i]);
    }
    for (i = 0; res == TRI_ERROR_NO_ERROR && i < shape_spec->_fixedEntries;
         i++) {
      // Fixed size subdocs cannot have inhomogeneous lists as subdocs:
      res = addShape(sids[i], data + offsetsF[i], static_cast<uint32_t>(offsetsF[i + 1] - offsetsF[i]));
    }
    for (i = 0; res == TRI_ERROR_NO_ERROR && i < shape_spec->_variableEntries;
         i++) {
      addShape(sids[i + shape_spec->_fixedEntries], data + offsetsV[i], static_cast<uint32_t>(offsetsV[i + 1] - offsetsV[i]));
    }
  }

  return res;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief round a value to the next multiple of 8
////////////////////////////////////////////////////////////////////////////////

static inline TRI_shape_size_t roundup8 (TRI_shape_size_t x) {
  return (x + 7) - ((x + 7) & 7);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get the total size in bytes of the legend
////////////////////////////////////////////////////////////////////////////////

size_t JsonLegend::getSize () const {
  // Add string pool size and shape pool size and add space for header
  // and tables in bytes.
  return   sizeof(TRI_shape_size_t)                 // number of aids
         + sizeof(AttributeId) * _attribs.size()    // aid entries
         + sizeof(TRI_shape_size_t)                 // number of sids
         + sizeof(Shape) * _shapes.size()           // sid entries
         + roundup8(_att_data.length())             // string data, padded
         + roundup8(_shape_data.length());          // shape data, padded
}

JsonLegend::AttributeComparerClass JsonLegend::AttributeComparerObject;
JsonLegend::ShapeComparerClass JsonLegend::ShapeComparerObject;

////////////////////////////////////////////////////////////////////////////////
/// @brief dump the legend to the buffer pointed to by buf
////////////////////////////////////////////////////////////////////////////////

void JsonLegend::dump (void* buf) {
  // Dump the resulting legend to a given buffer.

  // First sort the aids in ascending order:
  sort(_attribs.begin(), _attribs.end(), AttributeComparerObject);

  // Then sort the sids in ascending order:
  sort(_shapes.begin(), _shapes.end(), ShapeComparerObject);

  // Total length of table data to add to offsets:
  TRI_shape_size_t socle =   sizeof(TRI_shape_size_t)
                           + sizeof(AttributeId) * _attribs.size()
                           + sizeof(TRI_shape_size_t)
                           + sizeof(Shape) * _shapes.size();

  // Attribute ID table:
  TRI_shape_size_t* p = reinterpret_cast<TRI_shape_size_t*>(buf);
  TRI_shape_size_t i;
  *p++ = _attribs.size();
  AttributeId* a = reinterpret_cast<AttributeId*>(p);
  for (i = 0; i < _attribs.size(); i++) {
    _attribs[i].offset += socle;
    *a++ = _attribs[i];
    _attribs[i].offset -= socle;
  }

  // Add the length of the string data to socle for second table:
  size_t const attDataLength = _att_data.length();
  socle += roundup8(attDataLength);

  // shape table:
  size_t const n = _shapes.size();
  p = reinterpret_cast<TRI_shape_size_t*>(a);
  *p++ = n;
  Shape* s = reinterpret_cast<Shape*>(p);
  for (i = 0; i < n; i++) {
    _shapes[i].offset += socle;
    *s++ = _shapes[i];
    _shapes[i].offset -= socle;
  }

  // Attribute ID string data:
  char* c = reinterpret_cast<char*>(s);
  memcpy(c, _att_data.c_str(), attDataLength);
  i = roundup8(attDataLength);
  if (i > attDataLength) {
    memset(c + attDataLength, 0, i - attDataLength);
  }
  c += i;

  // Shape data:
  size_t const shapeDataLength = _shape_data.length();
  memcpy(c, _shape_data.c_str(), shapeDataLength);
  i = roundup8(shapeDataLength);
  if (i > shapeDataLength) {
    memset(c + shapeDataLength, 0, i - shapeDataLength);
  }
}
// -----------------------------------------------------------------------------
// --SECTION--                                                       END-OF-FILE
// -----------------------------------------------------------------------------

// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:
<commit_msg>use auto<commit_after>////////////////////////////////////////////////////////////////////////////////
/// @brief legends for shaped JSON objects to make them self-contained
///
/// @file
/// Code for legends.
///
/// DISCLAIMER
///
/// Copyright 2014 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// Licensed 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Max Neunhoeffer
/// @author Copyright 2014-2014, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "ShapedJson/Legends.h"

using namespace std;
using namespace triagens;
using namespace triagens::basics;

////////////////////////////////////////////////////////////////////////////////
/// Data format of a legend in memory:
///
/// Rough overview description:
///
///   - attribute-ID table
///   - shape table
///   - attribute-ID string data
///   - padding to achieve 8-byte alignment
///   - shape data
///   - padding to achieve 8-byte alignment
///
/// Description of the attribute-ID table (actual binary types in
/// [square brackets]):
///
///   - number of entries [TRI_shape_size_t]
///   - each entry consists of:
///
///       - attribute ID (aid) [TRI_shape_aid_t]
///       - offset to string value, measured from the beginning of the legend
///         [TRI_shape_size_t]
///
/// The entries in the attribute-ID table are sorted by ascending order of
/// shape IDs to allow for binary search if needed.
///
/// Description of the shape table:
///
///   - number of entries [TRI_shape_size_t]
///   - each entry consists of:
///
///       - shape ID (sid) [TRI_shape_sid_t]
///       - offset to shape data, measured from the beginning of the legend
///         [TRI_shape_size_t]
///       - size in bytes of the shape data for this shape ID [TRI_shape_size_t]
///
/// The entries in the shape table are sorted by ascending order of
/// shape IDs to allow for binary search if needed.
///
/// The strings for the attribute IDs are stored one after another, each
/// including a terminating zero byte. At the end of the string data follow
/// zero bytes to pad to a total length that is divisible by 8.
///
/// The actual entries of the shape data is stored one after another. Alignment
/// for each entry is automatically given by the length of the shape data. At
/// the end there is padding to make the length of the total legend divisible
/// by 8.
///
/// Note that the builtin shapes are never dumped and that proper legends
/// contain all attribute IDs
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// @brief clear all data to build a new legend, keep shaper
////////////////////////////////////////////////////////////////////////////////

void JsonLegend::clear () {
  _have_attribute.clear();
  _attribs.clear();
  _att_data.clear();
  _have_shape.clear();
  _shapes.clear();
  _shape_data.clear();
}

////////////////////////////////////////////////////////////////////////////////
/// @brief add an attribute ID to the legend
////////////////////////////////////////////////////////////////////////////////

int JsonLegend::addAttributeId (TRI_shape_aid_t aid) {
  auto it = _have_attribute.find(aid);
  if (it != _have_attribute.end()) {
    return TRI_ERROR_NO_ERROR;
  }

  char const* p = _shaper->lookupAttributeId(_shaper, aid);
  if (nullptr == p) {
    return TRI_ERROR_AID_NOT_FOUND;
  }

  _have_attribute.insert(it, aid);
  size_t len = strlen(p);
  _attribs.emplace_back(aid, _att_data.length());
  _att_data.appendText(p, len + 1);   // including the zero byte
  return TRI_ERROR_NO_ERROR;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief add a shape to the legend
////////////////////////////////////////////////////////////////////////////////

int JsonLegend::addShape (TRI_shape_sid_t sid,
                          char const* data,
                          uint32_t len) {
  // data and len must always be given, because in general we might have
  // to sniff recursively into the subobjects. :-(
  int res = TRI_ERROR_NO_ERROR;

  TRI_ASSERT(data != nullptr);

  TRI_shape_t const* shape = nullptr;

  // First the trivial cases:
  if (sid < TRI_FirstCustomShapeIdShaper()) {
    shape = TRI_LookupSidBasicShapeShaper(sid);

    TRI_ASSERT(shape != nullptr);
  }
  else {
    shape = _shaper->lookupShapeId(_shaper, sid);

    if (nullptr == shape) {
      return TRI_ERROR_LEGEND_INCOMPLETE;
    }

    auto it = _have_shape.find(sid);

    if (it == _have_shape.end()) {
      _have_shape.insert(it, sid);
      Shape sh(sid, _shape_data.length(), shape->_size);
      _shapes.push_back(sh);
      _shape_data.appendText(reinterpret_cast<char const*>(shape), shape->_size);
    }
  }

  // Now we have to add all attribute IDs and all shapes used by this
  // one recursively, note that the data of this object is in a
  // consistent state, such that we can call ourselves recursively.

  if (shape->_type == TRI_SHAPE_HOMOGENEOUS_SIZED_LIST) {
    // Handle a homogeneous list with equal size entries. Note that
    // this does not imply that no subobject contains any array or
    // inhomogeneous list, because they could be lists that have the
    // same size by sheer coincidence. Therefore we have to visit them
    // all recursively. :-(
    auto shape_spec = reinterpret_cast<TRI_homogeneous_sized_list_shape_t const*>(shape);
    auto len = reinterpret_cast<TRI_shape_length_list_t const*>(data);
    auto ptr = reinterpret_cast<char const*>(len+1);
    res = TRI_ERROR_NO_ERROR;  // just in case the length is 0
    TRI_shape_length_list_t i;
    for (i = 0; i < *len; i++) {
      res = addShape(shape_spec->_sidEntry, ptr, static_cast<uint32_t>(shape_spec->_sizeEntry));
      ptr += shape_spec->_sizeEntry;
      if (res != TRI_ERROR_NO_ERROR) {
        break;
      }
    }
  }
  else if (shape->_type == TRI_SHAPE_HOMOGENEOUS_LIST) {
    // Handle a homogeneous list: Only one sid, but the subobjects can
    // contain inhomogeneous lists.
    auto shape_spec = reinterpret_cast<TRI_homogeneous_list_shape_t const*> (shape);
    res = TRI_ERROR_NO_ERROR;  // just in case the length is 0
    auto len = reinterpret_cast<TRI_shape_length_list_t const*>(data);
    auto offsets = reinterpret_cast<TRI_shape_size_t const*>(len + 1);
    TRI_shape_length_list_t i;
    for (i = 0; i < *len; i++) {
      res = addShape(shape_spec->_sidEntry, data + offsets[i], static_cast<uint32_t>(offsets[i + 1] - offsets[i]));
      if (res != TRI_ERROR_NO_ERROR) {
        break;
      }
    }
  }
  else if (shape->_type == TRI_SHAPE_LIST) {
    // Handle an inhomogeneous list:
    // We have to scan recursively all entries of the list since they
    // contain sids in the data area.
    res = TRI_ERROR_NO_ERROR;  // just in case the length is 0
    auto len = reinterpret_cast<TRI_shape_length_list_t const*>(data);
    auto sids = reinterpret_cast<TRI_shape_sid_t const*>(len + 1);
    auto offsets = reinterpret_cast<TRI_shape_size_t const*>(sids + *len);
    TRI_shape_length_list_t i;

    for (i = 0; i < *len; i++) {
      res = addShape(sids[i], data + offsets[i], static_cast<uint32_t>(offsets[i + 1] - offsets[i]));
      if (res != TRI_ERROR_NO_ERROR) {
        break;
      }
    }
  }
  else if (shape->_type == TRI_SHAPE_ARRAY) {
    // Handle an array:
    // Distinguish between fixed size subobjects and variable size
    // subobjects. The fixed ones cannot contain inhomogeneous lists.
    auto shape_spec = reinterpret_cast<TRI_array_shape_t const*>(shape);
    auto sids = reinterpret_cast<TRI_shape_sid_t const*>(shape_spec + 1);
    auto aids = reinterpret_cast<TRI_shape_aid_t const*>(sids + (shape_spec->_fixedEntries + shape_spec->_variableEntries));
    auto offsetsF = reinterpret_cast<TRI_shape_size_t const*>(aids + (shape_spec->_fixedEntries + shape_spec->_variableEntries));
    auto offsetsV = reinterpret_cast<TRI_shape_size_t const*>(data);

    TRI_shape_size_t i;
    for (i = 0; res == TRI_ERROR_NO_ERROR &&
                i < shape_spec->_fixedEntries + shape_spec->_variableEntries;
         i++) {
      res = addAttributeId(aids[i]);
    }
    for (i = 0; res == TRI_ERROR_NO_ERROR && i < shape_spec->_fixedEntries;
         i++) {
      // Fixed size subdocs cannot have inhomogeneous lists as subdocs:
      res = addShape(sids[i], data + offsetsF[i], static_cast<uint32_t>(offsetsF[i + 1] - offsetsF[i]));
    }
    for (i = 0; res == TRI_ERROR_NO_ERROR && i < shape_spec->_variableEntries;
         i++) {
      addShape(sids[i + shape_spec->_fixedEntries], data + offsetsV[i], static_cast<uint32_t>(offsetsV[i + 1] - offsetsV[i]));
    }
  }

  return res;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief round a value to the next multiple of 8
////////////////////////////////////////////////////////////////////////////////

static inline TRI_shape_size_t roundup8 (TRI_shape_size_t x) {
  return (x + 7) - ((x + 7) & 7);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get the total size in bytes of the legend
////////////////////////////////////////////////////////////////////////////////

size_t JsonLegend::getSize () const {
  // Add string pool size and shape pool size and add space for header
  // and tables in bytes.
  return   sizeof(TRI_shape_size_t)                 // number of aids
         + sizeof(AttributeId) * _attribs.size()    // aid entries
         + sizeof(TRI_shape_size_t)                 // number of sids
         + sizeof(Shape) * _shapes.size()           // sid entries
         + roundup8(_att_data.length())             // string data, padded
         + roundup8(_shape_data.length());          // shape data, padded
}

JsonLegend::AttributeComparerClass JsonLegend::AttributeComparerObject;
JsonLegend::ShapeComparerClass JsonLegend::ShapeComparerObject;

////////////////////////////////////////////////////////////////////////////////
/// @brief dump the legend to the buffer pointed to by buf
////////////////////////////////////////////////////////////////////////////////

void JsonLegend::dump (void* buf) {
  // Dump the resulting legend to a given buffer.

  // First sort the aids in ascending order:
  sort(_attribs.begin(), _attribs.end(), AttributeComparerObject);

  // Then sort the sids in ascending order:
  sort(_shapes.begin(), _shapes.end(), ShapeComparerObject);

  // Total length of table data to add to offsets:
  TRI_shape_size_t socle =   sizeof(TRI_shape_size_t)
                           + sizeof(AttributeId) * _attribs.size()
                           + sizeof(TRI_shape_size_t)
                           + sizeof(Shape) * _shapes.size();

  // Attribute ID table:
  TRI_shape_size_t* p = reinterpret_cast<TRI_shape_size_t*>(buf);
  TRI_shape_size_t i;
  *p++ = _attribs.size();
  AttributeId* a = reinterpret_cast<AttributeId*>(p);
  for (i = 0; i < _attribs.size(); i++) {
    _attribs[i].offset += socle;
    *a++ = _attribs[i];
    _attribs[i].offset -= socle;
  }

  // Add the length of the string data to socle for second table:
  size_t const attDataLength = _att_data.length();
  socle += roundup8(attDataLength);

  // shape table:
  size_t const n = _shapes.size();
  p = reinterpret_cast<TRI_shape_size_t*>(a);
  *p++ = n;
  Shape* s = reinterpret_cast<Shape*>(p);
  for (i = 0; i < n; i++) {
    _shapes[i].offset += socle;
    *s++ = _shapes[i];
    _shapes[i].offset -= socle;
  }

  // Attribute ID string data:
  char* c = reinterpret_cast<char*>(s);
  memcpy(c, _att_data.c_str(), attDataLength);
  i = roundup8(attDataLength);
  if (i > attDataLength) {
    memset(c + attDataLength, 0, i - attDataLength);
  }
  c += i;

  // Shape data:
  size_t const shapeDataLength = _shape_data.length();
  memcpy(c, _shape_data.c_str(), shapeDataLength);
  i = roundup8(shapeDataLength);
  if (i > shapeDataLength) {
    memset(c + shapeDataLength, 0, i - shapeDataLength);
  }
}
// -----------------------------------------------------------------------------
// --SECTION--                                                       END-OF-FILE
// -----------------------------------------------------------------------------

// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:
<|endoftext|>


<commit_before>#include <iostream>
#include <unistd.h>
#include <sys/stat.h>
#include <stdio.h>
#include <vector>
#include <sstream>
#include <dirent.h>
#include <errno.h>
#include <sys/types.h>
using namespace std;

bool isDirectory(char* directoryName) {

	struct stat directoryInCurrent;

	if (-1 == (stat(directoryName, &directoryInCurrent))) {

		perror("stat failed");
		return false;
	}

	if (directoryInCurrent.st_mode & S_IFDIR) {
		return true;
	}
	else {
		return false;
	}
}

int ls(char* directoryName) {

		char const *dirName = ".";
		DIR *dirp;
		if (!(dirp = opendir(dirName))) {
			cerr << "Error(" << errno << ") opening " << dirName << endl;
		}

		dirent *direntp;
		while ((direntp = readdir(dirp))) {
			if (direntp->d_name[0] != '.') {

				//cout << direntp->d_name << endl; // use stat here to find attributes of a file
				printf(direntp->d_name, 8);
				cout << " ";
			}
		}
		cout << endl;
		closedir(dirp);
		return 0;
}

int lsWithFlags(char* directoryName, vector<string> flags) {

	bool isA = false;
	bool isL = false;
	bool isR = false;
	for (unsigned i = 0; i < flags.size(); ++i) {
		for (unsigned k = 0; k < flags.at(i).size(); ++k) {
			if (flags.at(i).at(k) == 'a')
				isA = true;
			else if (flags.at(i).at(k) == 'l')
				isL = true;
			else if (flags.at(i).at(k) == 'R')
				isR = true;
		}

	}
	char const *dirName = directoryName;
	DIR *dirp;
	if (!(dirp = opendir(dirName))) {
		cerr << "Error(" << errno << ") opening " << dirName << endl;
		return errno;
	}

	dirent *direntp;
	if (isA) {
		while ((direntp = readdir(dirp))) {

			//cout << direntp->d_name << endl; // use stat here to find attributes of a file
			printf(direntp->d_name, 8);
			cout << " ";

		}
	}
	cout << endl;
	closedir(dirp);
	return 0;
}

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

	if (argc == 1) {

		if (errno == ls(".")) {

			return errno;
		}
	}

	else {

		vector<string> directories;
		vector<string> flags;
		vector<int> directoryIndex;
		bool directoryInArgv = false;
		for (int i = 1; i < argc; ++i) {

			if (isDirectory(argv[i])) {
				directoryInArgv = true;
				break;
			}
			else {

				if (argv[i][0] == '-') {

					flags.push_back(argv[i]);
				}
			}
		}
		if (!directoryInArgv) {

			if (errno == lsWithFlags(".", flags)) {

				return errno;
			}
		}
		else {

			for (int i = 0; i < argc; ++i) {

				if (isDirectory(argv[i])) {
					directories.push_back(argv[i]);
					directoryIndex.push_back(i);
				}
			}

			for (unsigned int i = 0; i < directories.size(); ++i) {
				flags.clear();
				for (unsigned int k = static_cast<unsigned>(directoryIndex.at(i));
					 (i + 1) < directoryIndex.size() &&
					 k != (unsigned)directoryIndex.at(i + 1);
					  ++k) {
					if (argv[k][0] == '-') {

						flags.push_back(argv[k]);
					}
				}

				char* directoryName = new char[directories.at(i).size() + 1];
				strcpy(directoryName, directories.at(i).c_str());
				if (errno == lsWithFlags(directoryName, flags)) {

					return errno;
				}
			}
		}
	}

}

<commit_msg>changed conditions for boolean variables in lswithflags function<commit_after>#include <iostream>
#include <unistd.h>
#include <sys/stat.h>
#include <stdio.h>
#include <vector>
#include <sstream>
#include <dirent.h>
#include <errno.h>
#include <sys/types.h>
using namespace std;

bool isDirectory(char* directoryName) {

	struct stat directoryInCurrent;

	if (-1 == (stat(directoryName, &directoryInCurrent))) {

		perror("stat failed");
		return false;
	}

	if (directoryInCurrent.st_mode & S_IFDIR) {
		return true;
	}
	else {
		return false;
	}
}

int ls(char* directoryName) {

		char const *dirName = ".";
		DIR *dirp;
		if (!(dirp = opendir(dirName))) {
			cerr << "Error(" << errno << ") opening " << dirName << endl;
		}

		dirent *direntp;
		while ((direntp = readdir(dirp))) {
			if (direntp->d_name[0] != '.') {

				//cout << direntp->d_name << endl; // use stat here to find attributes of a file
				printf(direntp->d_name, 8);
				cout << " ";
			}
		}
		cout << endl;
		closedir(dirp);
		return 0;
}

int lsWithFlags(char* directoryName, vector<string> flags) {

	bool isA = false;
	bool isL = false;
	bool isR = false;
	for (unsigned i = 0; i < flags.size(); ++i) {
		for (unsigned k = 0; k < flags.at(i).size(); ++k) {
			if (flags.at(i).at(k) == 'a')
				isA = true;
			else if (flags.at(i).at(k) == 'l')
				isL = true;
			else if (flags.at(i).at(k) == 'R')
				isR = true;
		}

	}
	char const *dirName = directoryName;
	DIR *dirp;
	if (!(dirp = opendir(dirName))) {
		cerr << "Error(" << errno << ") opening " << dirName << endl;
		return errno;
	}

	dirent *direntp;
	if (isA) {
		while ((direntp = readdir(dirp))) {

			//cout << direntp->d_name << endl; // use stat here to find attributes of a file
			printf(direntp->d_name, 8);
			cout << " ";

		}
	}
	cout << endl;
	closedir(dirp);
	return 0;
}

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

	if (argc == 1) {

		if (errno == ls(".")) {

			return errno;
		}
	}

	else {

		vector<string> directories;
		vector<string> flags;
		vector<int> directoryIndex;
		bool directoryInArgv = false;
		for (int i = 1; i < argc; ++i) {

			if (isDirectory(argv[i])) {
				directoryInArgv = true;
				break;
			}
			else {

				if (argv[i][0] == '-') {

					flags.push_back(argv[i]);
				}
			}
		}
		if (!directoryInArgv) {

			if (errno == lsWithFlags(".", flags)) {

				return errno;
			}
		}
		else {
			cout << 130 << endl;
			for (int i = 0; i < argc; ++i) {

				if (isDirectory(argv[i])) {
					directories.push_back(argv[i]);
					directoryIndex.push_back(i);
				}
			}

			for (unsigned int i = 0; i < directories.size(); ++i) {
				flags.clear();
				for (unsigned int k = static_cast<unsigned>(directoryIndex.at(i));
					 (i + 1) < directoryIndex.size() &&
					 k != (unsigned)directoryIndex.at(i + 1);
					  ++k) {
					if (argv[k][0] == '-') {

						flags.push_back(argv[k]);
					}
				}

				char* directoryName = new char[directories.at(i).size() + 1];
				strcpy(directoryName, directories.at(i).c_str());
				if (errno == lsWithFlags(directoryName, flags)) {

					return errno;
				}
			}
		}
	}

}

<|endoftext|>


<commit_before>#pragma once

#include "gc.hh"
#include "percpu.hh"

// name spaces
// XXX maybe use open hash table, no chain, better cache locality

#if SPINLOCK_DEBUG
#define NHASH 10
#else
#define NHASH 257
#endif

template<class K, class V>
class xelem : public rcu_freed {
 public:
  V val;
  K key;

  std::atomic<int> next_lock;
  std::atomic<xelem<K, V>*> next;

  int percore_c;
  std::atomic<xelem<K, V>*> percore_next;
  std::atomic<xelem<K, V>*>* percore_pprev;

  xelem(const K &k, const V &v)
    : rcu_freed("xelem"), val(v), key(k),
      next_lock(0), next(0),
      percore_next(0), percore_pprev(0) {}
  virtual void do_gc() {
    delete this;
  }

  NEW_DELETE_OPS(xelem)
};

// XXX maybe not cache align, because it takes too much space
template<class K, class V>
struct xbucket {
  std::atomic<xelem<K, V>*> volatile chain;
} ; // __attribute__((aligned (CACHELINE)));

template<class K, class V, u64 (*HF)(const K&)>
class xns : public rcu_freed {
 private:
  bool allowdup;
  std::atomic<u64> nextkey;
  xbucket<K, V> table[NHASH];
  std::atomic<xelem<K, V>*> percore[NCPU];
  spinlock percore_lock[NCPU];

 public:
  xns(bool dup) : rcu_freed("xns") {
    allowdup = dup;
    nextkey = 1;
    for (int i = 0; i < NHASH; i++)
      table[i].chain = 0;
    for (int i = 0; i < NCPU; i++) {
      percore[i] = nullptr;
      percore_lock[i] = spinlock("xns_lock", LOCKSTAT_NS);
    }
  }

  ~xns() {
    for (int i = 0; i < NHASH; i++)
      if (table[i].chain)
        panic("~xns: not empty");
  }

  virtual void do_gc() {
    delete this;
  }

  u64 allockey() {
    return nextkey++;
  }

  u64 h(const K &key) {
    return HF(key) % NHASH;
  }

  int insert(const K &key, const V &val) {
    auto e = new xelem<K, V>(key, val);
    if (!e)
      return -1;

    u64 i = h(key);
    scoped_gc_epoch gc;

    for (;;) {
      auto root = table[i].chain;
      if (!allowdup) {
        for (auto x = root.load(); x; x = x->next) {
          if (x->key == key) {
            gc_delayed(e);
            return -1;
          }
        }
      }

      e->next = root.load();
      if (cmpxch(&table[i].chain, e->next.load(), e)) {
        int c = myid();
        acquire(&percore_lock[c]);
        e->percore_c = c;
        e->percore_next = percore[c].load();
        if (percore[c])
          percore[c].load()->percore_pprev = &e->percore_next;
        e->percore_pprev = &percore[c];
        percore[c] = e;
        release(&percore_lock[c]);
        return 0;
      }
    }
  }

  V lookup(const K &key) {
    u64 i = h(key);

    scoped_gc_epoch gc;
    auto e = table[i].chain.load();

    while (e) {
      if (e->key == key)
        return e->val;
      e = e->next;
    }

    return 0;
  }

  bool remove(const K &key, const V *vp = 0) {
    u64 i = h(key);
    scoped_gc_epoch gc;

    for (;;) {
      std::atomic<int> fakelock(0);
      std::atomic<int> *pelock = &fakelock;
      auto pe = &table[i].chain;

      for (;;) {
        auto e = pe->load();
        if (!e)
          return false;

        if (e->key == key && (!vp || e->val == *vp)) {
          if (!cmpxch(&e->next_lock, 0, 1))
            break;
          if (!cmpxch(pelock, 0, 1)) {
            e->next_lock = 0;
            break;
          }

          if (!cmpxch(pe, e, e->next.load())) {
            pelock->store(0);
            e->next_lock = 0;
            break;
          }

          int c = e->percore_c;
          acquire(&percore_lock[c]);
          *e->percore_pprev = e->percore_next.load();
          if (e->percore_next)
            e->percore_next.load()->percore_pprev = e->percore_pprev;
          release(&percore_lock[c]);

          pelock->store(0);
          gc_delayed(e);
          return true;
        }

        pe = &e->next;
        pelock = &e->next_lock;
      }
    }
  }

  template<class CB>
  void enumerate(CB cb) {
    scoped_gc_epoch gc;
    int cpuoffset = myid();
    for (int i = 0; i < NCPU; i++) {
      auto e = percore[(i + cpuoffset) % NCPU].load();
      while (e) {
        if (cb(e->key, e->val))
          return;
        e = e->percore_next;
      }
    }
  }

  template<class CB>
  void enumerate_key(const K &key, CB cb) {
    scoped_gc_epoch gc;
    u64 i = h(key);
    auto e = table[i].chain;
    while (e) {
      if (e->key == key && cb(e->key, e->val))
        return;
      e = e->next;
    }
  }

  class iterator {
  private:
    xns<K, V, HF> *ns_;
    xelem<K, V> *chain_;
    int ndx_;

  public:
    iterator(xns<K, V, HF> *ns) {
      if (ns_)
        gc_begin_epoch();
      ns_ = ns;
      ndx_ = 0;
      chain_ = ns->table[ndx_++].chain;
      for (; chain_ == 0 && ndx_ < NHASH; ndx_++)
        chain_ = ns_->table[ndx_].chain;
    }

    iterator() {
      ns_ = 0;
      ndx_ = NHASH;
      chain_ = 0;
    }

    ~iterator() {
      if (ns_)
        gc_end_epoch();
    }

    bool operator!=(const iterator &other) const {
      return other.chain_ != this->chain_;
    }

    iterator& operator ++() {
      for (chain_ = chain_->next; chain_ == 0 && ndx_ < NHASH; ndx_++)
        chain_ = ns_->table[ndx_].chain;
      return *this;
    }

    V& operator *() {
      return chain_->val;
    }
  };

  iterator begin() {
    return iterator(this);
  }

  iterator end() {
    return iterator();
  }

  NEW_DELETE_OPS(xns)
};

template<class K, class V, u64 (*HF)(const K&)>
static inline
typename xns<K, V, HF>::iterator
begin(xns<K, V, HF> *&ns)
{
  return ns->begin();
}

template<class K, class V, u64 (*HF)(const K&)>
static inline
typename xns<K, V, HF>::iterator
end(xns<K, V, HF> *&ns)
{
  return ns->end();
}
<commit_msg>ns: Reduce repeated atomic loads in insert<commit_after>#pragma once

#include "gc.hh"
#include "percpu.hh"

// name spaces
// XXX maybe use open hash table, no chain, better cache locality

#if SPINLOCK_DEBUG
#define NHASH 10
#else
#define NHASH 257
#endif

template<class K, class V>
class xelem : public rcu_freed {
 public:
  V val;
  K key;

  std::atomic<int> next_lock;
  std::atomic<xelem<K, V>*> next;

  int percore_c;
  std::atomic<xelem<K, V>*> percore_next;
  std::atomic<xelem<K, V>*>* percore_pprev;

  xelem(const K &k, const V &v)
    : rcu_freed("xelem"), val(v), key(k),
      next_lock(0), next(0),
      percore_next(0), percore_pprev(0) {}
  virtual void do_gc() {
    delete this;
  }

  NEW_DELETE_OPS(xelem)
};

// XXX maybe not cache align, because it takes too much space
template<class K, class V>
struct xbucket {
  std::atomic<xelem<K, V>*> volatile chain;
} ; // __attribute__((aligned (CACHELINE)));

template<class K, class V, u64 (*HF)(const K&)>
class xns : public rcu_freed {
 private:
  bool allowdup;
  std::atomic<u64> nextkey;
  xbucket<K, V> table[NHASH];
  std::atomic<xelem<K, V>*> percore[NCPU];
  spinlock percore_lock[NCPU];

 public:
  xns(bool dup) : rcu_freed("xns") {
    allowdup = dup;
    nextkey = 1;
    for (int i = 0; i < NHASH; i++)
      table[i].chain = 0;
    for (int i = 0; i < NCPU; i++) {
      percore[i] = nullptr;
      percore_lock[i] = spinlock("xns_lock", LOCKSTAT_NS);
    }
  }

  ~xns() {
    for (int i = 0; i < NHASH; i++)
      if (table[i].chain)
        panic("~xns: not empty");
  }

  virtual void do_gc() {
    delete this;
  }

  u64 allockey() {
    return nextkey++;
  }

  u64 h(const K &key) {
    return HF(key) % NHASH;
  }

  int insert(const K &key, const V &val) {
    auto e = new xelem<K, V>(key, val);
    if (!e)
      return -1;

    u64 i = h(key);
    scoped_gc_epoch gc;

    for (;;) {
      auto root = table[i].chain.load();
      if (!allowdup) {
        for (auto x = root; x; x = x->next) {
          if (x->key == key) {
            gc_delayed(e);
            return -1;
          }
        }
      }

      e->next = root;
      if (cmpxch(&table[i].chain, root, e)) {
        int c = myid();
        acquire(&percore_lock[c]);
        e->percore_c = c;
        e->percore_next = percore[c].load();
        if (percore[c])
          percore[c].load()->percore_pprev = &e->percore_next;
        e->percore_pprev = &percore[c];
        percore[c] = e;
        release(&percore_lock[c]);
        return 0;
      }
    }
  }

  V lookup(const K &key) {
    u64 i = h(key);

    scoped_gc_epoch gc;
    auto e = table[i].chain.load();

    while (e) {
      if (e->key == key)
        return e->val;
      e = e->next;
    }

    return 0;
  }

  bool remove(const K &key, const V *vp = 0) {
    u64 i = h(key);
    scoped_gc_epoch gc;

    for (;;) {
      std::atomic<int> fakelock(0);
      std::atomic<int> *pelock = &fakelock;
      auto pe = &table[i].chain;

      for (;;) {
        auto e = pe->load();
        if (!e)
          return false;

        if (e->key == key && (!vp || e->val == *vp)) {
          if (!cmpxch(&e->next_lock, 0, 1))
            break;
          if (!cmpxch(pelock, 0, 1)) {
            e->next_lock = 0;
            break;
          }

          if (!cmpxch(pe, e, e->next.load())) {
            pelock->store(0);
            e->next_lock = 0;
            break;
          }

          int c = e->percore_c;
          acquire(&percore_lock[c]);
          *e->percore_pprev = e->percore_next.load();
          if (e->percore_next)
            e->percore_next.load()->percore_pprev = e->percore_pprev;
          release(&percore_lock[c]);

          pelock->store(0);
          gc_delayed(e);
          return true;
        }

        pe = &e->next;
        pelock = &e->next_lock;
      }
    }
  }

  template<class CB>
  void enumerate(CB cb) {
    scoped_gc_epoch gc;
    int cpuoffset = myid();
    for (int i = 0; i < NCPU; i++) {
      auto e = percore[(i + cpuoffset) % NCPU].load();
      while (e) {
        if (cb(e->key, e->val))
          return;
        e = e->percore_next;
      }
    }
  }

  template<class CB>
  void enumerate_key(const K &key, CB cb) {
    scoped_gc_epoch gc;
    u64 i = h(key);
    auto e = table[i].chain;
    while (e) {
      if (e->key == key && cb(e->key, e->val))
        return;
      e = e->next;
    }
  }

  class iterator {
  private:
    xns<K, V, HF> *ns_;
    xelem<K, V> *chain_;
    int ndx_;

  public:
    iterator(xns<K, V, HF> *ns) {
      if (ns_)
        gc_begin_epoch();
      ns_ = ns;
      ndx_ = 0;
      chain_ = ns->table[ndx_++].chain;
      for (; chain_ == 0 && ndx_ < NHASH; ndx_++)
        chain_ = ns_->table[ndx_].chain;
    }

    iterator() {
      ns_ = 0;
      ndx_ = NHASH;
      chain_ = 0;
    }

    ~iterator() {
      if (ns_)
        gc_end_epoch();
    }

    bool operator!=(const iterator &other) const {
      return other.chain_ != this->chain_;
    }

    iterator& operator ++() {
      for (chain_ = chain_->next; chain_ == 0 && ndx_ < NHASH; ndx_++)
        chain_ = ns_->table[ndx_].chain;
      return *this;
    }

    V& operator *() {
      return chain_->val;
    }
  };

  iterator begin() {
    return iterator(this);
  }

  iterator end() {
    return iterator();
  }

  NEW_DELETE_OPS(xns)
};

template<class K, class V, u64 (*HF)(const K&)>
static inline
typename xns<K, V, HF>::iterator
begin(xns<K, V, HF> *&ns)
{
  return ns->begin();
}

template<class K, class V, u64 (*HF)(const K&)>
static inline
typename xns<K, V, HF>::iterator
end(xns<K, V, HF> *&ns)
{
  return ns->end();
}
<|endoftext|>


<commit_before>#include <stdlib.h>
#include <time.h>
#include <cstdlib>
#include <ctime>
#include <time.h>
#include <set>
#include <fstream>

#include "hlt.hpp"
#include "networking.hpp"

int main() {
    srand(time(NULL));

    std::cout.sync_with_stdio(0);

    unsigned char myID;
    hlt::GameMap presentMap;
    getInit(myID, presentMap);
    sendInit("C++Bot");

    std::set<hlt::Move> moves;
    while(true) {
        moves.clear();

        getFrame(presentMap);

        for(unsigned short a = 0; a < presentMap.height; a++) {
            for(unsigned short b = 0; b < presentMap.width; b++) {
                if (presentMap.getSite({ b, a }).owner == myID) {

                    bool movedPiece = false;

                    for(int d : CARDINALS) {
                        if(presentMap.getSite({ b, a }, d).owner != myID && presentMap.getSite({ b, a }, d).strength < presentMap.getSite({ b, a }).strength) {
                            moves.insert({ { b, a }, d });
                            movedPiece = true;
                            break;
                        }
                    }

                    if(!movedPiece && presentMap.getSite({ b, a }).strength < presentMap.getSite({ b, a }).production * 5) {
                        moves.insert({ { b, a }, STILL });
                        movedPiece = true;
                    }

                    if(!movedPiece) {
                        moves.insert({ { b, a }, (bool)(rand() % 2) ? NORTH : WEST });
                        movedPiece = true;
                    }
                }
            }
        }

        sendFrame(moves);
    }

    return 0;
}
<commit_msg>Took out extra includes from C++ rand tut<commit_after>#include <stdlib.h>
#include <time.h>

#include "hlt.hpp"
#include "networking.hpp"

int main() {
    srand(time(NULL));

    std::cout.sync_with_stdio(0);

    unsigned char myID;
    hlt::GameMap presentMap;
    getInit(myID, presentMap);
    sendInit("C++Bot");

    std::set<hlt::Move> moves;
    while(true) {
        moves.clear();

        getFrame(presentMap);

        for(unsigned short a = 0; a < presentMap.height; a++) {
            for(unsigned short b = 0; b < presentMap.width; b++) {
                if (presentMap.getSite({ b, a }).owner == myID) {

                    bool movedPiece = false;

                    for(int d : CARDINALS) {
                        if(presentMap.getSite({ b, a }, d).owner != myID && presentMap.getSite({ b, a }, d).strength < presentMap.getSite({ b, a }).strength) {
                            moves.insert({ { b, a }, d });
                            movedPiece = true;
                            break;
                        }
                    }

                    if(!movedPiece && presentMap.getSite({ b, a }).strength < presentMap.getSite({ b, a }).production * 5) {
                        moves.insert({ { b, a }, STILL });
                        movedPiece = true;
                    }

                    if(!movedPiece) {
                        moves.insert({ { b, a }, (bool)(rand() % 2) ? NORTH : WEST });
                        movedPiece = true;
                    }
                }
            }
        }

        sendFrame(moves);
    }

    return 0;
}
<|endoftext|>


<commit_before>#ifndef PITO_SANDBOX_HELPER_HPP
#define PITO_SANDBOX_HELPER_HPP

#include <pito/system_call.hpp>
#include <pito/lib/c_traits.hpp>

#include <chilon/singleton.hpp>
#include <chilon/iterator_range.hpp>

#include <vector>

#define PITO_SANDBOX_DEFAULT  "PITO_SANDBOX_DEFAULT"
#define PITO_SANDBOX_PATHS    "PITO_SANDBOX_PATHS"

namespace pito { namespace sandbox {

enum write_mode {
    WRITE_MODE_PRETEND,
    WRITE_MODE_WHITELIST,
    WRITE_MODE_BLACKLIST
};

struct context {
    context();

    std::vector<range> paths;
    write_mode         mode;
};

extern context& ctxt;

using namespace system_call_tag;

template <class Tag>
struct system_call;

template <class Tag>
struct system_call : detail::system_call<Tag> {
    template <class... Args>
    PITO_RETURN(Tag) operator()(Args... args) {
        return PITO_SUPER(Tag, args...);
    }
};

template <>
struct system_call<chmod> : detail::system_call<chmod> {
    PITO_RETURN(chmod) operator()(const char *path, mode_t mode) {
        return PITO_SUPER(system_call_tag::chmod, path, mode);
    }
};

template <>
struct system_call<fchmod> : detail::system_call<fchmod> {
    PITO_RETURN(fchmod) operator()(int fd, mode_t mode) {
        return PITO_SUPER(system_call_tag::fchmod, fd, mode);
    }
};

template <>
struct system_call<fchmodat> : detail::system_call<fchmodat> {
    PITO_RETURN(fchmodat) operator()(int arg1, const char *arg2, mode_t arg3, int arg4) {
        return PITO_SUPER(system_call_tag::fchmodat, arg1, arg2, arg3, arg4);
    }
};

template <>
struct system_call<chown> : detail::system_call<chown> {
    PITO_RETURN(chown) operator()(const char *path, uid_t uid, gid_t gid) {
        return PITO_SUPER(system_call_tag::chown, path, uid, gid);
    }
};

template <>
struct system_call<fchown> : detail::system_call<fchown> {
    PITO_RETURN(fchown) operator()(int fd, uid_t uid, gid_t gid) {
        return PITO_SUPER(system_call_tag::fchown, fd, uid, gid);
    }
};

template <>
struct system_call<fchownat> : detail::system_call<fchownat> {
    PITO_RETURN(fchownat) operator()(int fd, const char *path, uid_t uid, gid_t gid, int flags) {
        return PITO_SUPER(system_call_tag::fchownat, fd, path, uid, gid, flags);
    }
};

template <>
struct system_call<open> : detail::system_call<open> {
    PITO_RETURN(open) operator()(const char *path, int flag) {
        return PITO_SUPER(system_call_tag::open, path, flag);
    }

    PITO_RETURN(open) operator()(const char *path, int flag, int mode) {
        return PITO_SUPER(system_call_tag::open, path, flag, mode);
    }
};

template <>
struct system_call<open64> : detail::system_call<open64> {
    PITO_RETURN(open64) operator()(const char *path, int flag) {
        return PITO_SUPER(system_call_tag::open64, path, flag);
    }

    PITO_RETURN(open64) operator()(const char *path, int flag, int mode) {
        return PITO_SUPER(system_call_tag::open64, path, flag, mode);
    }
};

template <>
struct system_call<openat> : detail::system_call<openat> {
    PITO_RETURN(openat) operator()(int fd, const char *path, int flags) {
        return PITO_SUPER(system_call_tag::openat, fd, path, flags);
    }

    PITO_RETURN(openat) operator()(int fd, const char *path, int flags, int mode) {
        return PITO_SUPER(system_call_tag::openat, fd, path, flags, mode);
    }
};

template <>
struct system_call<openat64> : detail::system_call<openat64> {
    PITO_RETURN(openat64) operator()(int fd, const char *path, int flags) {
        return PITO_SUPER(system_call_tag::openat64, fd, path, flags);
    }

    PITO_RETURN(openat64) operator()(int fd, const char *path, int flags, int mode) {
        return PITO_SUPER(system_call_tag::openat64, fd, path, flags, mode);
    }
};

template <>
struct system_call<creat> : detail::system_call<creat> {
    PITO_RETURN(creat) operator()(const char *path, mode_t mode) {
        return PITO_SUPER(system_call_tag::creat, path, mode);
    }
};

template <>
struct system_call<creat64> : detail::system_call<creat64> {
    PITO_RETURN(creat) operator()(const char *path, mode_t mode) {
        return PITO_SUPER(system_call_tag::creat64, path, mode);
    }
};

template <>
struct system_call<fopen> : detail::system_call<fopen> {
    PITO_RETURN(fopen) operator()(const char *path, const char *mode) {
        return PITO_SUPER(system_call_tag::fopen, path, mode);
    }
};

template <>
struct system_call<fopen64> : detail::system_call<fopen64> {
    PITO_RETURN(fopen64) operator()(const char *path, const char *mode) {
        return PITO_SUPER(system_call_tag::fopen64, path, mode);
    }
};

template <>
struct system_call<lchown> : detail::system_call<lchown> {
    PITO_RETURN(lchown) operator()(const char *path, uid_t uid, gid_t gid) {
        return PITO_SUPER(system_call_tag::lchown, path, uid, gid);
    }
};

template <>
struct system_call<link> : detail::system_call<link> {
    PITO_RETURN(link) operator()(const char *oldpath, const char *newpath) {
        return PITO_SUPER(system_call_tag::link, oldpath, newpath);
    }
};

template <>
struct system_call<linkat> : detail::system_call<linkat> {
    PITO_RETURN(linkat) operator()(int olddirfd,
                                   const char *oldpath,
                                   int newdirfd,
                                   const char *newpath,
                                   int flags)
    {
        return PITO_SUPER(system_call_tag::linkat,
                olddirfd, oldpath, newdirfd, newpath, flags);
    }
};

template <>
struct system_call<mkdir> : detail::system_call<mkdir> {
    PITO_RETURN(mkdir) operator()(const char *path, mode_t mode) {
        return PITO_SUPER(system_call_tag::mkdir, path, mode);
    }
};

template <>
struct system_call<mkdirat> : detail::system_call<mkdirat> {
    PITO_RETURN(mkdirat) operator()(int fd, const char *path, mode_t mode) {
        return PITO_SUPER(system_call_tag::mkdirat, fd, path, mode);
    }
};

template <>
struct system_call<opendir> : detail::system_call<opendir> {
    PITO_RETURN(opendir) operator()(const char *path) {
        return PITO_SUPER(system_call_tag::opendir, path);
    }
};

template <>
struct system_call<readdir> : detail::system_call<readdir> {
    PITO_RETURN(readdir) operator()(DIR *dir) {
        return PITO_SUPER(system_call_tag::readdir, dir);
    }
};

template <>
struct system_call<mknod> : detail::system_call<mknod> {
    PITO_RETURN(mknod) operator()(const char *path, mode_t mode, dev_t dev) {
        return PITO_SUPER(system_call_tag::mknod, path, mode, dev);
    }
};

template <>
struct system_call<mknodat> : detail::system_call<mknodat> {
    PITO_RETURN(mknodat) operator()(int fd, const char *path, mode_t mode, dev_t dev) {
        return PITO_SUPER(system_call_tag::mknodat, fd, path, mode, dev);
    }
};

template <>
struct system_call<mkfifo> : detail::system_call<mkfifo> {
    PITO_RETURN(mkfifo) operator()(const char *path, mode_t mode) {
        return PITO_SUPER(system_call_tag::mkfifo, path, mode);
    }
};

template <>
struct system_call<mkfifoat> : detail::system_call<mkfifoat> {
    PITO_RETURN(mkfifoat) operator()(int fd, const char *path, mode_t mode) {
        return PITO_SUPER(system_call_tag::mkfifoat, fd, path, mode);
    }
};

template <>
struct system_call<access> : detail::system_call<access> {
    PITO_RETURN(access) operator()(const char *path, int amode) {
        return PITO_SUPER(system_call_tag::access, path, amode);
    }
};

template <>
struct system_call<faccessat> : detail::system_call<faccessat> {
    PITO_RETURN(faccessat) operator()(int fd, const char *path,
                                      int mode, int flags)
    {
        return PITO_SUPER(system_call_tag::faccessat, fd, path, mode, flags);
    }
};

template <>
struct system_call<rename> : detail::system_call<rename> {
    PITO_RETURN(rename) operator()(const char *oldpath, const char *newpath) {
        return PITO_SUPER(system_call_tag::rename, oldpath, newpath);
    }
};

template <>
struct system_call<renameat> : detail::system_call<renameat> {
    PITO_RETURN(renameat) operator()(int olddirfd, const char *oldpath,
                                     int newdirfd, const char *newpath) {
        return PITO_SUPER(system_call_tag::renameat,
                olddirfd, oldpath, newdirfd, newpath);
    }
};

template <>
struct system_call<rmdir> : detail::system_call<rmdir> {
    PITO_RETURN(rmdir) operator()(const char *path) {
        return PITO_SUPER(system_call_tag::rmdir, path);
    }
};

template <>
struct system_call<symlink> : detail::system_call<symlink> {
    PITO_RETURN(symlink) operator()(const char *entry, const char *path) {
        return PITO_SUPER(system_call_tag::symlink, entry, path);
    }
};

template <>
struct system_call<symlinkat> : detail::system_call<symlinkat> {
    PITO_RETURN(symlinkat) operator()(const char *oldpath,
                                      int newdirfd, const char *newpath) {
        return PITO_SUPER(
            system_call_tag::symlinkat, oldpath, newdirfd, newpath);
    }
};

template <>
struct system_call<truncate> : detail::system_call<truncate> {
    PITO_RETURN(truncate) operator()(const char *path, off_t length) {
        return PITO_SUPER(system_call_tag::truncate, path, length);
    }
};

template <>
struct system_call<truncate64> : detail::system_call<truncate64> {
    PITO_RETURN(truncate64) operator()(const char *path, PITO_OFF64_TYPE length) {
        return PITO_SUPER(system_call_tag::truncate64, path, length);
    }
};

template <>
struct system_call<unlink> : detail::system_call<unlink> {
    PITO_RETURN(unlink) operator()(const char *path) {
        return PITO_SUPER(system_call_tag::unlink, path);
    }
};

template <>
struct system_call<unlinkat> : detail::system_call<unlinkat> {
    PITO_RETURN(unlinkat) operator()(int fd, const char *path, int flags) {
        return PITO_SUPER(system_call_tag::unlinkat, fd, path, flags);
    }
};

template <>
struct system_call<utime> : detail::system_call<utime> {
    PITO_RETURN(utime) operator()(const char *path, const struct utimbuf *time) {
        return PITO_SUPER(system_call_tag::utime, path, time);
    }
};

template <>
struct system_call<utimes> : detail::system_call<utimes> {
    PITO_RETURN(utimes) operator()(const char *path, const struct timeval times[2]) {
        return PITO_SUPER(system_call_tag::utimes, path, times);
    }
};

template <>
struct system_call<utimensat> : detail::system_call<utimensat> {
    PITO_RETURN(utimensat) operator()(
        int fd, const char *path, const struct timespec time[2], int flags)
    {
        return PITO_SUPER(system_call_tag::utimensat, fd, path, time, flags);
    }
};

template <>
struct system_call<futimesat> : detail::system_call<futimesat> {
    PITO_RETURN(futimesat) operator()(
        int fd, const char *path, const struct timeval time[2])
    {
        return PITO_SUPER(system_call_tag::futimesat, fd, path, time);
    }
};

template <>
struct system_call<lutimes> : detail::system_call<lutimes> {
    PITO_RETURN(lutimes) operator()(const char *path, const struct timeval time[2]) {
        return PITO_SUPER(system_call_tag::lutimes, path, time);
    }
};

} }

#endif
<commit_msg>have included system call tag already, better TEMPLATE2<commit_after>#ifndef PITO_SANDBOX_HELPER_HPP
#define PITO_SANDBOX_HELPER_HPP

#include <pito/system_call.hpp>
#include <pito/lib/c_traits.hpp>

#include <chilon/singleton.hpp>
#include <chilon/iterator_range.hpp>

#include <vector>

#define PITO_SANDBOX_DEFAULT  "PITO_SANDBOX_DEFAULT"
#define PITO_SANDBOX_PATHS    "PITO_SANDBOX_PATHS"

namespace pito { namespace sandbox {

enum write_mode {
    WRITE_MODE_PRETEND,
    WRITE_MODE_WHITELIST,
    WRITE_MODE_BLACKLIST
};

struct context {
    context();

    std::vector<range> paths;
    write_mode         mode;
};

extern context& ctxt;

using namespace system_call_tag;

template <class Tag>
struct system_call;

template <class Tag>
struct system_call : detail::system_call<Tag> {
    template <class... Args>
    PITO_RETURN(Tag) operator()(Args... args) {
        return PITO_SUPER(Tag, args...);
    }
};

template <>
struct system_call<chmod> : detail::system_call<chmod> {
    PITO_RETURN(chmod) operator()(const char *path, mode_t mode) {
        return PITO_SUPER(chmod, path, mode);
    }
};

template <>
struct system_call<fchmod> : detail::system_call<fchmod> {
    PITO_RETURN(fchmod) operator()(int fd, mode_t mode) {
        return PITO_SUPER(fchmod, fd, mode);
    }
};

template <>
struct system_call<fchmodat> : detail::system_call<fchmodat> {
    PITO_RETURN(fchmodat) operator()(int arg1, const char *arg2, mode_t arg3, int arg4) {
        return PITO_SUPER(fchmodat, arg1, arg2, arg3, arg4);
    }
};

template <>
struct system_call<chown> : detail::system_call<chown> {
    PITO_RETURN(chown) operator()(const char *path, uid_t uid, gid_t gid) {
        return PITO_SUPER(chown, path, uid, gid);
    }
};

template <>
struct system_call<fchown> : detail::system_call<fchown> {
    PITO_RETURN(fchown) operator()(int fd, uid_t uid, gid_t gid) {
        return PITO_SUPER(fchown, fd, uid, gid);
    }
};

template <>
struct system_call<fchownat> : detail::system_call<fchownat> {
    PITO_RETURN(fchownat) operator()(int fd, const char *path, uid_t uid, gid_t gid, int flags) {
        return PITO_SUPER(fchownat, fd, path, uid, gid, flags);
    }
};

template <>
struct system_call<open> : detail::system_call<open> {
    PITO_RETURN(open) operator()(const char *path, int flag) {
        return PITO_SUPER(open, path, flag);
    }

    PITO_RETURN(open) operator()(const char *path, int flag, int mode) {
        return PITO_SUPER(open, path, flag, mode);
    }
};

template <>
struct system_call<open64> : detail::system_call<open64> {
    PITO_RETURN(open64) operator()(const char *path, int flag) {
        return PITO_SUPER(open64, path, flag);
    }

    PITO_RETURN(open64) operator()(const char *path, int flag, int mode) {
        return PITO_SUPER(open64, path, flag, mode);
    }
};

template <>
struct system_call<openat> : detail::system_call<openat> {
    PITO_RETURN(openat) operator()(int fd, const char *path, int flags) {
        return PITO_SUPER(openat, fd, path, flags);
    }

    PITO_RETURN(openat) operator()(int fd, const char *path, int flags, int mode) {
        return PITO_SUPER(openat, fd, path, flags, mode);
    }
};

template <>
struct system_call<openat64> : detail::system_call<openat64> {
    PITO_RETURN(openat64) operator()(int fd, const char *path, int flags) {
        return PITO_SUPER(openat64, fd, path, flags);
    }

    PITO_RETURN(openat64) operator()(int fd, const char *path, int flags, int mode) {
        return PITO_SUPER(openat64, fd, path, flags, mode);
    }
};

template <>
struct system_call<creat> : detail::system_call<creat> {
    PITO_RETURN(creat) operator()(const char *path, mode_t mode) {
        return PITO_SUPER(creat, path, mode);
    }
};

template <>
struct system_call<creat64> : detail::system_call<creat64> {
    PITO_RETURN(creat) operator()(const char *path, mode_t mode) {
        return PITO_SUPER(creat64, path, mode);
    }
};

template <>
struct system_call<fopen> : detail::system_call<fopen> {
    PITO_RETURN(fopen) operator()(const char *path, const char *mode) {
        return PITO_SUPER(fopen, path, mode);
    }
};

template <>
struct system_call<fopen64> : detail::system_call<fopen64> {
    PITO_RETURN(fopen64) operator()(const char *path, const char *mode) {
        return PITO_SUPER(fopen64, path, mode);
    }
};

template <>
struct system_call<lchown> : detail::system_call<lchown> {
    PITO_RETURN(lchown) operator()(const char *path, uid_t uid, gid_t gid) {
        return PITO_SUPER(lchown, path, uid, gid);
    }
};

template <>
struct system_call<link> : detail::system_call<link> {
    PITO_RETURN(link) operator()(const char *oldpath, const char *newpath) {
        return PITO_SUPER(link, oldpath, newpath);
    }
};

template <>
struct system_call<linkat> : detail::system_call<linkat> {
    PITO_RETURN(linkat) operator()(int olddirfd,
                                   const char *oldpath,
                                   int newdirfd,
                                   const char *newpath,
                                   int flags)
    {
        return PITO_SUPER(linkat, olddirfd, oldpath, newdirfd, newpath, flags);
    }
};

template <>
struct system_call<mkdir> : detail::system_call<mkdir> {
    PITO_RETURN(mkdir) operator()(const char *path, mode_t mode) {
        return PITO_SUPER(mkdir, path, mode);
    }
};

template <>
struct system_call<mkdirat> : detail::system_call<mkdirat> {
    PITO_RETURN(mkdirat) operator()(int fd, const char *path, mode_t mode) {
        return PITO_SUPER(mkdirat, fd, path, mode);
    }
};

template <>
struct system_call<opendir> : detail::system_call<opendir> {
    PITO_RETURN(opendir) operator()(const char *path) {
        return PITO_SUPER(opendir, path);
    }
};

template <>
struct system_call<readdir> : detail::system_call<readdir> {
    PITO_RETURN(readdir) operator()(DIR *dir) {
        return PITO_SUPER(readdir, dir);
    }
};

template <>
struct system_call<mknod> : detail::system_call<mknod> {
    PITO_RETURN(mknod) operator()(const char *path, mode_t mode, dev_t dev) {
        return PITO_SUPER(mknod, path, mode, dev);
    }
};

template <>
struct system_call<mknodat> : detail::system_call<mknodat> {
    PITO_RETURN(mknodat) operator()(int fd, const char *path, mode_t mode, dev_t dev) {
        return PITO_SUPER(mknodat, fd, path, mode, dev);
    }
};

template <>
struct system_call<mkfifo> : detail::system_call<mkfifo> {
    PITO_RETURN(mkfifo) operator()(const char *path, mode_t mode) {
        return PITO_SUPER(mkfifo, path, mode);
    }
};

template <>
struct system_call<mkfifoat> : detail::system_call<mkfifoat> {
    PITO_RETURN(mkfifoat) operator()(int fd, const char *path, mode_t mode) {
        return PITO_SUPER(mkfifoat, fd, path, mode);
    }
};

template <>
struct system_call<access> : detail::system_call<access> {
    PITO_RETURN(access) operator()(const char *path, int amode) {
        return PITO_SUPER(access, path, amode);
    }
};

template <>
struct system_call<faccessat> : detail::system_call<faccessat> {
    PITO_RETURN(faccessat) operator()(int fd, const char *path,
                                      int mode, int flags)
    {
        return PITO_SUPER(faccessat, fd, path, mode, flags);
    }
};

template <>
struct system_call<rename> : detail::system_call<rename> {
    PITO_RETURN(rename) operator()(const char *oldpath, const char *newpath) {
        return PITO_SUPER(rename, oldpath, newpath);
    }
};

template <>
struct system_call<renameat> : detail::system_call<renameat> {
    PITO_RETURN(renameat) operator()(int olddirfd, const char *oldpath,
                                     int newdirfd, const char *newpath) {
        return PITO_SUPER(renameat,
                olddirfd, oldpath, newdirfd, newpath);
    }
};

template <>
struct system_call<rmdir> : detail::system_call<rmdir> {
    PITO_RETURN(rmdir) operator()(const char *path) {
        return PITO_SUPER(rmdir, path);
    }
};

template <>
struct system_call<symlink> : detail::system_call<symlink> {
    PITO_RETURN(symlink) operator()(const char *entry, const char *path) {
        return PITO_SUPER(symlink, entry, path);
    }
};

template <>
struct system_call<symlinkat> : detail::system_call<symlinkat> {
    PITO_RETURN(symlinkat) operator()(const char *oldpath,
                                      int newdirfd, const char *newpath) {
        return PITO_SUPER(symlinkat, oldpath, newdirfd, newpath);
    }
};

template <>
struct system_call<truncate> : detail::system_call<truncate> {
    PITO_RETURN(truncate) operator()(const char *path, off_t length) {
        return PITO_SUPER(truncate, path, length);
    }
};

template <>
struct system_call<truncate64> : detail::system_call<truncate64> {
    PITO_RETURN(truncate64) operator()(const char *path, PITO_OFF64_TYPE length) {
        return PITO_SUPER(truncate64, path, length);
    }
};

template <>
struct system_call<unlink> : detail::system_call<unlink> {
    PITO_RETURN(unlink) operator()(const char *path) {
        return PITO_SUPER(unlink, path);
    }
};

template <>
struct system_call<unlinkat> : detail::system_call<unlinkat> {
    PITO_RETURN(unlinkat) operator()(int fd, const char *path, int flags) {
        return PITO_SUPER(unlinkat, fd, path, flags);
    }
};

template <>
struct system_call<utime> : detail::system_call<utime> {
    PITO_RETURN(utime) operator()(const char *path, const struct utimbuf *time) {
        return PITO_SUPER(utime, path, time);
    }
};

template <>
struct system_call<utimes> : detail::system_call<utimes> {
    PITO_RETURN(utimes) operator()(const char *path, const struct timeval times[2]) {
        return PITO_SUPER(utimes, path, times);
    }
};

template <>
struct system_call<utimensat> : detail::system_call<utimensat> {
    PITO_RETURN(utimensat) operator()(
        int fd, const char *path, const struct timespec time[2], int flags)
    {
        return PITO_SUPER(utimensat, fd, path, time, flags);
    }
};

template <>
struct system_call<futimesat> : detail::system_call<futimesat> {
    PITO_RETURN(futimesat) operator()(
        int fd, const char *path, const struct timeval time[2])
    {
        return PITO_SUPER(futimesat, fd, path, time);
    }
};

template <>
struct system_call<lutimes> : detail::system_call<lutimes> {
    PITO_RETURN(lutimes) operator()(const char *path, const struct timeval time[2]) {
        return PITO_SUPER(lutimes, path, time);
    }
};

} }

#endif
<|endoftext|>


<commit_before>/*
 *
 *    Copyright (c) 2020-2022 Project CHIP Authors
 *    All rights reserved.
 *
 *    Licensed 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.
 */

/* this file behaves like a config.h, comes first */
#include <platform/internal/CHIPDeviceLayerInternal.h>

#include <core/CHIPEncoding.h>
#include <platform/Ameba/AmebaConfig.h>
#include <support/CHIPMem.h>
#include <support/CHIPMemString.h>
#include <support/CodeUtils.h>
#include <support/logging/CHIPLogging.h>

enum
{
    kPrefsTypeBoolean = 1,
    kPrefsTypeInteger = 2,
    kPrefsTypeString  = 3,
    kPrefsTypeBuffer  = 4,
    kPrefsTypeBinary  = 5
};

namespace chip {
namespace DeviceLayer {
namespace Internal {

// *** CAUTION ***: Changing the names or namespaces of these values will *break* existing devices.

// NVS namespaces used to store device configuration information.
const char AmebaConfig::kConfigNamespace_ChipFactory[]              = "chip-factory";
const char AmebaConfig::kConfigNamespace_ChipConfig[]               = "chip-config";
const char AmebaConfig::kConfigNamespace_ChipCounters[]             = "chip-counters";
const char AmebaConfig::kConfigNamespace_ChipFabric1[]              = "chip-fabric-1";
const char AmebaConfig::kConfigNamespace_ChipFabric2[]              = "chip-fabric-2";
const char AmebaConfig::kConfigNamespace_ChipFabric3[]              = "chip-fabric-3";
const char AmebaConfig::kConfigNamespace_ChipFabric4[]              = "chip-fabric-4";
const char AmebaConfig::kConfigNamespace_ChipFabric5[]              = "chip-fabric-5";
const char AmebaConfig::kConfigNamespace_ChipACL[]                  = "chip-acl";
const char AmebaConfig::kConfigNamespace_ChipGroupMessageCounters[] = "chip-groupmsgcounters";
const char AmebaConfig::kConfigNamespace_ChipAttributes[]           = "chip-attributes";
const char AmebaConfig::kConfigNamespace_ChipBindingTable[]         = "chip-bindingtable";
const char AmebaConfig::kConfigNamespace_ChipOTA[]                  = "chip-ota";
const char AmebaConfig::kConfigNamespace_ChipFailSafe[]             = "chip-failsafe";
const char AmebaConfig::kConfigNamespace_ChipSessionResumption[]    = "chip-sessionresumption";
const char AmebaConfig::kConfigNamespace_ChipDeviceInfoProvider[]   = "chip-deviceinfoprovider";
const char AmebaConfig::kConfigNamespace_ChipGroupDataProvider[]    = "chip-groupdataprovider";
const char AmebaConfig::kConfigNamespace_ChipOthers[]               = "chip-others";
const char AmebaConfig::kConfigNamespace_ChipOthers2[]              = "chip-others2";

// Keys stored in the chip-factory namespace
const AmebaConfig::Key AmebaConfig::kConfigKey_SerialNum             = { kConfigNamespace_ChipFactory, "serial-num" };
const AmebaConfig::Key AmebaConfig::kConfigKey_MfrDeviceId           = { kConfigNamespace_ChipFactory, "device-id" };
const AmebaConfig::Key AmebaConfig::kConfigKey_MfrDeviceCert         = { kConfigNamespace_ChipFactory, "device-cert" };
const AmebaConfig::Key AmebaConfig::kConfigKey_MfrDeviceICACerts     = { kConfigNamespace_ChipFactory, "device-ca-certs" };
const AmebaConfig::Key AmebaConfig::kConfigKey_MfrDevicePrivateKey   = { kConfigNamespace_ChipFactory, "device-key" };
const AmebaConfig::Key AmebaConfig::kConfigKey_HardwareVersion       = { kConfigNamespace_ChipFactory, "hardware-ver" };
const AmebaConfig::Key AmebaConfig::kConfigKey_ManufacturingDate     = { kConfigNamespace_ChipFactory, "mfg-date" };
const AmebaConfig::Key AmebaConfig::kConfigKey_SetupPinCode          = { kConfigNamespace_ChipFactory, "pin-code" };
const AmebaConfig::Key AmebaConfig::kConfigKey_SetupDiscriminator    = { kConfigNamespace_ChipFactory, "discriminator" };
const AmebaConfig::Key AmebaConfig::kConfigKey_Spake2pIterationCount = { kConfigNamespace_ChipFactory, "iteration-count" };
const AmebaConfig::Key AmebaConfig::kConfigKey_Spake2pSalt           = { kConfigNamespace_ChipFactory, "salt" };
const AmebaConfig::Key AmebaConfig::kConfigKey_Spake2pVerifier       = { kConfigNamespace_ChipFactory, "verifier" };
const AmebaConfig::Key AmebaConfig::kConfigKey_UniqueId              = { kConfigNamespace_ChipFactory, "uniqueId" };

// Keys stored in the chip-config namespace
const AmebaConfig::Key AmebaConfig::kConfigKey_ServiceConfig               = { kConfigNamespace_ChipConfig, "service-config" };
const AmebaConfig::Key AmebaConfig::kConfigKey_PairedAccountId             = { kConfigNamespace_ChipConfig, "account-id" };
const AmebaConfig::Key AmebaConfig::kConfigKey_ServiceId                   = { kConfigNamespace_ChipConfig, "service-id" };
const AmebaConfig::Key AmebaConfig::kConfigKey_LastUsedEpochKeyId          = { kConfigNamespace_ChipConfig, "last-ek-id" };
const AmebaConfig::Key AmebaConfig::kConfigKey_FailSafeArmed               = { kConfigNamespace_ChipConfig, "fail-safe-armed" };
const AmebaConfig::Key AmebaConfig::kConfigKey_WiFiStationSecType          = { kConfigNamespace_ChipConfig, "sta-sec-type" };
const AmebaConfig::Key AmebaConfig::kConfigKey_OperationalDeviceId         = { kConfigNamespace_ChipConfig, "op-device-id" };
const AmebaConfig::Key AmebaConfig::kConfigKey_OperationalDeviceCert       = { kConfigNamespace_ChipConfig, "op-device-cert" };
const AmebaConfig::Key AmebaConfig::kConfigKey_OperationalDeviceICACerts   = { kConfigNamespace_ChipConfig, "op-device-ca-certs" };
const AmebaConfig::Key AmebaConfig::kConfigKey_OperationalDevicePrivateKey = { kConfigNamespace_ChipConfig, "op-device-key" };
const AmebaConfig::Key AmebaConfig::kConfigKey_RegulatoryLocation          = { kConfigNamespace_ChipConfig, "regulatory-location" };
const AmebaConfig::Key AmebaConfig::kConfigKey_CountryCode                 = { kConfigNamespace_ChipConfig, "country-code" };

// Keys stored in the Chip-counters namespace
const AmebaConfig::Key AmebaConfig::kCounterKey_RebootCount           = { kConfigNamespace_ChipCounters, "reboot-count" };
const AmebaConfig::Key AmebaConfig::kCounterKey_UpTime                = { kConfigNamespace_ChipCounters, "up-time" };
const AmebaConfig::Key AmebaConfig::kCounterKey_TotalOperationalHours = { kConfigNamespace_ChipCounters, "total-hours" };
const AmebaConfig::Key AmebaConfig::kCounterKey_BootReason            = { kConfigNamespace_ChipCounters, "boot-reason" };

CHIP_ERROR AmebaConfig::ReadConfigValue(Key key, bool & val)
{
    uint8_t intVal;
    int32_t success = 0;

    success = getPref_bool_new(key.Namespace, key.Name, &intVal);
    if (success != 0)
        ChipLogProgress(DeviceLayer, "getPref_bool_new: %s/%s failed\n", key.Namespace, key.Name);

    val = (intVal != 0);

    if (success == 0)
        return CHIP_NO_ERROR;
    else
        return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
}

CHIP_ERROR AmebaConfig::ReadConfigValue(Key key, uint32_t & val)
{
    int32_t success = 0;

    success = getPref_u32_new(key.Namespace, key.Name, &val);
    if (success != 0)
        ChipLogProgress(DeviceLayer, "getPref_u32_new: %s/%s failed\n", key.Namespace, key.Name);

    if (success == 0)
        return CHIP_NO_ERROR;
    else
        return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
}

CHIP_ERROR AmebaConfig::ReadConfigValue(Key key, uint64_t & val)
{
    int32_t success = 0;

    success = getPref_u64_new(key.Namespace, key.Name, &val);
    if (success != 0)
        ChipLogProgress(DeviceLayer, "getPref_u32_new: %s/%s failed\n", key.Namespace, key.Name);

    if (success == 0)
        return CHIP_NO_ERROR;
    else
        return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
}

CHIP_ERROR AmebaConfig::ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen)
{
    int32_t success = 0;

    success = getPref_str_new(key.Namespace, key.Name, buf, bufSize, &outLen);
    if (success != 0)
        ChipLogProgress(DeviceLayer, "getPref_str_new: %s/%s failed\n", key.Namespace, key.Name);

    if (success == 0)
    {
        return CHIP_NO_ERROR;
    }
    else
    {
        outLen = 0;
        return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
    }
}

CHIP_ERROR AmebaConfig::ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen)
{
    int32_t success = 0;

    success = getPref_bin_new(key.Namespace, key.Name, buf, bufSize, &outLen);
    if (success != 0)
        ChipLogProgress(DeviceLayer, "getPref_bin_new: %s/%s failed\n", key.Namespace, key.Name);

    if (success == 0)
    {
        return CHIP_NO_ERROR;
    }
    else
    {
        outLen = 0;
        return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
    }
}

CHIP_ERROR AmebaConfig::WriteConfigValue(Key key, bool val)
{
    int32_t success;
    uint8_t value;

    if (val == 1)
        value = 1;
    else
        value = 0;
    success = setPref_new(key.Namespace, key.Name, &value, 1);
    if (!success)
        ChipLogError(DeviceLayer, "setPref: %s/%s = %s failed\n", key.Namespace, key.Name, value ? "true" : "false");

    return CHIP_NO_ERROR;
}

CHIP_ERROR AmebaConfig::WriteConfigValue(Key key, uint32_t val)
{
    int32_t success;

    success = setPref_new(key.Namespace, key.Name, (uint8_t *) &val, sizeof(uint32_t));
    if (!success)
        ChipLogError(DeviceLayer, "setPref: %s/%s = %d(0x%x) failed\n", key.Namespace, key.Name, val, val);

    return CHIP_NO_ERROR;
}

CHIP_ERROR AmebaConfig::WriteConfigValue(Key key, uint64_t val)
{
    int32_t success;

    success = setPref_new(key.Namespace, key.Name, (uint8_t *) &val, sizeof(uint64_t));
    if (!success)
        ChipLogError(DeviceLayer, "setPref: %s/%s = %d(0x%x) failed\n", key.Namespace, key.Name, val, val);

    return CHIP_NO_ERROR;
}

CHIP_ERROR AmebaConfig::WriteConfigValueStr(Key key, const char * str)
{
    int32_t success;

    success = setPref_new(key.Namespace, key.Name, (uint8_t *) str, strlen(str) + 1);
    if (!success)
        ChipLogError(DeviceLayer, "setPref: %s/%s = %s failed\n", key.Namespace, key.Name, str);
    return CHIP_NO_ERROR;
}

CHIP_ERROR AmebaConfig::WriteConfigValueStr(Key key, const char * str, size_t strLen)
{
    CHIP_ERROR err;
    chip::Platform::ScopedMemoryBuffer<char> strCopy;

    if (str != NULL)
    {
        strCopy.Calloc(strLen + 1);
        VerifyOrExit(strCopy, err = CHIP_ERROR_NO_MEMORY);
        strncpy(strCopy.Get(), str, strLen);
    }
    err = AmebaConfig::WriteConfigValueStr(key, strCopy.Get());
exit:
    return err;
}

CHIP_ERROR AmebaConfig::WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen)
{
    int32_t success;

    success = setPref_new(key.Namespace, key.Name, (uint8_t *) data, dataLen);
    if (!success)
        ChipLogError(DeviceLayer, "setPref: %s/%s failed\n", key.Namespace, key.Name);

    return CHIP_NO_ERROR;
}

CHIP_ERROR AmebaConfig::ClearConfigValue(Key key)
{
    int32_t success;

    success = deleteKey(key.Namespace, key.Name);
    if (!success)
        ChipLogProgress(DeviceLayer, "%s : %s/%s failed\n", __FUNCTION__, key.Namespace, key.Name);

    return CHIP_NO_ERROR;
}

bool AmebaConfig::ConfigValueExists(Key key)
{
    return checkExist(key.Namespace, key.Name);
}

CHIP_ERROR AmebaConfig::EnsureNamespace(const char * ns)
{
    int32_t success = -1;

    success = registerPref(ns);
    if (success != 0)
    {
        ChipLogError(DeviceLayer, "dct_register_module failed\n");
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR AmebaConfig::EnsureNamespace2(const char * ns)
{
    int32_t success = -1;

    success = registerPref2(ns);
    if (success != 0)
    {
        ChipLogError(DeviceLayer, "dct_register_module2 failed\n");
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR AmebaConfig::ClearNamespace(const char * ns)
{
    int32_t success = -1;

    success = clearPref(ns);
    if (success != 0)
    {
        ChipLogError(DeviceLayer, "ClearNamespace failed\n");
    }

    return CHIP_NO_ERROR;
}

void AmebaConfig::RunConfigUnitTest() {}

} // namespace Internal
} // namespace DeviceLayer
} // namespace chip
<commit_msg>[Logs] Add NVS logs (#22662)<commit_after>/*
 *
 *    Copyright (c) 2020-2022 Project CHIP Authors
 *    All rights reserved.
 *
 *    Licensed 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.
 */

/* this file behaves like a config.h, comes first */
#include <platform/internal/CHIPDeviceLayerInternal.h>

#include <core/CHIPEncoding.h>
#include <platform/Ameba/AmebaConfig.h>
#include <support/CHIPMem.h>
#include <support/CHIPMemString.h>
#include <support/CodeUtils.h>
#include <support/logging/CHIPLogging.h>

enum
{
    kPrefsTypeBoolean = 1,
    kPrefsTypeInteger = 2,
    kPrefsTypeString  = 3,
    kPrefsTypeBuffer  = 4,
    kPrefsTypeBinary  = 5
};

namespace chip {
namespace DeviceLayer {
namespace Internal {

// *** CAUTION ***: Changing the names or namespaces of these values will *break* existing devices.

// NVS namespaces used to store device configuration information.
const char AmebaConfig::kConfigNamespace_ChipFactory[]              = "chip-factory";
const char AmebaConfig::kConfigNamespace_ChipConfig[]               = "chip-config";
const char AmebaConfig::kConfigNamespace_ChipCounters[]             = "chip-counters";
const char AmebaConfig::kConfigNamespace_ChipFabric1[]              = "chip-fabric-1";
const char AmebaConfig::kConfigNamespace_ChipFabric2[]              = "chip-fabric-2";
const char AmebaConfig::kConfigNamespace_ChipFabric3[]              = "chip-fabric-3";
const char AmebaConfig::kConfigNamespace_ChipFabric4[]              = "chip-fabric-4";
const char AmebaConfig::kConfigNamespace_ChipFabric5[]              = "chip-fabric-5";
const char AmebaConfig::kConfigNamespace_ChipACL[]                  = "chip-acl";
const char AmebaConfig::kConfigNamespace_ChipGroupMessageCounters[] = "chip-groupmsgcounters";
const char AmebaConfig::kConfigNamespace_ChipAttributes[]           = "chip-attributes";
const char AmebaConfig::kConfigNamespace_ChipBindingTable[]         = "chip-bindingtable";
const char AmebaConfig::kConfigNamespace_ChipOTA[]                  = "chip-ota";
const char AmebaConfig::kConfigNamespace_ChipFailSafe[]             = "chip-failsafe";
const char AmebaConfig::kConfigNamespace_ChipSessionResumption[]    = "chip-sessionresumption";
const char AmebaConfig::kConfigNamespace_ChipDeviceInfoProvider[]   = "chip-deviceinfoprovider";
const char AmebaConfig::kConfigNamespace_ChipGroupDataProvider[]    = "chip-groupdataprovider";
const char AmebaConfig::kConfigNamespace_ChipOthers[]               = "chip-others";
const char AmebaConfig::kConfigNamespace_ChipOthers2[]              = "chip-others2";

// Keys stored in the chip-factory namespace
const AmebaConfig::Key AmebaConfig::kConfigKey_SerialNum             = { kConfigNamespace_ChipFactory, "serial-num" };
const AmebaConfig::Key AmebaConfig::kConfigKey_MfrDeviceId           = { kConfigNamespace_ChipFactory, "device-id" };
const AmebaConfig::Key AmebaConfig::kConfigKey_MfrDeviceCert         = { kConfigNamespace_ChipFactory, "device-cert" };
const AmebaConfig::Key AmebaConfig::kConfigKey_MfrDeviceICACerts     = { kConfigNamespace_ChipFactory, "device-ca-certs" };
const AmebaConfig::Key AmebaConfig::kConfigKey_MfrDevicePrivateKey   = { kConfigNamespace_ChipFactory, "device-key" };
const AmebaConfig::Key AmebaConfig::kConfigKey_HardwareVersion       = { kConfigNamespace_ChipFactory, "hardware-ver" };
const AmebaConfig::Key AmebaConfig::kConfigKey_ManufacturingDate     = { kConfigNamespace_ChipFactory, "mfg-date" };
const AmebaConfig::Key AmebaConfig::kConfigKey_SetupPinCode          = { kConfigNamespace_ChipFactory, "pin-code" };
const AmebaConfig::Key AmebaConfig::kConfigKey_SetupDiscriminator    = { kConfigNamespace_ChipFactory, "discriminator" };
const AmebaConfig::Key AmebaConfig::kConfigKey_Spake2pIterationCount = { kConfigNamespace_ChipFactory, "iteration-count" };
const AmebaConfig::Key AmebaConfig::kConfigKey_Spake2pSalt           = { kConfigNamespace_ChipFactory, "salt" };
const AmebaConfig::Key AmebaConfig::kConfigKey_Spake2pVerifier       = { kConfigNamespace_ChipFactory, "verifier" };
const AmebaConfig::Key AmebaConfig::kConfigKey_UniqueId              = { kConfigNamespace_ChipFactory, "uniqueId" };

// Keys stored in the chip-config namespace
const AmebaConfig::Key AmebaConfig::kConfigKey_ServiceConfig               = { kConfigNamespace_ChipConfig, "service-config" };
const AmebaConfig::Key AmebaConfig::kConfigKey_PairedAccountId             = { kConfigNamespace_ChipConfig, "account-id" };
const AmebaConfig::Key AmebaConfig::kConfigKey_ServiceId                   = { kConfigNamespace_ChipConfig, "service-id" };
const AmebaConfig::Key AmebaConfig::kConfigKey_LastUsedEpochKeyId          = { kConfigNamespace_ChipConfig, "last-ek-id" };
const AmebaConfig::Key AmebaConfig::kConfigKey_FailSafeArmed               = { kConfigNamespace_ChipConfig, "fail-safe-armed" };
const AmebaConfig::Key AmebaConfig::kConfigKey_WiFiStationSecType          = { kConfigNamespace_ChipConfig, "sta-sec-type" };
const AmebaConfig::Key AmebaConfig::kConfigKey_OperationalDeviceId         = { kConfigNamespace_ChipConfig, "op-device-id" };
const AmebaConfig::Key AmebaConfig::kConfigKey_OperationalDeviceCert       = { kConfigNamespace_ChipConfig, "op-device-cert" };
const AmebaConfig::Key AmebaConfig::kConfigKey_OperationalDeviceICACerts   = { kConfigNamespace_ChipConfig, "op-device-ca-certs" };
const AmebaConfig::Key AmebaConfig::kConfigKey_OperationalDevicePrivateKey = { kConfigNamespace_ChipConfig, "op-device-key" };
const AmebaConfig::Key AmebaConfig::kConfigKey_RegulatoryLocation          = { kConfigNamespace_ChipConfig, "regulatory-location" };
const AmebaConfig::Key AmebaConfig::kConfigKey_CountryCode                 = { kConfigNamespace_ChipConfig, "country-code" };

// Keys stored in the Chip-counters namespace
const AmebaConfig::Key AmebaConfig::kCounterKey_RebootCount           = { kConfigNamespace_ChipCounters, "reboot-count" };
const AmebaConfig::Key AmebaConfig::kCounterKey_UpTime                = { kConfigNamespace_ChipCounters, "up-time" };
const AmebaConfig::Key AmebaConfig::kCounterKey_TotalOperationalHours = { kConfigNamespace_ChipCounters, "total-hours" };
const AmebaConfig::Key AmebaConfig::kCounterKey_BootReason            = { kConfigNamespace_ChipCounters, "boot-reason" };

CHIP_ERROR AmebaConfig::ReadConfigValue(Key key, bool & val)
{
    uint8_t intVal;
    int32_t success = 0;

    success = getPref_bool_new(key.Namespace, key.Name, &intVal);
    if (success != 0)
        ChipLogProgress(DeviceLayer, "getPref_bool_new: %s/%s failed\n", key.Namespace, key.Name);

    val = (intVal != 0);

    if (success == 0)
        return CHIP_NO_ERROR;
    else
        return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
}

CHIP_ERROR AmebaConfig::ReadConfigValue(Key key, uint32_t & val)
{
    int32_t success = 0;

    success = getPref_u32_new(key.Namespace, key.Name, &val);
    if (success != 0)
        ChipLogProgress(DeviceLayer, "getPref_u32_new: %s/%s failed\n", key.Namespace, key.Name);

    if (success == 0)
        return CHIP_NO_ERROR;
    else
        return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
}

CHIP_ERROR AmebaConfig::ReadConfigValue(Key key, uint64_t & val)
{
    int32_t success = 0;

    success = getPref_u64_new(key.Namespace, key.Name, &val);
    if (success != 0)
        ChipLogProgress(DeviceLayer, "getPref_u32_new: %s/%s failed\n", key.Namespace, key.Name);

    if (success == 0)
        return CHIP_NO_ERROR;
    else
        return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
}

CHIP_ERROR AmebaConfig::ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen)
{
    int32_t success = 0;

    success = getPref_str_new(key.Namespace, key.Name, buf, bufSize, &outLen);
    if (success != 0)
        ChipLogProgress(DeviceLayer, "getPref_str_new: %s/%s failed\n", key.Namespace, key.Name);

    if (success == 0)
    {
        return CHIP_NO_ERROR;
    }
    else
    {
        outLen = 0;
        return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
    }
}

CHIP_ERROR AmebaConfig::ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen)
{
    int32_t success = 0;

    success = getPref_bin_new(key.Namespace, key.Name, buf, bufSize, &outLen);
    if (success != 0)
        ChipLogProgress(DeviceLayer, "getPref_bin_new: %s/%s failed\n", key.Namespace, key.Name);

    if (success == 0)
    {
        return CHIP_NO_ERROR;
    }
    else
    {
        outLen = 0;
        return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
    }
}

CHIP_ERROR AmebaConfig::WriteConfigValue(Key key, bool val)
{
    int32_t success;
    uint8_t value;

    if (val == 1)
        value = 1;
    else
        value = 0;
    success = setPref_new(key.Namespace, key.Name, &value, 1);
    if (!success)
        ChipLogError(DeviceLayer, "setPref: %s/%s = %s failed\n", key.Namespace, key.Name, value ? "true" : "false");
    else
        ChipLogProgress(DeviceLayer, "NVS set: %s/%s = %s", key.Namespace, key.Name, val ? "true" : "false");

    return CHIP_NO_ERROR;
}

CHIP_ERROR AmebaConfig::WriteConfigValue(Key key, uint32_t val)
{
    int32_t success;

    success = setPref_new(key.Namespace, key.Name, (uint8_t *) &val, sizeof(uint32_t));
    if (!success)
        ChipLogError(DeviceLayer, "setPref: %s/%s = %d(0x%x) failed\n", key.Namespace, key.Name, val, val);
    else
        ChipLogProgress(DeviceLayer, "NVS set: %s/%s = %" PRIu32 " (0x%" PRIX32 ")", key.Namespace, key.Name, val, val);

    return CHIP_NO_ERROR;
}

CHIP_ERROR AmebaConfig::WriteConfigValue(Key key, uint64_t val)
{
    int32_t success;

    success = setPref_new(key.Namespace, key.Name, (uint8_t *) &val, sizeof(uint64_t));
    if (!success)
        ChipLogError(DeviceLayer, "setPref: %s/%s = %d(0x%x) failed\n", key.Namespace, key.Name, val, val);
    else
        ChipLogProgress(DeviceLayer, "NVS set: %s/%s = %" PRIu64 " (0x%" PRIX64 ")", key.Namespace, key.Name, val, val);

    return CHIP_NO_ERROR;
}

CHIP_ERROR AmebaConfig::WriteConfigValueStr(Key key, const char * str)
{
    int32_t success;

    success = setPref_new(key.Namespace, key.Name, (uint8_t *) str, strlen(str) + 1);
    if (!success)
        ChipLogError(DeviceLayer, "setPref: %s/%s = %s failed\n", key.Namespace, key.Name, str);
    else
        ChipLogProgress(DeviceLayer, "NVS set: %s/%s = \"%s\"", key.Namespace, key.Name, str);
    return CHIP_NO_ERROR;
}

CHIP_ERROR AmebaConfig::WriteConfigValueStr(Key key, const char * str, size_t strLen)
{
    CHIP_ERROR err;
    chip::Platform::ScopedMemoryBuffer<char> strCopy;

    if (str != NULL)
    {
        strCopy.Calloc(strLen + 1);
        VerifyOrExit(strCopy, err = CHIP_ERROR_NO_MEMORY);
        strncpy(strCopy.Get(), str, strLen);
    }
    err = AmebaConfig::WriteConfigValueStr(key, strCopy.Get());
exit:
    return err;
}

CHIP_ERROR AmebaConfig::WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen)
{
    int32_t success;

    success = setPref_new(key.Namespace, key.Name, (uint8_t *) data, dataLen);
    if (!success)
        ChipLogError(DeviceLayer, "setPref: %s/%s failed\n", key.Namespace, key.Name);
    else
        ChipLogProgress(DeviceLayer, "NVS set: %s/%s = (blob length %" PRId32 ")", key.Namespace, key.Name, dataLen);

    return CHIP_NO_ERROR;
}

CHIP_ERROR AmebaConfig::ClearConfigValue(Key key)
{
    int32_t success;

    success = deleteKey(key.Namespace, key.Name);
    if (!success)
        ChipLogProgress(DeviceLayer, "%s : %s/%s failed\n", __FUNCTION__, key.Namespace, key.Name);
    else
        ChipLogProgress(DeviceLayer, "NVS erase: %s/%s", key.Namespace, key.Name);

    return CHIP_NO_ERROR;
}

bool AmebaConfig::ConfigValueExists(Key key)
{
    return checkExist(key.Namespace, key.Name);
}

CHIP_ERROR AmebaConfig::EnsureNamespace(const char * ns)
{
    int32_t success = -1;

    success = registerPref(ns);
    if (success != 0)
    {
        ChipLogError(DeviceLayer, "dct_register_module failed\n");
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR AmebaConfig::EnsureNamespace2(const char * ns)
{
    int32_t success = -1;

    success = registerPref2(ns);
    if (success != 0)
    {
        ChipLogError(DeviceLayer, "dct_register_module2 failed\n");
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR AmebaConfig::ClearNamespace(const char * ns)
{
    int32_t success = -1;

    success = clearPref(ns);
    if (success != 0)
    {
        ChipLogError(DeviceLayer, "ClearNamespace failed\n");
    }

    return CHIP_NO_ERROR;
}

void AmebaConfig::RunConfigUnitTest() {}

} // namespace Internal
} // namespace DeviceLayer
} // namespace chip
<|endoftext|>