Browse Source

Added Config and INIConfig classes, which will replace INIFile

Hash_Table: Added valueless set()
Changed version to 0.19-dev
release/0.19
Jessica James 8 years ago
parent
commit
e8120ccf5b
  1. 145
      Jupiter/Config.cpp
  2. 253
      Jupiter/Config.h
  3. 7
      Jupiter/Hash_Table.h
  4. 31
      Jupiter/Hash_Table_Imp.h
  5. 285
      Jupiter/INIConfig.cpp
  6. 62
      Jupiter/INIConfig.h
  7. 2
      Jupiter/Jupiter.h
  8. 4
      Jupiter/Jupiter.vcxproj
  9. 18
      Jupiter/Jupiter.vcxproj.filters

145
Jupiter/Config.cpp

@ -0,0 +1,145 @@
/**
* Copyright (C) 2016 Jessica James.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Written by Jessica James <jessica.aj@outlook.com>
*/
#include "Config.h"
const Jupiter::Config o_null_section;
const Jupiter::ReadableString &Jupiter::Config::get(const Jupiter::ReadableString &in_key, const Jupiter::ReadableString &in_default_value) const
{
const Jupiter::ReadableString *result = m_table.get(in_key);
if (result == nullptr)
return in_default_value;
return *result;
}
const Jupiter::ReadableString *Jupiter::Config::getValue(const Jupiter::ReadableString &in_key) const
{
return m_table.get(in_key);
}
Jupiter::Config *Jupiter::Config::getSection(const Jupiter::ReadableString &in_key) const
{
return m_sections.get(in_key);
}
Jupiter::Config &Jupiter::Config::getSectionReference(const Jupiter::ReadableString &in_key)
{
Config *section = m_sections.get(in_key);
if (section == nullptr)
{
m_sections.set(in_key);
section = m_sections.get(in_key);
section->m_name = in_key;
return *section;
}
return *section;
}
bool Jupiter::Config::set(const Jupiter::ReadableString &in_key, const Jupiter::ReadableString &in_value)
{
return m_table.set(in_key, in_value);
}
bool Jupiter::Config::remove(const Jupiter::ReadableString &in_key)
{
return m_table.remove(in_key);
}
const Jupiter::ReadableString &Jupiter::Config::getName() const
{
return m_name;
}
void Jupiter::Config::erase()
{
m_table.erase();
m_sections.erase();
}
bool Jupiter::Config::read(const char *in_filename)
{
m_name = in_filename;
return this->read_internal(in_filename);
}
bool Jupiter::Config::read(const Jupiter::ReadableString &in_filename)
{
m_name = in_filename;
return this->read_internal(m_name.c_str());
}
bool Jupiter::Config::write()
{
return this->write(m_name.c_str());
}
bool Jupiter::Config::write(const char *)
{
return false;
}
bool Jupiter::Config::write(const Jupiter::ReadableString &in_filename)
{
return this->write(Jupiter::CStringS(in_filename).c_str());
}
bool Jupiter::Config::reload()
{
this->erase();
return this->read_internal(m_name.c_str());
}
bool Jupiter::Config::reload(const char *in_filename)
{
this->erase();
return this->read(in_filename);
}
bool Jupiter::Config::reload(const Jupiter::ReadableString &in_filename)
{
this->erase();
return this->read(in_filename);
}
/** Operators */
Jupiter::Config &Jupiter::Config::operator[](const Jupiter::ReadableString &in_key)
{
return this->getSectionReference(in_key);
}
/** Private functions */
bool Jupiter::Config::read_internal(const char *)
{
return false;
}
void Jupiter::Config::Buffer::set_length(size_t in_length)
{
this->length = in_length;
}
char *Jupiter::Config::Buffer::get_str() const
{
return this->str;
}

253
Jupiter/Config.h

