Impresionante cargador INI -- ++ campo con parsing camp codereview Relacionados El problema

Awesome INI Loader


6
vote

problema

Español

Escribí un parser de archivo I ++ I ++ Ini. Lo único que requiere es la STD LIBS (por supuesto, que viene con la mayoría de los compiladores principales de C ++) hasta ahora funciona muy bien, y lo único que necesita trabajo es el analizador de cadenas para manejar caracteres especiales en el valor de la clave. I.e ", n r.

Puede ver el código aquí:

Awesome_ini.H

  #ifndef AWESOME_INI_H     #define AWESOME_INI_H      /*     AUTHOR: Andrew McRobb      DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE     Version 2, December 2004      Copyright (C) 2015 Andrew McRobb <andrewmcrobb@gmail.com>      Everyone is permitted to copy and distribute verbatim or modified     copies of this license document, and changing it is allowed as long     as the name is changed.      DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE     TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION      0. You just DO WHAT THE FUCK YOU WANT TO.      */      #include <stdlib.h>     #include <iostream>     #include <string.h>     #include <ctype.h>     #include <vector>     #include <fstream>      //Options you can set...     #define AWI_SEPERATOR_CHAR '='     #define AWI_COMMENT_CHAR ';'     #define AWI_STRING_CHAR '"'     #define AWI_REMOVE_DATA_ON_ERROR    true      //Not so awesome error codes...     enum AWESOME_ERROR_CODES     {         AWESOME_ERROR_NONE = 0, /*Everything is fine!*/         AWESOME_ERROR_FILE_PATH, /*The INI specified has an invalid path!*/         AWESOME_ERROR_MEMORY, /*Rare error code if something happens to break memory limits.*/         AWESOME_ERROR_PARSING_INVALID_SEPERATOR_POS, /*The seperator is ether in the wrong location of the line or does not exsist!*/         AWESOME_ERROR_PARSING_INVALID_VALUE_TYPE, /*The key value type is not reconized.*/         AWESOME_ERROR_PARSING_LINE_TOO_SHORT, /*The line of the file is too short to read. Usually because of invalid syntax.*/         AWESOME_ERROR_PARSING_INVALID_NAME, /*The key or group name has unsupported characters*/         AWESOME_ERROR_PARSING_INVALID_LINE, /*The line entered usually means another syntax error.*/         AWESOME_ERROR_DUPLICATED_KEY, /*The key entered has already been parsed in the same group.*/         AWESOME_ERROR_DUBLICATED_GROUP_NAME, /*The group name has already been entered.*/         AWESOME_ERROR_GROUP_NOT_FOUND, /*Usually called when the INI file no longer has a exsisting group.*/         AWESOME_ERROR_KEY_NOT_FOUND,    /*The key entered is no longer in the correct group.*/         AWESOME_ERROR_NO_GROUP_DEFINED, /*The group was not entered at the top of the INI file.*/         AWESOME_ERROR_INVALID_DATA_TYPE_RETRIVED /*The data type attempted to be retrived is not the correct type.*/     };      enum AWESOME_INI_KEY_TYPE     {         AWESOME_TYPE_VOID = 0,         AWESOME_TYPE_STRING,         AWESOME_TYPE_INT,         AWESOME_TYPE_FLOAT,         AWESOME_TYPE_BOOL     };       struct awesome_key_element     {         std::string m_key;         std::string m_value;         AWESOME_INI_KEY_TYPE key_type;     };      struct awesome_key_groups     {         std::string m_name;         std::vector<awesome_key_element> m_elements;     };       class awesome_ini     {     public:         awesome_ini(std::string file);         virtual ~awesome_ini(void);           AWESOME_ERROR_CODES        getError(void);         size_t                    getErrorLine(void);          //Simple reads         bool    getKeyType(AWESOME_INI_KEY_TYPE &type, std::string group, std::string key);         bool    getKeyType(AWESOME_INI_KEY_TYPE &type, std::size_t group, std::string key);          bool                   getKeyInt(int &p, std::string group, std::string key);         bool                   getKeyInt(int &p, std::size_t group, std::string key);          bool                   getKeyBool(bool &p, std::string group, std::string key);         bool                   getKeyBool(bool &p, std::size_t group, std::string key);          bool                   getKeyString(std::string &p, std::string group, std::string key);         bool                   getKeyString(std::string &p, std::size_t group, std::string key);          bool                   getKeyFloat(float &p, std::string group, std::string key);         bool                   getKeyFloat(float &p, std::size_t group, std::string key);          std::size_t            findGroup(std::string name);          void                   clearAll(void);     protected:         //Vector          bool                    findDuplicateGroupName(std::string name);         bool                    findDuplicateKeyName(size_t group, std::string name);          AWESOME_INI_KEY_TYPE    figureType(std::string val);          AWESOME_INI_KEY_TYPE    getDataType(const char* line, size_t length);          std::string                trim(std::string line); /*Trims useless white spacese...*/         bool                    isNameValid(std::string name);         std::string                aw_strToLower(std::string line);          inline bool                throwError(AWESOME_ERROR_CODES error);     private:           AWESOME_ERROR_CODES        m_error;         size_t                    m_error_line;          std::vector<awesome_key_groups> m_list;     };      #endif   

