<commit_before>////////////////////////////////////////////////////////////////////////////////
/// @brief Ahuacatl, explain
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2004-2013 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 triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "Ahuacatl/ahuacatl-explain.h"

#include "BasicsC/json.h"
#include "BasicsC/string-buffer.h"

#include "Ahuacatl/ahuacatl-collections.h"
#include "Ahuacatl/ahuacatl-context.h"
#include "Ahuacatl/ahuacatl-conversions.h"
#include "Ahuacatl/ahuacatl-node.h"
#include "Ahuacatl/ahuacatl-scope.h"
#include "Ahuacatl/ahuacatl-statement-walker.h"

// -----------------------------------------------------------------------------
// --SECTION--                                                 private functions
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Ahuacatl
/// @{
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// @brief convert a node to a string describing its type
////////////////////////////////////////////////////////////////////////////////

static TRI_json_t* NodeType (const TRI_aql_node_t* const node) {
  TRI_json_t* result;
  TRI_string_buffer_t buffer;

  TRI_ASSERT(node);

  TRI_InitStringBuffer(&buffer, TRI_UNKNOWN_MEM_ZONE);

  if (TRI_ERROR_NO_ERROR != TRI_AppendStringStringBuffer(&buffer, TRI_NodeGroupAql(node, true))) {
    TRI_DestroyStringBuffer(&buffer);

    return NULL;
  }

  result = TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, buffer._buffer);

  TRI_DestroyStringBuffer(&buffer);

  return result;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief convert a node to a string describing its content
////////////////////////////////////////////////////////////////////////////////

static TRI_json_t* NodeDescription (const TRI_aql_node_t* const node) {
  TRI_string_buffer_t buffer;
  TRI_json_t* result;

  TRI_ASSERT(node);

  TRI_InitStringBuffer(&buffer, TRI_UNKNOWN_MEM_ZONE);

  if (! TRI_NodeStringAql(&buffer, node)) {
    TRI_DestroyStringBuffer(&buffer);

    return NULL;
  }

  result = TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, buffer._buffer);
  TRI_DestroyStringBuffer(&buffer);

  return result;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief add an expression node to the json result structure
////////////////////////////////////////////////////////////////////////////////

static bool AddNodeValue (TRI_json_t* row, TRI_aql_node_t* const node) {
  TRI_json_t* result;
  TRI_json_t* type;
  TRI_json_t* value;

  result = TRI_CreateArrayJson(TRI_UNKNOWN_MEM_ZONE);

  if (result == NULL) {
    return false;
  }

  type = NodeType(node);

  if (type != NULL) {
    TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
                         result,
                         "type",
                         type);
  }

  value = NodeDescription(node);
  if (value != NULL) {
    TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
                         result,
                         "value",
                         value);
  }

  if (node->_type == TRI_AQL_NODE_COLLECTION) {
    TRI_json_t* extra = TRI_GetJsonCollectionHintAql(
        static_cast<TRI_aql_collection_hint_t*>
                   (TRI_AQL_NODE_DATA(node)) );

    if (extra != NULL) {
      TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
                           result,
                           "extra",
                           extra);
    }
  }

  TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, row, "expression", result);

  return true;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief add a row to the result json structure
////////////////////////////////////////////////////////////////////////////////

static inline bool AddRow (TRI_aql_explain_t* const explain, TRI_json_t* value) {
  return TRI_PushBack3ListJson(TRI_UNKNOWN_MEM_ZONE, explain->_result, value) == TRI_ERROR_NO_ERROR;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get an empty row protoype
////////////////////////////////////////////////////////////////////////////////

static inline TRI_json_t* GetRowProtoType (TRI_aql_explain_t* const explain,
                                           const TRI_aql_node_type_e type) {
  TRI_json_t* row;

  row = TRI_CreateArrayJson(TRI_UNKNOWN_MEM_ZONE);

  if (row == NULL) {
    return NULL;
  }

  TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
                       row,
                       "id",
                       TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, (double) ++explain->_count));

  TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
                       row,
                       "loopLevel",
                       TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, (double) explain->_level));

  TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
                       row,
                       "type",
                       TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, TRI_NodeNameAql(type)));

  return row;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief create an explain structure
////////////////////////////////////////////////////////////////////////////////

static TRI_aql_explain_t* CreateExplain (TRI_aql_context_t* context) {
  TRI_aql_explain_t* explain;

  explain = (TRI_aql_explain_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_aql_explain_t), false);

  if (explain == NULL) {
    return NULL;
  }

  explain->_context = context;

  explain->_count = 0;
  explain->_level = 0;

  explain->_result = TRI_CreateListJson(TRI_UNKNOWN_MEM_ZONE);

  if (explain->_result == NULL) {
    TRI_Free(TRI_UNKNOWN_MEM_ZONE, explain);

    return NULL;
  }

  return explain;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief free an explain structure
////////////////////////////////////////////////////////////////////////////////

static void FreeExplain (TRI_aql_explain_t* const explain) {
  TRI_ASSERT(explain);

  // note: explain->_result is intentionally not freed here
  // the value is returned by TRI_ExplainAql() and must be
  // freed by the caller

  TRI_Free(TRI_UNKNOWN_MEM_ZONE, explain);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief process a single statement
////////////////////////////////////////////////////////////////////////////////

static TRI_aql_node_t* ProcessStatement (TRI_aql_statement_walker_t* const walker,
                                         TRI_aql_node_t* node) {
  TRI_aql_explain_t* explain;
  TRI_aql_node_type_e type = node->_type;

  explain = (TRI_aql_explain_t*) walker->_data;

  switch (type) {
    case TRI_AQL_NODE_SCOPE_START: {
      TRI_aql_scope_t* scope = (TRI_aql_scope_t*) TRI_AQL_NODE_DATA(node);

      TRI_ASSERT(scope);

      if (scope->_type != TRI_AQL_SCOPE_SUBQUERY && scope->_type != TRI_AQL_SCOPE_MAIN) {
        ++explain->_level;
      }
      break;
    }

    case TRI_AQL_NODE_SCOPE_END: {
      TRI_aql_scope_t* scope = (TRI_aql_scope_t*) TRI_AQL_NODE_DATA(node);

      TRI_ASSERT(scope);
      if (scope->_type != TRI_AQL_SCOPE_SUBQUERY && scope->_type != TRI_AQL_SCOPE_MAIN) {
        --explain->_level;
      }
      break;
    }

    case TRI_AQL_NODE_EXPAND: {
      TRI_json_t* row;

      row = GetRowProtoType(explain, TRI_AQL_NODE_REFERENCE);

      if (row != NULL) {
        TRI_aql_node_t* variableNode = TRI_AQL_NODE_MEMBER(node, 0);

        TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
                             row,
                             "resultVariable",
                             TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, TRI_AQL_NODE_STRING(variableNode)));

        AddNodeValue(row, TRI_AQL_NODE_MEMBER(node, 2));
        AddRow(explain, row);
      }

      row = GetRowProtoType(explain, TRI_AQL_NODE_EXPAND);

      if (row != NULL) {
        TRI_aql_node_t* variableNode = TRI_AQL_NODE_MEMBER(node, 1);

        TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
                             row,
                             "resultVariable",
                             TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, TRI_AQL_NODE_STRING(variableNode)));

        AddNodeValue(row, TRI_AQL_NODE_MEMBER(node, 3));
        AddRow(explain, row);
      }
      break;
    }

    case TRI_AQL_NODE_SUBQUERY:
    case TRI_AQL_NODE_SUBQUERY_CACHED: {
      TRI_json_t* row;

      row = GetRowProtoType(explain, node->_type);

      if (row != NULL) {
        TRI_aql_node_t* variableNode = TRI_AQL_NODE_MEMBER(node, 0);

        TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
                             row,
                             "resultVariable",
                             TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, TRI_AQL_NODE_STRING(variableNode)));

        AddRow(explain, row);
      }
      break;
    }

    case TRI_AQL_NODE_FOR: {
      TRI_json_t* row;

      row = GetRowProtoType(explain, node->_type);

      if (row != NULL) {
        TRI_aql_node_t* variableNode = TRI_AQL_NODE_MEMBER(node, 0);
        TRI_aql_node_t* expressionNode = TRI_AQL_NODE_MEMBER(node, 1);
        TRI_aql_for_hint_t* hint;

        TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
                             row,
                             "resultVariable",
                             TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, TRI_AQL_NODE_STRING(variableNode)));

        hint = static_cast<TRI_aql_for_hint_t*>(TRI_AQL_NODE_DATA(node));
        if (hint != NULL &&
            hint->_limit._status == TRI_AQL_LIMIT_USE) {
          TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
                               row,
                               "limit",
                               TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, true));
        }

        AddNodeValue(row, expressionNode);
        AddRow(explain, row);
      }
      break;
    }

    case TRI_AQL_NODE_RETURN:
    case TRI_AQL_NODE_RETURN_EMPTY: {
      TRI_json_t* row;

      row = GetRowProtoType(explain, node->_type);

      if (row != NULL) {
        TRI_aql_node_t* expressionNode = TRI_AQL_NODE_MEMBER(node, 0);

        AddNodeValue(row, expressionNode);
        AddRow(explain, row);
      }
      break;
    }

    case TRI_AQL_NODE_FILTER: {
      TRI_json_t* row;

      row = GetRowProtoType(explain, node->_type);

      if (row != NULL) {
        TRI_aql_node_t* expressionNode = TRI_AQL_NODE_MEMBER(node, 0);

        AddNodeValue(row, expressionNode);
        AddRow(explain, row);
      }
      break;
    }

    case TRI_AQL_NODE_LET: {
      TRI_json_t* row;

      row = GetRowProtoType(explain, node->_type);

      if (row != NULL) {
        TRI_aql_node_t* variableNode = TRI_AQL_NODE_MEMBER(node, 0);
        TRI_aql_node_t* expressionNode = TRI_AQL_NODE_MEMBER(node, 1);

        TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
                             row,
                             "resultVariable",
                             TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, TRI_AQL_NODE_STRING(variableNode)));

        AddNodeValue(row, expressionNode);
        AddRow(explain, row);
      }
      break;
    }

    case TRI_AQL_NODE_SORT: {
      TRI_json_t* row;

      row = GetRowProtoType(explain, node->_type);

      if (row != NULL) {
        TRI_aql_node_t* listNode = TRI_AQL_NODE_MEMBER(node, 0);

        AddNodeValue(row, listNode);
        AddRow(explain, row);
      }
      break;
    }

    case TRI_AQL_NODE_LIMIT: {
      TRI_json_t* row;

      row = GetRowProtoType(explain, node->_type);

      if (row != NULL) {
        TRI_aql_node_t* offsetNode = TRI_AQL_NODE_MEMBER(node, 0);
        TRI_aql_node_t* countNode  = TRI_AQL_NODE_MEMBER(node, 1);

        TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
                             row,
                             "offset",
                             TRI_NodeJsonAql(explain->_context, offsetNode));

        TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
                             row,
                             "count",
                             TRI_NodeJsonAql(explain->_context, countNode));

        AddRow(explain, row);
      }
      break;
    }

    case TRI_AQL_NODE_COLLECT: {
      TRI_json_t* row;

      row = GetRowProtoType(explain, node->_type);

      if (row != NULL) {
        TRI_aql_node_t* listNode = TRI_AQL_NODE_MEMBER(node, 0);

        if (node->_members._length > 1) {
          TRI_aql_node_t* variableNode = TRI_AQL_NODE_MEMBER(node, 1);

          TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
                               row,
                               "resultVariable",
                               TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, TRI_AQL_NODE_STRING(variableNode)));
        }

        AddNodeValue(row, listNode);
        AddRow(explain, row);
      }
      break;
    }

    default: {
    }
  }

  return NULL;
}