@ -0,0 +1,253 @@
/**
* Copyright (C) 2016 Jessica James.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Written by Jessica James <jessica.aj@outlook.com>
*/
#if !defined JUPITER_CONFIG_H_HEADER
#define JUPITER_CONFIG_H_HEADER
/**
* @file Config.h
* @brief Defines the Config class, which provides common functionality for Config files in differing formats.
*/
#include "Jupiter.h"
#include "Hash_Table.h"
#include "Reference_String.h"
#include "CString.h"
/** DLL Linkage Nagging */
#if defined _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4251)
#endif
namespace Jupiter
{
/**
* @brief Base class for all Config type files
*/
class JUPITER_API Config
{
public:
/** Hash_Table type for sections */
typedef Hash_Table<StringS, Config, ReadableString> SectionHashTable;
/**
* @brief Fetches the value of an entry.
*
* @param in_key Key of the entry to fetch
* @param in_default_value Value to return if no such entry exists
* @return Value of the entry if it exists, an empty string otherwise.
*/
const Jupiter::ReadableString &get(const Jupiter::ReadableString &in_key, const Jupiter::ReadableString &in_default_value = Jupiter::ReferenceString::empty) const;
/**
* @brief Fetches the value of an entry
*
* @param in_key Key of the entry to fetch
* @return Pointer to the value of the entry on success, nullptr otherwise
*/
const Jupiter::ReadableString *getValue(const Jupiter::ReadableString &in_key) const;
/**
* @brief Fetches the value of an entry and interprets it as another type.
*
* @param T Type to interpret the value as
*
* @param in_key Key of the entry to fetch
* @param in_default_value Value to return if no such entry exists
* @return Value of the entry if it exists, 0 otherwise.
*/
template<typename T> T get(const Jupiter::ReadableString &in_key, T in_default_value = 0);
/**
* @brief Fetches a section based on its name
*
* @param in_key Name of the section to fetch
* @return Pointer to a section if it exists, nullptr otherwise
*/
Config *getSection(const Jupiter::ReadableString &in_key) const;
/**
* @brief Fetches a section based on its name
* Note: This will create new sections as necessary if they do not exist
*
* @param in_key Name of the section to fetch
* @return Reference to the section
*/
Config &getSectionReference(const Jupiter::ReadableString &in_key);
/**
* @brief Sets an entry's value in the table
*
* @param in_key Key of the entry to write to
* @param in_value Value to write to the entry
* @return True if a new entry was added, false if an entry was overwritten
*/
bool set(const Jupiter::ReadableString &in_key, const Jupiter::ReadableString &in_value);
/**
* @brief Removes an entry from the table
*
* @param in_key Key of the entry to remove
* @return True if an entry was removed, false otherwise
*/
bool remove(const Jupiter::ReadableString &in_key);
/**
* @brief Fetches the name of this config section
* Note: This is the filename on the root node
*
* @return Name of this section
*/
const Jupiter::ReadableString &getName() const;
/**
* @brief Erases all data from this section
*/
void erase();
/**
* @brief Reads config data from a file and stores it in this config
*
* @param in_filename Name of the file to read from
* @return True on success, false otherwise
*/
bool read(const char *in_filename);
/**
* @brief Reads config data from a file and stores it in this config
*
* @param in_filename Name of the file to read from
* @return True on success, false otherwise
*/
bool read(const Jupiter::ReadableString &in_filename);
/**
* @brief Writes config data to the last read file
*
* @return True on success, false otherwise
*/
bool write();
/**
* @brief Writes config data to a file
*
* @param in_filename Name of the file to write to
* @return True on success, false otherwise
*/
virtual bool write(const char *in_filename);
/**
* @brief Writes config data to a file
*
* @param in_filename Name of the file to write to
* @return True on success, false otherwise
*/
bool write(const Jupiter::ReadableString &in_filename);
/**
* @brief Empties config data from memory and reads from the last read file
*
* @return True on success, false otherwise
*/
bool reload();
/**
* @brief Empties config data from memory and reads from a file
*
* @param in_filename Name of the file to read from
* @return True on success, false otherwise
*/
bool reload(const char *in_filename);
/**
* @brief Empties config data from memory and reads from a file
*
* @param in_filename Name of the file to read from
* @return True on success, false otherwise
*/
bool reload(const Jupiter::ReadableString &in_filename);
/**
* @brief Fetches a reference to this config's entry table
*
* @return Reference to m_table
*/
inline const HashTable &getTable() const { return m_table; }
/**
* @brief Fetches a reference to this config's subsections
*
* @return Reference to m_sections
*/
inline const SectionHashTable getSections() const { return m_sections; }
/** Subscript operator */
Config &operator[](const Jupiter::ReadableString &in_key);
/** Used for low-level string operations */
class Buffer : public Jupiter::StringL
{
public:
/**
* @brief Sets the length of the string
*
* @param in_length Length of the string
*/
void set_length(size_t in_length);
/**
* @brief Returns a pointer to the underlying string
*
* @return Pointer to an array of characters
*/
char *get_str() const;
};
protected:
virtual bool read_internal(const char *in_filename);
/** Name of this Config section. This is empty or the filename at the root level. */
Jupiter::CStringS m_name;
/** Table of entries within this section */
HashTable m_table;
/** Table of sections within this section */
SectionHashTable m_sections;
};
}
/** Template function implementations */
template<typename T> inline T Jupiter::Config::get(const Jupiter::ReadableString &in_key, T in_default_value)
{
const Jupiter::ReadableString *result = m_table.get(in_key);
if (result == nullptr)
return in_default_value;
return static_cast<T>(*result);
}
/** Re-enable warnings */
#if defined _MSC_VER
#pragma warning(pop)
#endif
#endif // JUPITER_CONFIG_H_HEADER