Awesome_ini.CPP

  #include "awesome_ini.h"  /* AUTHOR: Andrew McRobb  DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE Version 2, December 2004  Copyright (C) 2015 Andrew McRobb <andrewmcrobb@gmail.com>  Everyone is permitted to copy and distribute verbatim or modified copies of this license document, and changing it is allowed as long as the name is changed.  DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION  0. You just DO WHAT THE FUCK YOU WANT TO.  */  awesome_ini::awesome_ini(std::string filename) {     m_error = AWESOME_ERROR_NONE;     m_error_line = 0;     std::ifstream myfile (filename);     if (!myfile.is_open())     {         m_error = AWESOME_ERROR_FILE_PATH;         return;     }      std::string line;     size_t lineNumber = 1;     size_t curGroup = 0;     while ( getline (myfile,line) )     {         line = trim(line);          if(line.size() < 1){             continue;         }          /* IS IT A NEW GROUP? */         if(line[0] == '['){              std::size_t endi = line.find_last_of(']');              if(endi == std::string::npos){                 m_error = AWESOME_ERROR_PARSING_INVALID_LINE;                 m_error_line = lineNumber;                  if(AWI_REMOVE_DATA_ON_ERROR){                     clearAll();                     return;                 }                  lineNumber++;                 continue;             }              std::string cat = aw_strToLower(line.substr(1, (endi-1)));              if(findDuplicateGroupName(cat)){                 m_error = AWESOME_ERROR_DUBLICATED_GROUP_NAME;                 m_error_line = lineNumber;                  if(AWI_REMOVE_DATA_ON_ERROR){                     clearAll();                     return;                 }                  lineNumber++;                 continue;             }              awesome_key_groups newGroup;             newGroup.m_name = cat;              m_list.push_back(newGroup);             curGroup++;             lineNumber++;             continue;         }          std::size_t deli = line.find(AWI_SEPERATOR_CHAR);          if(deli == std::string::npos){              m_error_line = lineNumber;             m_error = AWESOME_ERROR_PARSING_INVALID_SEPERATOR_POS;              if(AWI_REMOVE_DATA_ON_ERROR){                 clearAll();                 return;             }              lineNumber++;             continue;          }          if(curGroup == 0){             m_error_line = lineNumber;             m_error = AWESOME_ERROR_NO_GROUP_DEFINED;             break;         }           //Get the key and value...         std::string key;         std::string val;          key = aw_strToLower(line.substr(0,deli));         val = line.substr(deli+1);           /* CHECK THE KEY IS VALID */         if(!isNameValid(key)){             m_error_line = lineNumber;             m_error = AWESOME_ERROR_PARSING_INVALID_NAME;              if(AWI_REMOVE_DATA_ON_ERROR){                 clearAll();                 return;             }              lineNumber++;             continue;         }          /* ENSURE THE NAME IS ALREADY TAKEN! */         if(findDuplicateKeyName((curGroup-1), key))         {             m_error_line = lineNumber;             m_error = AWESOME_ERROR_DUPLICATED_KEY;              if(AWI_REMOVE_DATA_ON_ERROR){                 clearAll();                 return;             }              lineNumber++;             continue;         }           awesome_key_element  newKey;         newKey.m_key = aw_strToLower(key);         newKey.m_value = val;         newKey.key_type = figureType(val);          m_list.at((curGroup-1)).m_elements.push_back(newKey);          lineNumber++;     }      myfile.close(); }  AWESOME_INI_KEY_TYPE awesome_ini::figureType(std::string val){      //Is number?     size_t string_length = val.length();      val = aw_strToLower(val);      /* IS IT A BOOL? */     if(string_length <= 5)     {         if(val.compare("true") == 0 || val.compare("false") == 0)         {             return AWESOME_TYPE_BOOL;         }     }      //Is it a stirng?     for(size_t i = 0; i<string_length; i++)     {         char c = val.at(i);         if(isalpha(c) && (c < 48 || c > 57))         {             return AWESOME_TYPE_STRING;         }     }      bool isInt = true;     for(size_t i = 0; i<string_length; i++)     {         char c = val.at(i);          if(c == ''){             break;         }          if(c < 48|| c > 57)         {             isInt = false;             break;         }     }      if(isInt){         return AWESOME_TYPE_INT;     }      bool isFloat = true;     for(size_t i = 0; i<string_length; i++)     {          char c = val.at(i);          if(c == ''){             break;         }          if((c < 48|| c > 57) && c != 46)         {             isFloat = false;             break;         }     }      if(isFloat){         return AWESOME_TYPE_FLOAT;     }      return AWESOME_TYPE_VOID; }   bool awesome_ini::throwError(AWESOME_ERROR_CODES error) {     m_error = error;     bool quit = false;     if (AWI_REMOVE_DATA_ON_ERROR)     {         clearAll();         quit = true;     }      return quit; }   //Does the key include characters not allowed? bool awesome_ini::isNameValid(std::string line) {     size_t length = line.size();     for (size_t i = 0; i < length; i++)     {         unsigned char c = line[i];         if (!isalpha(c) && c != '_')         {             return false;         }     }      return true; }   awesome_ini::~awesome_ini() {     clearAll(); }  std::string awesome_ini::trim(std::string line) {     size_t length = line.size();      if(length == 0)     {         return "";     }      //Look for comments and strip them!      std::size_t comindex = line.find(AWI_COMMENT_CHAR);      if(comindex != std::string::npos){         line = line.substr(0, comindex);          if(line.size() == 0){             return "";         }     }      bool ignoreSpaces = false;     std::string destBuffer = "";      for (size_t i = 0; i < length; i++)     {         char c = line[i];          if(c == AWI_STRING_CHAR && !ignoreSpaces){             ignoreSpaces = true;             continue;         }          if(c == AWI_STRING_CHAR && ignoreSpaces){             if(i > 1){                 if(line[i-1] == '\'){                     destBuffer += c;                     continue;                 }             }             ignoreSpaces = false;             continue;         }          if ((c == ' ' || c == ' ' || c == ' ' || c == ' ') && !ignoreSpaces)         {             continue;         }            destBuffer += c;     }      return destBuffer; }  std::string awesome_ini::aw_strToLower(std::string line) {      size_t length = line.size();      if(length == 0)     {         return "";     }      std::string dstBuffer;      for (size_t i = 0; i < length; i++)     {         if(line[i]<='Z' && line[i]>='A')         {             char c = line[i];             dstBuffer += c-('Z'-'z');             continue;         }          dstBuffer += line[i];     }      return dstBuffer; }  AWESOME_ERROR_CODES awesome_ini::getError(void) {     return m_error; }  size_t awesome_ini::getErrorLine(void) {     return m_error_line; }  std::size_t   awesome_ini::findGroup(std::string name) {     size_t group_size = m_list.size();      if(group_size == 0){         return std::string::npos;     }      for(size_t i = 0; i<group_size; i++)     {         if(m_list.at(i).m_name.compare(name) == 0)         {             return i;         }     }      return std::string::npos; }  bool awesome_ini::findDuplicateGroupName(std::string name) {     if(findGroup(name) != std::string::npos)     {         return true;     }      return false; }  bool awesome_ini::findDuplicateKeyName(size_t group, std::string name) {     size_t group_size = m_list.size();      if(group >= group_size){         return false;     }      size_t group_key_size = m_list.at(group).m_elements.size();      if(group_key_size == 0) {         return false;     }      for(size_t i = 0; i<group_key_size; i++)     {         if(m_list.at(group).m_elements.at(i).m_key.compare(name) == 0){             return true;         }     }      return false; }   //delete all data! void awesome_ini::clearAll(void) {     size_t group_size = m_list.size();      for(size_t i = 0; i<group_size; i++)     {         m_list.at(i).m_elements.clear();     }      m_list.clear(); }  //Gets key value. Returns data type void if nothing found and error. bool awesome_ini::getKeyType(AWESOME_INI_KEY_TYPE &type, std::string group, std::string key) {     std::size_t group_index = findGroup(group);      if(group_index == std::string::npos){         m_error = AWESOME_ERROR_GROUP_NOT_FOUND;         return false;     }      size_t key_size = m_list.at(group_index).m_elements.size();      if(key_size == 0){         return false;     }      for(size_t i = 0; i<key_size; i++){         if(m_list.at(group_index).m_elements.at(i).m_key.compare(key) == 0){             type = m_list.at(group_index).m_elements.at(i).key_type;             return true;         }     }      return false; }  //Gets key value. Returns data type void if nothing found and error. bool awesome_ini::getKeyType(AWESOME_INI_KEY_TYPE &type, size_t group, std::string key) {     std::size_t group_size = m_list.size();     if(group >= group_size){         m_error = AWESOME_ERROR_GROUP_NOT_FOUND;         return false;     }      size_t key_size = m_list.at(group).m_elements.size();      if(key_size == 0){         return false;     }      for(size_t i = 0; i<key_size; i++){         if(m_list.at(group).m_elements.at(i).m_key.compare(key) == 0){             type = m_list.at(group).m_elements.at(i).key_type;             return true;         }     }      return false; }     bool awesome_ini::getKeyInt(int &p, std::string group, std::string key) {     std::size_t group_index = findGroup(group);      if(group_index == std::string::npos){         m_error = AWESOME_ERROR_GROUP_NOT_FOUND;         return false;     }       size_t key_size = m_list.at(group_index).m_elements.size();      if(key_size == 0){         return false;     }      for(size_t i = 0; i<key_size; i++){         if(m_list.at(group_index).m_elements.at(i).m_key.compare(key) == 0){              if(m_list.at(group_index).m_elements.at(i).key_type != AWESOME_TYPE_INT) {                 m_error = AWESOME_ERROR_INVALID_DATA_TYPE_RETRIVED;                 return false;             }              p = atoi(m_list.at(group_index).m_elements.at(i).m_value.c_str());             return true;         }     }      m_error = AWESOME_ERROR_KEY_NOT_FOUND;     return false; }  bool awesome_ini::getKeyInt(int &p, size_t group, std::string key) {     std::size_t group_size = m_list.size();     if(group >= group_size){         m_error = AWESOME_ERROR_GROUP_NOT_FOUND;         return false;     }      size_t key_size = m_list.at(group).m_elements.size();      if(key_size == 0){         return false;     }      for(size_t i = 0; i<key_size; i++){         if(m_list.at(group).m_elements.at(i).m_key.compare(key) == 0){              if(m_list.at(group).m_elements.at(i).key_type != AWESOME_TYPE_INT) {                 m_error = AWESOME_ERROR_INVALID_DATA_TYPE_RETRIVED;                 return false;             }              p = atoi(m_list.at(group).m_elements.at(i).m_value.c_str());             return true;         }     }      m_error = AWESOME_ERROR_KEY_NOT_FOUND;     return false; }   bool awesome_ini::getKeyBool(bool &p, std::string group, std::string key) {     std::size_t group_index = findGroup(group);      if(group_index == std::string::npos){         m_error = AWESOME_ERROR_GROUP_NOT_FOUND;         return false;     }      size_t key_size = m_list.at(group_index).m_elements.size();      if(key_size == 0){         return false;     }      std::string buffer;      for(size_t i = 0; i<key_size; i++){         if(m_list.at(group_index).m_elements.at(i).m_key.compare(key) == 0){              if(m_list.at(group_index).m_elements.at(i).key_type != AWESOME_TYPE_BOOL) {                 m_error = AWESOME_ERROR_INVALID_DATA_TYPE_RETRIVED;                 return false;             }             buffer = m_list.at(group_index).m_elements.at(i).m_value;         }     }      if(buffer.size() == 0){         m_error = AWESOME_ERROR_KEY_NOT_FOUND;         return false;     }      //Convert string to lowercase...     buffer = aw_strToLower(buffer);      p = false;     if (buffer.compare("true") == 0)     {         p = true;     }      return true; }  bool awesome_ini::getKeyBool(bool &p, size_t group, std::string key) {      std::size_t group_size = m_list.size();     if(group >= group_size){         m_error = AWESOME_ERROR_GROUP_NOT_FOUND;         return false;     }      size_t key_size = m_list.at(group).m_elements.size();      if(key_size == 0){         return false;     }      std::string buffer;      for(size_t i = 0; i<key_size; i++){         if(m_list.at(group).m_elements.at(i).m_key.compare(key) == 0){             if(m_list.at(group).m_elements.at(i).key_type != AWESOME_TYPE_BOOL) {                 m_error = AWESOME_ERROR_INVALID_DATA_TYPE_RETRIVED;                 return false;             }             buffer = m_list.at(group).m_elements.at(i).m_value;         }     }      if(buffer.size() == 0){         m_error = AWESOME_ERROR_KEY_NOT_FOUND;         return false;     }      //Convert string to lowercase...     buffer = aw_strToLower(buffer);      p = false;     if (buffer.compare("true") == 0)     {         p = true;     }      return true; }    bool awesome_ini::getKeyFloat(float &p, std::string group, std::string key) {     std::size_t group_index = findGroup(group);      if(group_index == std::string::npos){         m_error = AWESOME_ERROR_GROUP_NOT_FOUND;         return false;     }      size_t key_size = m_list.at(group_index).m_elements.size();      if(key_size == 0){         return false;     }      for(size_t i = 0; i<key_size; i++){         if(m_list.at(group_index).m_elements.at(i).m_key.compare(key) == 0){             if(m_list.at(group_index).m_elements.at(i).key_type != AWESOME_TYPE_FLOAT) {                 m_error = AWESOME_ERROR_INVALID_DATA_TYPE_RETRIVED;                 return false;             }             p = atof(m_list.at(group_index).m_elements.at(i).m_value.c_str());             return true;         }     }      m_error = AWESOME_ERROR_KEY_NOT_FOUND;     return false; }  bool awesome_ini::getKeyFloat(float &p, size_t group, std::string key) {     std::size_t group_size = m_list.size();     if(group >= group_size){         m_error = AWESOME_ERROR_GROUP_NOT_FOUND;         return false;     }      size_t key_size = m_list.at(group).m_elements.size();      if(key_size == 0){         return false;     }      for(size_t i = 0; i<key_size; i++){         if(m_list.at(group).m_elements.at(i).m_key.compare(key) == 0){             if(m_list.at(group).m_elements.at(i).key_type != AWESOME_TYPE_FLOAT) {                 m_error = AWESOME_ERROR_INVALID_DATA_TYPE_RETRIVED;                 return false;             }             p = atof(m_list.at(group).m_elements.at(i).m_value.c_str());             return true;         }     }      m_error = AWESOME_ERROR_KEY_NOT_FOUND;     return false; }  bool awesome_ini::getKeyString(std::string &p, std::string group, std::string key) {     std::size_t group_index = findGroup(group);      if(group_index == std::string::npos){         m_error = AWESOME_ERROR_GROUP_NOT_FOUND;         return false;     }      size_t key_size = m_list.at(group_index).m_elements.size();      if(key_size == 0){         return false;     }      for(size_t i = 0; i<key_size; i++){         if(m_list.at(group_index).m_elements.at(i).m_key.compare(key) == 0){             if(m_list.at(group_index).m_elements.at(i).key_type != AWESOME_TYPE_STRING) {                 m_error = AWESOME_ERROR_INVALID_DATA_TYPE_RETRIVED;                 return false;             }             p = m_list.at(group_index).m_elements.at(i).m_value.c_str();             return true;         }     }      m_error = AWESOME_ERROR_KEY_NOT_FOUND;     return false; }  bool awesome_ini::getKeyString(std::string &p, size_t group, std::string key) {     std::size_t group_size = m_list.size();     if(group >= group_size){         m_error = AWESOME_ERROR_GROUP_NOT_FOUND;         return false;     }      size_t key_size = m_list.at(group).m_elements.size();      if(key_size == 0){         return false;     }      for(size_t i = 0; i<key_size; i++){         if(m_list.at(group).m_elements.at(i).m_key.compare(key) == 0){             if(m_list.at(group).m_elements.at(i).key_type != AWESOME_TYPE_STRING) {                 m_error = AWESOME_ERROR_INVALID_DATA_TYPE_RETRIVED;                 return false;             }             p = m_list.at(group).m_elements.at(i).m_value.c_str();             return true;         }     }      m_error = AWESOME_ERROR_KEY_NOT_FOUND;      return false; }   