////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

// -----------------------------------------------------------------------------
// --SECTION--                                                  public functions
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Ahuacatl
/// @{
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// @brief explain a query
////////////////////////////////////////////////////////////////////////////////

TRI_json_t* TRI_ExplainAql (TRI_aql_context_t* const context) {
  TRI_aql_statement_walker_t* walker;
  TRI_aql_explain_t* explain;
  TRI_json_t* result;

  explain = CreateExplain(context);

  if (explain == NULL) {
    TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_OUT_OF_MEMORY, NULL);

    return NULL;
  }

  walker = TRI_CreateStatementWalkerAql((void*) explain,
                                        false,
                                        NULL,
                                        &ProcessStatement,
                                        NULL);

  if (walker == NULL) {
    FreeExplain(explain);
    TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_OUT_OF_MEMORY, NULL);

    return NULL;
  }

  TRI_WalkStatementsAql(walker, context->_statements);
  result = explain->_result;

  FreeExplain(explain);

  TRI_FreeStatementWalkerAql(walker);

  return result;
}

////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:
<commit_msg>add handlers for remove, update, save, replace<commit_after>////////////////////////////////////////////////////////////////////////////////
/// @brief Ahuacatl, explain
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2004-2013 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 triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "Ahuacatl/ahuacatl-explain.h"

#include "BasicsC/json.h"
#include "BasicsC/string-buffer.h"

#include "Ahuacatl/ahuacatl-collections.h"
#include "Ahuacatl/ahuacatl-context.h"
#include "Ahuacatl/ahuacatl-conversions.h"
#include "Ahuacatl/ahuacatl-node.h"
#include "Ahuacatl/ahuacatl-scope.h"
#include "Ahuacatl/ahuacatl-statement-walker.h"

// -----------------------------------------------------------------------------
// --SECTION--                                                 private functions
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Ahuacatl
/// @{
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// @brief convert a node to a string describing its type
////////////////////////////////////////////////////////////////////////////////

static TRI_json_t* NodeType (const TRI_aql_node_t* const node) {
  TRI_json_t* result;
  TRI_string_buffer_t buffer;

  TRI_ASSERT(node);

  TRI_InitStringBuffer(&buffer, TRI_UNKNOWN_MEM_ZONE);

  if (TRI_ERROR_NO_ERROR != TRI_AppendStringStringBuffer(&buffer, TRI_NodeGroupAql(node, true))) {
    TRI_DestroyStringBuffer(&buffer);

    return NULL;
  }

  result = TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, buffer._buffer);

  TRI_DestroyStringBuffer(&buffer);

  return result;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief convert a node to a string describing its content
////////////////////////////////////////////////////////////////////////////////

static TRI_json_t* NodeDescription (const TRI_aql_node_t* const node) {
  TRI_string_buffer_t buffer;
  TRI_json_t* result;

  TRI_ASSERT(node);

  TRI_InitStringBuffer(&buffer, TRI_UNKNOWN_MEM_ZONE);

  if (! TRI_NodeStringAql(&buffer, node)) {
    TRI_DestroyStringBuffer(&buffer);

    return NULL;
  }

  result = TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, buffer._buffer);
  TRI_DestroyStringBuffer(&buffer);

  return result;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief add an expression node to the json result structure
////////////////////////////////////////////////////////////////////////////////

static bool AddNodeValue (TRI_json_t* row, TRI_aql_node_t* const node) {
  TRI_json_t* result;
  TRI_json_t* type;
  TRI_json_t* value;

  result = TRI_CreateArrayJson(TRI_UNKNOWN_MEM_ZONE);

  if (result == NULL) {
    return false;
  }

  type = NodeType(node);

  if (type != NULL) {
    TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
                         result,
                         "type",
                         type);
  }

  value = NodeDescription(node);
  if (value != NULL) {
    TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
                         result,
                         "value",
                         value);
  }

  if (node->_type == TRI_AQL_NODE_COLLECTION) {
    TRI_json_t* extra = TRI_GetJsonCollectionHintAql(
        static_cast<TRI_aql_collection_hint_t*>
                   (TRI_AQL_NODE_DATA(node)) );

    if (extra != NULL) {
      TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
                           result,
                           "extra",
                           extra);
    }
  }

  TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, row, "expression", result);

  return true;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief add a row to the result json structure
////////////////////////////////////////////////////////////////////////////////

static inline bool AddRow (TRI_aql_explain_t* const explain, TRI_json_t* value) {
  return TRI_PushBack3ListJson(TRI_UNKNOWN_MEM_ZONE, explain->_result, value) == TRI_ERROR_NO_ERROR;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief get an empty row protoype
////////////////////////////////////////////////////////////////////////////////

static inline TRI_json_t* GetRowProtoType (TRI_aql_explain_t* const explain,
                                           const TRI_aql_node_type_e type) {
  TRI_json_t* row;

  row = TRI_CreateArrayJson(TRI_UNKNOWN_MEM_ZONE);

  if (row == NULL) {
    return NULL;
  }

  TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
                       row,
                       "id",
                       TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, (double) ++explain->_count));

  TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
                       row,
                       "loopLevel",
                       TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, (double) explain->_level));

  TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
                       row,
                       "type",
                       TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, TRI_NodeNameAql(type)));

  return row;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief create an explain structure
////////////////////////////////////////////////////////////////////////////////

static TRI_aql_explain_t* CreateExplain (TRI_aql_context_t* context) {
  TRI_aql_explain_t* explain;

  explain = (TRI_aql_explain_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_aql_explain_t), false);

  if (explain == NULL) {
    return NULL;
  }

  explain->_context = context;

  explain->_count = 0;
  explain->_level = 0;

  explain->_result = TRI_CreateListJson(TRI_UNKNOWN_MEM_ZONE);

  if (explain->_result == NULL) {
    TRI_Free(TRI_UNKNOWN_MEM_ZONE, explain);

    return NULL;
  }

  return explain;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief free an explain structure
////////////////////////////////////////////////////////////////////////////////

static void FreeExplain (TRI_aql_explain_t* const explain) {
  TRI_ASSERT(explain);

  // note: explain->_result is intentionally not freed here
  // the value is returned by TRI_ExplainAql() and must be
  // freed by the caller

  TRI_Free(TRI_UNKNOWN_MEM_ZONE, explain);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief process a single statement
////////////////////////////////////////////////////////////////////////////////

static TRI_aql_node_t* ProcessStatement (TRI_aql_statement_walker_t* const walker,
                                         TRI_aql_node_t* node) {
  TRI_aql_explain_t* explain;
  TRI_aql_node_type_e type = node->_type;

  explain = (TRI_aql_explain_t*) walker->_data;

  switch (type) {
    case TRI_AQL_NODE_SCOPE_START: {
      TRI_aql_scope_t* scope = (TRI_aql_scope_t*) TRI_AQL_NODE_DATA(node);

      TRI_ASSERT(scope);

      if (scope->_type != TRI_AQL_SCOPE_SUBQUERY && scope->_type != TRI_AQL_SCOPE_MAIN) {
        ++explain->_level;
      }
      break;
    }

    case TRI_AQL_NODE_SCOPE_END: {
      TRI_aql_scope_t* scope = (TRI_aql_scope_t*) TRI_AQL_NODE_DATA(node);

      TRI_ASSERT(scope);
      if (scope->_type != TRI_AQL_SCOPE_SUBQUERY && scope->_type != TRI_AQL_SCOPE_MAIN) {
        --explain->_level;
      }
      break;
    }

    case TRI_AQL_NODE_EXPAND: {
      TRI_json_t* row;

      row = GetRowProtoType(explain, TRI_AQL_NODE_REFERENCE);

      if (row != NULL) {
        TRI_aql_node_t* variableNode = TRI_AQL_NODE_MEMBER(node, 0);

        TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
                             row,
                             "resultVariable",
                             TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, TRI_AQL_NODE_STRING(variableNode)));

        AddNodeValue(row, TRI_AQL_NODE_MEMBER(node, 2));
        AddRow(explain, row);
      }

      row = GetRowProtoType(explain, TRI_AQL_NODE_EXPAND);

      if (row != NULL) {
        TRI_aql_node_t* variableNode = TRI_AQL_NODE_MEMBER(node, 1);

        TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
                             row,
                             "resultVariable",
                             TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, TRI_AQL_NODE_STRING(variableNode)));

        AddNodeValue(row, TRI_AQL_NODE_MEMBER(node, 3));
        AddRow(explain, row);
      }
      break;
    }

    case TRI_AQL_NODE_SUBQUERY:
    case TRI_AQL_NODE_SUBQUERY_CACHED: {
      TRI_json_t* row;

      row = GetRowProtoType(explain, node->_type);

      if (row != NULL) {
        TRI_aql_node_t* variableNode = TRI_AQL_NODE_MEMBER(node, 0);

        TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
                             row,
                             "resultVariable",
                             TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, TRI_AQL_NODE_STRING(variableNode)));

        AddRow(explain, row);
      }
      break;
    }

    case TRI_AQL_NODE_REMOVE:
    case TRI_AQL_NODE_SAVE:
    case TRI_AQL_NODE_UPDATE:
    case TRI_AQL_NODE_REPLACE: {
      TRI_json_t* row;

      row = GetRowProtoType(explain, node->_type);

      if (row != NULL) {
        TRI_aql_node_t* expressionNode = TRI_AQL_NODE_MEMBER(node, 0);

        AddNodeValue(row, expressionNode);
        AddRow(explain, row);
      }
      break;
    }

    case TRI_AQL_NODE_FOR: {
      TRI_json_t* row;

      row = GetRowProtoType(explain, node->_type);

      if (row != NULL) {
        TRI_aql_node_t* variableNode = TRI_AQL_NODE_MEMBER(node, 0);
        TRI_aql_node_t* expressionNode = TRI_AQL_NODE_MEMBER(node, 1);
        TRI_aql_for_hint_t* hint;

        TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
                             row,
                             "resultVariable",
                             TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, TRI_AQL_NODE_STRING(variableNode)));

        hint = static_cast<TRI_aql_for_hint_t*>(TRI_AQL_NODE_DATA(node));
        if (hint != NULL &&
            hint->_limit._status == TRI_AQL_LIMIT_USE) {
          TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
                               row,
                               "limit",
                               TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, true));
        }

        AddNodeValue(row, expressionNode);
        AddRow(explain, row);
      }
      break;
    }

    case TRI_AQL_NODE_RETURN:
    case TRI_AQL_NODE_RETURN_EMPTY: {
      TRI_json_t* row;

      row = GetRowProtoType(explain, node->_type);

      if (row != NULL) {
        TRI_aql_node_t* expressionNode = TRI_AQL_NODE_MEMBER(node, 0);

        AddNodeValue(row, expressionNode);
        AddRow(explain, row);
      }
      break;
    }

    case TRI_AQL_NODE_FILTER: {
      TRI_json_t* row;

      row = GetRowProtoType(explain, node->_type);

      if (row != NULL) {
        TRI_aql_node_t* expressionNode = TRI_AQL_NODE_MEMBER(node, 0);

        AddNodeValue(row, expressionNode);
        AddRow(explain, row);
      }
      break;
    }

    case TRI_AQL_NODE_LET: {
      TRI_json_t* row;

      row = GetRowProtoType(explain, node->_type);

      if (row != NULL) {
        TRI_aql_node_t* variableNode = TRI_AQL_NODE_MEMBER(node, 0);
        TRI_aql_node_t* expressionNode = TRI_AQL_NODE_MEMBER(node, 1);

        TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
                             row,
                             "resultVariable",
                             TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, TRI_AQL_NODE_STRING(variableNode)));

        AddNodeValue(row, expressionNode);
        AddRow(explain, row);
      }
      break;
    }

    case TRI_AQL_NODE_SORT: {
      TRI_json_t* row;

      row = GetRowProtoType(explain, node->_type);

      if (row != NULL) {
        TRI_aql_node_t* listNode = TRI_AQL_NODE_MEMBER(node, 0);

        AddNodeValue(row, listNode);
        AddRow(explain, row);
      }
      break;
    }

    case TRI_AQL_NODE_LIMIT: {
      TRI_json_t* row;

      row = GetRowProtoType(explain, node->_type);

      if (row != NULL) {
        TRI_aql_node_t* offsetNode = TRI_AQL_NODE_MEMBER(node, 0);
        TRI_aql_node_t* countNode  = TRI_AQL_NODE_MEMBER(node, 1);

        TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
                             row,
                             "offset",
                             TRI_NodeJsonAql(explain->_context, offsetNode));

        TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
                             row,
                             "count",
                             TRI_NodeJsonAql(explain->_context, countNode));

        AddRow(explain, row);
      }
      break;
    }

    case TRI_AQL_NODE_COLLECT: {
      TRI_json_t* row;

      row = GetRowProtoType(explain, node->_type);

      if (row != NULL) {
        TRI_aql_node_t* listNode = TRI_AQL_NODE_MEMBER(node, 0);

        if (node->_members._length > 1) {
          TRI_aql_node_t* variableNode = TRI_AQL_NODE_MEMBER(node, 1);

          TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE,
                               row,
                               "resultVariable",
                               TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, TRI_AQL_NODE_STRING(variableNode)));
        }

        AddNodeValue(row, listNode);
        AddRow(explain, row);
      }
      break;
    }

    default: {
    }
  }

  return NULL;
}