7
Jupiter/Hash_Table.h

@ -59,6 +59,7 @@ namespace Jupiter
KeyT key;
ValueT value;
Entry(const InKeyT &in_key);
Entry(const InKeyT &in_key, const InValueT &in_value);
};
@ -78,6 +79,7 @@ namespace Jupiter
* @return True if a new entry was added, false if an entry was overwritten
*/
bool set(const InKeyT &in_key, const InValueT &in_value);
bool set(const InKeyT &in_key);
/**
* @brief Removes an entry from the bucket
@ -164,12 +166,13 @@ namespace Jupiter
* @return True if a new entry was added, false if an entry was overwritten
*/
bool set(const InKeyT &in_key, const InValueT &in_value);
bool set(const InKeyT &in_key);
/**
* @brief Removes an entry from the table and returns its value
* @brief Removes an entry from the table
*
* @param in_key Key of the entry to remove
* @return Value of the entry that was removed if it exists, nullptr otherwise
* @return True if an entry was removed, false otherwise
*/
bool remove(const InKeyT &in_key);

31
Jupiter/Hash_Table_Imp.h

@ -53,6 +53,12 @@ template<typename T> inline size_t Jupiter::default_hash_function(const T &in)
/** Hash_Table::Bucket::Entry */
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::Entry::Entry(const InKeyT &in_key)
{
key = in_key;
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::Entry::Entry(const InKeyT &in_key, const InValueT &in_value)
{
@ -86,6 +92,17 @@ bool Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::set(con
return true;
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
bool Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::set(const InKeyT &in_key)
{
for (Jupiter::SLList<Entry>::Node *node = m_entries.getHead(); node != nullptr; node = node->next)
if (node->data->key == in_key)
return false;
m_entries.add(new Entry(in_key));
return true;
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
bool Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::remove(const InKeyT &in_key)
{
@ -196,6 +213,20 @@ bool Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::set(const InKey
return false;
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
bool Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::set(const InKeyT &in_key)
{
if (m_buckets[HashF(in_key) % m_buckets_size].set(in_key))
{
if (++m_length == m_buckets_size)
expand();
return true;
}
return false;
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
bool Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::remove(const InKeyT &in_key)
{

285
Jupiter/INIConfig.cpp

@ -0,0 +1,285 @@
/**
* Copyright (C) 2016 Jessica James.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Written by Jessica James <jessica.aj@outlook.com>
*/
#include <stack>
#include <functional>
#include "INIConfig.h"
#include "Socket.h"
void Jupiter::INIConfig::write_helper(FILE *in_file, const Jupiter::Config *in_section, size_t in_depth)
{
size_t index;
if (in_depth != 0)
{
// Write header
fputs("\r\n", in_file);
// Tabs
for (index = 1; index < in_depth; ++index)
fputc('\t', in_file);
for (index = 0; index != in_depth; ++index)
fputc('[', in_file);
in_section->getName().print(in_file);
for (index = 0; index != in_depth; ++index)
fputc(']', in_file);
fputs("\r\n", in_file);
}
// Write table entries
{
auto bucket_itr = in_section->getTable().begin();
auto bucket_end = in_section->getTable().end();
Jupiter::SLList<HashTable::Bucket::Entry>::Node *entry_itr;
while (bucket_itr != bucket_end)
{
for (entry_itr = bucket_itr->m_entries.getHead(); entry_itr != nullptr; entry_itr = entry_itr->next)
{
// Tabs
for (index = 1; index < in_depth; ++index)
fputc('\t', in_file);
// Write entry
entry_itr->data->key.print(in_file);
fputs(" = ", in_file);
entry_itr->data->value.println(in_file);
}
++bucket_itr;
}
}
// Write subsections
{
auto bucket_itr = in_section->getSections().begin();
auto bucket_end = in_section->getSections().end();
Jupiter::SLList<SectionHashTable::Bucket::Entry>::Node *entry_itr;
while (bucket_itr != bucket_end)
{
for (entry_itr = bucket_itr->m_entries.getHead(); entry_itr != nullptr; entry_itr = entry_itr->next)
write_helper(in_file, &entry_itr->data->value, in_depth + 1);
++bucket_itr;
}
}
}
bool Jupiter::INIConfig::write(const char *in_filename)
{
// Open file
FILE *file = fopen(in_filename, "wb");
if (file == nullptr)
return false;
// Iterate through table and sections
write_helper(file, this, 0);
// File writing completed; close and return
fclose(file);
return true;
}
bool Jupiter::INIConfig::read_internal(const char *in_filename)
{
Jupiter::ReferenceString line;
std::stack<Jupiter::Config *> section_stack;
section_stack.push(this);
auto process_line = [&line, &section_stack]()
{
const char *itr = line.ptr();
const char *end = itr + line.size(); // guaranteed to be greater than itr
// Shift to right of spaces
while (isspace(*itr))
if (++itr == end)
return; // Line is purely whitespace
line.shiftRight(itr - line.ptr());
if (*itr == ';')
return; // Comment
if (*itr == '[')
{
// Parse header
size_t depth = 1;
for (++itr; itr != end && *itr == '['; ++itr)
++depth;
line.shiftRight(itr - line.ptr());
while (end != itr)
{
--end;
if (*end != ']' && isspace(*end) == 0)
{
++end;
break;
}
}
line.set(itr, end - itr);
// Add section to stack; pop sections or push blanks as necessary
while (depth < section_stack.size())
section_stack.pop();
while (depth > section_stack.size())
section_stack.push(std::addressof(section_stack.top()->getSectionReference(Jupiter::ReferenceString::empty)));
section_stack.push(&section_stack.top()->getSectionReference(line));
}
else
{
// Truncate spaces
--end;
while (isspace(*end))
--end; // don't need a safety check since we know there is at least 1 non-space character
// end now points to a non-space character within the bounds
++end;
line.truncate(itr + line.size() - end);
// Parse key (can be empty)
while (*itr != '=')
if (++itr == end)
return; // Error: no assignment exists; ignore line
Jupiter::ReferenceString key;
if (itr != line.ptr())
{
// Truncate spaces from key; a non-space character is guaranteed
end = itr - 1;
while (isspace(*end))
--end;
key = line.substring(size_t{ 0 }, end + 1 - line.ptr());
end = line.ptr() + line.size();
}
// Parse value (can be empty)
if (++itr != end)
{
// Shift to right of spaces; a non-space character is guaranteed
while (isspace(*itr))
++itr;
line.shiftRight(itr - line.ptr());
}
else
line = Jupiter::ReferenceString::empty;
// Add entry to current table on stack
section_stack.top()->set(key, line);
}
};
constexpr size_t READ_CHUNK_SIZE = 1024;
size_t read_count = READ_CHUNK_SIZE;
Buffer buffer;
char *itr;
char *end;
// Open file
FILE *file = fopen(in_filename, "rb");
if (file == nullptr)
return false;
buffer.setBufferSize(READ_CHUNK_SIZE * 2);
// Parse file contents
while (read_count == READ_CHUNK_SIZE)
{
// Ensure the buffer has at least READ_CHUNK_SIZE space remaining
buffer.setBufferSize(buffer.size() + READ_CHUNK_SIZE);
// Read data from file to end of buffer
itr = buffer.get_str();
read_count = fread(itr + buffer.size(), sizeof(char), READ_CHUNK_SIZE, file);
buffer.set_length(buffer.size() + read_count);
end = itr + buffer.size();
// Reset line
line.set(buffer.ptr(), 0);
// Parse buffer for lines
while (itr != end)
{
// Check if the line is over
if (*itr == '\n' || *itr == '\r')
{
// Process line
line.set(buffer.ptr(), itr - buffer.ptr());
if (line.isNotEmpty())
process_line();
// Keep iterating until next non-newline character
while (true)
{
++itr;
if (itr == end)
{
// No data remains to be parsed in buffer; erase buffer and break
buffer.erase();
break;
}
if (*itr != '\n' && *itr != '\r')
{
// Shift buffer and break
buffer.shiftRight(itr - buffer.ptr());
break;
}
}
}
else
++itr;
}
}
// Process data remaining in buffer as a line
line.set(buffer.ptr(), buffer.size());
if (line.isNotEmpty())
process_line();
// File has been successfully read, or an error occurred.
fclose(file);
return true;
}

62
Jupiter/INIConfig.h

@ -0,0 +1,62 @@
/**
* Copyright (C) 2016 Jessica James.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Written by Jessica James <jessica.aj@outlook.com>
*/
#if !defined JUPITER_INICONFIG_H_HEADER
#define JUPITER_INICONFIG_H_HEADER
/**
* @file INIConfig.h
* @brief Provides an INI config implementation for the Config interface.
*/
#include "Config.h"
/** DLL Linkage Nagging */
#if defined _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4251)
#endif
namespace Jupiter
{
/**
* @brief INI-based Config class
*/
class JUPITER_API INIConfig : public Jupiter::Config
{
public:
/**
* @brief Writes config data to a file
*
* @param in_filename Name of the file to write to
* @return True on success, false otherwise
*/
bool write(const char *in_filename);
private:
bool read_internal(const char *in_filename);
void write_helper(FILE *in_file, const Jupiter::Config *in_section, size_t in_depth);
};
}
/** Re-enable warnings */
#if defined _MSC_VER
#pragma warning(pop)
#endif
#endif // JUPITER_INICONFIG_H_HEADER

2
Jupiter/Jupiter.h

@ -36,7 +36,7 @@
#define JUPITER_API
#endif // _WIN32
#define JUPITER_VERSION "Jupiter 0.18.1" /** Version of this program at compile time. */
#define JUPITER_VERSION "Jupiter 0.19-dev" /** Version of this program at compile time. */
#if defined __cplusplus
extern "C"

4
Jupiter/Jupiter.vcxproj

@ -179,6 +179,7 @@
<ClCompile Include="Base64.cpp" />
<ClCompile Include="Base64C.c" />
<ClCompile Include="Command.cpp" />
<ClCompile Include="Config.cpp" />
<ClCompile Include="Database.cpp" />
<ClCompile Include="DataBuffer.cpp" />
<ClCompile Include="File.cpp" />
@ -198,11 +199,13 @@
<ClCompile Include="TCPSocket.cpp" />
<ClCompile Include="Timer.cpp" />
<ClCompile Include="UDPSocket.cpp" />
<ClCompile Include="INIConfig.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="ArrayList.h" />
<ClInclude Include="Base64.h" />
<ClInclude Include="Command.h" />
<ClInclude Include="Config.h" />
<ClInclude Include="CString.h" />
<ClInclude Include="CString_Imp.h" />
<ClInclude Include="Database.h" />
@ -247,6 +250,7 @@
<ClInclude Include="Thinker.h" />
<ClInclude Include="Timer.h" />
<ClInclude Include="UDPSocket.h" />
<ClInclude Include="INIConfig.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Jupiter.rc" />

18
Jupiter/Jupiter.vcxproj.filters

@ -58,6 +58,12 @@
<Filter Include="Header Files\Hash">
<UniqueIdentifier>{7db21243-8b23-4dd2-9888-0bdd3c5a1edd}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Files\Configs">
<UniqueIdentifier>{da033f3a-f5fd-4592-900f-f17bb3520547}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\Files\Configs">
<UniqueIdentifier>{b5b148d5-c636-41eb-838a-7555114e1589}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Functions.c">
@ -126,6 +132,12 @@
<ClCompile Include="Hash.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Config.cpp">
<Filter>Source Files\Files\Configs</Filter>
</ClCompile>
<ClCompile Include="INIConfig.cpp">
<Filter>Source Files\Files\Configs</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Functions.h">
@ -269,6 +281,12 @@
<ClInclude Include="Hash_Table_Imp.h">
<Filter>Header Files\Hash</Filter>
</ClInclude>
<ClInclude Include="Config.h">
<Filter>Header Files\Files\Configs</Filter>
</ClInclude>
<ClInclude Include="INIConfig.h">
<Filter>Header Files\Files\Configs</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Jupiter.rc">

Loading…
Cancel
Save