Ejemplo:

  #include "awesome_ini_loader/awesome_ini.h"  int main(int argc, const char * argv[]) {     // insert code here...     awesome_ini parser("config.ini");      std::cout << "Error Code: " << parser.getError() << " Error Line:" << parser.getErrorLine() << " ";      if(parser.getError() > 0)     {         std::cout << "Quit on error!";         return EXIT_FAILURE;     }      //Get group ID.     size_t gid = parser.findGroup("config");      int val = 0;     if(parser.getKeyInt(val, gid, "test"))     {         std::cout << "Int Val: " << val << " ";     }      std::string sVal = "";     if(parser.getKeyString(sVal, gid, "string"))     {         std::cout << "String Val: " << sVal.c_str() << " ";     }      bool bVal = false;     if(parser.getKeyBool(bVal, gid, "boolean"))     {         if(bVal){             std::cout << "Bool Val: TRUE ";         }else{             std::cout << "Bool Val: FALSE ";         }     }      float fVal = 0;     if(parser.getKeyFloat(fVal, gid, "floatnumber"))     {         std::cout << "Float Val: " << fVal << " ";     }      parser.clearAll();      std::cout << "Done. ";     return EXIT_SUCCESS; }   
Original en ingles

I wrote a simple to use C++ INI file parser. The only thing it requires is the STD libs (of course that come with most major C++ compilers) So far it works very well, and the only thing that needs work is the string parser to handle special characters in the key's value. I.E \", \ \n \r.

You can view the code here:

awesome_ini.h

