Spippity boppity, my code is now the trashcans property

This commit is contained in:
sam-astro 2022-01-12 19:21:11 -05:00
parent 79ec9f6cd7
commit b3ac3ce18f
7 changed files with 263 additions and 175 deletions

View File

@ -263,7 +263,42 @@ bool BooleanLogic(const string& valA, const string& determinant, const string& v
int varOperation(const vector<string>& str, unordered_map<string, boost::any>& variableValues) int varOperation(const vector<string>& str, unordered_map<string, boost::any>& variableValues)
{ {
if (IsVar(str[0], variableValues)) if (count(str[0], '.') > 0)
{
if (IsVar(split(str[0], '.')[0], variableValues))
{
if (str[1] == "=")
EditClassSubComponent(variableValues[split(str[0], '.')[0]], str[1], EvalExpression(unWrapVec(vector<string>(str.begin() + 2, str.end())), variableValues), split(str[0], '.')[1]);
else if (str[1] == "+=")
EditClassSubComponent(variableValues[split(str[0], '.')[0]], str[1], EvalExpression(unWrapVec(vector<string>(str.begin() + 2, str.end())), variableValues), split(str[0], '.')[1]);
else if (str[1] == "-=")
EditClassSubComponent(variableValues[split(str[0], '.')[0]], str[1], EvalExpression(unWrapVec(vector<string>(str.begin() + 2, str.end())), variableValues), split(str[0], '.')[1]);
else if (str[1] == "*=")
EditClassSubComponent(variableValues[split(str[0], '.')[0]], str[1], EvalExpression(unWrapVec(vector<string>(str.begin() + 2, str.end())), variableValues), split(str[0], '.')[1]);
else if (str[1] == "/=")
EditClassSubComponent(variableValues[split(str[0], '.')[0]], str[1], EvalExpression(unWrapVec(vector<string>(str.begin() + 2, str.end())), variableValues), split(str[0], '.')[1]);
else
LogWarning("unrecognized operator \'" + str[1] + "\'");
return 0;
}
else if (IsVar(split(str[0], '.')[0], globalVariableValues))
{
if (str[1] == "=")
EditClassSubComponent(globalVariableValues[split(str[0], '.')[0]], str[1], EvalExpression(unWrapVec(vector<string>(str.begin() + 2, str.end())), variableValues), split(str[0], '.')[1]);
else if (str[1] == "+=")
EditClassSubComponent(globalVariableValues[split(str[0], '.')[0]], str[1], EvalExpression(unWrapVec(vector<string>(str.begin() + 2, str.end())), variableValues), split(str[0], '.')[1]);
else if (str[1] == "-=")
EditClassSubComponent(globalVariableValues[split(str[0], '.')[0]], str[1], EvalExpression(unWrapVec(vector<string>(str.begin() + 2, str.end())), variableValues), split(str[0], '.')[1]);
else if (str[1] == "*=")
EditClassSubComponent(globalVariableValues[split(str[0], '.')[0]], str[1], EvalExpression(unWrapVec(vector<string>(str.begin() + 2, str.end())), variableValues), split(str[0], '.')[1]);
else if (str[1] == "/=")
EditClassSubComponent(globalVariableValues[split(str[0], '.')[0]], str[1], EvalExpression(unWrapVec(vector<string>(str.begin() + 2, str.end())), variableValues), split(str[0], '.')[1]);
else
LogWarning("unrecognized operator \'" + str[1] + "\'");
return 0;
}
}
else if (IsVar(str[0], variableValues))
{ {
if (str[1] == "=") if (str[1] == "=")
variableValues[str[0]] = EvalExpression(unWrapVec(vector<string>(str.begin() + 2, str.end())), variableValues); variableValues[str[0]] = EvalExpression(unWrapVec(vector<string>(str.begin() + 2, str.end())), variableValues);
@ -277,7 +312,6 @@ int varOperation(const vector<string>& str, unordered_map<string, boost::any>& v
variableValues[str[0]] = AnyAsFloat(variableValues[str[0]]) / AnyAsFloat(EvalExpression(unWrapVec(vector<string>(str.begin() + 2, str.end())), variableValues)); variableValues[str[0]] = AnyAsFloat(variableValues[str[0]]) / AnyAsFloat(EvalExpression(unWrapVec(vector<string>(str.begin() + 2, str.end())), variableValues));
else else
LogWarning("unrecognized operator \'" + str[1] + "\'"); LogWarning("unrecognized operator \'" + str[1] + "\'");
//cout << variables[v] << " is " << variableValues[v] << endl;
return 0; return 0;
} }
else if (IsVar(str[0], globalVariableValues)) else if (IsVar(str[0], globalVariableValues))
@ -294,7 +328,6 @@ int varOperation(const vector<string>& str, unordered_map<string, boost::any>& v
globalVariableValues[str[0]] = AnyAsFloat(variableValues[str[0]]) / AnyAsFloat(EvalExpression(unWrapVec(vector<string>(str.begin() + 2, str.end())), variableValues)); globalVariableValues[str[0]] = AnyAsFloat(variableValues[str[0]]) / AnyAsFloat(EvalExpression(unWrapVec(vector<string>(str.begin() + 2, str.end())), variableValues));
else else
LogWarning("unrecognized operator \'" + str[1] + "\'"); LogWarning("unrecognized operator \'" + str[1] + "\'");
//cout << variables[v] << " is " << variableValues[v] << endl;
return 0; return 0;
} }
LogWarning("uninitialized variable or typo in \'" + str[0] + "\'"); LogWarning("uninitialized variable or typo in \'" + str[0] + "\'");
@ -355,6 +388,14 @@ boost::any ProcessLine(const vector<vector<string>>& words, int lineNum, unorder
return nullType; return nullType;
} }
// Check existing variables: To see if class sub component matches
else if (IsVar(split(words[lineNum][0], '.')[0], variableValues) || IsVar(split(words[lineNum][0], '.')[0], globalVariableValues))
{
// Evaluates what the operator (ex. '=', '+=') does to the value on the left by the value on the right
varOperation(vector<string>(words[lineNum].begin(), words[lineNum].end()), variableValues);
return nullType;
}
// Gathers while loop contents // Gathers while loop contents
else if (words[lineNum][0] == "while") else if (words[lineNum][0] == "while")
{ {
@ -501,7 +542,7 @@ boost::any ExecuteFunction(const string& functionName, const vector<boost::any>&
} }
catch (const std::exception&) catch (const std::exception&)
{ {
LogCriticalError("\'" + unWrapVec(words[lineNum]) + "\'\nIn function: " + functionName + "\nLine: " + to_string(lineNum)); LogCriticalError("\'" + unWrapVec(words[lineNum]) + "\'\n In function: " + functionName + "\n Line: " + to_string(lineNum));
} }
if (!returnVal.empty()) if (!returnVal.empty())
return returnVal; return returnVal;

View File

@ -90,6 +90,30 @@ boost::any GetClassSubComponent(boost::any value, string subComponentName)
{ {
return any_cast<Vec2>(value).SubComponent(subComponentName); return any_cast<Vec2>(value).SubComponent(subComponentName);
} }
// If a Sprite Class
if (any_type(value) == 4)
{
return any_cast<Sprite>(value).SubComponent(subComponentName);
}
return nullType;
}
boost::any EditClassSubComponent(boost::any value, string oper, boost::any otherVal, string subComponentName)
{
// If a Vec2 Class
if (any_type(value) == 5)
{
Vec2 v = any_cast<Vec2>(value);
v.EditSubComponent(subComponentName, oper, otherVal);
return v;
}
// If a Sprite Class
if (any_type(value) == 4)
{
Sprite v = any_cast<Sprite>(value);
v.EditSubComponent(subComponentName, oper, otherVal);
return v;
}
return nullType; return nullType;
} }
@ -191,15 +215,14 @@ boost::any CPPFunction(const string& name, const vector<boost::any>& args)
} }
else if (name == "CPP.Graphics.Draw") else if (name == "CPP.Graphics.Draw")
{ {
Sprite d = any_cast<Sprite>(args[0]); any_cast<Sprite>(args[0]).Draw();
d.Draw();
} }
else if (name == "CPP.Input.GetKey") else if (name == "CPP.Input.GetKey")
return KEYS[any_cast<string>(args[0])] == 1; return KEYS[StringRaw(any_cast<string>(args[0]))] == 1;
else if (name == "CPP.System.Print") else if (name == "CPP.System.Print")
cout << AnyAsString(args[0]); cout << StringRaw(AnyAsString(args[0]));
else if (name == "CPP.System.PrintLine") else if (name == "CPP.System.PrintLine")
cout << AnyAsString(args[0]) << endl; cout << StringRaw(AnyAsString(args[0])) << endl;
else if (name == "CPP.System.Vec2") else if (name == "CPP.System.Vec2")
{ {
Vec2 v(AnyAsFloat(args[0]), AnyAsFloat(args[1])); Vec2 v(AnyAsFloat(args[0]), AnyAsFloat(args[1]));
@ -208,7 +231,7 @@ boost::any CPPFunction(const string& name, const vector<boost::any>& args)
else else
LogWarning("CPP function \'" + name + "\' does not exist."); LogWarning("CPP function \'" + name + "\' does not exist.");
return 0; return nullType;
} }
#endif #endif