////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

// -----------------------------------------------------------------------------
// --SECTION--                                                  public functions
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Ahuacatl
/// @{
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// @brief explain a query
////////////////////////////////////////////////////////////////////////////////

TRI_json_t* TRI_ExplainAql (TRI_aql_context_t* const context) {
  TRI_aql_statement_walker_t* walker;
  TRI_aql_explain_t* explain;
  TRI_json_t* result;

  explain = CreateExplain(context);

  if (explain == NULL) {
    TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_OUT_OF_MEMORY, NULL);

    return NULL;
  }

  walker = TRI_CreateStatementWalkerAql((void*) explain,
                                        false,
                                        NULL,
                                        &ProcessStatement,
                                        NULL);

  if (walker == NULL) {
    FreeExplain(explain);
    TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_OUT_OF_MEMORY, NULL);

    return NULL;
  }

  TRI_WalkStatementsAql(walker, context->_statements);
  result = explain->_result;

  FreeExplain(explain);

  TRI_FreeStatementWalkerAql(walker);

  return result;
}

////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

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


<commit_before><commit_msg>`UniverseStruct`: fields `framebuffer_width` & `framebuffer_height`.<commit_after><|endoftext|>


<commit_before>
/*!
	\file

	\author Igor Mironchik (igor.mironchik at gmail dot com).

	Copyright (c) 2014 Igor Mironchik

	Permission is hereby granted, free of charge, to any person
	obtaining a copy of this software and associated documentation
	files (the "Software"), to deal in the Software without
	restriction, including without limitation the rights to use,
	copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the
	Software is furnished to do so, subject to the following
	conditions:

	The above copyright notice and this permission notice shall be
	included in all copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
	OTHER DEALINGS IN THE SOFTWARE.
*/

// Qt include.
#include <QObject>
#include <QtTest/QtTest>
#include <QSharedPointer>
#include <QStringListModel>
#include <QtGlobal>

// QtMWidgets include.
#include <QtMWidgets/Picker>

class StringListEvenDisabledModel
	:	public QStringListModel
{
public:
	explicit StringListEvenDisabledModel( QObject * parent = nullptr )
		:	QStringListModel( parent )
	{
	}

protected:
	Qt::ItemFlags flags( const QModelIndex & index ) const override
	{
		if( index.row() % 2 )
			return QStringListModel::flags( index );
		else
			return Qt::NoItemFlags;
	}
};

class TestPicker
	:	public QObject
{
	Q_OBJECT

private slots:

	void initTestCase()
	{
		m_data.append( QStringLiteral( "English" ) );
		m_data.append( QStringLiteral( "Russian" ) );
		m_data.append( QStringLiteral( "German" ) );
		m_data.append( QStringLiteral( "Spanish" ) );
		m_data.append( QStringLiteral( "Portuguese" ) );
		m_data.append( QStringLiteral( "Belorussian" ) );
		m_data.append( QStringLiteral( "Polish" ) );
		m_data.append( QStringLiteral( "Ukrainian" ) );

		m_model.setStringList( m_data );

		m_picker.reset( new QtMWidgets::Picker );

		m_picker->setMouseTracking( true );

		for( int i = 0; i < m_data.size(); ++i )
			m_picker->addItem( m_data.at( i ) );

		m_font = m_picker->font();
		m_font.setBold( true );
		m_font.setPixelSize( 15 );

		m_picker->setFont( m_font );

		m_picker->show();

		QVERIFY( QTest::qWaitForWindowActive( m_picker.data() ) );

		QFontMetrics fm( m_font );
		m_lineHeight = fm.boundingRect( QStringLiteral( "A" ) ).height();

		m_delta = QPoint( 0, - ( m_lineHeight + m_lineHeight / 3 ) );
	}

	void testPicker()
	{
		m_picker->setCurrentIndex( 2 );

		QVERIFY( m_picker->currentIndex() == 2 );
		QVERIFY( m_picker->currentText() == m_data.at( 2 ) );

		QVERIFY( m_picker->count() == 8 );

		QVERIFY( m_picker->findText( m_data.at( 6 ) ) == 6 );
		QVERIFY( m_picker->itemText( 6 ) == m_data.at( 6 ) );

		QPoint c( m_picker->width() / 2, m_picker->height() / 2 );

		QTest::mousePress( m_picker.data(), Qt::LeftButton, {}, c );
		QMouseEvent me( QEvent::MouseMove, c + m_delta, Qt::LeftButton,
			Qt::LeftButton, {} );
		QApplication::sendEvent( m_picker.data(), &me );
		QTest::mouseRelease( m_picker.data(), Qt::LeftButton, {}, c + m_delta, 20 );
		QTest::mouseClick( m_picker.data(), Qt::LeftButton, {}, c, 20 );

		QVERIFY( m_picker->currentIndex() == 3 );

		int idx = 4;

		for( int i = 0; i < 8; ++i )
		{
			QTest::mousePress( m_picker.data(), Qt::LeftButton, {}, c );
			QMouseEvent me( QEvent::MouseMove, c + m_delta, Qt::LeftButton,
				Qt::LeftButton, {} );
			QApplication::sendEvent( m_picker.data(), &me );
			QTest::mouseRelease( m_picker.data(), Qt::LeftButton, {}, c + m_delta, 20 );
			QTest::mouseClick( m_picker.data(), Qt::LeftButton, {}, c, 20 );

			QVERIFY( m_picker->currentIndex() == idx );

			++idx;

			if( idx == m_data.size() )
				idx = 0;
		}

		QVERIFY( m_picker->currentIndex() == 3 );
	}

	void testWithModel()
	{
		m_picker->setModel( &m_model );
		m_picker->setCurrentIndex( 0 );

		QVERIFY( m_picker->currentText() == m_data.at( 0 ) );
		QVERIFY( m_picker->currentData( Qt::DisplayRole ).toString() == m_data.at( 0 ) );
		QVERIFY( m_picker->findData( m_data.at( 0 ), Qt::DisplayRole ) == 0 );
		QVERIFY( m_picker->itemData( 0, Qt::DisplayRole ).toString() == m_data.at( 0 ) );

		const auto wrong = QStringLiteral( "Wrong" );

		m_picker->setItemText( 0, wrong );

		QVERIFY( m_picker->currentText() == wrong );

		m_picker->setItemData( 0, m_data.at( 0 ), Qt::DisplayRole );

		QVERIFY( m_picker->currentText() == m_data.at( 0 ) );

		QSignalSpy spy( m_picker.data(), &QtMWidgets::Picker::currentTextChanged );

		m_picker->removeItem( 0 );

		QVERIFY( spy.count() == 1 );

		QVERIFY( m_picker->count() == m_data.size() - 1 );
		QVERIFY( m_picker->currentIndex() == 0 );
		QVERIFY( m_picker->currentText() == m_data.at( 1 ) );

		m_picker->setCurrentText( m_data.at( 6 ) );

		QVERIFY( m_picker->currentIndex() == 5 );
		QVERIFY( m_picker->currentText() == m_data.at( 6 ) );

		QVERIFY( m_picker->rootModelIndex() == QModelIndex() );
		QVERIFY( m_picker->modelColumn() == 0 );
		QVERIFY( m_picker->model() == &m_model );

		m_picker->insertItem( 0, m_data.at( 0 ) );

		QVERIFY( m_picker->count() == m_data.size() );
		QVERIFY( m_picker->itemText( 0 ) == m_data.at( 0 ) );

		m_picker->addItems( m_data );

		QVERIFY( m_picker->count() == m_data.size() * 2 );

		m_picker->clear();

		QVERIFY( m_picker->count() == 0 );
	}

	void testEvenDisabled()
	{
		StringListEvenDisabledModel model;
		model.setStringList( m_data );

		m_picker->setModel( &model );

		m_picker->setCurrentIndex( 3 );

		QPoint c( m_picker->width() / 2, m_picker->height() / 2 );

		QSignalSpy spy( m_picker.data(), QOverload< int >::of(
			&QtMWidgets::Picker::currentIndexChanged ) );

		QTest::mousePress( m_picker.data(), Qt::LeftButton, {}, c );
		QMouseEvent me( QEvent::MouseMove, c + m_delta, Qt::LeftButton,
			Qt::LeftButton, {} );
		QApplication::sendEvent( m_picker.data(), &me );
		QTest::mouseRelease( m_picker.data(), Qt::LeftButton, {}, c + m_delta, 20 );
		QTest::mouseClick( m_picker.data(), Qt::LeftButton, {}, c, 20 );

		QVERIFY( spy.count() == 0 );

		m_picker->setModel( &m_model );
	}

	void testThreeItems()
	{
		QStringList data;
		data << QStringLiteral( "One" ) << QStringLiteral( "Very very very very very long line" )
			<< QStringLiteral( "Three" );
		m_model.setStringList( data );

		m_picker->resize( 150, 100 );
		m_picker->setCurrentIndex( 1 );
	}

private:
	QStringList m_data;
	QSharedPointer< QtMWidgets::Picker > m_picker;
	QStringListModel m_model;
	QFont m_font;
	int m_lineHeight;
	QPoint m_delta;
};