#ifndef AWESOME_INI_H     #define AWESOME_INI_H      /*     AUTHOR: Andrew McRobb      DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE     Version 2, December 2004      Copyright (C) 2015 Andrew McRobb <andrewmcrobb@gmail.com>      Everyone is permitted to copy and distribute verbatim or modified     copies of this license document, and changing it is allowed as long     as the name is changed.      DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE     TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION      0. You just DO WHAT THE FUCK YOU WANT TO.      */      #include <stdlib.h>     #include <iostream>     #include <string.h>     #include <ctype.h>     #include <vector>     #include <fstream>      //Options you can set...     #define AWI_SEPERATOR_CHAR '='     #define AWI_COMMENT_CHAR ';'     #define AWI_STRING_CHAR '"'     #define AWI_REMOVE_DATA_ON_ERROR    true      //Not so awesome error codes...     enum AWESOME_ERROR_CODES     {         AWESOME_ERROR_NONE = 0, /*Everything is fine!*/         AWESOME_ERROR_FILE_PATH, /*The INI specified has an invalid path!*/         AWESOME_ERROR_MEMORY, /*Rare error code if something happens to break memory limits.*/         AWESOME_ERROR_PARSING_INVALID_SEPERATOR_POS, /*The seperator is ether in the wrong location of the line or does not exsist!*/         AWESOME_ERROR_PARSING_INVALID_VALUE_TYPE, /*The key value type is not reconized.*/         AWESOME_ERROR_PARSING_LINE_TOO_SHORT, /*The line of the file is too short to read. Usually because of invalid syntax.*/         AWESOME_ERROR_PARSING_INVALID_NAME, /*The key or group name has unsupported characters*/         AWESOME_ERROR_PARSING_INVALID_LINE, /*The line entered usually means another syntax error.*/         AWESOME_ERROR_DUPLICATED_KEY, /*The key entered has already been parsed in the same group.*/         AWESOME_ERROR_DUBLICATED_GROUP_NAME, /*The group name has already been entered.*/         AWESOME_ERROR_GROUP_NOT_FOUND, /*Usually called when the INI file no longer has a exsisting group.*/         AWESOME_ERROR_KEY_NOT_FOUND,    /*The key entered is no longer in the correct group.*/         AWESOME_ERROR_NO_GROUP_DEFINED, /*The group was not entered at the top of the INI file.*/         AWESOME_ERROR_INVALID_DATA_TYPE_RETRIVED /*The data type attempted to be retrived is not the correct type.*/     };      enum AWESOME_INI_KEY_TYPE     {         AWESOME_TYPE_VOID = 0,         AWESOME_TYPE_STRING,         AWESOME_TYPE_INT,         AWESOME_TYPE_FLOAT,         AWESOME_TYPE_BOOL     };       struct awesome_key_element     {         std::string m_key;         std::string m_value;         AWESOME_INI_KEY_TYPE key_type;     };      struct awesome_key_groups     {         std::string m_name;         std::vector<awesome_key_element> m_elements;     };       class awesome_ini     {     public:         awesome_ini(std::string file);         virtual ~awesome_ini(void);           AWESOME_ERROR_CODES        getError(void);         size_t                    getErrorLine(void);          //Simple reads         bool    getKeyType(AWESOME_INI_KEY_TYPE &type, std::string group, std::string key);         bool    getKeyType(AWESOME_INI_KEY_TYPE &type, std::size_t group, std::string key);          bool                   getKeyInt(int &p, std::string group, std::string key);         bool                   getKeyInt(int &p, std::size_t group, std::string key);          bool                   getKeyBool(bool &p, std::string group, std::string key);         bool                   getKeyBool(bool &p, std::size_t group, std::string key);          bool                   getKeyString(std::string &p, std::string group, std::string key);         bool                   getKeyString(std::string &p, std::size_t group, std::string key);          bool                   getKeyFloat(float &p, std::string group, std::string key);         bool                   getKeyFloat(float &p, std::size_t group, std::string key);          std::size_t            findGroup(std::string name);          void                   clearAll(void);     protected:         //Vector          bool                    findDuplicateGroupName(std::string name);         bool                    findDuplicateKeyName(size_t group, std::string name);          AWESOME_INI_KEY_TYPE    figureType(std::string val);          AWESOME_INI_KEY_TYPE    getDataType(const char* line, size_t length);          std::string                trim(std::string line); /*Trims useless white spacese...*/         bool                    isNameValid(std::string name);         std::string                aw_strToLower(std::string line);          inline bool                throwError(AWESOME_ERROR_CODES error);     private:           AWESOME_ERROR_CODES        m_error;         size_t                    m_error_line;          std::vector<awesome_key_groups> m_list;     };      #endif 

awesome_ini.cpp