View File

@ -85,9 +85,23 @@ func NSprite(path, x, y, r)
return s return s
} }
// Draws sprite to window
func Draw(spr)
{
CPP.Graphics.Draw(spr)
}
// Creates new Vector2 class // Creates new Vector2 class
func NVec2(x, y) func NVec2(x, y)
{ {
Vec2 v = CPP.System.Vec2(x, y) Vec2 v = CPP.System.Vec2(x, y)
return v return v
} }
// Gets if key is down
func GetKey(keyName)
{
bool b = CPP.Input.GetKey(keyName)
print b
return b
}

View File

@ -10,7 +10,6 @@
#include <algorithm> #include <algorithm>
#include <boost/any.hpp> #include <boost/any.hpp>
#include "strops.h" #include "strops.h"
#include "builtin.h"
#include "main.h" #include "main.h"
#include <SDL.h> #include <SDL.h>
#include <SDL_image.h> #include <SDL_image.h>
@ -184,6 +183,27 @@ public:
return Vec2(x * rhs, y * rhs); return Vec2(x * rhs, y * rhs);
} }
Vec2 operator*=(float rhs)
{
x *= rhs;
y *= rhs;
return *this;
}
Vec2 operator/(float rhs)
{
return Vec2(x / rhs, y / rhs);
}
Vec2 operator/=(float rhs)
{
x /= rhs;
y /= rhs;
return *this;
}
boost::any SubComponent(std::string componentName) boost::any SubComponent(std::string componentName)
{ {
if (componentName == "x") if (componentName == "x")
@ -192,6 +212,36 @@ public:
return y; return y;
} }
int EditSubComponent(std::string componentName, std::string oper, boost::any otherVal)
{
if (componentName == "x")
{
if (oper == "=")
x = AnyAsFloat(otherVal);
else if (oper == "+=")
x += AnyAsFloat(otherVal);
else if (oper == "-=")
x -= AnyAsFloat(otherVal);
else if (oper == "*=")
x *= AnyAsFloat(otherVal);
else if (oper == "/=")
x /= AnyAsFloat(otherVal);
}
if (componentName == "y")
{
if (oper == "=")
y = AnyAsFloat(otherVal);
else if (oper == "+=")
y += AnyAsFloat(otherVal);
else if (oper == "-=")
y -= AnyAsFloat(otherVal);
else if (oper == "*=")
y *= AnyAsFloat(otherVal);
else if (oper == "/=")
y /= AnyAsFloat(otherVal);
}
}
float x, y; float x, y;
}; };
@ -302,76 +352,84 @@ public:
rect.y = static_cast<int>(position.y); rect.y = static_cast<int>(position.y);
rect.w = scale.x; rect.w = scale.x;
rect.h = scale.y; rect.h = scale.y;
Load();
} }
void Load() int Load()
{ {
SDL_Surface* surface = loadSurface(path); SDL_Surface* surface = loadSurface(path);
texture = SDL_CreateTextureFromSurface(gRenderer, surface); texture = SDL_CreateTextureFromSurface(gRenderer, surface);
SDL_FreeSurface(surface); SDL_FreeSurface(surface);
return 0;
isLoaded = true;
} }
void Draw() int Draw()
{ {
if (texture == NULL)
Load();
rect.y = static_cast<int>(position.y); rect.y = static_cast<int>(position.y);
SDL_RenderCopy(gRenderer, texture, NULL, &rect); SDL_RenderCopy(gRenderer, texture, NULL, &rect);
return 0;
} }
boost::any SubComponent(std::string componentName) boost::any SubComponent(std::string componentName)
{ {
if (componentName == "position") if (componentName == "position")
return position; return position;
if (componentName == "position.x")
return position.x;
if (componentName == "position.y")
return position.y;
}
int EditSubComponent(std::string componentName, std::string oper, boost::any otherVal)
{
if (componentName == "position")
{
if(oper == "=")
position = any_cast<Vec2>(otherVal);
else if(oper == "+=")
position += any_cast<Vec2>(otherVal);
else if(oper == "-=")
position -= any_cast<Vec2>(otherVal);
else if(oper == "*=")
position *= AnyAsFloat(otherVal);
else if(oper == "/=")
position /= AnyAsFloat(otherVal);
}
if (componentName == "position.x")
{
if (oper == "=")
position.x = AnyAsFloat(otherVal);
else if (oper == "+=")
position.x += AnyAsFloat(otherVal);
else if (oper == "-=")
position.x -= AnyAsFloat(otherVal);
else if (oper == "*=")
position.x *= AnyAsFloat(otherVal);
else if (oper == "/=")
position.x /= AnyAsFloat(otherVal);
}
if (componentName == "position.y")
{
if (oper == "=")
position.y = AnyAsFloat(otherVal);
else if (oper == "+=")
position.y += AnyAsFloat(otherVal);
else if (oper == "-=")
position.y -= AnyAsFloat(otherVal);
else if (oper == "*=")
position.y *= AnyAsFloat(otherVal);
else if (oper == "/=")
position.y /= AnyAsFloat(otherVal);
}
} }
Vec2 position; Vec2 position;
double angle; double angle;
std::string path; std::string path;
SDL_Rect rect{}; SDL_Rect rect{};
SDL_Texture* texture = NULL; SDL_Texture* texture;
bool isLoaded = false; };
};/*
class PlayerScore
{
public:
PlayerScore(Vec2 position, SDL_Renderer* renderer, TTF_Font* font, SDL_Color scoreColor)
: renderer(renderer), font(font)
{
surface = TTF_RenderText_Solid(font, "0", scoreColor);
texture = SDL_CreateTextureFromSurface(renderer, surface);
int width, height;
SDL_QueryTexture(texture, nullptr, nullptr, &width, &height);
rect.x = static_cast<int>(position.x);
rect.y = static_cast<int>(position.y);
rect.w = width;
rect.h = height;
}
~PlayerScore()
{
SDL_FreeSurface(surface);
SDL_DestroyTexture(texture);
}
void Draw()
{
SDL_RenderCopy(renderer, texture, nullptr, &rect);
}
SDL_Renderer* renderer;
TTF_Font* font;
SDL_Surface* surface{};
SDL_Texture* texture{};
SDL_Rect rect{};
};*/
int cleanupGraphics() int cleanupGraphics()
{ {
@ -429,25 +487,25 @@ int updateLoop()
else if (event.key.keysym.sym == SDLK_TAB) else if (event.key.keysym.sym == SDLK_TAB)
KEYS["TAB"] = 1; KEYS["TAB"] = 1;
else if (event.key.keysym.sym == SDLK_q) else if (event.key.keysym.sym == SDLK_q)
KEYS["q"] = 1; KEYS["Q"] = 1;
else if (event.key.keysym.sym == SDLK_w) else if (event.key.keysym.sym == SDLK_w)
KEYS["w"] = 1; KEYS["W"] = 1;
else if (event.key.keysym.sym == SDLK_e) else if (event.key.keysym.sym == SDLK_e)
KEYS["e"] = 1; KEYS["E"] = 1;
else if (event.key.keysym.sym == SDLK_r) else if (event.key.keysym.sym == SDLK_r)
KEYS["r"] = 1; KEYS["R"] = 1;
else if (event.key.keysym.sym == SDLK_t) else if (event.key.keysym.sym == SDLK_t)
KEYS["t"] = 1; KEYS["T"] = 1;
else if (event.key.keysym.sym == SDLK_y) else if (event.key.keysym.sym == SDLK_y)
KEYS["y"] = 1; KEYS["Y"] = 1;
else if (event.key.keysym.sym == SDLK_u) else if (event.key.keysym.sym == SDLK_u)
KEYS["u"] = 1; KEYS["U"] = 1;
else if (event.key.keysym.sym == SDLK_i) else if (event.key.keysym.sym == SDLK_i)
KEYS["i"] = 1; KEYS["I"] = 1;
else if (event.key.keysym.sym == SDLK_o) else if (event.key.keysym.sym == SDLK_o)
KEYS["o"] = 1; KEYS["O"] = 1;
else if (event.key.keysym.sym == SDLK_p) else if (event.key.keysym.sym == SDLK_p)
KEYS["p"] = 1; KEYS["P"] = 1;
else if (event.key.keysym.sym == SDLK_LEFTBRACKET) else if (event.key.keysym.sym == SDLK_LEFTBRACKET)
KEYS["BRACKET_L"] = 1; KEYS["BRACKET_L"] = 1;
else if (event.key.keysym.sym == SDLK_RIGHTBRACKET) else if (event.key.keysym.sym == SDLK_RIGHTBRACKET)
@ -552,25 +610,25 @@ int updateLoop()
else if (event.key.keysym.sym == SDLK_TAB) else if (event.key.keysym.sym == SDLK_TAB)
KEYS["TAB"] = 0; KEYS["TAB"] = 0;
else if (event.key.keysym.sym == SDLK_q) else if (event.key.keysym.sym == SDLK_q)
KEYS["q"] = 0; KEYS["Q"] = 0;
else if (event.key.keysym.sym == SDLK_w) else if (event.key.keysym.sym == SDLK_w)
KEYS["w"] = 0; KEYS["W"] = 0;
else if (event.key.keysym.sym == SDLK_e) else if (event.key.keysym.sym == SDLK_e)
KEYS["e"] = 0; KEYS["E"] = 0;
else if (event.key.keysym.sym == SDLK_r) else if (event.key.keysym.sym == SDLK_r)
KEYS["r"] = 0; KEYS["R"] = 0;
else if (event.key.keysym.sym == SDLK_t) else if (event.key.keysym.sym == SDLK_t)
KEYS["t"] = 0; KEYS["T"] = 0;
else if (event.key.keysym.sym == SDLK_y) else if (event.key.keysym.sym == SDLK_y)
KEYS["y"] = 0; KEYS["Y"] = 0;
else if (event.key.keysym.sym == SDLK_u) else if (event.key.keysym.sym == SDLK_u)
KEYS["u"] = 0; KEYS["U"] = 0;
else if (event.key.keysym.sym == SDLK_i) else if (event.key.keysym.sym == SDLK_i)
KEYS["i"] = 0; KEYS["I"] = 0;
else if (event.key.keysym.sym == SDLK_o) else if (event.key.keysym.sym == SDLK_o)
KEYS["o"] = 0; KEYS["O"] = 0;
else if (event.key.keysym.sym == SDLK_p) else if (event.key.keysym.sym == SDLK_p)
KEYS["p"] = 0; KEYS["P"] = 0;
else if (event.key.keysym.sym == SDLK_LEFTBRACKET) else if (event.key.keysym.sym == SDLK_LEFTBRACKET)
KEYS["BRACKET_L"] = 0; KEYS["BRACKET_L"] = 0;
else if (event.key.keysym.sym == SDLK_RIGHTBRACKET) else if (event.key.keysym.sym == SDLK_RIGHTBRACKET)
@ -646,65 +704,8 @@ int updateLoop()
} }
} }
//if (buttons[Buttons::PaddleOneUp])
//{
// paddleOne.velocity.y = -PADDLE_SPEED;
//}
//else if (buttons[Buttons::PaddleOneDown])
//{
// paddleOne.velocity.y = PADDLE_SPEED;
//}
//else
//{
// paddleOne.velocity.y = 0.0f;
//}
//if (buttons[Buttons::PaddleTwoUp])
//{
// paddleTwo.velocity.y = -PADDLE_SPEED;
//}
//else if (buttons[Buttons::PaddleTwoDown])
//{
// paddleTwo.velocity.y = PADDLE_SPEED;
//}
//else
//{
// paddleTwo.velocity.y = 0.0f;
//}
//// Update the paddle positions
//paddleOne.Update(dt);
//paddleTwo.Update(dt);
//// Clear the window to black
//SDL_SetRenderDrawColor(gRenderer, 0x0, 0x0, 0x0, 0xFF);
SDL_RenderClear(gRenderer); SDL_RenderClear(gRenderer);
//// Set the draw color to be white
//SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
//// Draw the net
//for (int y = 0; y < WINDOW_HEIGHT; ++y)
//{
// if (y % 5)
// {
// SDL_RenderDrawPoint(gRenderer, WINDOW_WIDTH / 2, y);
// }
//}
//// Draw the ball
//ball.Draw(gRenderer);
//// Draw the paddles
//paddleOne.Draw(gRenderer);
//paddleTwo.Draw(gRenderer);
//// Display the scores
//playerOneScoreText.Draw();
//playerTwoScoreText.Draw();
//randomAssSprite.Draw();
ExecuteFunction("Update", vector<boost::any> {}); ExecuteFunction("Update", vector<boost::any> {});
// Present the backbuffer // Present the backbuffer
@ -732,12 +733,8 @@ int initGraphics(std::string windowTitle, int width, int height)
//Get window surface //Get window surface
gScreenSurface = SDL_GetWindowSurface(gWindow); gScreenSurface = SDL_GetWindowSurface(gWindow);
//Sprite randomAssSprite( ExecuteFunction("Start", vector<boost::any> {});
// Vec2((WINDOW_WIDTH / 2.0f) - (100 / 2.0f), (WINDOW_HEIGHT / 2.0f) - (100 / 2.0f)),
// Vec2(100, 100),
// 0,
// "./circle.png");
updateLoop(); updateLoop();