QTEST_MAIN( TestPicker )

#include "main.moc"
<commit_msg>Add test.<commit_after>
/*!
	\file

	\author Igor Mironchik (igor.mironchik at gmail dot com).

	Copyright (c) 2014 Igor Mironchik

	Permission is hereby granted, free of charge, to any person
	obtaining a copy of this software and associated documentation
	files (the "Software"), to deal in the Software without
	restriction, including without limitation the rights to use,
	copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the
	Software is furnished to do so, subject to the following
	conditions:

	The above copyright notice and this permission notice shall be
	included in all copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
	OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
	HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
	OTHER DEALINGS IN THE SOFTWARE.
*/

// Qt include.
#include <QObject>
#include <QtTest/QtTest>
#include <QSharedPointer>
#include <QStringListModel>
#include <QtGlobal>

// QtMWidgets include.
#include <QtMWidgets/Picker>

class StringListEvenDisabledModel
	:	public QStringListModel
{
public:
	explicit StringListEvenDisabledModel( QObject * parent = nullptr )
		:	QStringListModel( parent )
	{
	}

protected:
	Qt::ItemFlags flags( const QModelIndex & index ) const override
	{
		if( index.row() % 2 )
			return QStringListModel::flags( index );
		else
			return Qt::NoItemFlags;
	}
};

class TestPicker
	:	public QObject
{
	Q_OBJECT

private slots:

	void initTestCase()
	{
		m_data.append( QStringLiteral( "English" ) );
		m_data.append( QStringLiteral( "Russian" ) );
		m_data.append( QStringLiteral( "German" ) );
		m_data.append( QStringLiteral( "Spanish" ) );
		m_data.append( QStringLiteral( "Portuguese" ) );
		m_data.append( QStringLiteral( "Belorussian" ) );
		m_data.append( QStringLiteral( "Polish" ) );
		m_data.append( QStringLiteral( "Ukrainian" ) );

		m_model.setStringList( m_data );

		m_picker.reset( new QtMWidgets::Picker );

		m_picker->setMouseTracking( true );

		for( int i = 0; i < m_data.size(); ++i )
			m_picker->addItem( m_data.at( i ) );

		m_font = m_picker->font();
		m_font.setBold( true );
		m_font.setPixelSize( 15 );

		m_picker->setFont( m_font );

		m_picker->show();

		QVERIFY( QTest::qWaitForWindowActive( m_picker.data() ) );

		QFontMetrics fm( m_font );
		m_lineHeight = fm.boundingRect( QStringLiteral( "A" ) ).height();

		m_delta = QPoint( 0, - ( m_lineHeight + m_lineHeight / 3 ) );
	}

	void testPicker()
	{
		m_picker->setCurrentIndex( 2 );

		QVERIFY( m_picker->currentIndex() == 2 );
		QVERIFY( m_picker->currentText() == m_data.at( 2 ) );

		QVERIFY( m_picker->count() == 8 );

		QVERIFY( m_picker->findText( m_data.at( 6 ) ) == 6 );
		QVERIFY( m_picker->itemText( 6 ) == m_data.at( 6 ) );

		QPoint c( m_picker->width() / 2, m_picker->height() / 2 );

		QTest::mousePress( m_picker.data(), Qt::LeftButton, {}, c );
		QMouseEvent me( QEvent::MouseMove, c + m_delta, Qt::LeftButton,
			Qt::LeftButton, {} );
		QApplication::sendEvent( m_picker.data(), &me );
		QTest::mouseRelease( m_picker.data(), Qt::LeftButton, {}, c + m_delta, 20 );
		QTest::mouseClick( m_picker.data(), Qt::LeftButton, {}, c, 20 );

		QVERIFY( m_picker->currentIndex() == 3 );

		int idx = 4;

		for( int i = 0; i < 8; ++i )
		{
			QTest::mousePress( m_picker.data(), Qt::LeftButton, {}, c );
			QMouseEvent me( QEvent::MouseMove, c + m_delta, Qt::LeftButton,
				Qt::LeftButton, {} );
			QApplication::sendEvent( m_picker.data(), &me );
			QTest::mouseRelease( m_picker.data(), Qt::LeftButton, {}, c + m_delta, 20 );
			QTest::mouseClick( m_picker.data(), Qt::LeftButton, {}, c, 20 );

			QVERIFY( m_picker->currentIndex() == idx );

			++idx;

			if( idx == m_data.size() )
				idx = 0;
		}

		QVERIFY( m_picker->currentIndex() == 3 );
	}

	void testWithModel()
	{
		m_picker->setModel( &m_model );
		m_picker->setCurrentIndex( 0 );

		QVERIFY( m_picker->currentText() == m_data.at( 0 ) );
		QVERIFY( m_picker->currentData( Qt::DisplayRole ).toString() == m_data.at( 0 ) );
		QVERIFY( m_picker->findData( m_data.at( 0 ), Qt::DisplayRole ) == 0 );
		QVERIFY( m_picker->itemData( 0, Qt::DisplayRole ).toString() == m_data.at( 0 ) );

		const auto wrong = QStringLiteral( "Wrong" );

		m_picker->setItemText( 0, wrong );

		QVERIFY( m_picker->currentText() == wrong );

		m_picker->setItemData( 0, m_data.at( 0 ), Qt::DisplayRole );

		QVERIFY( m_picker->currentText() == m_data.at( 0 ) );

		QSignalSpy spy( m_picker.data(), &QtMWidgets::Picker::currentTextChanged );

		m_picker->removeItem( 0 );

		QVERIFY( spy.count() == 1 );

		QVERIFY( m_picker->count() == m_data.size() - 1 );
		QVERIFY( m_picker->currentIndex() == 0 );
		QVERIFY( m_picker->currentText() == m_data.at( 1 ) );

		m_picker->setCurrentText( m_data.at( 6 ) );

		QVERIFY( m_picker->currentIndex() == 5 );
		QVERIFY( m_picker->currentText() == m_data.at( 6 ) );

		QVERIFY( m_picker->rootModelIndex() == QModelIndex() );
		QVERIFY( m_picker->modelColumn() == 0 );
		QVERIFY( m_picker->model() == &m_model );

		m_picker->insertItem( 0, m_data.at( 0 ) );

		QVERIFY( m_picker->count() == m_data.size() );
		QVERIFY( m_picker->itemText( 0 ) == m_data.at( 0 ) );

		m_picker->addItems( m_data );

		QVERIFY( m_picker->count() == m_data.size() * 2 );

		m_picker->clear();

		QVERIFY( m_picker->count() == 0 );
	}

	void testEvenDisabled()
	{
		StringListEvenDisabledModel model;
		model.setStringList( m_data );

		m_picker->setModel( &model );

		m_picker->setCurrentIndex( 3 );

		QPoint c( m_picker->width() / 2, m_picker->height() / 2 );

		QSignalSpy spy( m_picker.data(), QOverload< int >::of(
			&QtMWidgets::Picker::currentIndexChanged ) );

		QTest::mousePress( m_picker.data(), Qt::LeftButton, {}, c );
		QMouseEvent me( QEvent::MouseMove, c + m_delta, Qt::LeftButton,
			Qt::LeftButton, {} );
		QApplication::sendEvent( m_picker.data(), &me );
		QTest::mouseRelease( m_picker.data(), Qt::LeftButton, {}, c + m_delta, 20 );
		QTest::mouseClick( m_picker.data(), Qt::LeftButton, {}, c, 20 );

		QVERIFY( spy.count() == 0 );

		m_picker->setModel( &m_model );
	}

	void testThreeItems()
	{
		QStringList data;
		data << QStringLiteral( "One" )
			<< QStringLiteral( "Very very very very very very very long line" )
			<< QStringLiteral( "Three" );
		m_model.setStringList( data );

		m_picker->resize( 150, 100 );
		m_picker->setCurrentIndex( 1 );
	}

private:
	QStringList m_data;
	QSharedPointer< QtMWidgets::Picker > m_picker;
	QStringListModel m_model;
	QFont m_font;
	int m_lineHeight;
	QPoint m_delta;
};

QTEST_MAIN( TestPicker )

#include "main.moc"
<|endoftext|>


<commit_before>#include "ConservedNoiseBase.h"

template<>
InputParameters validParams<ConservedNoiseBase>()
{
  InputParameters params = validParams<ElementUserObject>();

  std::vector<MooseEnum> setup_options(SetupInterface::getExecuteOptions());
  setup_options[0] = "timestep_begin";
  params.set<std::vector<MooseEnum> >("execute_on") = setup_options;
  return params;
}

ConservedNoiseBase::ConservedNoiseBase(const std::string & name, InputParameters parameters) :
    ElementUserObject(name, parameters),
    _integral(0),
    _volume(0),
    _qp(0)
{
  /**
   * This call turns on Random Number generation for this object, it can be called either in
   * the constructor or in initialSetup().
   */
  setRandomResetFrequency(EXEC_TIMESTEP);
}

ConservedNoiseBase::~ConservedNoiseBase()
{
}

void
ConservedNoiseBase::initialize()
{
  _random_data.clear();
  _integral = 0.0;
  _volume = 0.0;
}

void
ConservedNoiseBase::execute()
{
  // reserve space for each quadrature point in the element
  std::vector<Real> & me = _random_data[_current_elem->id()] = std::vector<Real>(_qrule->n_points());

  // store a random number for each quadrature point
  for (_qp=0; _qp<_qrule->n_points(); _qp++)
  {
    me[_qp] = getQpRandom();
    _integral += _JxW[_qp] * _coord[_qp] * me[_qp];
    _volume   += _JxW[_qp] * _coord[_qp];
  }
}

void
ConservedNoiseBase::threadJoin(const UserObject &y)
{
  const ConservedNoiseBase & uo = static_cast<const ConservedNoiseBase &>(y);

  _random_data.insert(uo._random_data.begin(), uo._random_data.end());
}

void
ConservedNoiseBase::finalize()
{
  gatherSum(_integral);
  gatherSum(_volume);

  _offset = _integral / _volume;
}

Real
ConservedNoiseBase::getQpValue(dof_id_type element_id, unsigned int qp) const
{
  LIBMESH_BEST_UNORDERED_MAP<dof_id_type, std::vector<Real> >::const_iterator me = _random_data.find(element_id);

  if (me == _random_data.end())
    mooseError("Element not found.");
  else
  {
    libmesh_assert_less(qp, me->second->size());
    return me->second[qp] - _offset;
  }
}
<commit_msg>Fixing bad debug code<commit_after>#include "ConservedNoiseBase.h"

template<>
InputParameters validParams<ConservedNoiseBase>()
{
  InputParameters params = validParams<ElementUserObject>();

  std::vector<MooseEnum> setup_options(SetupInterface::getExecuteOptions());
  setup_options[0] = "timestep_begin";
  params.set<std::vector<MooseEnum> >("execute_on") = setup_options;
  return params;
}

ConservedNoiseBase::ConservedNoiseBase(const std::string & name, InputParameters parameters) :
    ElementUserObject(name, parameters),
    _integral(0),
    _volume(0),
    _qp(0)
{
  /**
   * This call turns on Random Number generation for this object, it can be called either in
   * the constructor or in initialSetup().
   */
  setRandomResetFrequency(EXEC_TIMESTEP);
}

ConservedNoiseBase::~ConservedNoiseBase()
{
}

void
ConservedNoiseBase::initialize()
{
  _random_data.clear();
  _integral = 0.0;
  _volume = 0.0;
}

void
ConservedNoiseBase::execute()
{
  // reserve space for each quadrature point in the element
  std::vector<Real> & me = _random_data[_current_elem->id()] = std::vector<Real>(_qrule->n_points());

  // store a random number for each quadrature point
  for (_qp=0; _qp<_qrule->n_points(); _qp++)
  {
    me[_qp] = getQpRandom();
    _integral += _JxW[_qp] * _coord[_qp] * me[_qp];
    _volume   += _JxW[_qp] * _coord[_qp];
  }
}

void
ConservedNoiseBase::threadJoin(const UserObject &y)
{
  const ConservedNoiseBase & uo = static_cast<const ConservedNoiseBase &>(y);

  _random_data.insert(uo._random_data.begin(), uo._random_data.end());
}

void
ConservedNoiseBase::finalize()
{
  gatherSum(_integral);
  gatherSum(_volume);

  _offset = _integral / _volume;
}

Real
ConservedNoiseBase::getQpValue(dof_id_type element_id, unsigned int qp) const
{
  LIBMESH_BEST_UNORDERED_MAP<dof_id_type, std::vector<Real> >::const_iterator me = _random_data.find(element_id);

  if (me == _random_data.end())
    mooseError("Element not found.");
  else
  {
    libmesh_assert_less(qp, me->second.size());
    return me->second[qp] - _offset;
  }
}
<|endoftext|>


<commit_before>#include "Tile.h"

const int Tile::getX()
{
    return x;
}

const int Tile::getY()
{
    return y;
}

const bool Tile::isAlive()
{
    return alive;
}

/**
 * returns whether this tile will be alive in the next generation
 * note that this function ONLY calculates whether THIS tile will live--does not give any information about neighboring tiles
 * this is OK because by looping through every tile you will get the correct generation
 * implement Conway's 4 rules of the game of life
 */
const bool Tile::willBeAlive()
{
    /** rules quoted from wikipedia: https://en.wikipedia.org/wiki/Conway's_Game_of_Life#Rules */
    int numLiveNeighbors = 0;
    if(leftAlive == true)
        numLiveNeighbors++;
    if(rightAlive == true)
        numLiveNeighbors++;
    if(topAlive == true)
        numLiveNeighbors++;
    if(bottomAlive == true)
        numLiveNeighbors++;

    /** 1. Any live cell with fewer than two live neighbours dies, as if caused by under-population. */
    if(numLiveNeighbors < 2)
        return false;

    /** 2. Any live cell with two or three live neighbours lives on to the next generation. */
    if((isAlive() && numLiveNeighbors == 2) || (isAlive() && numLiveNeighbors == 3))
        return true;

    /** 3. Any live cell with more than three live neighbours dies, as if by overcrowding. */
    if(numLiveNeighbors > 3)
        return false;

    /** 4. Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction. */
    if(!isAlive() && numLiveNeighbors == 3)
        return true;

    throw TileException("Invalid game board state -- should never reach here.");
}
<commit_msg>removed redundant const<commit_after>#include "Tile.h"

int Tile::getX()
{
    return x;
}

int Tile::getY()
{
    return y;
}

bool Tile::isAlive()
{
    return alive;
}

/**
 * returns whether this tile will be alive in the next generation
 * note that this function ONLY calculates whether THIS tile will live--does not give any information about neighboring tiles
 * this is OK because by looping through every tile you will get the correct generation
 * implement Conway's 4 rules of the game of life
 */
bool Tile::willBeAlive()
{
    /** rules quoted from wikipedia: https://en.wikipedia.org/wiki/Conway's_Game_of_Life#Rules */
    int numLiveNeighbors = 0;
    if(leftAlive == true)
        numLiveNeighbors++;
    if(rightAlive == true)
        numLiveNeighbors++;
    if(topAlive == true)
        numLiveNeighbors++;
    if(bottomAlive == true)
        numLiveNeighbors++;

    /** 1. Any live cell with fewer than two live neighbours dies, as if caused by under-population. */
    if(numLiveNeighbors < 2)
        return false;

    /** 2. Any live cell with two or three live neighbours lives on to the next generation. */
    if((isAlive() && numLiveNeighbors == 2) || (isAlive() && numLiveNeighbors == 3))
        return true;

    /** 3. Any live cell with more than three live neighbours dies, as if by overcrowding. */
    if(numLiveNeighbors > 3)
        return false;

    /** 4. Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction. */
    if(!isAlive() && numLiveNeighbors == 3)
        return true;

    throw TileException("Invalid game board state -- should never reach here.");
}
<|endoftext|>


<commit_before>#include "Track.h"
#import "Artwork.h"
#import "async_macros.h"

using namespace node;
using namespace v8;

namespace node_iTunes {

static Persistent<String> TRACK_CLASS_SYMBOL;

//Persistent<FunctionTemplate> Track::constructor_template;

void Track::Init(v8::Handle<Object> target) {
  HandleScope scope;

  // String Constants
  TRACK_CLASS_SYMBOL = NODE_PSYMBOL("Track");

  Local<FunctionTemplate> t = FunctionTemplate::New(New);
  track_constructor_template = Persistent<FunctionTemplate>::New(t);
  track_constructor_template->Inherit(item_constructor_template);
  track_constructor_template->SetClassName(TRACK_CLASS_SYMBOL);
  t->InstanceTemplate()->SetInternalFieldCount(1);

  NODE_SET_PROTOTYPE_METHOD(t, "artworks", Artworks);

  target->Set(TRACK_CLASS_SYMBOL, track_constructor_template->GetFunction());
}

// JavaScript Constructor//////////////////////////////////////////////////////
v8::Handle<Value> Track::New(const Arguments& args) {
  HandleScope scope;

  Track* track = new Track();
  track->Wrap(args.This());
  return args.This();
}

// Artworks ///////////////////////////////////////////////////////////////////
// Readonly
v8::Handle<Value> Track::Artworks(const Arguments& args) {
  HandleScope scope;
  REQUIRE_CALLBACK_ARG;
  INIT(Track);
  GET_CALLBACK;
  BEGIN_ASYNC(EIO_Artworks, EIO_AfterArtworks);
}

int Track::EIO_Artworks(eio_req *req) {
  INIT_EIO_FUNC;
  iTunesTrack *item = (iTunesTrack *)ar->itemRef;
  SBElementArray *artworks = [item artworks];
  [artworks retain];
  // I would normally want to move these into an NSMutableDictionary before
  // returning to the main thread, however it seems as though these Artwork
  // instances don't return a 'persistentID', so we have no key to cache the
  // values off of...
  ar->result = artworks;
  FINISH_EIO_FUNC;
}

int Track::EIO_AfterArtworks(eio_req *req) {
  INIT_AFTER_FUNC;
  argv[0] = Null();
  SBElementArray *res = (SBElementArray *)ar->result;
  NSUInteger count = [res count];
  Local<Array> result = Array::New(count);
  iTunesArtwork *a;
  for (NSUInteger i = 0; i < count; i++) {
    a = [res objectAtIndex: i];
    Local<Object> aWrap = artwork_constructor_template->GetFunction()->NewInstance();
    Artwork *aUnwrap = ObjectWrap::Unwrap<Artwork>(aWrap);
    aUnwrap->itemRef = a;
    result->Set(Integer::New(i), aWrap);
  }
  argv[1] = result;
  FINISH_AFTER_FUNC;
}

/*v8::Handle<Value> Application::IsRunning(const Arguments& args) {
  HandleScope scope;
  Application* it = ObjectWrap::Unwrap<Application>(args.This());
  iTunesApplication* iTunes = it->iTunesRef;
  v8::Handle<v8::Boolean> result = v8::Boolean::New([iTunes isRunning]);
  return scope.Close(result);
}*/

} // namespace node_iTunes
<commit_msg>Remove unused stuff.<commit_after>#include "Track.h"
#import "Artwork.h"
#import "async_macros.h"

using namespace node;
using namespace v8;

namespace node_iTunes {

static Persistent<String> TRACK_CLASS_SYMBOL;

//Persistent<FunctionTemplate> Track::constructor_template;

void Track::Init(v8::Handle<Object> target) {
  HandleScope scope;

  // String Constants
  TRACK_CLASS_SYMBOL = NODE_PSYMBOL("Track");

  Local<FunctionTemplate> t = FunctionTemplate::New(New);
  track_constructor_template = Persistent<FunctionTemplate>::New(t);
  track_constructor_template->Inherit(item_constructor_template);
  track_constructor_template->SetClassName(TRACK_CLASS_SYMBOL);
  t->InstanceTemplate()->SetInternalFieldCount(1);

  NODE_SET_PROTOTYPE_METHOD(t, "artworks", Artworks);

  target->Set(TRACK_CLASS_SYMBOL, track_constructor_template->GetFunction());
}

// JavaScript Constructor//////////////////////////////////////////////////////
v8::Handle<Value> Track::New(const Arguments& args) {
  HandleScope scope;

  Track* track = new Track();
  track->Wrap(args.This());
  return args.This();
}

// Artworks ///////////////////////////////////////////////////////////////////
// Readonly
v8::Handle<Value> Track::Artworks(const Arguments& args) {
  HandleScope scope;
  REQUIRE_CALLBACK_ARG;
  INIT(Track);
  GET_CALLBACK;
  BEGIN_ASYNC(EIO_Artworks, EIO_AfterArtworks);
}

int Track::EIO_Artworks(eio_req *req) {
  INIT_EIO_FUNC;
  iTunesTrack *item = (iTunesTrack *)ar->itemRef;
  SBElementArray *artworks = [item artworks];
  [artworks retain];
  // I would normally want to move these into an NSMutableDictionary before
  // returning to the main thread, however it seems as though these Artwork
  // instances don't return a 'persistentID', so we have no key to cache the
  // values off of...
  ar->result = artworks;
  FINISH_EIO_FUNC;
}

int Track::EIO_AfterArtworks(eio_req *req) {
  INIT_AFTER_FUNC;
  argv[0] = Null();
  SBElementArray *res = (SBElementArray *)ar->result;
  NSUInteger count = [res count];
  Local<Array> result = Array::New(count);
  iTunesArtwork *a;
  for (NSUInteger i = 0; i < count; i++) {
    a = [res objectAtIndex: i];
    Local<Object> aWrap = artwork_constructor_template->GetFunction()->NewInstance();
    Artwork *aUnwrap = ObjectWrap::Unwrap<Artwork>(aWrap);
    aUnwrap->itemRef = a;
    result->Set(Integer::New(i), aWrap);
  }
  argv[1] = result;
  FINISH_AFTER_FUNC;
}

} // namespace node_iTunes
<|endoftext|>


<commit_before>#include "Util.h"
#include "Introspection.h"
#include "Debug.h"
#include "Error.h"
#include <sstream>
#include <map>
#include <atomic>
#include <mutex>
#include <string>
#include <iomanip>

#ifdef _MSC_VER
#include <io.h>
#else
#include <unistd.h>
#include <stdlib.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>

#ifdef __linux__
#define CAN_GET_RUNNING_PROGRAM_NAME
#include <linux/limits.h>  // For PATH_MAX
#endif
#ifdef _WIN32
#include <windows.h>
#endif
#ifdef __APPLE__
#define CAN_GET_RUNNING_PROGRAM_NAME
#include <mach-o/dyld.h>
#endif

namespace Halide {
namespace Internal {

using std::string;
using std::vector;
using std::ostringstream;
using std::map;

std::string get_env_variable(char const *env_var_name) {
    if (!env_var_name) {
        return "";
    }

    #ifdef _MSC_VER
    char lvl[128];
    size_t read = 0;
    if (getenv_s(&read, lvl, env_var_name) != 0) read = 0;
    if (read) return std::string(lvl);
    #else
    char *lvl = getenv(env_var_name);
    if (lvl) return std::string(lvl);
    #endif

    return "";
}

string running_program_name() {
    #ifndef CAN_GET_RUNNING_PROGRAM_NAME
        return "";
    #else
        string program_name;
        char path[PATH_MAX] = { 0 };
        uint32_t size = sizeof(path);
        #if defined(__linux__)
            ssize_t len = ::readlink("/proc/self/exe", path, size - 1);
        #elif defined(__APPLE__)
            ssize_t len = ::_NSGetExecutablePath(path, &size);
        #endif
        if (len != -1) {
            #if defined(__linux__)
                path[len] = '\0';
            #endif
            string tmp = std::string(path);
            program_name = tmp.substr(tmp.find_last_of("/") + 1);
        } else {
            return "";
        }
        return program_name;
    #endif
}

namespace {
// We use 64K of memory to store unique counters for the purpose of
// making names unique. Using less memory increases the likelihood of
// hash collisions. This wouldn't break anything, but makes stmts
// slightly confusing to read because names that are actually unique
// will get suffixes that falsely hint that they are not.

const int num_unique_name_counters = (1 << 14);
std::atomic<int> unique_name_counters[num_unique_name_counters];

int unique_count(size_t h) {
    h = h & (num_unique_name_counters - 1);
    return unique_name_counters[h]++;
}
}

// There are three possible families of names returned by the methods below:
// 1) char pattern: (char that isn't '$') + number (e.g. v234)
// 2) string pattern: (string without '$') + '$' + number (e.g. fr#nk82$42)
// 3) a string that does not match the patterns above
// There are no collisions within each family, due to the unique_count
// done above, and there can be no collisions across families by
// construction.

string unique_name(char prefix) {
    if (prefix == '$') prefix = '_';
    return prefix + std::to_string(unique_count((size_t)(prefix)));
}

string unique_name(const std::string &prefix) {
    string sanitized = prefix;

    // Does the input string look like something returned from unique_name(char)?
    bool matches_char_pattern = true;

    // Does the input string look like something returned from unique_name(string)?
    bool matches_string_pattern = true;

    // Rewrite '$' to '_'. This is a many-to-one mapping, but that's
    // OK, we're about to hash anyway. It just means that some names
    // will share the same counter.
    int num_dollars = 0;
    for (size_t i = 0; i < sanitized.size(); i++) {
        if (sanitized[i] == '$') {
            num_dollars++;
            sanitized[i] = '_';
        }
        if (i > 0 && !isdigit(sanitized[i])) {
            // Found a non-digit after the first char
            matches_char_pattern = false;
            if (num_dollars) {
                // Found a non-digit after a '$'
                matches_string_pattern = false;
            }
        }
    }
    matches_string_pattern &= num_dollars == 1;
    matches_char_pattern &= prefix.size() > 1;

    // Then add a suffix that's globally unique relative to the hash
    // of the sanitized name.
    int count = unique_count(std::hash<std::string>()(sanitized));
    if (count == 0) {
        // We can return the name as-is if there's no risk of it
        // looking like something unique_name has ever returned in the
        // past or will ever return in the future.
        if (!matches_char_pattern && !matches_string_pattern) {
            return prefix;
        }
    }

    return sanitized + "$" + std::to_string(count);
}

bool starts_with(const string &str, const string &prefix) {
    if (str.size() < prefix.size()) return false;
    for (size_t i = 0; i < prefix.size(); i++) {
        if (str[i] != prefix[i]) return false;
    }
    return true;
}

bool ends_with(const string &str, const string &suffix) {
    if (str.size() < suffix.size()) return false;
    size_t off = str.size() - suffix.size();
    for (size_t i = 0; i < suffix.size(); i++) {
        if (str[off+i] != suffix[i]) return false;
    }
    return true;
}

string replace_all(const string &str, const string &find, const string &replace) {
    size_t pos = 0;
    string result = str;
    while ((pos = result.find(find, pos)) != string::npos) {
        result.replace(pos, find.length(), replace);
        pos += replace.length();
    }
    return result;
}

string make_entity_name(void *stack_ptr, const string &type, char prefix) {
    string name = Introspection::get_variable_name(stack_ptr, type);

    if (name.empty()) {
        return unique_name(prefix);
    } else {
        // Halide names may not contain '.'
        for (size_t i = 0; i < name.size(); i++) {
            if (name[i] == '.') {
                name[i] = ':';
            }
        }
        return unique_name(name);
    }
}

std::vector<std::string> split_string(const std::string &source, const std::string &delim) {
    std::vector<std::string> elements;
    size_t start = 0;
    size_t found = 0;
    while ((found = source.find(delim, start)) != std::string::npos) {
        elements.push_back(source.substr(start, found - start));
        start = found + delim.size();
    }

    // If start is exactly source.size(), the last thing in source is a
    // delimiter, in which case we want to add an empty string to elements.
    if (start <= source.size()) {
        elements.push_back(source.substr(start, std::string::npos));
    }
    return elements;
}

std::string extract_namespaces(const std::string &name, std::vector<std::string> &namespaces) {
    namespaces = split_string(name, "::");
    std::string result = namespaces.back();
    namespaces.pop_back();
    return result;
}

bool file_exists(const std::string &name) {
    #ifdef _MSC_VER
    return _access(name.c_str(), 0) == 0;
    #else
    return ::access(name.c_str(), F_OK) == 0;
    #endif
}

void assert_file_exists(const std::string &name) {
    internal_assert(file_exists(name)) << "File not found: " << name;
}

void assert_no_file_exists(const std::string &name) {
    internal_assert(!file_exists(name)) << "File (wrongly) found: " << name;
}

void file_unlink(const std::string &name) {
    #ifdef _MSC_VER
    _unlink(name.c_str());
    #else
    ::unlink(name.c_str());
    #endif
}

void ensure_no_file_exists(const std::string &name) {
    if (file_exists(name)) {
        file_unlink(name);
    }
    assert_no_file_exists(name);
}

void dir_rmdir(const std::string &name) {
    #ifdef _MSC_VER
    BOOL r = RemoveDirectoryA(name.c_str());
    internal_assert(r != 0) << "Unable to remove dir: " << name << ":" << GetLastError() << "\n";
    #else
    int r = ::rmdir(name.c_str());
    internal_assert(r == 0) << "Unable to remove dir: " << name << "\n";
    #endif
}

FileStat file_stat(const std::string &name) {
    #ifdef _MSC_VER
    struct _stat a;
    if (_stat(name.c_str(), &a) != 0) {
        user_error << "Could not stat " << name << "\n";
    }
    #else
    struct stat a;
    if (::stat(name.c_str(), &a) != 0) {
        user_error << "Could not stat " << name << "\n";
    }
    #endif
    return {static_cast<uint64_t>(a.st_size),
            static_cast<uint32_t>(a.st_mtime),
            static_cast<uint32_t>(a.st_uid),
            static_cast<uint32_t>(a.st_gid),
            static_cast<uint32_t>(a.st_mode)};
}

std::string file_make_temp(const std::string &prefix, const std::string &suffix) {
    internal_assert(prefix.find("/") == string::npos &&
                    prefix.find("\\") == string::npos &&
                    suffix.find("/") == string::npos &&
                    suffix.find("\\") == string::npos);
    #ifdef _WIN32
    // Windows implementations of mkstemp() try to create the file in the root
    // directory, which is... problematic.
    char tmp_path[MAX_PATH], tmp_file[MAX_PATH];
    DWORD ret = GetTempPathA(MAX_PATH, tmp_path);
    internal_assert(ret != 0);
    // Note that GetTempFileNameA() actually creates the file.
    ret = GetTempFileNameA(tmp_path, prefix.c_str(), 0, tmp_file);
    internal_assert(ret != 0);
    return std::string(tmp_file);
    #else
    std::string templ = "/tmp/" + prefix + "XXXXXX" + suffix;
    // Copy into a temporary buffer, since mkstemp modifies the buffer in place.
    std::vector<char> buf(templ.size() + 1);
    strcpy(&buf[0], templ.c_str());
    int fd = mkstemps(&buf[0], suffix.size());
    internal_assert(fd != -1) << "Unable to create temp file for (" << &buf[0] << ")\n";
    close(fd);
    return std::string(&buf[0]);
    #endif
}

std::string dir_make_temp() {
    #ifdef _WIN32
    char tmp_path[MAX_PATH];
    DWORD ret = GetTempPathA(MAX_PATH, tmp_path);
    internal_assert(ret != 0);
    // There's no direct API to do this in Windows;
    // our clunky-but-adequate approach here is to use
    // CoCreateGuid() to create a probably-unique name.
    // Add a limit on the number of tries just in case.
    for (int tries = 0; tries < 100; ++tries) {
        GUID guid;
        HRESULT hr = CoCreateGuid(&guid);
        internal_assert(hr == S_OK);
        std::ostringstream name;
        name << std::hex
             << std::setfill('0')
             << std::setw(8)
             << guid.Data1
             << std::setw(4)
             << guid.Data2
             << guid.Data3
             << std::setw(2);
        for (int i = 0; i < 8; i++) {
            name << (int)guid.Data4[i];
        }
        std::string dir = std::string(tmp_path) + std::string(name.str());
        BOOL result = CreateDirectoryA(dir.c_str(), nullptr);
        if (result) {
            debug(1) << "temp dir is: " << dir << "\n";
            return dir;
        }
        // If name already existed, just loop and try again.
        // Any other error, break from loop and fail.
        if (GetLastError() != ERROR_ALREADY_EXISTS) {
            break;
        }
    }
    internal_assert(false) << "Unable to create temp directory.\n";
    return "";
    #else
    std::string templ = "/tmp/XXXXXX";
    // Copy into a temporary buffer, since mkdtemp modifies the buffer in place.
    std::vector<char> buf(templ.size() + 1);
    strcpy(&buf[0], templ.c_str());
    char* result = mkdtemp(&buf[0]);
    internal_assert(result != nullptr) << "Unable to create temp directory.\n";
    return std::string(result);
    #endif
}

bool add_would_overflow(int bits, int64_t a, int64_t b) {
    int64_t max_val = 0x7fffffffffffffffLL >> (64 - bits);
    int64_t min_val = -max_val - 1;
    return
        ((b > 0 && a > max_val - b) || // (a + b) > max_val, rewritten to avoid overflow
         (b < 0 && a < min_val - b));  // (a + b) < min_val, rewritten to avoid overflow
}

bool sub_would_overflow(int bits, int64_t a, int64_t b) {
    int64_t max_val = 0x7fffffffffffffffLL >> (64 - bits);
    int64_t min_val = -max_val - 1;
    return
        ((b < 0 && a > max_val + b) || // (a - b) > max_val, rewritten to avoid overflow
         (b > 0 && a < min_val + b));  // (a - b) < min_val, rewritten to avoid overflow
}

bool mul_would_overflow(int bits, int64_t a, int64_t b) {
    int64_t max_val = 0x7fffffffffffffffLL >> (64 - bits);
    int64_t min_val = -max_val - 1;
    if (a == 0) {
        return false;
    } else if (a == -1) {
        return b == min_val;
    } else {
        // Do the multiplication as a uint64, for which overflow is
        // well defined, then cast the bits back to int64 to get
        // multiplication modulo 2^64.
        int64_t ab = (int64_t)((uint64_t)a)*((uint64_t)b);
        // The first two clauses catch overflow mod 2^bits, assuming
        // no 64-bit overflow occurs, and the third clause catches
        // 64-bit overflow.
        return ab < min_val || ab > max_val || (ab / a != b);
    }
}

}
}
<commit_msg>Add #include Objbase.h<commit_after>#include "Util.h"
#include "Introspection.h"
#include "Debug.h"
#include "Error.h"
#include <sstream>
#include <map>
#include <atomic>
#include <mutex>
#include <string>
#include <iomanip>

#ifdef _MSC_VER
#include <io.h>
#else
#include <unistd.h>
#include <stdlib.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>

#ifdef __linux__
#define CAN_GET_RUNNING_PROGRAM_NAME
#include <linux/limits.h>  // For PATH_MAX
#endif
#ifdef _WIN32
#include <windows.h>
#include <Objbase.h>  // needed for CoCreateGuid
#endif
#ifdef __APPLE__
#define CAN_GET_RUNNING_PROGRAM_NAME
#include <mach-o/dyld.h>
#endif

namespace Halide {
namespace Internal {

using std::string;
using std::vector;
using std::ostringstream;
using std::map;

std::string get_env_variable(char const *env_var_name) {
    if (!env_var_name) {
        return "";
    }

    #ifdef _MSC_VER
    char lvl[128];
    size_t read = 0;
    if (getenv_s(&read, lvl, env_var_name) != 0) read = 0;
    if (read) return std::string(lvl);
    #else
    char *lvl = getenv(env_var_name);
    if (lvl) return std::string(lvl);
    #endif

    return "";
}

string running_program_name() {
    #ifndef CAN_GET_RUNNING_PROGRAM_NAME
        return "";
    #else
        string program_name;
        char path[PATH_MAX] = { 0 };
        uint32_t size = sizeof(path);
        #if defined(__linux__)
            ssize_t len = ::readlink("/proc/self/exe", path, size - 1);
        #elif defined(__APPLE__)
            ssize_t len = ::_NSGetExecutablePath(path, &size);
        #endif
        if (len != -1) {
            #if defined(__linux__)
                path[len] = '\0';
            #endif
            string tmp = std::string(path);
            program_name = tmp.substr(tmp.find_last_of("/") + 1);
        } else {
            return "";
        }
        return program_name;
    #endif
}

namespace {
// We use 64K of memory to store unique counters for the purpose of
// making names unique. Using less memory increases the likelihood of
// hash collisions. This wouldn't break anything, but makes stmts
// slightly confusing to read because names that are actually unique
// will get suffixes that falsely hint that they are not.

const int num_unique_name_counters = (1 << 14);
std::atomic<int> unique_name_counters[num_unique_name_counters];

int unique_count(size_t h) {
    h = h & (num_unique_name_counters - 1);
    return unique_name_counters[h]++;
}
}

// There are three possible families of names returned by the methods below:
// 1) char pattern: (char that isn't '$') + number (e.g. v234)
// 2) string pattern: (string without '$') + '$' + number (e.g. fr#nk82$42)
// 3) a string that does not match the patterns above
// There are no collisions within each family, due to the unique_count
// done above, and there can be no collisions across families by
// construction.

string unique_name(char prefix) {
    if (prefix == '$') prefix = '_';
    return prefix + std::to_string(unique_count((size_t)(prefix)));
}

string unique_name(const std::string &prefix) {
    string sanitized = prefix;

    // Does the input string look like something returned from unique_name(char)?
    bool matches_char_pattern = true;

    // Does the input string look like something returned from unique_name(string)?
    bool matches_string_pattern = true;

    // Rewrite '$' to '_'. This is a many-to-one mapping, but that's
    // OK, we're about to hash anyway. It just means that some names
    // will share the same counter.
    int num_dollars = 0;
    for (size_t i = 0; i < sanitized.size(); i++) {
        if (sanitized[i] == '$') {
            num_dollars++;
            sanitized[i] = '_';
        }
        if (i > 0 && !isdigit(sanitized[i])) {
            // Found a non-digit after the first char
            matches_char_pattern = false;
            if (num_dollars) {
                // Found a non-digit after a '$'
                matches_string_pattern = false;
            }
        }
    }
    matches_string_pattern &= num_dollars == 1;
    matches_char_pattern &= prefix.size() > 1;

    // Then add a suffix that's globally unique relative to the hash
    // of the sanitized name.
    int count = unique_count(std::hash<std::string>()(sanitized));
    if (count == 0) {
        // We can return the name as-is if there's no risk of it
        // looking like something unique_name has ever returned in the
        // past or will ever return in the future.
        if (!matches_char_pattern && !matches_string_pattern) {
            return prefix;
        }
    }

    return sanitized + "$" + std::to_string(count);
}

bool starts_with(const string &str, const string &prefix) {
    if (str.size() < prefix.size()) return false;
    for (size_t i = 0; i < prefix.size(); i++) {
        if (str[i] != prefix[i]) return false;
    }
    return true;
}

bool ends_with(const string &str, const string &suffix) {
    if (str.size() < suffix.size()) return false;
    size_t off = str.size() - suffix.size();
    for (size_t i = 0; i < suffix.size(); i++) {
        if (str[off+i] != suffix[i]) return false;
    }
    return true;
}

string replace_all(const string &str, const string &find, const string &replace) {
    size_t pos = 0;
    string result = str;
    while ((pos = result.find(find, pos)) != string::npos) {
        result.replace(pos, find.length(), replace);
        pos += replace.length();
    }
    return result;
}

string make_entity_name(void *stack_ptr, const string &type, char prefix) {
    string name = Introspection::get_variable_name(stack_ptr, type);

    if (name.empty()) {
        return unique_name(prefix);
    } else {
        // Halide names may not contain '.'
        for (size_t i = 0; i < name.size(); i++) {
            if (name[i] == '.') {
                name[i] = ':';
            }
        }
        return unique_name(name);
    }
}

std::vector<std::string> split_string(const std::string &source, const std::string &delim) {
    std::vector<std::string> elements;
    size_t start = 0;
    size_t found = 0;
    while ((found = source.find(delim, start)) != std::string::npos) {
        elements.push_back(source.substr(start, found - start));
        start = found + delim.size();
    }

    // If start is exactly source.size(), the last thing in source is a
    // delimiter, in which case we want to add an empty string to elements.
    if (start <= source.size()) {
        elements.push_back(source.substr(start, std::string::npos));
    }
    return elements;
}

std::string extract_namespaces(const std::string &name, std::vector<std::string> &namespaces) {
    namespaces = split_string(name, "::");
    std::string result = namespaces.back();
    namespaces.pop_back();
    return result;
}

bool file_exists(const std::string &name) {
    #ifdef _MSC_VER
    return _access(name.c_str(), 0) == 0;
    #else
    return ::access(name.c_str(), F_OK) == 0;
    #endif
}

void assert_file_exists(const std::string &name) {
    internal_assert(file_exists(name)) << "File not found: " << name;
}

void assert_no_file_exists(const std::string &name) {
    internal_assert(!file_exists(name)) << "File (wrongly) found: " << name;
}

void file_unlink(const std::string &name) {
    #ifdef _MSC_VER
    _unlink(name.c_str());
    #else
    ::unlink(name.c_str());
    #endif
}

void ensure_no_file_exists(const std::string &name) {
    if (file_exists(name)) {
        file_unlink(name);
    }
    assert_no_file_exists(name);
}

void dir_rmdir(const std::string &name) {
    #ifdef _MSC_VER
    BOOL r = RemoveDirectoryA(name.c_str());
    internal_assert(r != 0) << "Unable to remove dir: " << name << ":" << GetLastError() << "\n";
    #else
    int r = ::rmdir(name.c_str());
    internal_assert(r == 0) << "Unable to remove dir: " << name << "\n";
    #endif
}

FileStat file_stat(const std::string &name) {
    #ifdef _MSC_VER
    struct _stat a;
    if (_stat(name.c_str(), &a) != 0) {
        user_error << "Could not stat " << name << "\n";
    }
    #else
    struct stat a;
    if (::stat(name.c_str(), &a) != 0) {
        user_error << "Could not stat " << name << "\n";
    }
    #endif
    return {static_cast<uint64_t>(a.st_size),
            static_cast<uint32_t>(a.st_mtime),
            static_cast<uint32_t>(a.st_uid),
            static_cast<uint32_t>(a.st_gid),
            static_cast<uint32_t>(a.st_mode)};
}

std::string file_make_temp(const std::string &prefix, const std::string &suffix) {
    internal_assert(prefix.find("/") == string::npos &&
                    prefix.find("\\") == string::npos &&
                    suffix.find("/") == string::npos &&
                    suffix.find("\\") == string::npos);
    #ifdef _WIN32
    // Windows implementations of mkstemp() try to create the file in the root
    // directory, which is... problematic.
    char tmp_path[MAX_PATH], tmp_file[MAX_PATH];
    DWORD ret = GetTempPathA(MAX_PATH, tmp_path);
    internal_assert(ret != 0);
    // Note that GetTempFileNameA() actually creates the file.
    ret = GetTempFileNameA(tmp_path, prefix.c_str(), 0, tmp_file);
    internal_assert(ret != 0);
    return std::string(tmp_file);
    #else
    std::string templ = "/tmp/" + prefix + "XXXXXX" + suffix;
    // Copy into a temporary buffer, since mkstemp modifies the buffer in place.
    std::vector<char> buf(templ.size() + 1);
    strcpy(&buf[0], templ.c_str());
    int fd = mkstemps(&buf[0], suffix.size());
    internal_assert(fd != -1) << "Unable to create temp file for (" << &buf[0] << ")\n";
    close(fd);
    return std::string(&buf[0]);
    #endif
}

std::string dir_make_temp() {
    #ifdef _WIN32
    char tmp_path[MAX_PATH];
    DWORD ret = GetTempPathA(MAX_PATH, tmp_path);
    internal_assert(ret != 0);
    // There's no direct API to do this in Windows;
    // our clunky-but-adequate approach here is to use
    // CoCreateGuid() to create a probably-unique name.
    // Add a limit on the number of tries just in case.
    for (int tries = 0; tries < 100; ++tries) {
        GUID guid;
        HRESULT hr = CoCreateGuid(&guid);
        internal_assert(hr == S_OK);
        std::ostringstream name;
        name << std::hex
             << std::setfill('0')
             << std::setw(8)
             << guid.Data1
             << std::setw(4)
             << guid.Data2
             << guid.Data3
             << std::setw(2);
        for (int i = 0; i < 8; i++) {
            name << (int)guid.Data4[i];
        }
        std::string dir = std::string(tmp_path) + std::string(name.str());
        BOOL result = CreateDirectoryA(dir.c_str(), nullptr);
        if (result) {
            debug(1) << "temp dir is: " << dir << "\n";
            return dir;
        }
        // If name already existed, just loop and try again.
        // Any other error, break from loop and fail.
        if (GetLastError() != ERROR_ALREADY_EXISTS) {
            break;
        }
    }
    internal_assert(false) << "Unable to create temp directory.\n";
    return "";
    #else
    std::string templ = "/tmp/XXXXXX";
    // Copy into a temporary buffer, since mkdtemp modifies the buffer in place.
    std::vector<char> buf(templ.size() + 1);
    strcpy(&buf[0], templ.c_str());
    char* result = mkdtemp(&buf[0]);
    internal_assert(result != nullptr) << "Unable to create temp directory.\n";
    return std::string(result);
    #endif
}

bool add_would_overflow(int bits, int64_t a, int64_t b) {
    int64_t max_val = 0x7fffffffffffffffLL >> (64 - bits);
    int64_t min_val = -max_val - 1;
    return
        ((b > 0 && a > max_val - b) || // (a + b) > max_val, rewritten to avoid overflow
         (b < 0 && a < min_val - b));  // (a + b) < min_val, rewritten to avoid overflow
}

bool sub_would_overflow(int bits, int64_t a, int64_t b) {
    int64_t max_val = 0x7fffffffffffffffLL >> (64 - bits);
    int64_t min_val = -max_val - 1;
    return
        ((b < 0 && a > max_val + b) || // (a - b) > max_val, rewritten to avoid overflow
         (b > 0 && a < min_val + b));  // (a - b) < min_val, rewritten to avoid overflow
}

bool mul_would_overflow(int bits, int64_t a, int64_t b) {
    int64_t max_val = 0x7fffffffffffffffLL >> (64 - bits);
    int64_t min_val = -max_val - 1;
    if (a == 0) {
        return false;
    } else if (a == -1) {
        return b == min_val;
    } else {
        // Do the multiplication as a uint64, for which overflow is
        // well defined, then cast the bits back to int64 to get
        // multiplication modulo 2^64.
        int64_t ab = (int64_t)((uint64_t)a)*((uint64_t)b);
        // The first two clauses catch overflow mod 2^bits, assuming
        // no 64-bit overflow occurs, and the third clause catches
        // 64-bit overflow.
        return ab < min_val || ab > max_val || (ab / a != b);
    }
}

}
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: XMLTextListAutoStylePool.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: mib $ $Date: 2000-10-31 08:59:05 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _XMLOFF_XMLTEXTLISTAUTOSTYLEPOOL_HXX
#define _XMLOFF_XMLTEXTLISTAUTOSTYLEPOOL_HXX

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

#ifndef _COM_SUN_STAR_UNO_REFERENCE_HXX_
#include <com/sun/star/uno/Reference.hxx>
#endif

namespace com { namespace sun { namespace star { namespace container {
    class XIndexReplace; } } } }
namespace rtl { class OUString; }

class XMLTextListAutoStylePool_Impl;
class XMLTextListAutoStylePoolNames_Impl;
class SvXMLExport;

class XMLTextListAutoStylePool
{
    SvXMLExport& rExport;

    const ::rtl::OUString sPrefix;

    XMLTextListAutoStylePool_Impl *pPool;
    XMLTextListAutoStylePoolNames_Impl *pNames;
    sal_uInt32 nName;

public:

    XMLTextListAutoStylePool( SvXMLExport& rExport );
    ~XMLTextListAutoStylePool();

    void RegisterName( const ::rtl::OUString& rName );
    sal_Bool HasName( const ::rtl::OUString& rName ) const;

    ::rtl::OUString Add(
            const ::com::sun::star::uno::Reference <
                ::com::sun::star::container::XIndexReplace > & rNumRules );

    ::rtl::OUString Find(
            const ::com::sun::star::uno::Reference <
                ::com::sun::star::container::XIndexReplace > & rNumRules ) const;
    ::rtl::OUString Find( const ::rtl::OUString& rInternalName ) const;

    void exportXML() const;
};

#endif  //  _XMLOFF_XMLTEXTLISTAUTOSTYLEPOOL_HXX
<commit_msg>#80914# fixed bullets for impress/draw<commit_after>/*************************************************************************
 *
 *  $RCSfile: XMLTextListAutoStylePool.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: cl $ $Date: 2000-12-01 18:49:59 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _XMLOFF_XMLTEXTLISTAUTOSTYLEPOOL_HXX
#define _XMLOFF_XMLTEXTLISTAUTOSTYLEPOOL_HXX

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

#ifndef _COM_SUN_STAR_UCB_XANYCOMPARE_HPP_
#include <com/sun/star/ucb/XAnyCompare.hpp>
#endif

namespace com { namespace sun { namespace star { namespace container {
    class XIndexReplace; } } } }
namespace rtl { class OUString; }

class XMLTextListAutoStylePool_Impl;
class XMLTextListAutoStylePoolNames_Impl;
class XMLTextListAutoStylePoolEntry_Impl;
class SvXMLExport;

class XMLTextListAutoStylePool
{
    SvXMLExport& rExport;

    const ::rtl::OUString sPrefix;

    XMLTextListAutoStylePool_Impl *pPool;
    XMLTextListAutoStylePoolNames_Impl *pNames;
    sal_uInt32 nName;

    /** this is an optional NumRule compare component for applications where
        the NumRules don't have names */
    ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XAnyCompare > mxNumRuleCompare;

    sal_uInt32 Find( XMLTextListAutoStylePoolEntry_Impl* pEntry ) const;
public:

    XMLTextListAutoStylePool( SvXMLExport& rExport );
    ~XMLTextListAutoStylePool();

    void RegisterName( const ::rtl::OUString& rName );
    sal_Bool HasName( const ::rtl::OUString& rName ) const;

    ::rtl::OUString Add(
            const ::com::sun::star::uno::Reference <
                ::com::sun::star::container::XIndexReplace > & rNumRules );

    ::rtl::OUString Find(
            const ::com::sun::star::uno::Reference <
                ::com::sun::star::container::XIndexReplace > & rNumRules ) const;
    ::rtl::OUString Find( const ::rtl::OUString& rInternalName ) const;

    void exportXML() const;
};

#endif  //  _XMLOFF_XMLTEXTLISTAUTOSTYLEPOOL_HXX
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: Transformer.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: hr $ $Date: 2004-11-09 12:25:50 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _XMLOFF_TRANSFORMER_HXX
#define _XMLOFF_TRANSFORMER_HXX

#ifndef _COM_SUN_STAR_XML_SAX_XEXTENDEDDOCUMENTHANDLER_HPP_
#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEL_HPP_
#include <com/sun/star/lang/XUnoTunnel.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XINITIALIZATION_HPP_
#include <com/sun/star/lang/XInitialization.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif

#ifndef _CPPUHELPER_IMPLBASE4_HXX_
#include <cppuhelper/implbase4.hxx>
#endif

class XMLTransformer : public ::cppu::WeakImplHelper4<
             ::com::sun::star::xml::sax::XExtendedDocumentHandler,
             ::com::sun::star::lang::XServiceInfo,
             ::com::sun::star::lang::XInitialization,
             ::com::sun::star::lang::XUnoTunnel>
{
};

#endif  //  _XMLOFF_TRANSFORMER_HXX
<commit_msg>INTEGRATION: CWS ooo19126 (1.2.220); FILE MERGED 2005/09/05 14:40:30 rt 1.2.220.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: Transformer.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 15:56:36 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _XMLOFF_TRANSFORMER_HXX
#define _XMLOFF_TRANSFORMER_HXX

#ifndef _COM_SUN_STAR_XML_SAX_XEXTENDEDDOCUMENTHANDLER_HPP_
#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEL_HPP_
#include <com/sun/star/lang/XUnoTunnel.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XINITIALIZATION_HPP_
#include <com/sun/star/lang/XInitialization.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif

#ifndef _CPPUHELPER_IMPLBASE4_HXX_
#include <cppuhelper/implbase4.hxx>
#endif

class XMLTransformer : public ::cppu::WeakImplHelper4<
             ::com::sun::star::xml::sax::XExtendedDocumentHandler,
             ::com::sun::star::lang::XServiceInfo,
             ::com::sun::star::lang::XInitialization,
             ::com::sun::star::lang::XUnoTunnel>
{
};

#endif  //  _XMLOFF_TRANSFORMER_HXX
<|endoftext|>