#include "awesome_ini.h"  /* AUTHOR: Andrew McRobb  DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE Version 2, December 2004  Copyright (C) 2015 Andrew McRobb <andrewmcrobb@gmail.com>  Everyone is permitted to copy and distribute verbatim or modified copies of this license document, and changing it is allowed as long as the name is changed.  DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION  0. You just DO WHAT THE FUCK YOU WANT TO.  */  awesome_ini::awesome_ini(std::string filename) {     m_error = AWESOME_ERROR_NONE;     m_error_line = 0;     std::ifstream myfile (filename);     if (!myfile.is_open())     {         m_error = AWESOME_ERROR_FILE_PATH;         return;     }      std::string line;     size_t lineNumber = 1;     size_t curGroup = 0;     while ( getline (myfile,line) )     {         line = trim(line);          if(line.size() < 1){             continue;         }          /* IS IT A NEW GROUP? */         if(line[0] == '['){              std::size_t endi = line.find_last_of(']');              if(endi == std::string::npos){                 m_error = AWESOME_ERROR_PARSING_INVALID_LINE;                 m_error_line = lineNumber;                  if(AWI_REMOVE_DATA_ON_ERROR){                     clearAll();                     return;                 }                  lineNumber++;                 continue;             }              std::string cat = aw_strToLower(line.substr(1, (endi-1)));              if(findDuplicateGroupName(cat)){                 m_error = AWESOME_ERROR_DUBLICATED_GROUP_NAME;                 m_error_line = lineNumber;                  if(AWI_REMOVE_DATA_ON_ERROR){                     clearAll();                     return;                 }                  lineNumber++;                 continue;             }              awesome_key_groups newGroup;             newGroup.m_name = cat;              m_list.push_back(newGroup);             curGroup++;             lineNumber++;             continue;         }          std::size_t deli = line.find(AWI_SEPERATOR_CHAR);          if(deli == std::string::npos){              m_error_line = lineNumber;             m_error = AWESOME_ERROR_PARSING_INVALID_SEPERATOR_POS;              if(AWI_REMOVE_DATA_ON_ERROR){                 clearAll();                 return;             }              lineNumber++;             continue;          }          if(curGroup == 0){             m_error_line = lineNumber;             m_error = AWESOME_ERROR_NO_GROUP_DEFINED;             break;         }           //Get the key and value...         std::string key;         std::string val;          key = aw_strToLower(line.substr(0,deli));         val = line.substr(deli+1);           /* CHECK THE KEY IS VALID */         if(!isNameValid(key)){             m_error_line = lineNumber;             m_error = AWESOME_ERROR_PARSING_INVALID_NAME;              if(AWI_REMOVE_DATA_ON_ERROR){                 clearAll();                 return;             }              lineNumber++;             continue;         }          /* ENSURE THE NAME IS ALREADY TAKEN! */         if(findDuplicateKeyName((curGroup-1), key))         {             m_error_line = lineNumber;             m_error = AWESOME_ERROR_DUPLICATED_KEY;              if(AWI_REMOVE_DATA_ON_ERROR){                 clearAll();                 return;             }              lineNumber++;             continue;         }           awesome_key_element  newKey;         newKey.m_key = aw_strToLower(key);         newKey.m_value = val;         newKey.key_type = figureType(val);          m_list.at((curGroup-1)).m_elements.push_back(newKey);          lineNumber++;     }      myfile.close(); }  AWESOME_INI_KEY_TYPE awesome_ini::figureType(std::string val){      //Is number?     size_t string_length = val.length();      val = aw_strToLower(val);      /* IS IT A BOOL? */     if(string_length <= 5)     {         if(val.compare("true") == 0 || val.compare("false") == 0)         {             return AWESOME_TYPE_BOOL;         }     }      //Is it a stirng?     for(size_t i = 0; i<string_length; i++)     {         char c = val.at(i);         if(isalpha(c) && (c < 48 || c > 57))         {             return AWESOME_TYPE_STRING;         }     }      bool isInt = true;     for(size_t i = 0; i<string_length; i++)     {         char c = val.at(i);          if(c == '\0'){             break;         }          if(c < 48|| c > 57)         {             isInt = false;             break;         }     }      if(isInt){         return AWESOME_TYPE_INT;     }      bool isFloat = true;     for(size_t i = 0; i<string_length; i++)     {          char c = val.at(i);          if(c == '\0'){             break;         }          if((c < 48|| c > 57) && c != 46)         {             isFloat = false;             break;         }     }      if(isFloat){         return AWESOME_TYPE_FLOAT;     }      return AWESOME_TYPE_VOID; }   bool awesome_ini::throwError(AWESOME_ERROR_CODES error) {     m_error = error;     bool quit = false;     if (AWI_REMOVE_DATA_ON_ERROR)     {         clearAll();         quit = true;     }      return quit; }   //Does the key include characters not allowed? bool awesome_ini::isNameValid(std::string line) {     size_t length = line.size();     for (size_t i = 0; i < length; i++)     {         unsigned char c = line[i];         if (!isalpha(c) && c != '_')         {             return false;         }     }      return true; }   awesome_ini::~awesome_ini() {     clearAll(); }  std::string awesome_ini::trim(std::string line) {     size_t length = line.size();      if(length == 0)     {         return "";     }      //Look for comments and strip them!      std::size_t comindex = line.find(AWI_COMMENT_CHAR);      if(comindex != std::string::npos){         line = line.substr(0, comindex);          if(line.size() == 0){             return "";         }     }      bool ignoreSpaces = false;     std::string destBuffer = "";      for (size_t i = 0; i < length; i++)     {         char c = line[i];          if(c == AWI_STRING_CHAR && !ignoreSpaces){             ignoreSpaces = true;             continue;         }          if(c == AWI_STRING_CHAR && ignoreSpaces){             if(i > 1){                 if(line[i-1] == '\\'){                     destBuffer += c;                     continue;                 }             }             ignoreSpaces = false;             continue;         }          if ((c == '\n' || c == ' ' || c == '\r' || c == '\t') && !ignoreSpaces)         {             continue;         }            destBuffer += c;     }      return destBuffer; }  std::string awesome_ini::aw_strToLower(std::string line) {      size_t length = line.size();      if(length == 0)     {         return "";     }      std::string dstBuffer;      for (size_t i = 0; i < length; i++)     {         if(line[i]<='Z' && line[i]>='A')         {             char c = line[i];             dstBuffer += c-('Z'-'z');             continue;         }          dstBuffer += line[i];     }      return dstBuffer; }  AWESOME_ERROR_CODES awesome_ini::getError(void) {     return m_error; }  size_t awesome_ini::getErrorLine(void) {     return m_error_line; }  std::size_t   awesome_ini::findGroup(std::string name) {     size_t group_size = m_list.size();      if(group_size == 0){         return std::string::npos;     }      for(size_t i = 0; i<group_size; i++)     {         if(m_list.at(i).m_name.compare(name) == 0)         {             return i;         }     }      return std::string::npos; }  bool awesome_ini::findDuplicateGroupName(std::string name) {     if(findGroup(name) != std::string::npos)     {         return true;     }      return false; }  bool awesome_ini::findDuplicateKeyName(size_t group, std::string name) {     size_t group_size = m_list.size();      if(group >= group_size){         return false;     }      size_t group_key_size = m_list.at(group).m_elements.size();      if(group_key_size == 0) {         return false;     }      for(size_t i = 0; i<group_key_size; i++)     {         if(m_list.at(group).m_elements.at(i).m_key.compare(name) == 0){             return true;         }     }      return false; }   //delete all data! void awesome_ini::clearAll(void) {     size_t group_size = m_list.size();      for(size_t i = 0; i<group_size; i++)     {         m_list.at(i).m_elements.clear();     }      m_list.clear(); }  //Gets key value. Returns data type void if nothing found and error. bool awesome_ini::getKeyType(AWESOME_INI_KEY_TYPE &type, std::string group, std::string key) {     std::size_t group_index = findGroup(group);      if(group_index == std::string::npos){         m_error = AWESOME_ERROR_GROUP_NOT_FOUND;         return false;     }      size_t key_size = m_list.at(group_index).m_elements.size();      if(key_size == 0){         return false;     }      for(size_t i = 0; i<key_size; i++){         if(m_list.at(group_index).m_elements.at(i).m_key.compare(key) == 0){             type = m_list.at(group_index).m_elements.at(i).key_type;             return true;         }     }      return false; }  //Gets key value. Returns data type void if nothing found and error. bool awesome_ini::getKeyType(AWESOME_INI_KEY_TYPE &type, size_t group, std::string key) {     std::size_t group_size = m_list.size();     if(group >= group_size){         m_error = AWESOME_ERROR_GROUP_NOT_FOUND;         return false;     }      size_t key_size = m_list.at(group).m_elements.size();      if(key_size == 0){         return false;     }      for(size_t i = 0; i<key_size; i++){         if(m_list.at(group).m_elements.at(i).m_key.compare(key) == 0){             type = m_list.at(group).m_elements.at(i).key_type;             return true;         }     }      return false; }     bool awesome_ini::getKeyInt(int &p, std::string group, std::string key) {     std::size_t group_index = findGroup(group);      if(group_index == std::string::npos){         m_error = AWESOME_ERROR_GROUP_NOT_FOUND;         return false;     }       size_t key_size = m_list.at(group_index).m_elements.size();      if(key_size == 0){         return false;     }      for(size_t i = 0; i<key_size; i++){         if(m_list.at(group_index).m_elements.at(i).m_key.compare(key) == 0){              if(m_list.at(group_index).m_elements.at(i).key_type != AWESOME_TYPE_INT) {                 m_error = AWESOME_ERROR_INVALID_DATA_TYPE_RETRIVED;                 return false;             }              p = atoi(m_list.at(group_index).m_elements.at(i).m_value.c_str());             return true;         }     }      m_error = AWESOME_ERROR_KEY_NOT_FOUND;     return false; }  bool awesome_ini::getKeyInt(int &p, size_t group, std::string key) {     std::size_t group_size = m_list.size();     if(group >= group_size){         m_error = AWESOME_ERROR_GROUP_NOT_FOUND;         return false;     }      size_t key_size = m_list.at(group).m_elements.size();      if(key_size == 0){         return false;     }      for(size_t i = 0; i<key_size; i++){         if(m_list.at(group).m_elements.at(i).m_key.compare(key) == 0){              if(m_list.at(group).m_elements.at(i).key_type != AWESOME_TYPE_INT) {                 m_error = AWESOME_ERROR_INVALID_DATA_TYPE_RETRIVED;                 return false;             }              p = atoi(m_list.at(group).m_elements.at(i).m_value.c_str());             return true;         }     }      m_error = AWESOME_ERROR_KEY_NOT_FOUND;     return false; }   bool awesome_ini::getKeyBool(bool &p, std::string group, std::string key) {     std::size_t group_index = findGroup(group);      if(group_index == std::string::npos){         m_error = AWESOME_ERROR_GROUP_NOT_FOUND;         return false;     }      size_t key_size = m_list.at(group_index).m_elements.size();      if(key_size == 0){         return false;     }      std::string buffer;      for(size_t i = 0; i<key_size; i++){         if(m_list.at(group_index).m_elements.at(i).m_key.compare(key) == 0){              if(m_list.at(group_index).m_elements.at(i).key_type != AWESOME_TYPE_BOOL) {                 m_error = AWESOME_ERROR_INVALID_DATA_TYPE_RETRIVED;                 return false;             }             buffer = m_list.at(group_index).m_elements.at(i).m_value;         }     }      if(buffer.size() == 0){         m_error = AWESOME_ERROR_KEY_NOT_FOUND;         return false;     }      //Convert string to lowercase...     buffer = aw_strToLower(buffer);      p = false;     if (buffer.compare("true") == 0)     {         p = true;     }      return true; }  bool awesome_ini::getKeyBool(bool &p, size_t group, std::string key) {      std::size_t group_size = m_list.size();     if(group >= group_size){         m_error = AWESOME_ERROR_GROUP_NOT_FOUND;         return false;     }      size_t key_size = m_list.at(group).m_elements.size();      if(key_size == 0){         return false;     }      std::string buffer;      for(size_t i = 0; i<key_size; i++){         if(m_list.at(group).m_elements.at(i).m_key.compare(key) == 0){             if(m_list.at(group).m_elements.at(i).key_type != AWESOME_TYPE_BOOL) {                 m_error = AWESOME_ERROR_INVALID_DATA_TYPE_RETRIVED;                 return false;             }             buffer = m_list.at(group).m_elements.at(i).m_value;         }     }      if(buffer.size() == 0){         m_error = AWESOME_ERROR_KEY_NOT_FOUND;         return false;     }      //Convert string to lowercase...     buffer = aw_strToLower(buffer);      p = false;     if (buffer.compare("true") == 0)     {         p = true;     }      return true; }    bool awesome_ini::getKeyFloat(float &p, std::string group, std::string key) {     std::size_t group_index = findGroup(group);      if(group_index == std::string::npos){         m_error = AWESOME_ERROR_GROUP_NOT_FOUND;         return false;     }      size_t key_size = m_list.at(group_index).m_elements.size();      if(key_size == 0){         return false;     }      for(size_t i = 0; i<key_size; i++){         if(m_list.at(group_index).m_elements.at(i).m_key.compare(key) == 0){             if(m_list.at(group_index).m_elements.at(i).key_type != AWESOME_TYPE_FLOAT) {                 m_error = AWESOME_ERROR_INVALID_DATA_TYPE_RETRIVED;                 return false;             }             p = atof(m_list.at(group_index).m_elements.at(i).m_value.c_str());             return true;         }     }      m_error = AWESOME_ERROR_KEY_NOT_FOUND;     return false; }  bool awesome_ini::getKeyFloat(float &p, size_t group, std::string key) {     std::size_t group_size = m_list.size();     if(group >= group_size){         m_error = AWESOME_ERROR_GROUP_NOT_FOUND;         return false;     }      size_t key_size = m_list.at(group).m_elements.size();      if(key_size == 0){         return false;     }      for(size_t i = 0; i<key_size; i++){         if(m_list.at(group).m_elements.at(i).m_key.compare(key) == 0){             if(m_list.at(group).m_elements.at(i).key_type != AWESOME_TYPE_FLOAT) {                 m_error = AWESOME_ERROR_INVALID_DATA_TYPE_RETRIVED;                 return false;             }             p = atof(m_list.at(group).m_elements.at(i).m_value.c_str());             return true;         }     }      m_error = AWESOME_ERROR_KEY_NOT_FOUND;     return false; }  bool awesome_ini::getKeyString(std::string &p, std::string group, std::string key) {     std::size_t group_index = findGroup(group);      if(group_index == std::string::npos){         m_error = AWESOME_ERROR_GROUP_NOT_FOUND;         return false;     }      size_t key_size = m_list.at(group_index).m_elements.size();      if(key_size == 0){         return false;     }      for(size_t i = 0; i<key_size; i++){         if(m_list.at(group_index).m_elements.at(i).m_key.compare(key) == 0){             if(m_list.at(group_index).m_elements.at(i).key_type != AWESOME_TYPE_STRING) {                 m_error = AWESOME_ERROR_INVALID_DATA_TYPE_RETRIVED;                 return false;             }             p = m_list.at(group_index).m_elements.at(i).m_value.c_str();             return true;         }     }      m_error = AWESOME_ERROR_KEY_NOT_FOUND;     return false; }  bool awesome_ini::getKeyString(std::string &p, size_t group, std::string key) {     std::size_t group_size = m_list.size();     if(group >= group_size){         m_error = AWESOME_ERROR_GROUP_NOT_FOUND;         return false;     }      size_t key_size = m_list.at(group).m_elements.size();      if(key_size == 0){         return false;     }      for(size_t i = 0; i<key_size; i++){         if(m_list.at(group).m_elements.at(i).m_key.compare(key) == 0){             if(m_list.at(group).m_elements.at(i).key_type != AWESOME_TYPE_STRING) {                 m_error = AWESOME_ERROR_INVALID_DATA_TYPE_RETRIVED;                 return false;             }             p = m_list.at(group).m_elements.at(i).m_value.c_str();             return true;         }     }      m_error = AWESOME_ERROR_KEY_NOT_FOUND;      return false; } 