View File

@ -1,42 +1,51 @@
int SCREENW = 780
int SCREENH = 500
int scoreOne = 0
int scoreTwo = 0
Vec2 paddleScale = NVec2(16, 70)
func Main(input, in) func Main(input, in)
{ {
print "PI is: " + PI CPP.Graphics.Init("This is a pong game", SCREENW, SCREENH)
int x = 1
print "xis" + x
float k = 0
print k
while x < 5
{
print x
float s = Sin(x)
print s
k = Sigmoid(s)
print k
x += 1
}
Vec2 aa = NVec2(6, 8)
print aa.x + " " + aa.y
global Sprite thisisasprite = CPP.Graphics.Sprite("./circle.png", aa, aa, 0)
CPP.Graphics.Init("This is a pong game", 500, 500)
} }
func Update(input) func Start()
{ {
//int x = 0 float xPosBall = SCREENW / 2
//int y = 0 float yPosBall = SCREENH / 2
//while x < 16 Vec2 ballPosition = NVec2(xPosBall, yPosBall)
//{ Vec2 ballScale = NVec2(16, 16)
// while y < 16
// { Vec2 paddleScale = NVec2(16, 70)
// SetPixel(x, y, 255, 0, 0)
// y += 1 float yPosPaddle = yPosBall - paddleScale.y / 2
// }
// y = 0 Vec2 lPaddlePosition = NVec2(15, yPosPaddle)
// x += 1
//} float rOffset = SCREENW - 15
CPP.Graphics.Draw(thisisasprite) Vec2 rPaddlePosition = NVec2(rOffset, yPosPaddle)
print "updating"
global Sprite ballSprite = CPP.Graphics.Sprite("./square.png", ballPosition, ballScale, 0)
global Sprite lPaddle = CPP.Graphics.Sprite("./square.png", lPaddlePosition, paddleScale, 0)
global Sprite rPaddle = CPP.Graphics.Sprite("./square.png", rPaddlePosition, paddleScale, 0)
}
func Update()
{
Vec2 as = NVec2(16, 70)
print "updating"
if GetKey("W") == true
{
print "W"
as.x += 4
// lPaddle.position.y += 1
}
print as.x + " , " + as.y
CPP.Graphics.Draw(ballSprite)
CPP.Graphics.Draw(lPaddle)
CPP.Graphics.Draw(rPaddle)
} }

BIN
Slang/square.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 B

View File

@ -5,6 +5,10 @@
using namespace std; using namespace std;
float AnyAsFloat(const boost::any& val);
bool isNumber(const string& str); bool isNumber(const string& str);
bool stob(const string& str); bool stob(const string& str);