Example:

#include "awesome_ini_loader/awesome_ini.h"  int main(int argc, const char * argv[]) {     // insert code here...     awesome_ini parser("config.ini");      std::cout << "Error Code: " << parser.getError() << " Error Line:" << parser.getErrorLine() << "\n";      if(parser.getError() > 0)     {         std::cout << "Quit on error!";         return EXIT_FAILURE;     }      //Get group ID.     size_t gid = parser.findGroup("config");      int val = 0;     if(parser.getKeyInt(val, gid, "test"))     {         std::cout << "Int Val: " << val << "\n";     }      std::string sVal = "";     if(parser.getKeyString(sVal, gid, "string"))     {         std::cout << "String Val: " << sVal.c_str() << "\n";     }      bool bVal = false;     if(parser.getKeyBool(bVal, gid, "boolean"))     {         if(bVal){             std::cout << "Bool Val: TRUE\n";         }else{             std::cout << "Bool Val: FALSE\n";         }     }      float fVal = 0;     if(parser.getKeyFloat(fVal, gid, "floatnumber"))     {         std::cout << "Float Val: " << fVal << "\n";     }      parser.clearAll();      std::cout << "Done.\n";     return EXIT_SUCCESS; } 
     
 
 

Lista de respuestas

6
 
vote
vote
La mejor respuesta
 

Aquí hay algunos puntos para comenzar, en su mayoría relacionados con el estilo de codificación y las prácticas generales de C ++ (aproximadamente en orden de apariencia):

  1. cuidado con sus comentarios, algunas personas pueden encontrar cosas como esta ofensiva o inapropiada:

      AtomicLong1  

    que podría alejar a los usuarios de su proyecto y personalmente nunca enviaría un código con este tipo de comentarios como una cartera para una posición de trabajo.

    Si desea saludar los derechos de autor sobre el código, esto debe ser suficiente:

      AtomicLong2  

    Y si quieres ser creativo, solo agrega una cita de tu filósofo favorito al final.

    Editar nota: por lo que resulta que wtfpl es una licencia real ... No estoy seguro de qué hacer con esto ... gracias @felixbytow por señalarlo. < / p>

  2. Ha anidado todo en el archivo de encabezado bajo el 99887766655443343 incluye la Directiva de guardia. No agregue ese nivel de sangría. No es solo muy inusual, sino que también agrega nada a la comprensión del Código al costo del espaciado extra horizontal.

  3. Evite AtomicLong4 para constantes. No tienen tipo y proporcionan malas mensajes de error cuando los use incorrectamente. Lo que desea para esas constantes de cadena en el archivo de encabezado es un 99887776655443345 o AtomicLong6 . Esas constantes de las cuerdas también deben declararse solo en el archivo AtomicLong7 , ya que solo son relevantes para los Parser Internals. Nunca exponga los detalles de la implementación a la interfaz pública.

  4. Considere el uso de los fuertemente mecanografiados AtomicLong8 < / a> Si está dirigido a C ++ 11.

  5. Escritura AtomicLong9 En la lista de parámetros de una función C ++ que no toma parámetros (como en private static final int PADDING = 8; // fight false sharing private static final int CONCURRENCY = 8; // use 8 counters private AtomicLongArray lastActivityTimes = new AtomicLongArray(CONCURRENCY * PADDING); public long getLastActivityTime() { long result = Long.MIN_VALUE; // the biggest of the values contains the maximum for (int i=0; i<CONCURRENCY; ++i) { result = Math.max(result, lastActivityTimes.get(i*PADDING); } return result; } public void update() { long now = System.currentTimeMillis(); Random random = ThreadLocalRandom.get(); while (true) { int i = PADDING * random.nextInt(CONCURRENCY); long stored = lastActivityTimes.get(i); if (stored >= now) break; if (lastActivityTimes.compareAndSet(i, stored, now)) break; } } 0 ) es un estilo C-ish. C ++ no requiere eso; private static final int PADDING = 8; // fight false sharing private static final int CONCURRENCY = 8; // use 8 counters private AtomicLongArray lastActivityTimes = new AtomicLongArray(CONCURRENCY * PADDING); public long getLastActivityTime() { long result = Long.MIN_VALUE; // the biggest of the values contains the maximum for (int i=0; i<CONCURRENCY; ++i) { result = Math.max(result, lastActivityTimes.get(i*PADDING); } return result; } public void update() { long now = System.currentTimeMillis(); Random random = ThreadLocalRandom.get(); while (true) { int i = PADDING * random.nextInt(CONCURRENCY); long stored = lastActivityTimes.get(i); if (stored >= now) break; if (lastActivityTimes.compareAndSet(i, stored, now)) break; } } 1 es igual de bueno. Así que evita la verbosidad innecesaria.

  6. private static final int PADDING = 8; // fight false sharing private static final int CONCURRENCY = 8; // use 8 counters private AtomicLongArray lastActivityTimes = new AtomicLongArray(CONCURRENCY * PADDING); public long getLastActivityTime() { long result = Long.MIN_VALUE; // the biggest of the values contains the maximum for (int i=0; i<CONCURRENCY; ++i) { result = Math.max(result, lastActivityTimes.get(i*PADDING); } return result; } public void update() { long now = System.currentTimeMillis(); Random random = ThreadLocalRandom.get(); while (true) { int i = PADDING * random.nextInt(CONCURRENCY); long stored = lastActivityTimes.get(i); if (stored >= now) break; if (lastActivityTimes.compareAndSet(i, stored, now)) break; } } 2 Los destructores solo son necesarios cuando su clase está destinada a ser heredada. En este código en particular, eso no parece ser el caso. Si lo hiciste para permitir que los usuarios de su código heredan desde private static final int PADDING = 8; // fight false sharing private static final int CONCURRENCY = 8; // use 8 counters private AtomicLongArray lastActivityTimes = new AtomicLongArray(CONCURRENCY * PADDING); public long getLastActivityTime() { long result = Long.MIN_VALUE; // the biggest of the values contains the maximum for (int i=0; i<CONCURRENCY; ++i) { result = Math.max(result, lastActivityTimes.get(i*PADDING); } return result; } public void update() { long now = System.currentTimeMillis(); Random random = ThreadLocalRandom.get(); while (true) { int i = PADDING * random.nextInt(CONCURRENCY); long stored = lastActivityTimes.get(i); if (stored >= now) break; if (lastActivityTimes.compareAndSet(i, stored, now)) break; } } 3 , a la que se aconsejaría, ya que la composición es generalmente mucho más elegante y con menos acoplamiento. Debe eliminar private static final int PADDING = 8; // fight false sharing private static final int CONCURRENCY = 8; // use 8 counters private AtomicLongArray lastActivityTimes = new AtomicLongArray(CONCURRENCY * PADDING); public long getLastActivityTime() { long result = Long.MIN_VALUE; // the biggest of the values contains the maximum for (int i=0; i<CONCURRENCY; ++i) { result = Math.max(result, lastActivityTimes.get(i*PADDING); } return result; } public void update() { long now = System.currentTimeMillis(); Random random = ThreadLocalRandom.get(); while (true) { int i = PADDING * random.nextInt(CONCURRENCY); long stored = lastActivityTimes.get(i); if (stored >= now) break; if (lastActivityTimes.compareAndSet(i, stored, now)) break; } } 4 de la declaración de destructor y quizás incluso marque su clase private static final int PADDING = 8; // fight false sharing private static final int CONCURRENCY = 8; // use 8 counters private AtomicLongArray lastActivityTimes = new AtomicLongArray(CONCURRENCY * PADDING); public long getLastActivityTime() { long result = Long.MIN_VALUE; // the biggest of the values contains the maximum for (int i=0; i<CONCURRENCY; ++i) { result = Math.max(result, lastActivityTimes.get(i*PADDING); } return result; } public void update() { long now = System.currentTimeMillis(); Random random = ThreadLocalRandom.get(); while (true) { int i = PADDING * random.nextInt(CONCURRENCY); long stored = lastActivityTimes.get(i); if (stored >= now) break; if (lastActivityTimes.compareAndSet(i, stored, now)) break; } } 5 .

  7. Considere usar un espacio de nombres para anidar su biblioteca, en lugar de preflexionar todo con private static final int PADDING = 8; // fight false sharing private static final int CONCURRENCY = 8; // use 8 counters private AtomicLongArray lastActivityTimes = new AtomicLongArray(CONCURRENCY * PADDING); public long getLastActivityTime() { long result = Long.MIN_VALUE; // the biggest of the values contains the maximum for (int i=0; i<CONCURRENCY; ++i) { result = Math.max(result, lastActivityTimes.get(i*PADDING); } return result; } public void update() { long now = System.currentTimeMillis(); Random random = ThreadLocalRandom.get(); while (true) { int i = PADDING * random.nextInt(CONCURRENCY); long stored = lastActivityTimes.get(i); if (stored >= now) break; if (lastActivityTimes.compareAndSet(i, stored, now)) break; } } 6 . Un private static final int PADDING = 8; // fight false sharing private static final int CONCURRENCY = 8; // use 8 counters private AtomicLongArray lastActivityTimes = new AtomicLongArray(CONCURRENCY * PADDING); public long getLastActivityTime() { long result = Long.MIN_VALUE; // the biggest of the values contains the maximum for (int i=0; i<CONCURRENCY; ++i) { result = Math.max(result, lastActivityTimes.get(i*PADDING); } return result; } public void update() { long now = System.currentTimeMillis(); Random random = ThreadLocalRandom.get(); while (true) { int i = PADDING * random.nextInt(CONCURRENCY); long stored = lastActivityTimes.get(i); if (stored >= now) break; if (lastActivityTimes.compareAndSet(i, stored, now)) break; } } 7 sería más íntimo.

  8. Usted tiene demasiadas incluyen expuestas en el archivo de encabezado. No necesita private static final int PADDING = 8; // fight false sharing private static final int CONCURRENCY = 8; // use 8 counters private AtomicLongArray lastActivityTimes = new AtomicLongArray(CONCURRENCY * PADDING); public long getLastActivityTime() { long result = Long.MIN_VALUE; // the biggest of the values contains the maximum for (int i=0; i<CONCURRENCY; ++i) { result = Math.max(result, lastActivityTimes.get(i*PADDING); } return result; } public void update() { long now = System.currentTimeMillis(); Random random = ThreadLocalRandom.get(); while (true) { int i = PADDING * random.nextInt(CONCURRENCY); long stored = lastActivityTimes.get(i); if (stored >= now) break; if (lastActivityTimes.compareAndSet(i, stored, now)) break; } } 8 , addAndGet59 y time0 allí. Aquellos deben ir en la implementación ( time1 ). Esto también cae en la categoría de no exponer detalles de implementación.

  9. Por cierto, los archivos de encabezado mencionados anteriormente son los encabezados C. En C ++ debe estar incluido time2 , time3 time4 .

  10. En la mayoría de los lugares, está utilizando time5 y en algunos otros simplemente time6 . Asegúrese de reemplazar a aquellos con time7 .

  11. El constructor de time8 es masivo. Sugiero romperlo en algunos métodos más específicos para lograr responsabilidad única .

  12. No use valores decimales para los literales de caracteres (por ejemplo, time9 y otros lugares). Utilice la representación de ASCII adecuada ( 99887776655443370 / import java.math.BigInteger; public class Euler25 { public static void main(String[] args) { int i = 0; int cnt = 2; BigInteger limit = (new BigInteger("10")).pow(999); BigInteger[] fib = new BigInteger[3]; fib[0] = BigInteger.ONE; fib[2] = BigInteger.ONE; while ((fib[i]).compareTo(limit) < 0) { i = (i + 1) % 3; cnt++; fib[i] = fib[(i + 1) % 3].add(fib[(i + 2) % 3]); } System.out.printf("Fibonacci %d has 1000 digits ", cnt); } } 1 ). import java.math.BigInteger; public class Euler25 { public static void main(String[] args) { int i = 0; int cnt = 2; BigInteger limit = (new BigInteger("10")).pow(999); BigInteger[] fib = new BigInteger[3]; fib[0] = BigInteger.ONE; fib[2] = BigInteger.ONE; while ((fib[i]).compareTo(limit) < 0) { i = (i + 1) % 3; cnt++; fib[i] = fib[(i + 1) % 3].add(fib[(i + 2) % 3]); } System.out.printf("Fibonacci %d has 1000 digits ", cnt); } } 2 también viene a la mente ... .

  13. que trae que se utilice a la siguiente. Evite reinventar la rueda. Esto:

      import java.math.BigInteger;  public class Euler25 {   public static void main(String[] args) {     int i = 0;     int cnt = 2;     BigInteger limit = (new BigInteger("10")).pow(999);     BigInteger[] fib = new BigInteger[3];      fib[0] = BigInteger.ONE;     fib[2] = BigInteger.ONE;      while ((fib[i]).compareTo(limit) < 0) {         i = (i + 1) % 3;         cnt++;         fib[i] = fib[(i + 1) % 3].add(fib[(i + 2) % 3]);     }     System.out.printf("Fibonacci %d has 1000 digits ", cnt);   } } 3  

    es realizado por la import java.math.BigInteger; public class Euler25 { public static void main(String[] args) { int i = 0; int cnt = 2; BigInteger limit = (new BigInteger("10")).pow(999); BigInteger[] fib = new BigInteger[3]; fib[0] = BigInteger.ONE; fib[2] = BigInteger.ONE; while ((fib[i]).compareTo(limit) < 0) { i = (i + 1) % 3; cnt++; fib[i] = fib[(i + 1) % 3].add(fib[(i + 2) % 3]); } System.out.printf("Fibonacci %d has 1000 digits ", cnt); } } 4 Función de 998877665 443375 .

  14. Tiene algunos métodos que toman un 99887766554443376 como parámetro y solo se lee desde la cadena (sin hacer copias de ella). En tales casos, es mejor simplemente tomar el objeto por Const Reference ( 99887776655443377 ). Deja en claro que la función solo mira el objeto sin copiarlo. Por supuesto que esto es válido solo para tipos definidos por el usuario. Tipos nativos tales como import java.math.BigInteger; public class Euler25 { public static void main(String[] args) { int i = 0; int cnt = 2; BigInteger limit = (new BigInteger("10")).pow(999); BigInteger[] fib = new BigInteger[3]; fib[0] = BigInteger.ONE; fib[2] = BigInteger.ONE; while ((fib[i]).compareTo(limit) < 0) { i = (i + 1) % 3; cnt++; fib[i] = fib[(i + 1) % 3].add(fib[(i + 2) % 3]); } System.out.printf("Fibonacci %d has 1000 digits ", cnt); } } 8 S y import java.math.BigInteger; public class Euler25 { public static void main(String[] args) { int i = 0; int cnt = 2; BigInteger limit = (new BigInteger("10")).pow(999); BigInteger[] fib = new BigInteger[3]; fib[0] = BigInteger.ONE; fib[2] = BigInteger.ONE; while ((fib[i]).compareTo(limit) < 0) { i = (i + 1) % 3; cnt++; fib[i] = fib[(i + 1) % 3].add(fib[(i + 2) % 3]); } System.out.printf("Fibonacci %d has 1000 digits ", cnt); } } 9 S Siempre debe pasarse por valor.

  15. La función ArrayList0 está en desuso y tiene bastantes temas . Prefiero ArrayList1 (C ++ 11 ) o 99887766555443382 .

  16. Dado que ha nombrado a todos sus tipos con ArrayList3 Creo que sería bueno mantener la consistencia y también nombrar los métodos utilizando esta notación. El otro camino también funcionaría. ArrayList4 Para los tipos y ArrayList5 para métodos y variables.

 

Here are some points to start with, mostly related to coding style and overall C++ practices (roughly in order of appearance):

  1. Careful with your comments, some people might find things like this offensive or inappropriate:

    DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 

    That could drive users away from your project and I would personally never send code with this sort of comments as a portfolio for a job position either.

    If you just wish to wave copyrights over the code, this should suffice:

    // This code is public domain. I claim no copyrights over it. // No warranty is offered or implied; use it at your own risk. 

    And if you want to get creative, just add a quote from your favorite philosopher at the end.

    Edit note: So it turns out that WTFPL is an actual license... Not sure what to make of this... Thanks @FelixBytow for pointing it out.

  2. You have nested everything in the header file under the #ifndef AWESOME_INI_H include guard directive. Don't add that level of indentation. It is not just very unusual, but it also adds nothing to the understanding of the code at the cost of extra horizontal spacing.

  3. Avoid #defines for constants. They have no type and provide bad error messages when you use them improperly. What you want for those string constants in the header file is a const char [] or const std::string. Those string constants should also be declared in the .cpp file only, since they are only relevant to the parser internals. Never expose implementation details to the public interface.

  4. Consider using the strongly typed enum class if you are targeting C++11.

  5. Writing void in the parameter list of a C++ function that takes no parameters (as in getError(void)) is a C-ish style. C++ does not require that; () is just as good. So avoid the unnecessary verbosity.

  6. virtual destructors are only necessary when your class is meant to be inherited from. In this particular code, that doesn't seem to be the case. If you did that to allow users of your code to inherit from awesome_ini, I would advise against, since Composition is usually much more elegant and with less coupling. You should remove virtual from the destructor declaration and perhaps even mark your class final.

  7. Consider using a namespace to nest your library, instead of prefixing everything with awesome_. A namespace awesome { } would be neater.

  8. You have way too many includes exposed in the header file. You don't need ctype.h, string.h and stdlib.h in there. Those should go in the implementation (.cpp). This also falls into the category of not exposing implementation details.

  9. By the way, the header files mentioned above are the C headers. In C++ you should be including <cctype>, <cstring> and <cstdlib>.

  10. In most places you are using std::size_t and in a few others just size_t. Make sure you replace those with std::size_t.

  11. The constructor of awesome_ini is massive. I suggest breaking it into a few more specific methods to achieve Single Responsibility.

  12. Don't use decimal values for character literals (e.g.: c < 48 || c > 57 and other places). Use the proper ascii representation ('0' / '9'). std::isdigit() also comes to mind...

  13. Which brings use to the next one. Avoid reinventing the wheel. This:

    (c == '\n' || c == ' ' || c == '\r' || c == '\t') 

    Is done by the std::isspace() function from <cctype>.

  14. You have a few methods that take a std::string as parameter and only read from the string (without making copies of it). In such cases, it is better to just take the object by const reference (const std::string & str). Makes it clear that the function only look at the object without copying it. Of course that this is valid for User Defined Types only. Native types such as ints and floats should always be passed by value.

  15. The atoi() function is deprecated and has quite a few issues. Prefer std::stoi() (C++11) or std::strtol() otherwise.

  16. Since you've named all of your types with snake_case I think it would be nice to keep consistency and also name the methods using this notation. The other way around would also work. PascalCase for types and camelCase for methods and variables.

 
 
         
         

Relacionados problema

6  Otro analizador de JSON y serializador para QT, pero con características adicionales  ( Yet another json parser and serializer for qt but with additional features ) 
Escribí QJson , una clase de utilidad en / para qt, necesito que eche un vistazo. Tanto es un analizador y serializador JSON, sino con una funcionalidad exte...

7  Analizador de cadena citado  ( Quoted string parser ) 
He escrito un analizador de cadena que está diseñado para dividir una cadena por espacios, excluyendo espacios envueltos en cuerdas. Aquí hay algunas entrad...

6  Usando GetOpt analizar y validar los argumentos de la línea de comandos  ( Using getopt parse and validate command line arguments ) 
Estoy aprendiendo getopt en Python para analizar y validar las entradas de la línea de comandos: #!/usr/bin/python ''' Mailing Script Usage: python scrip...

4  Clase de análisis y manejo de URI  ( Uri parsing and handling class ) 
Escribí una clase simple para lidiar con el análisis y manejar URIS para el proyecto en el que estoy trabajando actualmente, ya que se basa mucho en esa funci...

7  Parser para fórmulas CNF  ( Parser for cnf formulas ) 
Tengo un analizador para las fórmulas CNF en Formato DIMACS , que es muy lento. ¿Alguna sugerencia sobre cómo mejorar su velocidad? Hice algún perfil y podrí...

2  libconfini (biblioteca compartida)  ( Libconfini shared library ) 
Recientemente escribí una pequeña biblioteca de análisis INI. El código también está en GitHub , con documentación . Me gustaría tener opiniones, sugerencia...

4  Posibles peligros de desbordamiento de búfer en el programa de análisis de registro C  ( Possible buffer overflow dangers in c log parsing program ) 
Después de horas de trabajo, finalmente terminé mi primer programa de análisis de registro C! (Anteriormente fue un guión bash, ahora es C). ¡Aunque creo qu...

8  Hola, Java World ~> analizando una cuadrícula de sudoku  ( Hello java world parsing a sudoku grid ) 
Este es mi primer intento, muy, muy, por primera vez en Java . No he empezado a abordar la resolución real de la sudoku Puzzle (ni siquiera estoy seguro de...

8  Dividir datos de diccionarios de texto lisos a múltiples archivos  ( Splitting plain text dictionary data to multiple files ) 
Tengo un archivo de texto simple con el contenido de un diccionario ( Diccionario no arabidgigado de Webster ) en este formato: A A (named a in the Englis...

6  Programa de Convertidor de Infix a Postfix  ( Infix to postfix converter program ) 
Esta es mi tarea. Amablemente ayúdame a verificarlo? Las instrucciones son: Implementar una expresión de infIX en el convertidor de expresión postfix. De...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos